Linux and Unix

One step production deployment

Here are some steps to install apache+python+mod_wsgi+web2py+postgresql from scratch.

On Ubuntu:

  1. wget https://raw.githubusercontent.com/web2py/web2py/master/scripts/setup-web2py-ubuntu.sh
  2. chmod +x setup-web2py-ubuntu.sh
  3. sudo ./setup-web2py-ubuntu.sh

On Fedora:

  1. wget https://raw.githubusercontent.com/web2py/web2py/master/scripts/setup-web2py-fedora.sh
  2. chmod +x setup-web2py-fedora.sh
  3. sudo ./setup-web2py-fedora.sh

Both of these scripts should run out of the box, but every Linux installation is a bit different, so make sure you check the source code of these scripts before you run them. In the case of Ubuntu, most of what they do is explained below. They do not implement the scalability optimizations discussed below.

Apache setup

In this section, we use Ubuntu Server Edition as the reference platform. The configuration commands are very similar on other Debian-based Linux distribution, but they may differ for Fedora-based systems (which uses yum instead of apt-get). You can use either 2.2.x or 2.4.x

First, make sure all the necessary Python and Apache packages are installed by typing the following shell commands:

  1. sudo apt-get update
  2. sudo apt-get -y upgrade
  3. sudo apt-get -y install openssh-server
  4. sudo apt-get -y install python
  5. sudo apt-get -y install python-dev
  6. sudo apt-get -y install apache2
  7. sudo apt-get -y install libapache2-mod-wsgi
  8. sudo apt-get -y install libapache2-mod-proxy-html

Then, enable the SSL module, the proxy module, and the WSGI module in Apache:

  1. sudo ln -s /etc/apache2/mods-available/proxy_http.load /etc/apache2/mods-enabled/proxy_http.load
  2. sudo a2enmod ssl
  3. sudo a2enmod proxy
  4. sudo a2enmod proxy_http
  5. sudo a2enmod wsgi

Create the SSL folder, and put the SSL certificates inside it:

  1. sudo mkdir /etc/apache2/ssl

You should obtain your SSL certificates from a trusted Certificate Authority such as verisign.com, but, for testing purposes, you can generate your own self-signed certificates following the instructions in ref.[openssl]

Then restart the web server:

  1. sudo /etc/init.d/apache2 restart

The Apache configuration file is:

  1. /etc/apache2/sites-available/default

The Apache logs are in:

  1. /var/log/apache2/

mod_wsgi

Download and unzip web2py source on the machine where you installed the web server above.

Install web2py under /home/www-data/, for example, and give ownership to user www-data and group www-data. These steps can be performed with the following shell commands:

  1. cd /home/www-data/
  2. sudo wget http://web2py.com/examples/static/web2py_src.zip
  3. sudo unzip web2py_src.zip
  4. sudo chown -R www-data:www-data /home/www-data/web2py

To set up web2py with mod_wsgi, create a new Apache configuration file:

  1. /etc/apache2/sites-available/web2py

