Deploy Flask App to Ubuntu Server with Nginx & gUnicorn a la Corey Schafer

03/11/2021 02:21

Corey Schafer's Flask Tutorial taught me how to code. It is also the first series I recommend anyone learning python (after a simple syntax lesson). While I have probably watched this tutorial 5 times already, the video in the series which explains setting up an Ubuntu server and deploying your flask app has yet to be retained. In order to circumvent this, I have compiled a step-by-step guide geared towards the experienced developer.  All syntax and order of operations without the hand-holding of an explanation for each command. 


    1. Initial Steps
      1. `update && upgrade`
        2. set hostname:
            1. `hostnamectl set-hostname <desired name of host>`
        3. set host in /etc/hosts/
            1. add public ip address and host name to list
        4. Add limited user to machine
            1. `adduser <username>`
                1. follow prompts
            2. `adduser <username> sudo`
        5. log out and log back in as new user
    2. Set up SSH keybased auth to log in without a password
        1. On Server: `cd && mkdir .ssh`
        2. On Local: `ssh-keygen -b 4096`
        3. On Local: `scp <location of public key> <username>@<host>:~/.ssh/authorized_keys`
        4. On Server: `sudo chmod 700 ~/.ssh`
        5. On Server: `sudo chmod 600 ~/.ssh/*`
        6. On Local: Make sure you can log in without a password.
        7. Disallow login via password (On Server)
            1. `sudo nano /etc/ssh/sshd_config`
            2. change PermitRootLogin to `no`
            3. change PasswordAuthentication to `no`
            4. restart SSH Service: `sudo systemctl restart sshd`
    3. Set up Firewall
        1. `sudo apt install ufw`
        2. `sudo ufw default allow outgoing`
        3. `sudo ufw default deny incoming`
        4. `sudo ufw allow ssh`
        5. `sudo ufw allow 5000` (Allow Flask local port for testing)
        6. `sudo ufw enable`
    4. Test Deploy Flask Application
        1. Consider venv, requirements.txt
        2. `cd && git clone <repo url> <dir>`
        3. `sudo apt install python3-pip python3-venv`
        4. `python3 -m venv <repo dir>/venv`
        5. check /venv/ exists in repo
        6. `cd <repo_dir> && source venv/bin/activate`
        7. Install requirements.
        6. Set environment variables if necessary (you can also do a config file and import to __init__ if you want)
        7. Let's test run Flask
            1. `export`
            2. `flask run --host=`
            3. navigate to <url or ip>:5000 in web browser to test site.
    5. Nginx & Gunicorn
        1. `cd && sudo apt install nginx`
        2. `pip3 install gunicorn` (may need to reinstall requirements???)
        3. update nginx config file:
            1. `sudo rm /etc/nginx/sites-enabled/default`
            2. `sudo nano /etc/nginx/sites-enabled/<site-name>`
            3. edit new file:
            server {
                listen 80;
                server_name <url> www.<url>;
                location /static {
                    alias /path/to/flask/app/static/dir;

                location / {
                    proxy_pass http://localhost:8000;
                    include /etc/nginx/proxy_params;
                    proxy_redirect off;
        4. Edit Firewall
            1. `sudo ufw allow http/tcp`
            2. `sudo ufw delete allow 5000`
            3. `sudo ufw enable`
        5. `sudo systemctl restart nginx`
        6. `cd <repo_dir> && gunicorn -w 3 run:app`
            1. Determine needed workers by w=(2 * number_of_cores) + 1
            2. Determine cores with `nproc --all`
        7.Navigate to your url without port, make sure it works.
    6. Supervisor
        1. `sudo apt install supervisor`
        2. setup config: `sudo nano /etc/supervisor/conf.d/<repo_name>.conf`
            command=/home/<username>/<repo_dir>/venv/bin/gunicorn -w 3 run:app  # you may need to `which gunicorn` to figure out where it exists
        3. `sudo mkdir -p /var/log/<repo_name>`
        4. `sudo touch /var/log/<repo_name>/<repo_name>.err.log && sudo touch /var/log/<repo_name>/<repo_name>.out.log`
        5. `sudo supervisorctl reload`
        6. Navigate to your url in browser, make sure it works.
Subscribe to Blog

Software Development
ubuntu, gunicorn, linux, nginx, python, flask, coding