This is a step-by-step guide to install and configure the uWSGI server in emperor mode and with multiple language support. It is mainly intended for macOS environments but, excluding the parts related to bonjour and launchd
, it can be adapted to other platforms.
Please make sure to read each of the following sections, and complete them in the specified order.
uWSGI will be installed from its sources with the support for multiple languages, then a plugin will be built for each language to be supported:
- get uwsgi latest sources from here;
- extract the files in a local directory;
- open a terminal and
cd
into the uwsgi sources directory; - build the uwsgi binary:
make nolang
- generate the plugins, being sure to already have installed, for each plugin, its corresponding binary (e.g.
python3.5
orpython27
). In the case of various Python versions, execute:
PYTHON=python2.7 ./uwsgi --build-plugin "plugins/python python27"
PYTHON=python3.6 ./uwsgi --build-plugin "plugins/python python36"
- create a local directory where you intend to collect all your uWSGI plugins (e.g.
~/uwsgi/plugins/
); - copy all the plugins to the directory you have just created:
cp python27_plugin.so ~/uwsgi/plugins/
cp python36_plugin.so ~/uwsgi/plugins/
- install the compiled uWSGI binary, e.g.:
cp uwsgi /usr/local/bin/
This part is only meant for macOS and makes it possible to assign a custom domain to each project (e.g. my_new_project.local/
):
- compile the bonjour uWSGI plugin:
uwsgi --build-plugin https://github.com/unbit/uwsgi-bonjour
- copy the plugin to the uWSGI plugins directory:
cp bonjour_plugin.so ~/uwsgi/plugins/
Bonjour works thanks to Unbit uwsgi-bonjour, for further information check here.
For more information on uWSGI emperor mode refer to the official documentation. Before configuring uWSGI:
- create a directory where to collect all the projects .ini configuration files (e.g.
~/uwsgi/vassals/
);
Provided emperor.ini
contains a sample configuration to run the uWSGI server in emperor mode. Customize it with the paths to your vassals and plugins directories and to the emperor log file, plus any other setting/option you wish to run the emperor with. Then:
- move the customised emperor configuration file to a convenient location:
cp emperor.ini ~/uwsgi/
Be careful not to put the emperor configuration file into the vassals configuration files directory. Also note that the provided configuration file sets the emperor to use port 80, which must be available for the server to work.
The emperor needs to be told the language of each project, therefore make sure to indicate the corresponding plugin in each vassal configuration file:
plugin = python35
In order to assign a custom domain to a project (e.g. my_new_project.local/
), also include the following lines in the corresponding vassal configuration file:
plugin = bonjour
bonjour-register = name=%(project_name).local,cname=localhost
socket = 127.0.0.1:0
subscribe-to = 127.0.0.1:5005:%(project_name).local
The emperor can now be launched both manually and automatically.
This is straightforward, just launch uWSGI as superuser and with the emperor configuration file:
sudo uwsgi ~/uwsgi/emperor.ini
Provided it.unbit.uwsgi.emperor.plist
is a sample property list file that instructs launchd
to run the emperor as a daemon. Customize it with the paths to your uwsgi
binary (e.g. /usr/local/bin/uwsgi
) and to the configuration file (~/uwsgi/emperor.ini
). Then move, as superuser, the property list file to its location, load it and start it:
sudo cp it.unbit.uwsgi.emperor.plist /Library/LaunchDaemons/
sudo launchctl load /Library/LaunchDaemons/it.unbit.uwsgi.emperor.plist
sudo launchctl start /Library/LaunchDaemons/it.unbit.uwsgi.emperor.plist
In case you need to stop the daemon:
sudo launchctl stop /Library/LaunchDaemons/it.unbit.uwsgi.emperor.plist
In case you need to unload the daemon:
sudo launchctl unload /Library/LaunchDaemons/it.unbit.uwsgi.emperor.plist
In order to enable SSL/HTTPS support, uWSGI must be compiled accordingly. Therefore, any existing uWSGI installation/setup must be deleted and created from scratch.
-
Make sure
openssl
is installed and updated (e.g. viabrew
):brew install openssl && brew upgrade openssl
-
Download uWSGI source files and build like this:
CFLAGS="-I/usr/local/opt/openssl/include" LDFLAGS="-L/usr/local/opt/openssl/lib" UWSGI_PROFILE_OVERRIDE=ssl=true make nolang
-
Delete and recreate, with the new
uwsgi
binary, all existing plugins (refer to the instructions above). -
Generate certificate files in a convenient location:
openssl genrsa -out my_cert.key 2048 openssl req -new -key my_cert.key -out my_cert.csr openssl x509 -req -days 365 -in my_cert.csr -signkey my_cert.key -out my_cert.crt
-
Add the following line to
emperor.ini
:https = :443,path-to-my_cert.crt,path-to-my_cert.key
-
If the following error occurs (e.g. when using the
requests
Python package):+[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called.```
add a line to
emperor.ini
with:env = OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES