.. _installation_apache2: 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 (:ref:`installation_base_packages`) and deploy a Python 3 virtual environment (:ref:`installation_base_virtualenv`) using ``/usr/local/virtualenv3`` as directory. .. code-block:: bash $ 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 :ref:`installation_base_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: .. code-block:: bash $ 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``. .. code-block:: bash $ 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: .. code-block:: python 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: .. code-block:: bash 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: .. code-block:: bash 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`. .. code-block:: bash $ 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: .. code-block:: ini # ------ 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: .. code-block:: ini # ------ 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: .. code-block:: bash $ sudo certbot --apache certonly -d www.project01.mycompany.com Configuring Apache ------------------ Installing Apache 2 ^^^^^^^^^^^^^^^^^^^ .. code-block:: bash $ 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: .. code-block:: bash $ 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: .. code-block:: bash $ sudo aptitude install apache2-dev Then, run the following command to put ``mod_wsgi`` into your virtual environment: .. code-block:: bash (virtualenv3)$ pip install mod_wsgi To verify that the installation was successful, run the ``mod_wsgi-express`` script with the ``start-server`` command: .. code-block:: bash (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**: .. code-block:: apacheconf WSGIPythonHome '/usr/local/virtualenv3' WSGIApplicationGroup %{GLOBAL} WSGIPassAuthorization On WSGIPythonOptimize 1 **wsgi.load**: .. code-block:: apacheconf 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: .. code-block:: bash $ 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: .. code-block:: apacheconf 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 Allow from all SSLRequireSSL 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" 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 Require all granted Alias /favicon.ico /home/mycompany/Repositories/MyCompany/Chrysalio/Project01/project01/Static/favicon.ico Alias /custom /home/mycompany/Repositories/MyCompany/Chrysalio/Project01/project01/Static/Custom Require all granted 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 WSGIProcessGroup project01 Require all granted ServerName www.project01.mycompany.com Redirect permanent / https://www.project01.mycompany.com/ 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: .. code-block:: bash $ 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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: bash $ cd Warehouses/Local/MyWarehouse $ git update-server-info $ git config receive.denyCurrentBranch updateInstead Configuring Apache ^^^^^^^^^^^^^^^^^^ Install the following packages: .. code-block:: bash $ 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: .. code-block:: apacheconf ServerName git.project01.mycompany.com CustomLog ${APACHE_LOG_DIR}/access_git_project01.log combined AssignUserID mycompany mycompany 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 Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains" SetEnv GIT_PROJECT_ROOT /home/mycompany/Chrysalio/Project01/Warehouses/Local SetEnv GIT_HTTP_EXPORT_ALL ScriptAlias / /usr/lib/git-core/git-http-backend/ SSLRequireSSL AuthType Basic AuthName "MyCompany - Git" AuthUserFile /home/mycompany/Chrysalio/Project01/Warehouses/users Require valid-user ServerName git.project01.mycompany.com Redirect permanent / https://git.project01.mycompany.com/ Finally, activate this configuration and reload Apache: .. code-block:: bash $ sudo a2ensite git.project01.mycompany.com.conf $ sudo systemctl restart apache2.service