.. _production: ================= 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 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 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. .. _production_software_requirements: Install Software ---------------- Install the :ref:`django_software_requirements`. .. _firewall: Firewall -------- For Ubuntu an easy way to restrict access is to use UFW: ``_ .. _swap_memory: Swap for extra memory --------------------- ``_ .. _fail2ban: Fail2ban -------- Limit access to repeat offenders: ``_ 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 :ref:`development` and develop one first. Follow the instructions for :ref:`using_an_existing_django_application`. .. _production_database: 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 :ref:`postgresql` instructions for setting up a production database. Follow the :ref:`postgresql_backup` instructions. 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 :ref:`nginx` instructions for more information. 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=- 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. 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 Daphne and Channels =================== ``_ 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 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. Fixtures ======== :: python manage.py dumpdata APP --indent=4 > APP-fixtures.json