This is every step, in detail, to create a Django App with Postgres, NGINX, Gunicorn, and HTTPS on Digital Ocean. The only thing I don't go over is how to create a droplet and manage the domain.
Reference: | |
Django/Postgres/Nginx/Gunicorn in Ubuntu: https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-16-04 | |
Encryption: https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-16-04 | |
Where you see "user", "myproject" and "myprojectuser" replace that with what is relevent to what you are working on. | |
User Setup | |
$ ssh root@SERVER_IP_ADDRESS | |
Complete login process | |
$ adduser demo - Creates new user | |
Complete new user process | |
$ gpasswd -a demo sudo - add new user to root group | |
Secure Server - SSH | |
$ cat ~/.ssh/id_rsa.pub | |
Copy key to clipboard | |
$ su - demo - switch to new user | |
$ mkdir .ssh - create ssh dir in new user home | |
$ chmod 700 .ssh - make it accessable | |
$ vim .ssh/authorized_keys to create file | |
Paste key in file | |
$ chmod 600 .ssh/authorized_keys to restrict permissions | |
$ exit - to return to root | |
$ vim /etc/ssh/sshd_config | |
Change PermitRootLogin to no | |
Change PasswordAuthentication to no | |
$ sudo service ssh restart to restart ssh | |
Test that you can login with SSH and the new user in a new terminal window BEFORE you logout of the ROOT user | |
Secure Server - Basic Firewall | |
$ sudo ufw allow ssh - Allows SSH | |
$ sudo ufw allow 80/tcp - for HTTP | |
$ sudo ufw allow 443/tcp - for SSL | |
$ sudo ufw show added - to show what was changed | |
$ sudo ufw enable - enable firewall | |
Setup Timezone and NTP | |
$ sudo dpkg-reconfigure tzdata | |
Set to timezone for local (or for choice) | |
$ sudo apt-get update - Because this is the first time you are running this it will be big | |
$ sudo apt-get install ntp | |
For Python 3 | |
sudo apt-get install python3-pip libpq-dev postgresql postgresql-contrib nginx build-essential libssl-dev libffi-dev python3-dev python3-venv | |
Create Postgres DB and User | |
$ sudo su - postgres | |
$ psql - login to server | |
$ CREATE DATABASE myproject; | |
$ CREATE USER myprojectuser WITH PASSWORD 'password'; | |
$ ALTER ROLE myprojectuser SET client_encoding TO 'utf8'; | |
$ ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed'; | |
$ ALTER ROLE myprojectuser SET timezone TO 'UTC'; | |
$ GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser; | |
$ \q to quit | |
$ exit to exit | |
Setup VE | |
$ mkdir ~/envs to create dir | |
$ cd ~/envs to cd into the virtualenvs | |
$ python3 -m venv myproject | |
$ source myproject/bin/activate - to fire up the env | |
Create SSH key for Git | |
$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com" | |
$ eval "$(ssh-agent -s)" | |
$ vim ~/.ssh/id_rsa.pub - Copy the Key | |
Follow these instructions to add key to Github account: https://help.github.com/articles/adding-a-new-ssh-key-to-your-github-account/ | |
Get project and install requirements | |
$ git clone git@github.com:youraccount/repo-name.git | |
$ cd projectname/ | |
In case you don’t have your VE enabled, $workon vename | |
$ pip install -r requirements/base.txt - Obviously, this will depend on how you have your requirements setup | |
If error: sudo apt-get install python-dev sudo apt-get install libncurses5-dev | |
$ python manage.py check - to ensure everything is right | |
$ python manage.py migrate - to install DB | |
$ python manage.py createsuperuser - create superuser | |
$ python manage.py createcachetable - If applicable | |
$ gunicorn --bind 0.0.0.0:8000 production - to test the gunicorn setup | |
Create an Upstart Script | |
$ mkdir ~/run to create the dir where the sock file will live | |
$ sudo vim /etc/systemd/system/gunicorn.service | |
[Unit] | |
Description=gunicorn daemon | |
After=network.target | |
[Service] | |
User=dave | |
Group=www-data | |
WorkingDirectory=/home/dave/myproject | |
ExecStart=/home/dave/envs/myproject/bin/gunicorn --workers 3 --bind unix:/home/dave/run/myproject.sock production | |
[Install] | |
WantedBy=multi-user.target | |
$ sudo systemctl start gunicorn | |
$ sudo systemctl enable gunicorn | |
Configure NGINX | |
# sudo vim /etc/nginx/sites-available/myproject | |
server { | |
listen 80; | |
access_log /home/user/logs/nginx/nginx-access.log; | |
error_log /home/user/logs/nginx/nginx-error.log; | |
client_max_body_size 4G; | |
server_name domain_name_or_ip; | |
root /home/user/myproject; | |
keepalive_timeout 5; | |
location = /favicon.ico { access_log off; log_not_found off; } | |
location /static { | |
alias /home/user/myproject/static; | |
} | |
location /uploads { | |
alias /home/user/myproject/uploads; | |
} | |
error_page 500 502 503 504 /500.html; | |
location = /500.html { | |
alias /home/user/myproject/templates; | |
} | |
location / { | |
include proxy_params; | |
proxy_pass http://unix:/home/user/myproject/project.sock; | |
} | |
} | |
2. $ sudo mkdir -p ~/logs/nginx/ | |
3. $ sudo nginx -t | |
4. $ sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled | |
5. $ sudo systemctl restart nginx | |
7. $ sudo ufw allow 'Nginx Full' | |
SSL Certificate: | |
Just go here: https://certbot.eff.org/ and do what it says. | |
8. $ sudo systemctl restart nginx | |
You’re done! |
This comment has been minimized.
This comment has been minimized.
Have you used certbot/SSL on an IP address? Or always on a named domain? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
Re: https://gist.github.com/davemerwin/75420b25ae8a975ec6916d5141eb39d4#file-step-by-step-virtualenv-django-postgres-nginx-gunicorn-https-on-digitalocean-L35-L39
Have you played with DO's built-in firewall? I tried it out this weekend and it worked really well for me. It prevents traffic from ever getting to your boxes with is a nice bonus.