Configure Web Services

Gunicorn

Copy the service files to systemd

sudo cp -R ~/app/bin/systemd/* /etc/systemd/system/

Create the sockets

sudo systemctl start gunicorn.socket

If copying new files, you may be asked to run:

sudo systemctl daemon-reload

Enable the sockets

sudo systemctl enable gunicorn.socket

Output

Created symlink /etc/systemd/system/sockets.target.wants/gunicorn.socket  /etc/systemd/system/gunicorn.socket.

If you wish, you can check the status of each:

sudo systemctl status gunicorn

Output, inactive (first time):

● gunicorn.service - gunicorn daemon
   Loaded: loaded (/etc/systemd/system/gunicorn.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Mon 2018-07-23 17:57:25 UTC; 2min 56s ago
 Main PID: 22953 (code=exited, status=0/SUCCESS)

Try accessing:

curl --unix-socket /run/gunicorn.sock localhost

Output now shows active:

● gunicorn.service - gunicorn daemon
   Loaded: loaded (/etc/systemd/system/gunicorn.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2018-07-23 16:09:01 UTC; 14s ago
 Main PID: 6839 (gunicorn)
    Tasks: 4 (limit: 2361)
   CGroup: /system.slice/gunicorn.service
           ├─6839 /home/ambition/.venvs/ambition/bin/python3 /home/ambition/.venvs/ambition/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/
           ├─6889 /home/ambition/.venvs/ambition/bin/python3 /home/ambition/.venvs/ambition/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/
           ├─6897 /home/ambition/.venvs/ambition/bin/python3 /home/ambition/.venvs/ambition/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/
           └─6908 /home/ambition/.venvs/ambition/bin/python3 /home/ambition/.venvs/ambition/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/

Jul 23 16:09:01 edc2 systemd[1]: Started gunicorn daemon.
Jul 23 16:09:03 edc2 gunicorn[6839]: [2018-07-23 16:09:03 +0000] [6839] [INFO] Starting gunicorn 19.9.0
Jul 23 16:09:03 edc2 gunicorn[6839]: [2018-07-23 16:09:03 +0000] [6839] [INFO] Listening at: unix:/run/gunicorn.sock (6839)
Jul 23 16:09:03 edc2 gunicorn[6839]: [2018-07-23 16:09:03 +0000] [6839] [INFO] Using worker: sync
Jul 23 16:09:03 edc2 gunicorn[6839]: [2018-07-23 16:09:03 +0000] [6889] [INFO] Booting worker with pid: 6889
Jul 23 16:09:03 edc2 gunicorn[6839]: [2018-07-23 16:09:03 +0000] [6897] [INFO] Booting worker with pid: 6897
Jul 23 16:09:03 edc2 gunicorn[6839]: [2018-07-23 16:09:03 +0000] [6908] [INFO] Booting worker with pid: 6908

if there are any problems check:

sudo journalctl -u gunicorn   # etc

If the code base changes:

sudo systemctl daemon-reload
sudo systemctl restart gunicorn

If needed to reset …

sudo systemctl stop gunicorn-live.socket \
        && sudo systemctl stop gunicorn-live \
        && sudo systemctl disable gunicorn-live.socket

sudo systemctl stop gunicorn-uat.socket \
        && sudo systemctl stop gunicorn-uat \
        && sudo systemctl disable gunicorn-uat.socket

Nginx

Copy the configurations to /etc/nginx/sites-available

sudo cp -R ~/app/bin/nginx/conf/* /etc/nginx/sites-available/

Replace town referred to in server name

# for example
sudo sed -i -e s/gaborone/blantyre/g /etc/nginx/sites-available/ambition.conf

# for example
sudo sed -i -e s/gaborone/blantyre/g /etc/nginx/sites-available/ambition-uat.conf

Enable each site:

sudo ln -s /etc/nginx/sites-available/ambition.conf /etc/nginx/sites-enabled

Inspect:

ls -la /etc/nginx/sites-enabled

Output:

ambition-uat.conf -> /etc/nginx/sites-available/ambition-uat.conf
ambition.conf -> /etc/nginx/sites-available/ambition.conf

Disable the default site, if enabled:

sudo unlink /etc/nginx/sites-enabled/default

Test the new configuration:

sudo nginx -t

Output:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Restart Nginx service:

sudo systemctl restart nginx

Firewall

On application/web-server, check ufw to open openSSH, http, https

e.g.

# review ports opened by application firewall rules
sudo ufw app info 'OpenSSH'
sudo ufw app info 'Nginx Full'

# configure application firewall rules
sudo ufw allow 'OpenSSH'
sudo ufw allow 'Nginx Full'

# review ports opened by application firewall rule
sudo ufw app info 'Nginx Full'

# enable the firewall, and check
sudo ufw enable
sudo ufw status

Also check cloud firewall to ensure these ports are open

If not already done, on DB server, ensure application server has access to 3306 from it’s private IP

e.g.

sudo ufw allow from <app.server.private.ip> to any port 3306

Certificates and HTTPS configuration

see https://certbot.eff.org or more specifically Certbot Instructions for Nginx on Ubuntu 20 (or later)

Remove certbot-auto and any Certbot OS packages:

sudo apt-get remove certbot

Install certbot and prepare command:

sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

Get and install certificates:

    sudo certbot --nginx

Saving debug log to /var/log/letsencrypt/letsencrypt.log

Which names would you like to activate HTTPS for?
We recommend selecting either all domains, or all domains in a VirtualHost/server block.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# select blank for all

Test automatic certificate renewal

sudo certbot renew --dry-run

Confirm Nginx config still valid:

sudo nginx -t
sudo systemctl restart nginx

Now check that the DB server will allow access

  • check the firewall (under DO)

  • check mysql user for this account (edc@privateIP)

See document prepare_database