This is a summarized document from this digital ocean doc
Any commands with "$" at the beginning run on your local machine and any "#" run when logged into the server
You can choose to create SSH keys to login if you want. If not, you will get the password sent to your email to login via SSH
To generate a key on your local machine
$ ssh-keygenHit enter all the way through and it will create a public and private key at
~/.ssh/id_rsa
~/.ssh/id_rsa.pubYou want to copy the public key (.pub file)
$ cat ~/.ssh/id_rsa.pubCopy the entire output and add as an SSH key for Digital Ocean
If you setup SSH keys correctly the command below will let you right in. If you did not use SSH keys, it will ask for a password. This is the one that was mailed to you
$ ssh root@YOUR_SERVER_IPIt will ask for a password, use something secure. You can just hit enter through all the fields. I used the user "djangoadmin" but you can use anything
# adduser djangoadmin# usermod -aG sudo djangoadminNow we need to setup SSH keys for the new user. You will need to get them from your local machine
You need to copy the key from your local machine so either exit or open a new terminal
# exitYou can generate a different key if you want but we will use the same one so lets output it, select it and copy it
$ cat ~/.ssh/id_rsa.pub$ ssh root@YOUR_SERVER_IPNavigate to the new users home folder and create a file at '.ssh/authorized_keys' and paste in the key
# cd /home/djangoadmin
# mkdir .ssh
# cd .ssh
# nano authorized_keys
Paste the key and hit "ctrl-x", hit "y" to save and "enter" to exitYou should now get let in as the new user
$ ssh djangoadmin@YOUR_SERVER_IP# sudo nano /etc/ssh/sshd_configPermitRootLogin no
PasswordAuthentication no# sudo systemctl reload sshdSee which apps are registered with the firewall
# sudo ufw app listAllow OpenSSH
# sudo ufw allow OpenSSH# sudo ufw enable# sudo ufw statusWe are now done with access and security and will move on to installing software
# sudo apt update
# sudo apt upgrade# sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl# sudo -u postgres psqlYou should now be logged into the pg shell
CREATE DATABASE db_prod;CREATE USER dbadmin WITH PASSWORD 'test1234';ALTER ROLE dbadmin SET client_encoding TO 'utf8';
ALTER ROLE dbadmin SET default_transaction_isolation TO 'read committed';
ALTER ROLE dbadmin SET timezone TO 'UTC';GRANT ALL PRIVILEGES ON DATABASE db_prod TO dbadmin;\qYou need to install the python3-venv package
# sudo apt install python3-venv# mkdir pyapps
# cd pyapps# python3 -m venv ./venv# source venv/bin/activateFrom your local machine, create a requirements.txt with your app dependencies. Make sure you push this to your repo
$ pip freeze > requirements.txtCreate a new repo and push to it (you guys know how to do that)
# git clone https://github.com/yourgithubname/your_project.gitYou could manually install each one as well
# pip install -r requirements.txtAdd code to your settings.py file and push to server
try:
from .prod_settings import *
except ImportError:
passCreate a file called prod_settings.py on your server along side of settings.py and add the following
- SECRET_KEY
- ALLOWED_HOSTS
- DATABASES
- DEBUG
# python manage.py makemigrations
# python manage.py migrate# python manage.py createsuperuserpython manage.py collectstatic# sudo ufw allow 8000# python manage.py runserver 0.0.0.0:8000Add some data in the admin area
Install gunicorn
# pip install gunicornAdd to requirements.txt
# pip freeze > requirements.txt# gunicorn --bind 0.0.0.0:8000 your_project.wsgiYour images, etc will be gone
ctrl-c
# deactivate# sudo nano /etc/systemd/system/gunicorn.socket[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target
# sudo nano /etc/systemd/system/gunicorn.service[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
User=djangoadmin
Group=www-data
WorkingDirectory=/home/djangoadmin/apps/your_project
ExecStart=/home/djangoadmin/apps/venv/bin/gunicorn \
--access-logfile - \
--workers 2 \
--bind unix:/run/gunicorn.sock \
your_project.wsgi:application
[Install]
WantedBy=multi-user.target
# sudo systemctl start gunicorn.socket
# sudo systemctl enable gunicorn.socket# sudo systemctl status gunicorn.socket# file /run/gunicorn.sock# sudo nano /etc/nginx/sites-available/your_projectserver {
listen 80;
server_name YOUR_IP_ADDRESS;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/djangoadmin/pyapps/your_project;
}
location /media/ {
root /home/djangoadmin/pyapps/your_project;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
}# sudo ln -s /etc/nginx/sites-available/your_project /etc/nginx/sites-enabled# sudo nginx -t# sudo systemctl restart nginx# sudo ufw delete allow 8000
# sudo ufw allow 'Nginx Full'Open up the nginx conf file
# sudo nano /etc/nginx/nginx.confclient_max_body_size 20M;# sudo systemctl restart nginxGo to your domain registrar and create the following a record
@ A Record YOUR_IP_ADDRESS
www CNAME example.com
ALLOWED_HOSTS = ['IP_ADDRESS', 'example.com', 'www.example.com']server {
listen: 80;
server_name xxx.xxx.xxx.xxx example.com www.example.com;
}# sudo systemctl restart nginx
# sudo systemctl restart gunicornInstall supervisor
apt-get install supervisor After installing supervisor create a supervisor conf file
sudo vim /etc/supervisor/conf.d/django_project.confA sample conf file for django project
[program:project]
command=/path_to/venv/bin/gunicorn --workers 2 --bind unix:/path_where_you_want_the_sock_file_to_reside/project.sock project.wsgi
directory=/root/path_to_project/project
autostart=true
autorestart=true
stderr_logfile=/var/log/project.err.log
stdout_logfile=/var/log/project.out.log
[supervisord]
environment=
DATABASE_URL="postgres://postgres:root@localhost:5432/db_name",
DEBUG_STATUS="False",
The conf file specifies how the project should be run by the gunicorn and where the log files should be and .env files for running the project
After adding the conf file run the below commands
sudo supervisorctl reread
sudo supervisorctl updateTo check if the supervisor services are running use the below commmands
sudo service supervisor status
sudo service supervisor restart
sudo service supervisor start
Nginx config will remain same
common nginx gotchas
For debugging statifiles check access and error logs for nginx at /etc/nginx/
Sometimes for staticfiles use alias instead of root with trailing slash
Difference between root and alias inside static block
based on static file settings your nginx conf could be
server {
listen 80;
server_name YOUR_IP_ADDRESS;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
alias /your_project/staticfiles/;
}
location /media/ {
root /pyapps/your_project;
}
location / {
include proxy_params;
proxy_pass http://unix:/path_where_the_sock_file_resides/project.sock;
}
}