and include the following code:

  1. <VirtualHost *:80>
  2. ServerName web2py.example.com
  3. WSGIDaemonProcess web2py user=www-data group=www-data display-name=%{GROUP}
  4. WSGIProcessGroup web2py
  5. WSGIScriptAlias / /home/www-data/web2py/wsgihandler.py
  6. #This is Apache 2.2.x permission syntax. See Apache docs for 2.4 syntax
  7. # http://httpd.apache.org/docs/2.4/upgrading.html#run-time
  8. <Directory /home/www-data/web2py>
  9. AllowOverride None
  10. Order Allow,Deny
  11. Deny from all
  12. <Files wsgihandler.py>
  13. Allow from all
  14. </Files>
  15. </Directory>
  16. AliasMatch ^/([^/]+)/static/(?:_[\d]+.[\d]+.[\d]+/)?(.*) /home/www-data/web2py/applications/$1/static/$2
  17. <Directory /home/www-data/web2py/applications/*/static/>
  18. Order Allow,Deny
  19. Allow from all
  20. </Directory>
  21. <Location /admin>
  22. Deny from all
  23. </Location>
  24. <LocationMatch ^/([^/]+)/appadmin>
  25. Deny from all
  26. </LocationMatch>
  27. CustomLog /private/var/log/apache2/access.log common
  28. ErrorLog /private/var/log/apache2/error.log
  29. </VirtualHost>

When you restart Apache, it should pass all the requests to web2py without going through the Rocket wsgiserver.

Move the handler script

Finally, you need to relocate the handler script web2py/handlers/wsgihandler.py. As documented in the handlers directory, the script you want should be moved or copied to the parent directory (i.e. the same directory as the web2py.py script). symlinking may cause apache permission problems.

Some wsgi background

Here are some explanations:

  1. WSGIDaemonProcess web2py user=www-data group=www-data display-name=%{GROUP}

defines a daemon process group in context of “web2py.example.com”. By defining this inside of the virtual host, only this virtual host can access this using WSGIProcessGroup, including any virtual host with the same server name but on a different port. The “user” and “group” options should be set to the user who has write access to the directory where web2py was setup. You do not need to set “user” and “group” if you made the web2py installation directory writable by the default user that Apache runs as. The “display-name” option makes the process name appears in ps output as “(wsgi-web2py)” instead of as name of Apache web server executable. As no “processes” or “threads” options are specified, the daemon process group will have a single process with 15 threads running within that process. This is usually more than adequate for most sites and should be left as is. If overriding it, do not use “processes=1” as doing so will disable any in-browser WSGI debugging tools that check the “wsgi.multiprocess” flag. This is because any use of the “processes” option will cause that flag to be set to true, even a single process, and such tools expect that it be set to false. Note: if your application code or third party extension module is not thread safe, use options “processes=5 threads=1” instead. This will create five processes in the daemon process group where each process is single threaded. You might consider using “maximum-requests=1000” if your application leaks Python objects because it is unable to garbage collect properly.

  1. WSGIProcessGroup web2py

delegates running of all WSGI applications to the daemon process group that was configured using the WSGIDaemonProcess directive.

  1. WSGIScriptAlias / /home/www-data/web2py/wsgihandler.py

mounts the web2py application. In this case it is mounted at the root of the web site.

  1. <Directory /home/www-data/web2py>
  2. ...
  3. </Directory>

gives Apache permission to access the WSGI script file.

  1. <Directory /home/www-data/web2py/applications/*/static/>
  2. Order Allow,Deny
  3. Allow from all
  4. </Directory>

Instructs Apache to bypass web2py when searching static files.

  1. <Location /admin>
  2. Deny from all
  3. </Location>

and

  1. <LocationMatch ^/([^/]+)/appadmin>
  2. Deny from all
  3. </LocationMatch>

blocks public access to admin and appadmin

Normally we would just allow permission to the whole directory where the WSGI script file is located, but web2py places the WSGI script file in a directory which contains other source code, including the admin interface password. Opening up the whole directory would cause security issues, because technically Apache would be given permission to serve all the files up to any user who traversed to that directory via a mapped URL. To avoid security problems, explicitly deny access to the contents of the directory, except for the WSGI script file, and prohibit a user from doing any overrides from a .htaccess file to be extra safe.

You can find a completed, commented, Apache wsgi configuration file in:

  1. scripts/web2py-wsgi.conf

This section was created with help from Graham Dumpleton, developer of mod_wsgi.

Setting password

In production it may be necessary to set the admin password programmatically. This can be done from the Bash shell with

  1. sudo -u www-data python -c "from gluon.main import save_password; save_password(raw_input('admin password: '), 443)"

mod_wsgi and SSL

To force some applications (for example admin and appadmin) to go over HTTPS, store the SSL certificate and key files:

  1. /etc/apache2/ssl/server.crt
  2. /etc/apache2/ssl/server.key

