Configure WSGI HTTP server for Python

Warning

This section depends on how you set up previous instructions with installing flsk app from external repository.

Step 1 - Create custom recipe

This WSGI HTTP server for python will be the base functionality of system so it will be placed inside recipes-base folder.

mkdir -p ../meta-golemos/recipes-base/python3-gunicorn/files
touch ../meta-golemos/recipes-base/python3-gunicorn/python3-gunicorn_%.bbappend

Inside created custom recipe place this instructions.

inherit allarch systemd

FILESEXTRAPATHS_prepend := "${THISDIR}/files:"

SRC_URI += " \
    file://datalogger_setup_page.service \
    file://datalogger_setup_page.socket \
"

SYSTEMD_AUTO_ENABLE = "enable"
SYSTEMD_SERVICE__append = " datalogger_setup_page.service datalogger_setup_page.socket "

FILES_${PN} += "${systemd_system_unitdir}"
FILES_${PN} += "${systemd_system_unitdir}/datalogger_setup_page.service"
FILES_${PN} += "${systemd_system_unitdir}/datalogger_setup_page.socket"

do_install_append () {
    install -d ${D}/${systemd_system_unitdir}
    install -m 0644 ${WORKDIR}/datalogger_setup_page.s* ${D}/${systemd_system_unitdir}

    install -d ${D}${sysconfdir}/systemd/system/multi-user.target.wants/
    install -d ${D}${sysconfdir}/systemd/system/sockets.target.wants/

    ln -s ${systemd_system_unitdir}/datalogger_setup_page.socket ${D}${sysconfdir}/systemd/system/sockets.target.wants/datalogger_setup_page.socket
    ln -s ${systemd_system_unitdir}/datalogger_setup_page.service ${D}${sysconfdir}/systemd/system/multi-user.target.wants/datalogger_setup_page.service
}

Note

This recipe depends on python3-gunicorn which is contained inside meta-python layer from OpenEmbedded. Clone this layer and add to bblayers.conf in order to satisfy dependencies.

Step 2 - Create service file

Previously created files folder are meant to store service file. It will also store socket file, but about this in the next step.

Create service file

touch ../meta-golemos/recipes-base/python3-gunicorn/files/datalogger_setup_page.service

and place in it this content.

[Unit]
Description=gunicorn daemon for datalogger_setup_page
Requires=datalogger_setup_page.socket
After=network.target

[Service]
Type=notify
RuntimeDirectory=gunicorn
WorkingDirectory=/var/www/datalogger-setup.local/
ExecStart=/usr/bin/gunicorn wsgi
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Warning

This service file depends on where you place your python app, in this situation it is /var/www/datalogger-setup.local/. It also requires that inside root folder there is wsgi file called wsgi.py.

Note

This service file requires socket file, which will be created in the next step.

Step 3 - Create socket file

This gunicorn server will be listening on unix socket. To enable this, you have to create file called datalogger_setup_page.socket.

touch ../meta-golemos/recipes-base/python3-gunicorn/files/datalogger_setup_page.socket

Inside this file place such a configuration.

[Unit]
Description=gunicorn socket for datalogger_setup_page

[Socket]
ListenStream=/run/datalogger_setup_page.sock
SocketUser=www

[Install]
WantedBy=sockets.target

Warning

In next section you will find how to configure nginx web server. You have to find out which user nginx is using and if needed change them here.

Step 4 - Add packages

To ensure that this recipe will take place add python3-gunicorn to your python packages inside base package group.

Summary

After all this steps your app should be exposed on

http://unix:/run/datalogger_setup_page.sock

In next section you can find steps how to connect this to nginx web server and expose this application to outside.

At the end your layer structure should look like this.

../meta-golemos
├── COPYING.MIT
├── README
├── conf
│   ├── bblayers.conf.sample
│   ├── conf-notes.txt
│   ├── distro
│   │   └── golemos.conf
│   ├── layer.conf
│   └── local.conf.sample
├── recipes-base
│   ├── datalogger-setup-page
│   │   └── datalogger-setup-page.bb
│   └── python3-gunicorn
│       ├── files
│       │   ├── datalogger_setup_page.service
│       │   └── datalogger_setup_page.socket
│       └── python3-gunicorn_%.bbappend
├── recipes-connectivity
│   ├── hostapd
│   │   ├── files
│   │   │   ├── hostapd@.service
│   │   │   └── wlan0.conf
│   │   └── hostapd_%.bbappend
│   ├── kea
│   │   ├── files
│   │   │   ├── kea-dhcp4.conf
│   │   │   └── kea-dhcp4.service
│   │   └── kea_%.bbappend
│   └── wpa-supplicant
│       ├── files
│       │   └── wpa_supplicant-nl80211-wlan0.conf
│       └── wpa-supplicant_%.bbappend
├── recipes-core
│   ├── images
│   │   ├── datalogger-dev-image.bb
│   │   ├── datalogger-extended-image.bb
│   │   └── datalogger-image.bb
│   ├── packagegroups
│   │   ├── datalogger-base-packagegroup.bb
│   │   ├── datalogger-core-packagegroup.bb
│   │   ├── datalogger-dev-packagegroup.bb
│   │   └── datalogger-extended-packagegroup.bb
│   ├── systemd
│   │   └── systemd_%.bbappend
│   └── systemd-conf
│       ├── files
│       │   └── wlan.network
│       └── systemd-conf_%.bbappend
└── recipes-example
    └── example
        └── example_0.1.bb