Even an embedded system is going to need a web application, be it on the embedded device, or a part of a test system.
We recommend flask applications, and serving them via Nginx and uWSGI.
There are a lot of examples online. The following one outlines most of the possibilities you can choose from: deploy-flask-uwsgi-nginx
We recommend using the apps-available and apps-enabled as the method for starting your uwsgi server flask application. This is less intrusive and requires less custom parts like an additional system specific service.
For additional security you could install your applications somewhere other than /var/www
if that is being served as your root for nginx (for example use /srv/uwsgi-apps
instead).
To ensure independent application environments, us a python virtual environment for each of your applications. If you do choose to use the system libraries, we touch on some issues you may run into.
For the nginx configuration, the default uwsgi socket location for your application can be used. On Ubuntu at least it has been:
uwsgi_pass unix:/run/uwsgi/app/<your-application>/socket;
Trouble Shooting
To help you trouble shoot during setup, once you have defined <yourapplication>.ini file under /etc/uwsgi/apps-available and symlinked to apps-enable, restart uwsgi and then tail the uwsgi log for your application.
sudo systemctl restart uwsgi
sudo tail -f /var/log/uwsgi/app/<yourapplication>.log
If something goes wrong inside your application on (re)starting uwsgi, that log will show it.
For example
- mapped 654912 bytes (639 KB) for 8 cores
- *** Operational MODE: preforking ***
Traceback (most recent call last):
File "./wsgi.py", line 1, in <module>
from app import app as application
File "./app.py", line 1, in <module>
from flask import Flask, jsonify, request
ModuleNotFoundError: No module named 'flask'
- unable to load app 0 (mountpoint='') (callable not found or import error)
Module Not Found Error: No module name
In the example above either the system (or your virtual environment) does not have flask installed or you are using the wrong python plugin.
If your python –version is 3.6.x the python plugin in your uwsgi .ini file should be
plugin = python36
When you run uwsgi through its apps-enabled/<yourapp>.ini method, the application will not be run as your user, so even if you have installed flask and other libraries using pip(3), they are attached to your user’s local, rather than the system library.
If you install using pip a library you will see the output.
Requirement already satisfied: flask in /home/user/.local/lib/python3.6/site-packages
Note the /home/user/.local
.
If you are not using a virtual environment, you need to ensure libraries are system libraries, either install them using their corresponding distribution package (e.g. in Ubuntu, sudo apt install python3-flask
, or using sudo -H pip
…)
No Python Application Found
If you see the error
--- no python application found, check your startup logs for errors ---
Then look earlier in the application log (/var/log/uwsgi/app/<yourapplication>.log
) to see if your application was started or if their was an exception.
Unable to load app
unable to load app 0 (mountpoint='') (callable not found or import error)
*** no app loaded. going in full dynamic mode ***
To decipher this, look into <yourapplication>.ini file for the module and chdir lines
chdir = /srv/uswgi-apps/yourapplication
module = wsgi:myapp
The wsgi of wsgi:myapp must correspond to the file name wsgi.py
in your /srv/uwsgi-apps/yourapplication
folder and the myapp
must correspond to the import line in your wsgi.py
file which imports your flask app
as ‘myapp
‘. In the example here, the flask app file was called app.py
(as many tutorials tend to name their app files).
from app import app as myapp
if __name__ == '__main__':
myapp.run()
Gracefully Reloading Applications
The uWSGI documentations detail how to manage your applications once deployed.
We recommend using at least the touch reload option and for finer grain control the Master FIFO method.
Touch Reload
The touch reload means that any time you change your ini file, that application will be reloaded.
touch-reload = /etc/uwsgi/apps-available/<yourapplication>.ini
DANGER! If using touch reload, verify your .ini changes on a staging server before deploying to a production server, because your application will be down if there is an error loading it.
Master FIFO
You can have one or more master-fifo lines.
master-fifo = /tmp/<yourapplication>-master-fifo
From the uwsgi docs: Only the uid running the master has write access to the fifo.
This means that most likely you need to echo commands to the master fifo as the www-data user (unless you specify a different user using uid in .ini file).
$ sudo -u www-data sh
[sudo] password for user:
$ echo r > /tmp/<yourapplication>-master-fifo
HUP System Signal
If you already deployed your application and you are not in a position to add touch reload or master fifo, you can use the -HUP signal to reload your application.
sudo kill -HUP $(cat /var/run/uwsgi/app/<yourapplication>/pid)