Skip to content

Instantly share code, notes, and snippets.

@Eucrow
Last active August 7, 2022 15:01
Show Gist options
  • Save Eucrow/d813b95291629533820e106b994c63f9 to your computer and use it in GitHub Desktop.
Save Eucrow/d813b95291629533820e106b994c63f9 to your computer and use it in GitHub Desktop.
pyenv + python + django + gunicorn + circus + nginx in ubuntu 16.04

pyenv + python + django + gunicorn + circus + nginx in ubuntu 16.04

Install dependencies (TODO: check dependencies)

sudo apt-get install -y postgresql-9.5 postgresql-contrib-9.5 postgresql-server-dev-9.5 nginx git circus make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils python-setuptools

Users

Create user for the app

sudo adduser app

Remove privileges to user

sudo passwd -l app

Add user www-data (user for nginx) to app group

sudo adduser www-data app

pyenv

Login as app user

sudo -u app -i

Install pyenv

git clone https://github.com/yyuu/pyenv.git ~/.pyenv

Update .bashrc

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.bash_profile

Logout and login again in the app user

exit
sudo -u app -i

Install desired python

pyenv install 3.7.0

Change to the new version to use

pyenv local 3.7.0

Know more about python versions

pyenv versions
which python

Clone app (as app user)

Clone app from the repository

git clone https... app

Update pip

cd app
pip install --upgrade pip

Install app requirements

pip install -r requirements.txt

Make migrations and migrate

python manage.py makemigrations
python manage.py migrate

Open port 8000

Run server

python manage.py runserver 0.0.0.0:8000

Gunicorn

Install gunicorn

pip install gunicorn

Run gunicorn in 8000 port

gunicorn -b 0.0.0.0:8000 app.wsgi

Circus

Create configuration file (in ubuntu user)

cd
sudo nano /etc/circus/conf.d/app.ini

Edit app.ini with:

[watcher:app]
cmd = gunicorn
args = -b 0.0.0.0 -w 2 app.wsgi
working_dir = /home/app/app
uid = app
numprocesses = 1
autostart = true
stdout_stream.class = FileStream
stdout_stream.filename = /home/app/logs/gunicorn.stdout.log
stderr_stream.class = FileStream
stderr_stream.filename = /home/app/logs/gunicorn.stderr.log
copy_env = true
virtualenv = /home/app/.pyenv/versions/3.5.2
virtualenv_py_ver = 3.5

Create log directory

sudo -u app -i
mkdir /home/app/logs

Run service (as ubuntu user)

sudo service circusd restart

Useful tools

sudo service circusd status
ps aux | grep gunicorn

Use nginx as a reverse proxy

Create file app in /etc/nginx/sites-available/ (as ubuntu user)

sudo nano /etc/nginx/sites-available/app

With this:

server {

        listen 80;
        server_name app.domain.com;

        access_log /home/app/logs/nginx.access.log;
        error_log /home/app/logs/nginx.error.log;

        location / {
                include proxy_params;
                proxy_pass http://127.0.0.1:8000/;
        }

}

Create simbolic link in /etc/nginx/sites-enabled

sudo ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled/app

Check if all is allright

sudo nginx -t

Restart nginx

sudo service nginx reload

Remove server tokens (security)

To avoid show the nginx version in 404 errors, modify file /etc/nginx/nginx.confuncommenting text server_tokens off;

Useful tools:

tail -f errors.log

Static files

The server included in django is not for production servers, so we have to create the static files. As app user:

sudo -u app -i

Create a production settings configuration file

In:

nano app/app/settings_production.py

Add:

import os
from app.settings import *

DEBUG = False
TEMPLATE_DEBUG = False

ALLOWED_HOSTS = ['*']

SECRET_KEY = 'n-3(f-lo&$%j0$8&_-5hkk8emsvlx840%_vb8ce$_98)a(x_74'

STATIC_ROOT = os.path.join(BASE_DIR, 'static')
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

Create static and media folders

cd app
mkdir static
mkdir media

Define an evironment variable with the path to the production settings file

export DJANGO_SETTINGS_MODULE=app.settings_production

Collect static files

python manage.py collectstatic

It is possible make the last two steps with:

python manage.py collectstatic --settings=app.settings_production

Configure nginx to use the static files

In general user

Modify /etc/nginx/sites-available/app adding, before "location /" :

        location /static {
                access_log off;
                alias /home/app/app/static;
        }

        location /media {
                access_log off;
                alias /home/app/app/media;
        }

Configure circus to use the settings production

Add to /etc/circus/conf.d/app.ini:

[env:app]
DJANGO_SETTINGS_MODULE = app.settings_production

Change default port of ssh

Firstly, open new port in aws but dosn't close the actual port.

Then, modify the line Port 22 in /etc/ssh/sshd_config with Port <numberport>.

To check ir there is any error in the ssh file config:

sudo sshd -t

If there is any error, it will show on screen. Otherwise it wioll not diplay any message.

Reload the service

sudo service ssh reload

Try, in other session witouth exit the actual session, to connect with by :

ssh -p <numberport> -i <route/pem> [email protected]

If this work, close the old port in aws.

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