Automation for nginx and uWSGI Emperor setup. Based on my pyweb tutorial and Ansible.
Version: 2.4 — changelog
The support list matches the tutorial:
- Ubuntu 18.04 LTS, 20.04 LTS or newer
- Debian 10 (buster), 11 (bullseye) or newer
- Fedora 33 or newer (with SELinux enabled and disabled)
- CentOS 7 (with SELinux enabled and disabled)
- AlmaLinux 8 (with SELinux enabled and disabled). Referred to as “EL8” collectively with Rocky Linux.
- Rocky Linux 8 (with SELinux enabled and disabled). Referred to as “EL8” collectively with AlmaLinux.
- Arch Linux
Debian 8 (jessie), 9 (stretch), Ubuntu 16.04 LTS, and Fedora 24 through 32 are not officially supported, even though they still probably work. Other operating systems are unsupported, because of packaging and default configuration differences.
Standard Ansible Playbooks procedure. Install Ansible, edit the applicable configuration in group_vars
, put hostnames in hosts
(the first line is [nginx-uwsgi]
and the following lines are hostnames
; default is to install on localhost) and run:
$ ansible-playbook nginx-uwsgi.yml -i hosts
(You may want to add the -K
option to be asked for the sudo password.)
To understand what the Playbook does, make sure to read the pyweb tutorial.
Configuration happens in three files: hosts
, group_vars/all
, and group_vars/os_<destination OS>
.
-
app_name
: the application name, used for configuration files (default:myapp
) -
app_package
,app_callable
: WSGI module to use (default:flaskapp
,app
)Framework Flask, Bottle Django Pyramid Package module where app
is definedproject.wsgi
(project
is the package withsettings.py
)module where app
is definedCallable Flask: app
instance
Bottle:app = bottle.default_app()
application
app = config.make_wsgi_app()
Module package:app
project.wsgi:application
package:app
Caveats Make sure app is not in an if __name__ == '__main__':
blockAdd environment variable for settings: env = DJANGO_SETTINGS_MODULE=project.settings
Make sure app is not in an if __name__ == '__main__':
block (the demo quickstart does that!) -
base_dir
: the base directory (and virtual environment) for the app (default:/srv/myapp
) -
appdata_dir
: the directory where app data files reside (default:{{ base_dir }}/appdata
) -
nginx_server_name
: hostnames the website is accessible under (default:localhost myapp.local
) -
nginx_http_port
: port to use when serving HTTP (default:80
) -
uwsgi_module
: WSGI module to use (constructed fromapp_package
,app_callable
— leave it as-is) -
uwsgi_processes
anduwsgi_threads
: control the resources devoted to this application. (default:1
and1
; should be more for bigger apps) -
uwsgi_env
: list of environment variables to pass to the app (in key=value format; default: empty) -
git_repo
: Git repository that contains app code (default:https://github.com/Kwpolska/flask-demo-app
) -
git_branch
: Git branch to pull from (default:master
) -
nginx_hostless_global_config
: Replace nginx.conf with one that does not have a default host. Destructive, see caveat below! (default:no
)
uid
: user used for files and socketsgid
: group used for files and socketsnginx_dir
: nginx sites directory (conf.d or sites-enabled)uwsgi_dir
: uWSGI vassals directoryuwsgi_plugins
: uWSGI plugins (python3,logfile
orpython
)uwsgi_service_name
: uWSGI systemd service name (uwsgi
oremperor.uwsgi
)
nginx_patch_confd_Archlinux
: patch/etc/nginx/nginx.conf
to useconf.d
(default:yes
; may fail)nginx_disable_default_site
: disable the default site by removing/etc/nginx/sites-enabled/default
(default:yes
; for Debian/Ubuntu)skip_selinux
: skip SELinux tasks (default:no
; for CentOS/EL8/Fedora)
Make sure you have the following packages installed first on the destination machine (Ansible dependencies):
- Debian/Ubuntu:
python
- Fedora:
python2 python2-dnf libselinux-python
- AlmaLinux, CentOS, Rocky Linux:
python libselinux-python
- Arch Linux:
python2
The default config of nginx creates some servers with default pages. Not everyone wants that. If you want this playbook to replace your nginx.conf file with one that has no servers (based on your OSes default nginx.conf
), set nginx_hostless_global_config
to yes
. You should not use it if you customized /etc/nginx/nginx.conf in any way, or if you have installed and configured nginx before. On Ubuntu and Debian, nginx_disable_default_site
is less destructive and enabled by default.
The nginx host config is rudimentary and does not include SSL/TLS support and custom error pages. For the former, see Remy van Elst’s guide.
By default, nginx on Arch Linux does not have any modular-include config directory. This playbook (and best practices) recommend having one for cleaner config. This playbook will try to patch your configuration file, but if you configured nginx in a way that makes the patch fail, you need to manually add this snippet to your server {}
block:
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*;
Afterwards, disable patching — set nginx_patch_confd_Archlinux
to no
. You should also disable this patch if you already used this playbook, or have a modular configuration directory already (you can change the path in config).
If you’re installing to a place that doesn’t like symlinks — for example, a VM
shared folder (eg. /vagrant
) on a Windows host, you may get a Protocol
error pointing to a os.symlink
call. You can fix this by amending the venv
command to use --copy
, or by using a more reasonable place to store your
virtual environment (a Unix filesystem, that is).
Copyright © 2016-2023, Chris Warrick. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
Redistributions of source code must retain the above copyright notice, this list of conditions, and the following disclaimer.
-
Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following disclaimer in the documentation and/or other materials provided with the distribution.
-
Neither the name of the author of this software nor the names of contributors to this software may be used to endorse or promote products derived from this software without specific prior written consent.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.