Deployment with Apache and mod_wsgi
This documentation assumes you have Apache already installed on your system. If you do not, install Apache 2.X for your platform in whatever manner makes sense.
Installing Chrysalio in a production mode
We suppose we have a user super
who is in the sudo
group and we are
using this user to install the application.
Install required packages (Installing Required Packages) and deploy a
Python 3 virtual environment (Installing a Virtual Environment) using
/usr/local/virtualenv3
as directory.
$ sudo python3 -m venv /usr/local/virtualenv3
$ sudo chown super:super -R /usr/local/virtualenv3
$ source /usr/local/virtualenv3/bin/activate
(virtualenv3)$ pip install -U pip setuptools wheel
(virtualenv3)$ pip install --extra-index-url=https://pypi.chrysal.io Chrysalio
Create a database (see Setting up the Database) named, for instance,
Project01
.
Setting an UTF-8 environment
Make sure that on your system an UTF-8 locale is generated. To do so, type:
$ sudo dpkg-reconfigure locales
Adding a User
Create a user for your instance so you can control use of resources
(Cf. ulimit
, quota
…). In this documentation, we suppose the name of
this user is mycompany
.
$ sudo adduser mycompany
If you plan to deploy several instances, we suggest to create a different user for each instance to isolate them.
Creating WSGI script
Log as mycompany
and within the Chrysalio/Project01
directory
(e.g. /home/mycompany/Chrysalio/Project01
), create a script named
project01.wsgi
with the following content:
from pyramid.paster import get_app, setup_logging
ini_path = '/home/mycompany/Chrysalio/Project01/myproject01.ini'
setup_logging(ini_path)
application = get_app(ini_path, 'main')
Creating Configuration File
You can retrieve an example of configuration file in the archive of example of configuration:
mycompany$ wget https://pypi.chrysal.io/conf/Chrysalio.zip
Copy the production.ini
into the /home/mycompany/Chrysalio/Project01
directory and name it project01.ini
. Tune its content according to your
needs.
Then, populate your database:
mycompany$ cd ~/Chrysalio/Project01
mycompany$ source /usr/local/virtualenv3/bin/activate
(virtualenv3) mycompany$ ciopopulate project01.ini
Installing Redis Server
Redis is an open source, in-memory data structure store, used as a cache. It’s a good practice to use it in a production configuration for Chrysalio.
$ sudo aptitude install redis-server
$ source /usr/local/virtualenv3/bin/activate
(virtualenv3)$ pip install redis pyramid_redis_sessions
Then, in your INI file (project01.ini
), add the following lines:
# ------ Includes
pyramid.includes =
pyramid_redis_sessions
# ------ Redis session
redis.sessions.secret = sekreet1
redis.sessions.timeout = 43200
redis.sessions.cookie_name = CIO_SESSION
If you plan to use a cache manager as well, you need to use Redis via Beaker. In that case, add the following lines instead:
# ------ Includes
pyramid.includes =
pyramid_beaker
# ------ Beaker session
beaker.session.type = ext:redis
beaker.session.url = redis://127.0.0.1:6379/0
beaker.session.lock_dir = %(here)s/Var/Sessions/Lock
beaker.session.secret = sekreet1
beaker.session.timeout = 43200
beaker.session.key = CIO_SESSION
# ------ Beaker cache
beaker.cache.type = ext:redis
beaker.cache.url = redis://127.0.0.1:6379/1
beaker.cache.lock_dir = %(here)s/Var/Cache/Lock
beaker.cache.expire = 43200
beaker.cache.regions = ciowarehouse_user, ciowarehouse_global
beaker.cache.ciowarehouse_user.expire = 3600
beaker.cache.ciowarehouse_global.expire = 3600
Installing Let’s Encrypt Certificate
It’s a good idea to use HTTPS instead HTTP to protect your password during log in.
You can create a certificate for Apache 2 using Certbot. Install certbot
according to the instruction
of the site.
Then, create your own certificate:
$ sudo certbot --apache certonly -d www.project01.mycompany.com
Configuring Apache
Installing Apache 2
$ sudo aptitude install apache2
Installing mod_wsgi
Once Apache is installed, we need to install mod_wsgi.
You can install this module with your package manager:
$ sudo aptitude install libapache2-mod-wsgi-py3
$ sudo a2enmod header ssl
However, we recommend installing the latest version from PyPi. To do this, we need the Apache development package:
$ sudo aptitude install apache2-dev
Then, run the following command to put mod_wsgi
into your virtual
environment:
(virtualenv3)$ pip install mod_wsgi
To verify that the installation was successful, run the mod_wsgi-express
script with the start-server
command:
(virtualenv3)$ mod_wsgi-express start-server
To activate the WSGI module, you need to create inside the
/etc/apache2/mods-available
directory the two following files.
wsgi.conf:
<IfModule mod_wsgi.c>
WSGIPythonHome '/usr/local/virtualenv3'
WSGIApplicationGroup %{GLOBAL}
WSGIPassAuthorization On
WSGIPythonOptimize 1
</IfModule>
wsgi.load:
LoadModule wsgi_module /usr/local/virtualenv3.5/lib/python3.5/site-packages/mod_wsgi/server/mod_wsgi-py35.cpython-35m-x86_64-linux-gnu.so
Then, enable it:
$ sudo a2enmod wsgi
$ sudo systemctl restart apache2.service
Creating the New Site
Now, in /etc/apache2/sites-available
, create a
www.project01.mycompany.com.conf
file with the following content:
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
ServerName www.project01.mycompany.com
CustomLog ${APACHE_LOG_DIR}/access_project01.log combined
SSLEngine on
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder off
SSLCompression off
SSLSessionTickets off
SSLOptions +StrictRequire
SSLCertificateFile /etc/letsencrypt/live/www.project01.mycompany.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.project01.mycompany.com/privkey.pem
<Location />
Allow from all
SSLRequireSSL
</Location>
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
Header always set Content-Security-Policy "\
default-src 'self' ; \
img-src 'self' data: blob: ; \
style-src 'self' 'unsafe-inline' cdn.jsdelivr.net ; \
script-src 'self' 'nonce-ICAgIHZhciBERUZBVU' cdn.jsdelivr.net ; \
font-src 'self' cdn.jsdelivr.net ; \
frame-src 'self' www.youtube.com www.dailymotion.com player.vimeo.com ; frame-ancestors 'self'"
Header always set X-Frame-Options "sameorigin"
Header always set X-Content-Type-Options: "nosniff"
</IfModule>
Protocols h2 http/1.1
KeepAlive Off
TimeOut 600
Alias /css /home/mycompany/Repositories/Chrysalio/chrysalio/Static/Css
Alias /images /home/mycompany/Repositories/Chrysalio/chrysalio/Static/Images
Alias /fonts /home/mycompany/Repositories/Chrysalio/chrysalio/Static/Fonts
Alias /js /home/mycompany/Repositories/Chrysalio/chrysalio/Static/Js
Alias /favicon.ico /home/mycompany/Repositories/Chrysalio/chrysalio/Static/favicon.ico
Alias /robots.txt /home/mycompany/Repositories/Chrysalio/chrysalio/Static/robots.txt
<Directory /home/mycompany/Repositories/Chrysalio/chrysalio/Static>
Require all granted
</Directory>
Alias /favicon.ico /home/mycompany/Repositories/MyCompany/Chrysalio/Project01/project01/Static/favicon.ico
Alias /custom /home/mycompany/Repositories/MyCompany/Chrysalio/Project01/project01/Static/Custom
<Directory /home/mycompany/Repositories/MyCompany/Chrysalio/Project01/project01/Static>
Require all granted
</Directory>
WSGIApplicationGroup %{GLOBAL}
WSGIDaemonProcess project01 \
user=mycompany group=mycompany \
python-path=/usr/local/virtualenv3/lib/python3.5/site-packages \
python-eggs=/home/mycompany/Chrysalio/Project01/Var/Tmp \
processes=2 \
threads=5 \
restart-interval=7200 \
listen-backlog=100 \
queue-timeout=45 \
socket-timeout=60 \
connect-timeout=15 \
request-timeout=60 \
deadlock-timeout=60 \
graceful-timeout=15 \
eviction-timeout=0 \
shutdown-timeout=5 \
send-buffer-size=0 \
receive-buffer-size=0 \
header-buffer-size=0 \
response-buffer-size=0 \
server-metrics=Off
WSGIImportScript /home/mycompany/Chrysalio/Project01/project01.wsgi \
process-group=project01 \
application-group=%{GLOBAL}
WSGIScriptAlias / /home/mycompany/Chrysalio/Project01/project01.wsgi
<Directory /home/mycompany/Chrysalio/Project01>
WSGIProcessGroup project01
Require all granted
</Directory>
</VirtualHost>
<VirtualHost _default_:80>
ServerName www.project01.mycompany.com
Redirect permanent / https://www.project01.mycompany.com/
</VirtualHost>
</IfModule>
The Alias /Static
block will greatly improve performance because requests
for this content (images, CSS, fonts, JavaScript, robots.txt and favicon.ico)
will not need to be proxied to Chrysalio application and can be served
directly. Correct the path according to your environment. You cannot use this
optimization if you use the theme system.
Finally, activate this configuration and reload Apache:
$ sudo a2ensite www.project01.mycompany.com.conf
$ sudo systemctl restart apache2.service
Activating a Git Access
If you want to use versioned Chrysalio warehouse as Git repository, follow theses steps:
Preparing a Non-bare Git repository
$ cd Warehouses/Local/MyWarehouse
$ git update-server-info
$ git config receive.denyCurrentBranch updateInstead
Configuring Apache
Install the following packages:
$ sudo aptitude install git libapache2-mpm-itk
$ sudo a2enmod cgi mpm_itk
In /etc/apache2/sites-available
, create a
git.project01.mycompany.com.conf
file with the following content:
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
ServerName git.project01.mycompany.com
CustomLog ${APACHE_LOG_DIR}/access_git_project01.log combined
<IfModule mpm_itk_module>
AssignUserID mycompany mycompany
</IfModule>
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLHonorCipherOrder on
SSLCompression off
SSLOptions +StrictRequire
SSLCertificateFile /etc/letsencrypt/live/git.project01.mycompany.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/git.project01.mycompany.com/privkey.pem
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
</IfModule>
SetEnv GIT_PROJECT_ROOT /home/mycompany/Chrysalio/Project01/Warehouses/Local
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias / /usr/lib/git-core/git-http-backend/
<Location />
SSLRequireSSL
AuthType Basic
AuthName "MyCompany - Git"
AuthUserFile /home/mycompany/Chrysalio/Project01/Warehouses/users
Require valid-user
</Location>
</VirtualHost>
<VirtualHost _default_:80>
ServerName git.project01.mycompany.com
Redirect permanent / https://git.project01.mycompany.com/
</VirtualHost>
</IfModule>
Finally, activate this configuration and reload Apache:
$ sudo a2ensite git.project01.mycompany.com.conf
$ sudo systemctl restart apache2.service