diff --git a/Production-setup-using-uWSGI-and-Nginx.md b/Production-setup-using-uWSGI-and-Nginx.md new file mode 100644 index 0000000..93ebac1 --- /dev/null +++ b/Production-setup-using-uWSGI-and-Nginx.md @@ -0,0 +1,155 @@ +## uWSGI + +It's not a good idea to just run the basic debug server and expose it to the outside world. +Instead, a component stack should be built. +The [uWSGI docs](https://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html) state the following: + +>A web server faces the outside world. It can serve files (HTML, images, CSS, etc) directly from the file system. However, it can’t talk directly to Django applications; it needs something that will run the application, feed it requests from web clients (such as browsers) and return responses. +>A Web Server Gateway Interface - WSGI - does this job. WSGI is a Python standard. +>uWSGI is a WSGI implementation. In this tutorial we will set up uWSGI so that it creates a Unix socket, and serves responses to the web server via the uwsgi protocol. At the end, our complete stack of components will look like this: + +> `the web client <-> the web server <-> the socket <-> uwsgi <-> Django` + +Note that different WSGI's exist and can be used, like for example Gunicorn. +However, in this tutorial uWSGI is used. + +### Installing uWSGI + +Installation of uWSGI is easily done via pip. +Root needs access to uWSGI later, so install it as superuser. + +``` +sudo pip3 install wsgi +``` + +### Testing uWSGI + +We can already test whether our uWSGI installation works. + +``` +cd path/to/server-skeleton +source venv/bin/activate # In case you haven't activated the venv yet. +uwsgi --http :8000 --module etesync_server.wsgi --virtualenv venv +``` + +This command runs the EteSync module, exposes it on port 8000 and uses the `venv` virtual environment. +You can now surf to the IP address followed by port 8000 in the browser to check if it works (you should see "It works!") + +## Nginx + +Nginx will form our proper web server. + +### Installing Nginx + +Installation if done via apt. + +``` +sudo apt-get install nginx +``` + +### Setup Nginx + +First of all, create Django's static files so that Nginx can access them. + +``` +./manage.py collectstatic +``` + +Now we need to configure Nginx, using a configuration file. +Create a new file called `etesync_nginx.conf` and paste the following into it. +Don't forget to change `server_name` and the path to `/static`. + +``` +# mysite_nginx.conf + +# the upstream component nginx needs to connect to +upstream django { + # server unix:///tmp/etesync_server.sock; # for a file socket + server 127.0.0.1:8001; # for a web port socket (we'll use this first) +} + +# configuration of the server +server { + # the port your site will be served on + listen 8000; + # the domain name it will serve for + server_name example.com; # substitute your machine's IP address or domain name + charset utf-8; + + # max upload size + client_max_body_size 75M; # adjust to taste + + location /static { + alias /path/to/server_skeleton/static # Project's static files + } + + # Finally, send all non-media requests to the Django server. + location / { + uwsgi_pass django; + include /etc/nginx/uwsgi_params; # the uwsgi_params file, this path by default + } +} +``` + +Move this file to `/etc/nginx/sites-available` and symlink it to `/etc/nginx/sites-enabled`. +After restarting Nginx and launching uWSGI (on port 8001), you should be able to surf to the same url as before and see "It works!". + +``` +sudo cp etesync_nginx.conf /etc/nginx/sites-available/ +sudo ln -s /etc/nginx/sites-available/etesync_nginx.conf /etc/nginx/sites-enables/etesync_nginx.conf +systemctl restart nginx +uwsgi --socket :8001 --module etesync_server.wsgi +``` + +If you encounter any errors, the Nginx log is located in `/var/log/nginx/error.log`. + +### Finalize Nginx & uWSGI setup + +For testing purposes, uWSGI exposes the Django application on port 8001. +A more elegant solution would be to expose the application using a file socket. + +Change `/etc/nginx/sites-available/etesync_nginx.conf` to accept file sockets by commenting in `server unix:///tmp/etesync_server.sock;` and commenting out `server 127.0.0.1:8001;`. +The first part should now look like this: + +``` + +# the upstream component nginx needs to connect to +upstream django { + server unix:///tmp/etesync_server.sock; # for a file socket + # server 127.0.0.1:8001; # for a web port socket (we'll use this first) +} + +``` + +This will create a file socket at `/tmp/etesync_server.sock`. +Now, configure uWSGI to also work using a file socket. +Because a lot of parameters are needed, create a `uwsgi.ini` and copy the following in it. +Don't forget to replace `` by the name of the user for the server. + +``` +[uwsgi] +chdir = /path/to/server-skeleton/ +socket = /tmp/etesync_server.sock +chown-socket = :www-data +chmod-socket = 660 +module = etesync_server.wsgi +master = true +uid = +virtualenv = venv +``` + +Now to run uWSGI, all you need to do is tell it to use the `.ini` server. +Restart Nginx and check if everything still works. + +``` +systemctl restart nginx +uwsgi --ini uwsgi.ini +``` + +### That's it! +You now have a working EteSync server over HTTP. +Don't forget to change `allowed_hosts` to your domain name in `etesync-server.ini` and to set `server_name` to your domain name in `/etc/nginx-sites-available/etesync.conf`. + +An optional next step is to have your uWSGI run automatically at boot. +It is also *highly* recommended **to enable SSL for your EteSync server!** +More info on both of these can be found in the wiki. \ No newline at end of file