and edit the Apache configuration file web2py.conf and append:

  1. <VirtualHost *:443>
  2. ServerName web2py.example.com
  3. SSLEngine on
  4. SSLCertificateFile /etc/apache2/ssl/server.crt
  5. SSLCertificateKeyFile /etc/apache2/ssl/server.key
  6. WSGIProcessGroup web2py
  7. WSGIScriptAlias / /home/www-data/web2py/wsgihandler.py
  8. <Directory /home/www-data/web2py>
  9. AllowOverride None
  10. Order Allow,Deny
  11. Deny from all
  12. <Files wsgihandler.py>
  13. Allow from all
  14. </Files>
  15. </Directory>
  16. AliasMatch ^/([^/]+)/static/(?:_[\d]+.[\d]+.[\d]+/)?(.*) /home/www-data/web2py/applications/$1/static/$2
  17. <Directory /home/www-data/web2py/applications/*/static/>
  18. Order Allow,Deny
  19. Allow from all
  20. </Directory>
  21. CustomLog /private/var/log/apache2/access.log common
  22. ErrorLog /private/var/log/apache2/error.log
  23. </VirtualHost>

Restart Apache and you should be able to access:

  1. https://www.example.com/admin
  2. https://www.example.com/examples/appadmin
  3. http://www.example.com/examples

but not:

  1. http://www.example.com/admin
  2. http://www.example.com/examples/appadmin

mod_proxy

Some Unix/Linux distributions can run Apache, but do not support mod_wsgi. In this case, the simplest solution is to run Apache as a proxy and have Apache deal with static files only.

Here is a minimal Apache configuration:

  1. NameVirtualHost *:80
  2. #### deal with requests on port 80
  3. <VirtualHost *:80>
  4. Alias / /home/www-data/web2py/applications
  5. ### serve static files directly
  6. <LocationMatch "^/welcome/static/.*">
  7. Order Allow, Deny
  8. Allow from all
  9. </LocationMatch>
  10. ### proxy all the other requests
  11. <Location "/welcome">
  12. Order deny,allow
  13. Allow from all
  14. ProxyRequests off
  15. ProxyPass http://localhost:8000/welcome
  16. ProxyPassReverse http://localhost:8000/
  17. ProxyHTMLURLMap http://127.0.0.1:8000/welcome/ /welcome
  18. </Location>
  19. LogFormat "%h %l %u %t "%r" %>s %b" common
  20. CustomLog /var/log/apache2/access.log common
  21. </VirtualHost>

The above script exposes only the “welcome” application. To expose other applications, you need to add the corresponding with the same syntax as done for the “welcome” app.

The script assumes there is a web2py server running on port 8000. Before restarting Apache, make sure this is the case:

  1. nohup python web2py.py -a '<recycle>' -i 127.0.0.1 -p 8000 &

You can specify a password with the -a option or use the ““ parameter instead of a password. In the latter case, the previously stored password is reused and the password is not stored in the shell history.

You can also use the parameter ““, to be prompted for a password.

The nohup commands makes sure the server does not die when you close the shell. nohup logs all output into nohup.out.

To force admin and appadmin over HTTPS use the following Apache configuration file instead:

  1. NameVirtualHost *:80
  2. NameVirtualHost *:443
  3. #### deal with requests on port 80
  4. <VirtualHost *:80>
  5. Alias / /home/www-data/web2py/applications
  6. ### admin requires SSL
  7. <LocationMatch "^/admin">
  8. SSLRequireSSL
  9. </LocationMatch>
  10. ### appadmin requires SSL
  11. <LocationMatch "^/welcome/appadmin/.*">
  12. SSLRequireSSL
  13. </LocationMatch>
  14. ### serve static files directly
  15. <LocationMatch "^/welcome/static/.*">
  16. Order Allow,Deny
  17. Allow from all
  18. </LocationMatch>
  19. ### proxy all the other requests
  20. <Location "/welcome">
  21. Order deny,allow
  22. Allow from all
  23. ProxyPass http://localhost:8000/welcome
  24. ProxyPassReverse http://localhost:8000/
  25. </Location>
  26. LogFormat "%h %l %u %t "%r" %>s %b" common
  27. CustomLog /var/log/apache2/access.log common
  28. </VirtualHost>
  29. <VirtualHost *:443>
  30. SSLEngine On
  31. SSLCertificateFile /etc/apache2/ssl/server.crt
  32. SSLCertificateKeyFile /etc/apache2/ssl/server.key
  33. <Location "/">
  34. Order deny,allow
  35. Allow from all
  36. ProxyPass http://localhost:8000/
  37. ProxyPassReverse http://localhost:8000/
  38. </Location>
  39. LogFormat "%h %l %u %t "%r" %>s %b" common
  40. CustomLog /var/log/apache2/access.log common
  41. </VirtualHost>

The administrative interface must be disabled when web2py runs on a shared host with mod_proxy, or it will be exposed to other users.

Start as Linux daemon

Unless you are using mod_wsgi, you should setup the web2py server so that it can be started/stopped/restarted as any other Linux daemon, and so it can start automatically at the computer boot stage.

The process to set this up is specific to various Linux/Unix distributions.

In the web2py folder, there are two scripts which can be used for this purpose:

  1. scripts/web2py.ubuntu.sh
  2. scripts/web2py.fedora.sh

On Ubuntu, or other Debian-based Linux distribution, edit “web2py.ubuntu.sh” and replace the “/usr/lib/web2py” path with the path of your web2py installation, then type the following shell commands to move the file into the proper folder, register it as a startup service, and start it:

  1. sudo cp scripts/web2py.ubuntu.sh /etc/init.d/web2py
  2. sudo update-rc.d web2py defaults
  3. sudo /etc/init.d/web2py start

On Fedora, or any other distributions based on Fedora, edit “web2py.fedora.sh” and replace the “/usr/lib/web2py” path with the path of your web2py installation, then type the following shell commands to move the file into the proper folder, register it as a startup service and start it:

  1. sudo cp scripts/web2py.fedora.sh /etc/rc.d/init.d/web2pyd
  2. sudo chkconfig --add web2pyd
  3. sudo service web2py start

Nginx

Nginx is a free, open-source web server that has rapidly been gaining popularity for its amazing performance.

Unlike traditional servers, Nginx does not use threads. Instead it uses an ansynchronous/event-driven architecture to handle concurrency. This architecture results in a small and predictable memory usage, even under heavy load.

Nginx is more than an HTTP server and reverse proxy, it is also an IMAP/POP3 proxy server.

Nginx is easy to configure and its configuration files and simpler and more compact than the corresponding Apache ones.

Nginx does not support WSGI but provides native support for the uWSGI [uwsgi] protocol.

On Ubuntu you can install Nginx with:

  1. apt-get -y install nginx-full

Then you will need to create a configuration file such as the following:

  1. # file /etc/nginx/sites-available/web2py
  2. server {
  3. listen 80;
  4. server_name $hostname;
  5. #to enable correct use of response.static_version
  6. #location ~* /(\w+)/static(?:/_[\d]+.[\d]+.[\d]+)?/(.*)$ {
  7. # alias /home/www-data/web2py/applications/$1/static/$2;
  8. # expires max;
  9. #}
  10. location ~* /(\w+)/static/ {
  11. root /home/www-data/web2py/applications/;
  12. #remove next comment on production
  13. #expires max;
  14. }
  15. location / {
  16. #uwsgi_pass 127.0.0.1:9001;
  17. uwsgi_pass unix:///tmp/web2py.socket;
  18. include uwsgi_params;
  19. uwsgi_param UWSGI_SCHEME $scheme;
  20. uwsgi_param SERVER_SOFTWARE nginx/$nginx_version;
  21. }
  22. }
  23. server {
  24. listen 443 default_server ssl;
  25. server_name $hostname;
  26. ssl_certificate /etc/nginx/ssl/web2py.crt;
  27. ssl_certificate_key /etc/nginx/ssl/web2py.key;
  28. ssl_prefer_server_ciphers on;
  29. ssl_session_cache shared:SSL:10m;
  30. ssl_session_timeout 10m;
  31. ssl_ciphers ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA;
  32. ssl_protocols SSLv3 TLSv1;
  33. keepalive_timeout 70;
  34. location / {
  35. #uwsgi_pass 127.0.0.1:9001;
  36. uwsgi_pass unix:///tmp/web2py.socket;
  37. include uwsgi_params;
  38. uwsgi_param UWSGI_SCHEME $scheme;
  39. uwsgi_param SERVER_SOFTWARE nginx/$nginx_version;
  40. }
  41. }

You will need to symlink the file and remove the default

  1. ln -s /etc/nginx/sites-available/web2py /etc/nginx/sites-enabled/web2py
  2. rm /etc/nginx/sites-enabled/default

You may also need to create the ssl folder for certificates and put certificates in there:

  1. mkdir /etc/nginx/ssl
  2. cp web2py.key /etc/nginx/ssl
  3. cp web2py.crt /etc/nginx/ssl

You then need to install and setup uWSGI

  1. sudo mkdir /etc/uwsgi
  2. sudo mkdir /var/log/uwsgi

And create a configuration file “/etc/uwsgi/web2py.xml”:

  1. <uwsgi>
  2. <socket>/tmp/web2py.socket</socket>
  3. <pythonpath>/home/www-data/web2py/</pythonpath>
  4. <mount>/=wsgihandler:application</mount>
  5. <master/>
  6. <processes>4</processes>
  7. <harakiri>60</harakiri>
  8. <reload-mercy>8</reload-mercy>
  9. <cpu-affinity>1</cpu-affinity>
  10. <stats>/tmp/stats.socket</stats>
  11. <max-requests>2000</max-requests>
  12. <limit-as>512</limit-as>
  13. <reload-on-as>256</reload-on-as>
  14. <reload-on-rss>192</reload-on-rss>
  15. <uid>www-data</uid>
  16. <gid>www-data</gid>
  17. <no-orphans/>
  18. </uwsgi>

This file assumes web2py is installed under “/home/www-data/web2py”, as in the Apache case.

You also need to edit a second configuration file “/etc/init/uwsgi-emperor.conf”:

  1. # Emperor uWSGI script
  2. description "uWSGI Emperor"
  3. start on runlevel [2345]
  4. stop on runlevel [06]
  5. respawn
  6. exec uwsgi --master --die-on-term --emperor /etc/uwsgi --logto /var/log/uwsgi/uwsgi.log

Finally restart everything:

  1. start uwsgi-emperor
  2. /etc/init.d/nginx restart

You can reload uwsgi with

  1. restart uwsgi-emperor

You can stop it with

  1. stop uwsgi-emperor

You can reload web2py only (without restarting uwsgi) with

  1. touch /etc/uwsgi/web2py.xml

All these steps are performed automatically by the provided scripts:

  1. scripts/setup-web2py-nginx-uwsgi-on-centos.sh
  2. scripts/setup-web2py-nginx-uwsgi-ubuntu.sh

Lighttpd

You can install Lighttpd on a Ubuntu or other Debian-based Linux distribution with the following shell command:

  1. apt-get -y install lighttpd

Once installed, edit /etc/rc.local and create a fcgi web2py background process

  1. cd /var/www/web2py && sudo -u www-data nohup python fcgihandler.py &

Then, you need to edit the Lighttpd configuration file

  1. /etc/lighttpd/lighttpd.conf

so that it can find the socket created by the above process. In the config file, write something like:

  1. server.modules = (
  2. "mod_access",
  3. "mod_alias",
  4. "mod_compress",
  5. "mod_rewrite",
  6. "mod_fastcgi",
  7. "mod_redirect",
  8. "mod_accesslog",
  9. "mod_status",
  10. )
  11. server.port = 80
  12. server.bind = "0.0.0.0"
  13. server.event-handler = "freebsd-kqueue"
  14. server.error-handler-404 = "/test.fcgi"
  15. server.document-root = "/home/www-data/web2py/"
  16. server.errorlog = "/tmp/error.log"
  17. fastcgi.server = (
  18. "/handler_web2py.fcgi" => (
  19. "handler_web2py" => ( #name for logs
  20. "check-local" => "disable",
  21. "socket" => "/tmp/fcgi.sock"
  22. )
  23. ),
  24. )
  25. $HTTP["host"] = "(^|.)example.com$" {
  26. server.document-root="/var/www/web2py"
  27. url.rewrite-once = (
  28. "^(/.+?/static/.+)$" => "/applications$1",
  29. "(^|/.*)$" => "/handler_web2py.fcgi$1",
  30. )
  31. }

Now check for syntax errors:

  1. lighttpd -t -f /etc/lighttpd/lighttpd.conf

and (re)start the web server with:

  1. /etc/init.d/lighttpd restart

Notice that FastCGI binds the web2py server to a Unix socket, not to an IP socket:

  1. /tmp/fcgi.sock

This is where Lighttpd forwards the HTTP requests to and receives responses from. Unix sockets are lighter than Internet sockets, and this is one of the reasons Lighttpd+FastCGI+web2py is fast. As in the case of Apache, it is possible to setup Lighttpd to deal with static files directly, and to force some applications over HTTPS. Refer to the Lighttpd documentation for details.

Examples in this section were taken from John Heenan’s post in web2pyslices.

The administrative interface must be disabled when web2py runs on a shared host with FastCGI, or it will be exposed to the other users.

Shared hosting with mod_python

There are times, specifically on shared hosts, when one does not have the permission to configure the Apache config files directly. At the time of writing most of these hosts still run mod_python even if it is not maintained any more in favor of mod_wsgi.

You can still run web2py. Here we show an example of how to set it up.

Place contents of web2py into the “htdocs” folder.

In the web2py folder, create a file “web2py_modpython.py” file with the following contents:

  1. from mod_python import apache
  2. import modpythonhandler
  3. def handler(req):
  4. req.subprocess_env['PATH_INFO'] = req.subprocess_env['SCRIPT_URL']
  5. return modpythonhandler.handler(req)

Create/update the file “.htaccess” with the following contents:

  1. SetHandler python-program
  2. PythonHandler web2py_modpython
  3. #PythonDebug On

This example was provided by Niktar.

Cherokee with FastCGI

Cherokee is a very fast web server and, like web2py, it provides an AJAX-enabled web-based interface for its configuration. Its web interface is written in Python. In addition, there is no restart required for most of the changes.

Here are the steps required to setup web2py with Cherokee:

Download Cherokee[cherokee]

Untar, build, and install:

  1. tar -xzf cherokee-0.9.4.tar.gz
  2. cd cherokee-0.9.4
  3. ./configure --enable-fcgi && make
  4. make install

Start web2py normally at least once to make sure it creates the “applications” folder.

Write a shell script named “startweb2py.sh” with the following code:

  1. #!/bin/bash
  2. cd /var/web2py
  3. python /var/web2py/fcgihandler.py &

and give the script execute privileges and run it. This will start web2py under FastCGI handler.

Start Cherokee and cherokee-admin:

  1. sudo nohup cherokee &
  2. sudo nohup cherokee-admin &

By default, cherokee-admin only listens at local interface on port 9090. This is not a problem if you have full, physical access on that machine. If this is not the case, you can force it to bind to an IP address and port by using the following options:

  1. -b, --bind[=IP]
  2. -p, --port=NUM

or do an SSH port-forward (more secure, recommended):

  1. ssh -L 9090:localhost:9090 remotehost

Open “http://localhost:9090“ in your browser. If everything is ok, you will get cherokee-admin.

In cherokee-admin web interface, click “info sources”. Choose “Local Interpreter”. Write in the following code, then click “Add New”.

  1. Nick: web2py
  2. Connection: /tmp/fcgi.sock
  3. Interpreter: /var/web2py/startweb2py.sh

Finally, perform the following remaining steps:

  • Click “Virtual Servers”, then click “Default”.
  • Click “Behavior”, then, under that, click “default”.
  • Choose “FastCGI” instead of “List and Send” from the list box.
  • At the bottom, select “web2py” as “Application Server”
  • Put a check in all the checkboxes (you can leave Allow-x-sendfile). If there is a warning displayed, disable and enable one of the checkboxes. (It will automatically re-submit the application server parameter. Sometimes it doesn’t, which is a bug).
  • Point your browser to “http://yoursite“, and “Welcome to web2py” will appear.

Postgresql

PostgreSQL is a free and open source database which is used in demanding production environments, for example, to store the .org domain name database, and has been proven to scale well into hundreds of terabytes of data. It has very fast and solid transaction support, and provides an auto-vacuum feature that frees the administrator from most database maintenance tasks.

On an Ubuntu or other Debian-based Linux distribution, it is easy to install PostgreSQL and its Python API with:

  1. sudo apt-get -y install postgresql
  2. sudo apt-get -y install python-psycopg2

It is wise to run the web server(s) and the database server on different machines. In this case, the machines running the web servers should be connected with a secure internal (physical) network, or should establish SSL tunnels to securely connect with the database server.

Edit the PostgreSQL configuration file

  1. sudo nano /etc/postgresql/9.1/main/postgresql.conf

and make sure it contains these two lines

  1. ...
  2. listen_addresses = 'localhost'
  3. ...
  4. track_counts = on
  5. ...
  6. autovacuum = on # Enable autovacuum subprocess? 'on'
  7. ...

Edit the PostgreSQL client authentication file

  1. sudo nano /etc/postgresql/9.1/main/pg_hba.conf

and change the method of those lines to trust

  1. ...
  2. # "local" is for Unix domain socket connections only
  3. local all all trust
  4. # IPv4 local connections:
  5. host all all 127.0.0.1/32 trust
  6. # IPv6 local connections:
  7. host all all ::1/128 trust
  8. ...

Start the database server with:

  1. sudo /etc/init.d/postgresql restart

When restarting the PostgreSQL server, it should notify which port it is running on. Unless you have multiple database servers, it should be 5432.

The PostgreSQL logs are in:

  1. /var/log/postgresql/

Once the database server is up and running, create a user and a database so that web2py applications can use it:

  1. sudo -u postgres createuser -PE -s myuser
  2. postgresql> createdb -O myuser -E UTF8 mydb
  3. postgresql> echo 'The following databases have been created:'
  4. postgresql> psql -l
  5. postgresql> psql mydb

The first of the commands will grant superuser-access to the new user, called myuser. It will prompt you for a password.

Any web2py application can connect to this database with the command:

  1. db = DAL("postgres://myuser:mypassword@localhost:5432/mydb")

where mypassword is the password you entered when prompted, and 5432 is the port where the database server is running.

Normally you use one database for each application, and multiple instances of the same application connect to the same database. It is also possible for different applications to share the same database.

For database backup details, read the PostgreSQL documentation; specifically the commands pg_dump and pg_restore.

Start the scheduler as a Linux service (upstart)

To install the scheduler as a permanent daemon on Linux (w/ Upstart), put the following into /etc/init/web2py-scheduler.conf, assuming your web2py instance is installed in ‘s home directory, running as , with app , on network interface eth0.

  1. description "web2py task scheduler"
  2. start on (local-filesystems and net-device-up IFACE=eth0)
  3. stop on shutdown
  4. respawn limit 8 60 # Give up if restart occurs 8 times in 60 seconds.
  5. exec sudo -u <user> python /home/<user>/web2py/web2py.py -K <myapp>
  6. respawn

You can then start/stop/restart/check status of the daemon with:

  1. sudo start web2py-scheduler
  2. sudo stop web2py-scheduler
  3. sudo restart web2py-scheduler
  4. sudo status web2py-scheduler

Initial Queuing of a Repeating Task

Task definition is done in a model file. But the initial queuing of a repeating task is most easily done from a non-exposed controller function. By doing this in a controller rather than in a model file, you remove unnecessary database accesses that would occur on every request to your website.

[The function could also be in a module or a private file, but in the controller, the web2py API and environment is readily accessible.]

A non-exposed function is any controller function that has an argument, so writing something like the following in a controller (e.g. default.py) gives you

  1. def reinit_sched(protect=None):
  2. # put any preparatory code here
  3. #
  4. # schedule 2 tasks:
  5. sched.queue_task(foo)
  6. sched.queue_task(bar)
  7. #
  8. # put any afters code here
  9. db.commit()

and you can then easily call it with web2py.py -M -S appname/default/reinit_sched (a similar function can be used to stop a repeating task, perhaps for maintenance reasons)

Populating a Database on Deployment

Your application may have a need for a pre-populated database table. A simple example might be a table of color names, or the names of the months (perhaps in a special format not used in Python datetime routines). More complicated examples might include an initial inventory of parts, or the initial pages of a wiki.

The simple examples might be done via db.mycolors.insert(); the more complex examples might use a CSV file to fill in the values. As in the task queuing section above, this should be done using non-exposed controller functions. Table definition for a database is done in model files, but model files are read on every request, so one-time actions should not be in the model files where they would lower the responsiveness of your site.

[The function could also be in a module or a private file, but in the controller, the web2py API and environment is readily accessible.]

Again, a non-exposed function is any controller function that has an argument, so writing something like the following in a controller (e.g. default.py) gives you

  1. def populate_colors(protected=None)
  2. collist = ["lime", "#00FF00", "olive", "#808000",
  3. "fuchsia", "#FF00FF", "maroon", "#800000"]:
  4. for i in range(0, len(collist), 2):
  5. k, v = collist[i:i+2]
  6. db.mycolors.insert(name=k, code=v)
  7. db.commit()

you can then easily call it with web2py.py -M -S appname/default/populate_colors

For the complex example using a CSV file, your function might look like:

  1. def populate_colors(exposed=False):
  2. db.mycolors.import_from_csv_file(
  3. open(os.path.join(request.folder,
  4. os.path.join('private', db_colors.csv')
  5. ),
  6. 'r')
  7. )
  8. db.commit()

and this would be called with web2py.py -M -S appname/default/populate_colors

See also Chapter 14, Populating database with dummy