Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save davemerwin/75420b25ae8a975ec6916d5141eb39d4 to your computer and use it in GitHub Desktop.
Save davemerwin/75420b25ae8a975ec6916d5141eb39d4 to your computer and use it in GitHub Desktop.
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!
@jefftriplett
Copy link

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.

@shariq1989
Copy link

Have you used certbot/SSL on an IP address? Or always on a named domain?

@davemerwin
Copy link
Author

Have you used certbot/SSL on an IP address? Or always on a named domain?

Embarrassing that it has taken this long to get back to you. I only use named domain. Though, you can do it with an IP. At least you used to be able to.

@davemerwin
Copy link
Author

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.

I have not. WIll take a look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment