The next post contains an advanced version of this guide.
This post is a update to the previous one on the same topic.
The environment is as usual a low-end VPS with freshly installed Ubuntu 10.04.3 Lucid LTS (minimal version). First things first, :
apt-get update apt-get dist-upgrade -y for i in busybox-static \ syslog-ng \ python-setuptools \ python-pip \ python-software-properties \ ; do apt-get install $i -yf done
Then we install web.py (0.36 at the time of this writing) itself using pip:
pip install web.py
Next comes the servers. Fortunately, there are now ‘official’ ppa for both Nginx and uWSGI on launchpad, which are updated regularly and make the job a lot easier than before:
add-apt-repository ppa:nginx/stable add-apt-repository ppa:uwsgi/release apt-get update apt-get install nginx uwsgi-python -yf
At the time of this writing, the above will install Nginx 1.0.11 and uWSGI 0.9.6.8. Note that in the last line we now have to use ‘uwsgi-python’ instead of ‘uwsgi’. If you have a version of uwsgi previously installed using other repositories, you most likely would need to remove it first.
For this demonstration, we use the minimalist ‘Hello World’ example from web.py tutorial as our web application. Save the following as ‘/var/www/apps/index.py’:
import web urls = ( '/', 'index' ) app = web.application(urls, globals()) class index: def GET(self): return "Hello, world!" if __name__ == "__main__": app.run()
We use the web.py built-in web server to test whether the above code is OK. In ‘/var/www/apps’ folder, type this:
python index.py
Point your browser to IP:8080 and you should be greeted with ‘Hello, world!’. Press Ctrl-C to stop the web.py built-in server.
Working upwards, next we set up uWSGI configuration for our demo app. uWSGI in Ubuntu now uses /etc/uwsgi-python/apps-available and /etc/uwsgi-python/apps-enabled folders for application configuration files, similar to Nginx and other servers. We will be using uWSGI in VirtualHosting mode, so that more applications can be added later dynamically without having to change uWSGI configuration. Create ‘/etc/uwsgi-python/apps-enabled/vhosts.ini’ with the following contents:
[uwsgi] gid = www-data uid = www-data vhost = true logdate socket = /tmp/uwsgi_vhosts.sock #socket = 127.0.0.1:3031 master = true processes = 1 harakiri = 20 limit-as = 128 memory-report no-orphans
We then set up Nginx by creating a site file in /etc/nginx/sites-enabled with the following contents:
server { # Change this if you want to serve your application on another port listen 80; # Replace this with your domain name server_name apps.example.com; # You can use virtual directory like '/apps/' here, but remember that # this should match 'urls' defined in your web.py application file location / { include uwsgi_params; # This should match the 'socket' entry in your uwsgi configuration uwsgi_pass unix:///tmp/uwsgi_vhosts.sock; #uwsgi_pass 127.0.0.1:3031; # This is the absolute path to the folder containing your application uwsgi_param UWSGI_CHDIR /var/www/apps; # This is actually not necessary for our simple application, # but you may need this in future uwsgi_param UWSGI_PYHOME /var/www/apps; # This is the name of your application file, minus the '.py' extension uwsgi_param UWSGI_SCRIPT index; } }
We are almost done, but there is one last and very important step: uWSGI requires a wsgi application to be defined in the application file (index.py in our case). Just add this line to the end of index.py:
application = app.wsgifunc()
Now that everything is in place, we can (re)start Nginx and uWSGI:
service nginx restart service uwsgi-python restart
Point your browser to your domain and you will now be greeted by ‘Hello, world!’ served by Nginx through uWSGI. Job done.
It didn’t work. However this does:
location /static/ {
root /var/www;
if (-f $request_filename) {
rewrite ^/static/(.*)$ /static/$1 break;
}
}
Found it at http://webpy.org/cookbook/fastcgi-nginx
Thanks in any case for your help and your excellent walkthrough!
It worked in my test, 🙂
Don’t use if statements when possible, for static files you definitely shouldn’t need them. Refer to http://wiki.nginx.org/IfIsEvil and http://wiki.nginx.org/Pitfalls
location /static {
alias /var/www/apps/static;
expires 7d;
}
or
location /static {
root /var/www/apps;
expires 7d;
}
should both work fine for serving static files.
I always put my named location blocks before my root location block to make sure that they are matched first. I’m not sure whether this is necessary but I had problems with an Nginx config years ago and changing the order of the location blocks fixed it so since then I’ve always put my named locations first.
Excellent guide and it’s working fine except the app can’t find static content like js, css and images located in /var/www/apps/static. It’s probably due to some nginx settings but I’m not at all familiar with it. Any ideas?
Just define a ‘location’ inside the server context in nginx conf:
location /static/ {
alias /var/www/apps/static/;
expires 7d;
}