- Ubuntu Setup
- Add GitHub SSH Key
- Install Python 3.x, Pip, and PipEnv
- PostgreSQL Setup
- Redis Setup
- Django Setup
- uWSGI Setup
- SSL & Nginx Setup
- Login to server as the root user account.
- Run sever upgrades
$ apt-get update
$ apt-get upgrade- Set server hostname.
$ hostnamectl set-hostname <server name>- Add your new hostname to the
/etc/hostsfile.
$ nano /etc/hosts...
127.0.1.1 <host name>
...- Set the timezone for the server.
$ dpkg-reconfigure tzdata- Create a user account to connect to server remotely.
$ adduser <username>- Add user to the sudo group.
$ moduser -aG sudo <username>- Switch to the new user account and move to their home directory
$ su <username>
$ cd ~- Create a SSH key-pair on the local computer with an appropriate program (e.g. Putty, ssh-keygen); copy the public key as a single line:
ssh-rsa AAAAAAAA....123BC== your-rsa-key
- Create an SSH folder.
$ mkdir ~/.ssh- Create an
authorized_keysfile and copy your public key into it.
$ nano ~/.ssh/authorized_keys- Update the permissions to the SSH directory and files.
$ chmod 700 -R ~/.ssh
$ chmod 600 ~/.ssh/authorized_keys- Logout and test that your SSH access works before proceeding.
- Once you have confirmed SSH access is working, update the SSH settings to disallow root logins, password authentication.
$ sudo nano /etc/ssh/sshd_config... PermitRootLogin no ... PasswordAuthentication no ...
- Restart the SSH service.
$ sudo systemctl restart ssh.- Configure the Universal Firewall (UFW) to allow SSH, HTTP, and HTTPS connections.
$ sudo ufw allow 22
$ sudo ufw allow 80
$ sudo ufw allow 443- Enable UFW.
$ sudo ufw enable
> Command may disrupt existing ssh connections. Proceed with operation (y|n)?
$ y- Install Fail2Ban.
$ sudo apt-get install fail2ban- Create a local version of the Fail2ban configuration file and jail file.
$ sudo cp /etc/fail2ban/fail2ban.conf /etc/fail2ban/fail2ban.local
$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local- Start and enable Fail2Ban.
$ sudo systemctl start fail2ban
$ sudo systemctl enable fail2ban- Create a user account to manage and run the Django application.
$ adduser <Django username>- Grant any sudo commands that this user may need. You will want to limit these for security purposes. For example, to allow the user to restart services:
$ sudo visudo... # User privilege specification root ALL=(ALL:ALL) ALL <user> ALL=(ALL:ALL) /bin/systemctl restart ...
See the GitHub Help topics on Generating a new SSH key and Add the SSH key to your GitHub account for all details on this process.
- If not done already, create an
.sshdirectory
$ mkdir .ssh- Create an SSH key for your Ubuntu user
$ ssh-keygen -t rsa -b 4096 -C "<your_email@example.com>"- Complete the prompts to finish the creation process. If you need to use this SSH key for CI/CD purposes, you will probably leave the passphrase blank.
- Go to the settings for your GitHub user and then to the SSH and GPG keys section.
- Click on the New SSH key button and enter in a title and your key. You can quickly get your key by using the following command:
$ cat .ssh/id_rsa.pub
> ssh-rsa AAAA...== example@email.com- If you have multiple SSH keys for your account you may need to add an SSH Configuration
file to ensure the
ssh-agentuses the right key:
$ nano .ssh/config... Host <name-to-identify-host> github.com HostName github.com User git IdentityFile ~/.ssh/<path_to_private_key> IdentitiesOnly yes ...
- Install your required python version and update any required sym links.
$ sudo apt-get install python3.x python3.x-dev
$ sudo unlink /usr/bin/python3
$ sudo ln -s /usr/bin/python3.x /usr/bin/python3- Install pip and confirm the installation.
$ sudo apt install python3-pip
$ pip3 --version
pip 9.0.1 from /usr/lib/python3/dist-packages (python 3.x)- Update pip.
$ sudo python3 -m pip install --upgrade pip- Install pipenv.
$ sudo pip3 install pipenv- Install required packages
$ sudo apt-get install postgresql postgresql-contrib- Log into a Postgres session
$ sudo -u postgres psql- Create a database for the Django project
CREATE DATABASE <database_name>;- Create a Postgres user for the Django project
CREATE USER <user_name> WITH PASSWORD '<user_password>';- Set some sane defaults for the Django user
ALTER ROLE <user_name> SET client_encoding TO 'utf8';
ALTER ROLE <user_name> SET default_transaction_isolation TO 'read committed';
ALTER ROLE <user_name> SET timezone TO 'UTC';- Grant all required privileges on the database to the database user
GRANT ALL PRIVILEGES ON DATABASE <database_name> TO <user_name>;- If this is a development environment, you may want your user to have additional access to reset the database. The following commands will easily allow this via the django-extensions package. DO NOT PROVIDE THIS ACCESS IN LIVE ENVIRONMENTS AS IT CAN RESULT IN COMPLETE DATA LOSS.
ALTER USER <user_name> CREATEDB;
ALTER DATABASE <database_name> OWNER TO <user_name>;- Exit the Psql shell
\q- Install Redis
$ sudo apt-get install redis-server- Enable Redis to start on system boot
$ sudo systemctl enable redis-server.service- Set some basic settings in the Redis configuration file (run as a daemon)
$ sudo nano /etc/redis/redis.conf... daemonize yes ...
- Restart the Redis service for the changes to take effect
$ sudo systemctl restart redis.service- Confirm Redis is working with some basic commands with
redis-cli
$ redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> SET <key> <value>
OK
127.0.0.1:6379> GET '<key>'
"<value>"
127.0.0.1:6379> KEYS *
1) "<key>"
127.0.0.1:6379> EXIT- If needed, install and update your
python,pip, andpipenvpackages. - If not done already, switch to the user account that will be running the Django app.
$ sudo su <user>
$ cd ~- Clone the git repository containing the Django app (this assumes you are using a SSH authentication).
$ git clone <site:repository.git>- Change to the repository directory and create your virtual environment.
$ pipenv install --dev- Run any deployment scripts or commands (e.g.
make deploy). You will probably need to setup environment variables, collect static files, etc.
- If needed, install and update your
python,pip, andpipenvpackages. - Install uWSGI
$ sudo pip3 install uwsgi- Test that uWSGI and the django project are working properly
$ uwsgi --http :8080 --home <path/to/environment> --chdir <path/to/django/project> --wsgi-file <path/to/django/project/wsgi/file/wsgi.py>- Setup the uWSGI configuration file
$ sudo nano /etc/uwsgi/sites/<site_init_file.ini>[uwsgi]
project = <project name>
base = /home/<user directory>
pipenv = <name of pipenv environment directory>
chdir = %(base)/%(project)
home = %(base)/.local/share/virtualenvs/%(pipenv)
module = <path.to.project.wsgi.module>:application
master = true
processes = 5
socket = %(base)/%(project)/%(project).sock
chmod-socket = 666
vacuum = true
logto = <location for logs>
env = DJANGO_SETTINGS_MODULE=<path.to.project.settings.module>
uid=<user>
gid=<user>
ignore-sigpipe = true
ignore-write-errors = true
ignore-write-exceptions = true
enable-threads = true- Setup the systemd script to run the uWSGI Emperor Service on startup
$ sudo nano /etc/systemd/system/uwsgi.service[Unit]
Description=uWSGI Emperor service
After=syslog.target
[Service]
ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/sites
Restart=always
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all
[Install]
WantedBy=multi-user.target- Refresh
systemctl.
$ sudo systemctl daemon-reload- Start the uWSGI service.
$ sudo systemctl start uwsgi- Set uWSGI to start on system boot.
$ sudo systemctl enable uwsgi- Check the UWSGI service status for any issues.
$ sudo systemctl status uwsgi- Install Nginx.
$ sudo apt-get install nginx- Create a server block configuration file for your site.
$ sudo nano /etc/nginx/sites-available/<site_name>server {
listen 80;
server_name <urls for site>;
# Logging details
access_log <path/to/access/log>;
error_log <path/to/error/log>;
# Deny illegal host headers
if ($host !~* ^(<path.to.site.com>|<www.path.to.site.com)$) {
return 444;
}
# Settings for uwsgi (if needed)
location / {
include uwsgi_params;
uwsgi_pass unix:<path/to/uwsgi/socket>;
}
}
- Create a sym for your server block to the
sites-enabledfolder.
$ sudo ln -s /etc/nginx/sites-available/<site_name> /etc/nginx/sites-enabled- Confirm your configuration for any issues.
$ sudo nginx -t- Restart the Nginx and UWSGI service to load the new configurations.
$ sudo systemctl restart nginx
$ sudo systemctl restart uwsgi- Install Certbot to setup a SSL certificate.
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update
$ sudo apt-get install python-certbot-nginx- Generate the needed certificate(s). You will need to ensure your DNS settings are pointing to the server correctly before proceeding with these steps.
$ sudo certbot --nginx -d <site_url.com> -d <www.site_url.com>- Set up the certificate for auto renewal by generating a cron job.
$ sudo crontab -e... 30 3 * * 5 /usr/bin/certbot renew --quiet ...
- Update your Nginx server blocks to make use of the SSL certificate (if you didn't do it automatically).
$ sudo nano /etc/nginx/sites-available/<site_name>server {
listen 80;
listen [::]:80;
server_name <server_name>;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
ssl_certificate <path/to/certificate>
ssl_certificate_key <path/to/certificate/key>
...
}
- If desired, generate a new Diffie-Hellman parameter (you can save
it at
/etc/ssl/certs/dhparam.pemif you need a location).
$ sudo openssl dhparam -out <path/to/save/file.pem> 2048- If you created a new Diffie-Hellman parameter, you will need to update your Nginx server block to point to the new file.
$ sudo nano /etc/nginx/sites-available/<site_name>... ssl_dhparam <path/to/save/file.pem>; ...
- Confirm that your configuration is correct.
$ sudo nginx -t- Restart the Nginx service to update any configuration changes.
$ sudo systemctl reload nginx- You can test out your SSL certificate at SSL Labs.