5.8. Production Server
Although there are a lot of similarities to the development environment, there are a few key differences especially when it comes to security and performance considerations.
Create the server
Secure the server
Install required software
Download the project
Set up configuration files
5.8.1. Create a Production Machine
Choose your host and create your new virtual server then use SSH to access it using a terminal on your local machine.
Note
It saves complications if you set up your server (including the site and Nginx etc.) before you change DNS settings and traffic starts getting routed.
Initial set up overview:
* SSH access
* Install software
* Firewall
* Swap for extra memory
* Fail2ban
5.8.1.1. SSH Access
Consider adding the dev machine SSH Key to the server when creating it or set up a very strong password then log in to it and create a priveleged user other than root:
ssh root@ip-address
adduser example.co.uk --force-badname
password
Note
For security on the production web server, each project will have its own user area and password but for development purposes each project will live in the home folder for the main developer.
You can add SUDO permissions for a user by running visudo while logged in as root and adding the following line:
newusername ALL=(ALL:ALL) ALL
CTRL+O followed by ENTER to save
CTRL+X followed by ENTER to close
exit (to log off)
Back on local machine:
ssh-copy-id th-example.co.uk@IP-ADDRESS
ssh th-example.co.uk@IP-ADDRESS
sudo nano /etc/ssh/sshd_config
permitrootlogin no
SAVE AND EXIT
sudo dpkg-reconfigure locales en_GB.UTF-8 # Might not be required
ssh-keygen -t rsa
COPY SSH KEY TO BITBUCKET
reboot
Note
SSH log in is dependent on whether the DNS is set up and working for your server or not. If not, use the IP address.
5.8.1.2. Install Software
Install the Django Software Requirements.
5.8.1.3. Firewall
For Ubuntu an easy way to restrict access is to use UFW:
https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-ubuntu-20-04
5.8.1.4. Swap for extra memory
https://www.digitalocean.com/community/tutorials/how-to-add-swap-space-on-ubuntu-20-04
5.8.1.5. Fail2ban
Limit access to repeat offenders:
https://linuxize.com/post/install-configure-fail2ban-on-ubuntu-20-04/
5.8.2. Download the Django application
Note
For production you should already have a Django application developed and uploaded to an online version control system such as BitBucket. If not, follow the instructions for creating a Development Machine and develop one first.
Follow the instructions for Using an existing Django application.
5.8.2.1. Database
For development in Django you can use a simple sqlite database that is just a file in the project folder and is simpler to set up and wipe and start fresh. Sometimes it is worth setting up a database to mirror production.
Create user and database
Backup
Follow the PostgreSQL instructions for setting up a production database.
Follow the Backup instructions.
5.8.2.2. Nginx
Note
When you use debian-base systems, you should fill /etc/hostname file with FQDN
Note
Set up Nginx for your site so it is listening before setting up DNS or it will set it to the default entry and be a pain to clear.
Add configuration file to sites-available then symbolic link to sites-enabled (sudo ln -s /etc/nginx/sites-available/hello /etc/nginx/sites-enabled/hello). Restart nginx to check there are no errors (sudo service nginx restart).
Run SSL certificate creation with Let’s Encrypt.
Refer to the Nginx instructions for more information.
5.8.3. Gunicorn
pip install gunicorn in the virtualenv and create config file called gunicorn_start(.bash?) and save it in /bin.
Set the executable bit on the file with sudo chmod u+x bin/gunicorn_start
“As a rule-of-thumb set the –workers (NUM_WORKERS) according to the following formula: 2 * CPUs + 1. The idea being, that at any given time half of your workers will be busy doing I/O. For a single CPU machine it would give you 3.”
Example config:
#!/bin/bash
NAME="hello_app" # Name of the application
DJANGODIR=/webapps/hello_django/hello # Django project directory
SOCKFILE=/webapps/hello_django/run/gunicorn.sock # we will communicte using this unix socket
USER=hello # the user to run as
GROUP=webapps # the group to run as
NUM_WORKERS=3 # how many worker processes should Gunicorn spawn
DJANGO_SETTINGS_MODULE=hello.settings # which settings file should Django use
DJANGO_WSGI_MODULE=hello.wsgi # WSGI module name
echo "Starting $NAME as `whoami`"
# Activate the virtual environment
cd $DJANGODIR
source ../bin/activate
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH
# Create the run directory if it doesn't exist
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR
# Start your Django Unicorn
# Programs meant to be run under supervisor should not daemonize themselves (do not use --daemon)
exec ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--bind=unix:$SOCKFILE \
--log-level=debug \
--log-file=-
5.8.4. Supervisor
Create config file in /etc/supervisor/conf.d
Example config file:
[program:hello]
command = /webapps/hello_django/bin/gunicorn_start ; Command to start app
user = hello ; User to run as
stdout_logfile = /webapps/hello_django/logs/gunicorn_supervisor.log ; Where to write log messages
redirect_stderr = true ; Save stderr in the same log
environment=LANG=en_US.UTF-8,LC_ALL=en_US.UTF-8 ; Set UTF-8 as default encoding
Create logs:
mkdir -p /home/project/logs/
touch /home/project/logs/gunicorn_supervisor.log
Reload:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl status
This should mean the application is automatically started after a system reboot.
5.8.5. Celery and Beat
ACTIVATE THE ENVIRONMENTS THEN ENTER THE PROJECT FOLDER
python -m celery -A proj worker
celery -A proj beat -l INFO –scheduler django_celery_beat.schedulers:DatabaseScheduler
5.8.6. Daphne and Channels
5.8.7. SSL
Let’s Encrypt
https://www.f5.com/company/blog/nginx/using-free-ssltls-certificates-from-lets-encrypt-with-nginx
Create conf files that get automatically adjusted by certbot instead of using the previous sites-available/enabled system.
Reload nginx with a different command:
sudo nginx -t && sudo nginx -s reload
5.8.8. DNS
Here is an example DNS configuration file:
A - @ - SERVER_IP
CNAME - www - DOMAIN.co.uk. # note the trailing dot
NS - ns1.digitalocean.com.
NS - ns2.digitalocean.com.
NS - ns3.digitalocean.com.
5.8.9. Fixtures
python manage.py dumpdata APP --indent=4 > APP-fixtures.json