Skip to content

Web Server Setup

We will set up a simple WSGI frontend using gunicorn and systemd for service persistence. As web server we will use Apache 2. You can of course use whatever combination of tool that you want.

Apache 2

Install the Apache 2 package and enable mod proxy.

# apt install apache2
# a2enmod headers
# a2enmod proxy
# a2enmod proxy_http

Now we will add a new virtual host that will be used to setup the proxy to the gunicorn server. We will create and edit the following file /etc/apache2/sites-available/peering-manager.conf.

The content of the file can be something like this.

<VirtualHost *:80>
  ProxyPreserveHost On
  ServerName peering.example.com
  Alias /static /opt/peering-manager/static

  <Directory /opt/peering-manager/static>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride None
    Require all granted
  </Directory>

  <Location /static>
    ProxyPass !
  </Location>

  RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
  ProxyPass / http://127.0.0.1:8001/
  ProxyPassReverse / http://127.0.0.1:8001/
</VirtualHost>

Remove the default virtual host and enable the new one.

# a2dissite 000-default.conf
# a2ensite peering-manager.conf

Restart Apache 2 to eanble our new configuration and mods.

# systemctl restart apache2

To avoid any issues with read/write permission, set the Apache 2 user as owner of the Peering Manager directory.

# chown -R www-data:www-data /opt/peering-manager

gunicorn

Install gunicorn using pip inside the Python virtual environment.

(venv) # pip3 install gunicorn

Save the following configuration in the root of the Peering Manager installation path as gunicorn.py. Be sure to verify the location of the gunicorn executable on your server (e.g. which gunicorn) and to update the pythonpath variable if needed. Note that some tasks such as importing existing peering sessions or generating prefix lists can take a lot of time to complete so setting a timeout greater than 30 seconds can be helpful.

bind = '127.0.0.1:8001'
workers = 5
threads = 3
timeout = 300
max_requests = 5000
max_requests_jitter = 500
user = 'peering-manager'

We can test if the configuration is correct by running (note the _ instead of - in the WSGI name):

(venv) # ./venv/bin/gunicorn -c /opt/peering-manager/gunicorn.py peering_manager.wsgi
[2017-09-27 22:49:02 +0200] [7214] [INFO] Starting gunicorn 19.7.1
[2017-09-27 22:49:02 +0200] [7214] [INFO] Listening at: http://127.0.0.1:8001 (7214)
[2017-09-27 22:49:02 +0200] [7214] [INFO] Using worker: sync
[2017-09-27 22:49:02 +0200] [7217] [INFO] Booting worker with pid: 7217
[2017-09-27 22:49:02 +0200] [7219] [INFO] Booting worker with pid: 7219
[2017-09-27 22:49:02 +0200] [7220] [INFO] Booting worker with pid: 7220
[2017-09-27 22:49:03 +0200] [7222] [INFO] Booting worker with pid: 7222

systemd

Create a service file /etc/systemd/system/peering-manager.service and set its content.

[Unit]
Description=Peering Manager WSGI Service
Documentation=https://peering-manager.readthedocs.io/
After=network-online.target
Wants=network-online.target

[Service]
Type=simple

User=peering-manager
Group=peering-manager
PIDFile=/var/tmp/peering-manager.pid
WorkingDirectory=/opt/peering-manager

ExecStart=/opt/peering-manager/venv/bin/gunicorn --pid /var/tmp/peering-manager.pid --pythonpath /opt/peering-manager --config /opt/peering-manager/gunicorn.py peering_manager.wsgi

Restart=on-failure
RestartSec=30
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Create another service file /etc/systemd/system/peering-manager-rq.service and set its content.

[Unit]
Description=Peering Manager Request Queue Worker
Documentation=https://peering-manager.readthedocs.io/
After=network-online.target
Wants=network-online.target

[Service]
Type=simple

User=peering-manager
Group=peering-manager
WorkingDirectory=/opt/peering-manager

ExecStart=/opt/peering-manager/venv/bin/python3 /opt/peering-manager/manage.py rqworker

Restart=on-failure
RestartSec=30
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Reload systemd to load the services, start them and enable them at boot time.

# systemctl daemon-reload
# systemctl start peering-manager
# systemctl enable peering-manager
# systemctl start peering-manager-rq
# systemctl enable peering-manager-rq

You can use the systemctl status peering-manager and systemctl status peering-manager-rq to verify that the WSGI service and the request queue worker service are respectively running.

At this point, you should be able to connect to the Apache 2 HTTP service at the server name or IP address you provided. If you receive a 502 (bad gateway) error, this indicates that gunicorn is misconfigured or not running.