.. docs/source/administrator/server_configuration.rst
.. Copyright (C) 2012, University of Cambridge, Department of Psychiatry.
Created by Rudolf Cardinal (rnc1001@cam.ac.uk).
.
This file is part of CamCOPS.
.
CamCOPS is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
.
CamCOPS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with CamCOPS. If not, see .
.. _Apache: http://httpd.apache.org/
.. _CherryPy: https://cherrypy.org/
.. _Debian policy: https://www.debian.org/doc/debian-policy/ch-opersys.html#file-system-hierarchy
.. _Filesystem Hierarchy Standard: https://refspecs.linuxfoundation.org/FHS_3.0/fhs/index.html
.. _Gunicorn: http://gunicorn.org/
.. _HTTPS: http://en.wikipedia.org/wiki/HTTP_Secure
.. _Lintian: https://lintian.debian.org/
.. _Linux: http://en.wikipedia.org/wiki/Linux
.. _Matplotlib: https://matplotlib.org/
.. _MySQL: http://www.mysql.com/
.. _Pyramid: https://trypyramid.com/
.. _Python: https://www.python.org/
.. _Supervisor: http://supervisord.org/
.. _Ubuntu: http://www.ubuntu.com/
.. _server_configuration:
(MANUAL) Configuring the server
===============================
.. include:: include_this_is_manual_see_docker.rst
The majority of CamCOPS configuration takes place via the :ref:`server
configuration file `. Here, we deal with everything else.
.. contents::
:local:
:depth: 3
Overview
--------
- CamCOPS will operate offline on your tablet, and you can view simple
summaries of your tasks there.
- You should set up a server to receive data from your CamCOPS tablet(s).
- The simplest way (involving only free software) is to set up a Linux_
(e.g. Ubuntu_) computer with an Apache_ web server and a MySQL_ database
(plus the Python_ interpreter, which comes with most Linux
distributions) – collectively known as a LAMP stack [#lamp]_. Alternative
(e.g. Windows) configurations are possible, but we’ve not used them so do
not provide details here.
- You must also obtain an HTTPS_ certificate (or create one for free
[#snakeoil]_ – not recommended), and configure your web server to do all
its CamCOPS work via HTTPS only (not HTTP), so that your information is
always encrypted in transit from the tablets to your server. The CamCOPS
tablet app will not use unencrypted links. (Where do certificates live on
disk? See [#linuxflavours]_.)
- Then, CamCOPS provides software so your web server can receive data from
your tablets, and offers a :ref:`web front end ` so you
can view your tasks in HTML and PDF format, and download data in various
formats.
- For very advanced analysis, you can use the MySQL database directly.
- You must also consider the server’s security carefully; see :ref:`Security
`.
- Having set up your server, you should point your tablet(s) to it (see
:ref:`configuring the tablet application `).
Data flow
---------
A generic CamCOPS server is arranged like this:
.. image:: images/server_diagram.png
Most servers will use a single database and a single CamCOPS instance, because
this is simpler and more powerful. In that simpler case, ignore all reference
to “instances” in the figure above.
There are two web servers in this diagram.
- The **front-end web server** talks to the “world”. Users connect to it.
Choose a high-performance web server capable of serving static files.
- A good choice, regardless of OS, is Apache_.
- The **back-end web server** is bundled with CamCOPS. Its code lives in the
CamCOPS Python virtual environment. Its job is to serve CamCOPS, and only
CamCOPS, to an internal TCP/IP port (or UNIX socket). The front-end web
server then routes appropriate requests through to it. CamCOPS offers a
choice:
- Gunicorn_ is probably the best choice for deployment under Linux/UNIX. It’s
pretty quick. It relies on the UNIX `fork()` function [#fork]_, so it
doesn’t run under Windows.
- CherryPy_ is a good cross-platform choice, and definitely the best choice
under Windows.
- Pyramid_ is the web framework that CamCOPS uses, and it comes with its own
demonstration server. This is handy for running the very helpful Pyramid
debug toolbar [#pyramiddebugtoolbar]_ during testing, but it is definitely
not a good choice for deployment.
Plan where to put files
-----------------------
Under Linux, we follow the `Filesystem Hierarchy Standard`_.
.. list-table::
:header-rows: 1
* - Directory
- FHS purpose
- CamCOPS use
- Typical filename
- UNIX permissions
* - ``/etc``
- Host-specific system configuration
- CamCOPS config file
- ``/etc/camcops/camcops_mysite.conf``
- Web server user only
* - ``/run``
- Run-time variable data, e.g. PID files, Unix domain sockets.
- Unix domain socket when using Gunicorn.
- ``/run/camcops/camcops.socket``
- Web server user only
* - ``/srv``
- Data for services provided by this system.
- Images, extra strings, SNOMED data...
- ``/srv/camcops/images/...``; ``/srv/camcops/extra_strings/...``;
``/srv/camcops/snomed/...``
- Web server user only (or more liberal if you wish)
* - ``/var/cache``
- Application cache data
- Matplotlib_ cache
- ``/var/cache/camcops/matplotlib/``
- Web server user only
* - ``/var/lock``
- Lock files, e.g. for export
- Note: ``/var/lock`` may be autodeleted on reboot; Linux distributions
may link this to ``/run/lock`` and mount this in a temporary filesystem
(``tmpfs``). CamCOPS will recreate directories used for lock files; see
:ref:`EXPORT_LOCKDIR `.
- ``/var/lock/camcops/``
- Web server user only
* - ``/var/log``
- Log files
- Log files, via Supervisor_.
- ``/var/log/supervisor/camcops_*.log``
- Root only
* - ``/var/tmp``
- Temporary files preserved between system reboots
- Temporary user download files, as per :ref:`USER_DOWNLOAD_DIR
`.
- ``/var/tmp/camcops//``
- Web server user only
For information, these directories are used (or not used, but worthy of
comment!) by CamCOPS during installation:
.. list-table::
:header-rows: 1
* - Directory
- FHS purpose
- CamCOPS use
- Typical filename
- UNIX permissions
* - ``/usr/bin``
- "Most user commands."
- CamCOPS launch commands
- ``/usr/bin/camcops_server``; ``/usr/bin/camcops_server_meta``
- Public read, root write.
* - ``/usr/share``
- Architecture-independent data.
- CamCOPS itself. This includes Python ``*.pyc`` files, pre-compiled
at installation time.
- ``/usr/share/camcops/*``
- Public read, root write.
* - ``/usr/local``
- "For use by the system administrator when installing software locally."
- **Not used.** ``/usr/local/bin`` and ``/usr/local/share`` would be an
alternative to ``/usr/share``, etc. [#swlocation]_.
-
- Public read, root write.
* - ``/opt``
- Add-on application software packages.
- **Not used.** This would be another alternative to ``/usr/share``
[#swlocation]_.
-
- Public read, root write.
... plus other Linux/UNIX standards (e.g. the location of ``man`` pages).
The location of web server configuration files, databases, backups, and so on
is up to you and your system; see :ref:`Linux flavours `.
Configure your firewall
-----------------------
Ensure your firewall is configured properly:
- You’ll need to allow HTTPS through, for tablet communications and the web
viewer. (The default port is 443; see :ref:`TCP/IP ports `. It’s
possible to use another, but it will confuse users.)
- You’ll probably want remote SSH access, either through the default port (22),
or a secret port known only to you.
- Other ports are up to you. If you want to run a plain web server as well,
that’ll normally be on port 80. Access to CamCOPS should only be via HTTPS,
not plain HTTP.
- Disable access to everything you don’t need.
.. _create_database:
Create a database
-----------------
The method to create a database depends on the database engine you plan to use.
Here’s a method for MySQL to create a database named `camcops`.
First, from the Linux command line, log in to MySQL as root:
.. code-block:: bash
mysql --host=127.0.0.1 --port=3306 --user=root --password
# ... or the usual short form: mysql -u root -p
Then in MySQL:
.. code-block:: mysql
# Create the database:
CREATE DATABASE camcops;
# Ideally, create another user that only has access to the CamCOPS database.
# You should do this, so that you don’t use the root account unnecessarily.
GRANT ALL PRIVILEGES ON camcops.* TO 'YYYYYY_REPLACE_ME'@'localhost' IDENTIFIED BY 'ZZZZZZ_REPLACE_ME';
# For future use: if you plan to explore your database directly for analysis,
# you may want to create a read-only user. Though it may not be ideal (check:
# are you happy the user can see the audit trail?), you can create a user with
# read-only access to the entire database like this:
GRANT SELECT camcops.* TO 'QQQQQQ_REPLACE_ME'@'localhost' IDENTIFIED BY 'PPPPPP_REPLACE_ME';
# All done. Quit MySQL:
exit
Create/edit a CamCOPS config file
---------------------------------
See :ref:`“The CamCOPS server configuration file” `.
The file is typically called `/etc/camcops/camcops.conf` and should be readable
by the web server user, such as `www-data` under Ubuntu [#linuxflavours]_.
Create the database structure
-----------------------------
To create tables and indexes, use the command:
.. code-block:: bash
camcops_server upgrade_db --config CONFIG
where CONFIG is the filename of your configuration file. If your configuration
file is only readable as `www-data`, you will need to run this with ``sudo``:
.. code-block:: bash
sudo -u www-data camcops_server upgrade_db --config CONFIG
Create a superuser
------------------
Use the command:
.. code-block:: bash
camcops_server make_superuser --config CONFIG
where CONFIG is the filename of your configuration file. (Again, use ``sudo``
as above if your configuration file requires privileged access to read.)
Start CamCOPS
-------------
Under Linux, this is best done via Supervisor_, which launches programs, keeps
log files for them, and restarts them when the computer is rebooted.
To generate a specimen Supervisor configuration file for CamCOPS, run the
command
.. code-block:: bash
camcops_server demo_supervisor_config > my_demo_camcops_supervisor_config.conf
Here's an example, which you would typically save as
`/etc/supervisor/conf.d/camcops.conf`:
.. literalinclude:: _demo_supervisor_config.ini
:language: ini
This is where you choose which back-end web server CamCOPS should use (see
above), by choosing the command you pass to `camcops`. For high-performance
work under Linux, use Gunicorn, with the `serve_gunicorn` command; see the
:ref:`options for the camcops_server command `.
Notes on supervisor and its config files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Supervisor is a system for controlling background processes running on
UNIX-like operating systems. See http://supervisord.org
- On Ubuntu systems, you would typically install supervisor with ``sudo apt
install supervisor`` and then save this file as
``/etc/supervisor/conf.d/camcops.conf``.
- **If you edit a supervisord config file,** run ``sudo service supervisor
restart`` (Ubuntu) or ``sudo service supervisord restart`` (CentOS 6).
- **To monitor supervisor,** run ``sudo supervisorctl status``, or just ``sudo
supervisorctl`` for an interactive prompt.
- Regarding the supervisor config files:
- Indented lines are treated as continuation (even in commands; no need for
end-of-line backslashes or similar).
- The downside of that is that indented comment blocks can join onto your
commands! Beware that.
- Indented comment blocks can also break supervisord entirely. If it won't
start, try inspecting with ``supervisord -n -c
/etc/supervisor/supervisord.conf``.
- You can't put quotes around the directory variable
(http://stackoverflow.com/questions/10653590).
- Python programs that are installed within a Python virtual environment
automatically use the virtualenv's copy of Python via their shebang; you do
not need to specify that by hand, nor the PYTHONPATH.
- The ``environment`` parameter sets the OS environment.
- Creating a group (see below; a.k.a. a "heterogeneous process group") allows
you to control all parts of CamCOPS together, as ``camcops`` in this
example (see
http://supervisord.org/configuration.html#group-x-section-settings). Thus,
you can do, for example: ``sudo supervisorctl start camcops:*``
- **Specific extra notes for CamCOPS:**
- The ``MPLCONFIGDIR`` environment variable specifies a cache directory for
``matplotlib``, which greatly speeds up its subsequent loading.
- The typical "web server" user is ``www-data`` under Ubuntu Linux and
``apache`` under CentOS; see :ref:`Linux flavours `.
.. _configure_apache:
Point the front-end web server to CamCOPS
-----------------------------------------
Under Linux, a typicaly front-end web server is Apache_.
To generate a specimen Apache configuration file for CamCOPS, run the command
.. code-block:: bash
camcops_server demo_apache_config > demo_apache_config_chunk.txt
Here's an example to mount CamCOPS at the URL path `/camcops`, which you would
edit into the Apache config file [#linuxflavours]_:
.. If you re-paste the demo below, make sure you do it from a copy installed
to /usr/share/camcops, not your user's home directory, otherwise the paths
will be silly.
.. literalinclude:: _demo_apache_config.conf
:language: apacheconf
Once you are happy with your Apache config file:
- Ensure file ownerships/permissions are correct (including, on CentOS, SELinux
permissions [#selinux]_).
- On Ubuntu, if you use `/srv/www` as your `DocumentRoot`, you may need to
do:
.. code-block:: bash
sudo chown -R www-data:www-data /srv/www
- On CentOS, assuming you use `/var/www` as your `DocumentRoot`, you may need
to do:
.. code-block:: bash
ls -alZ /var/www # shows owners and SELinux security context
sudo chown -R apache:apache /var/www
sudo chcon -R -h system_u:object_r:httpd_sys_content_t /var/www
sudo chown -R apache:apache /etc/camcops
sudo chcon -R -h system_u:object_r:httpd_sys_content_t /etc/camcops
sudo chown -R apache:apache /var/cache/camcops
sudo chcon -R -h system_u:object_r:httpd_sys_content_t /var/cache/camcops
sudo chown -R apache:apache /usr/share/camcops/server/static
sudo chcon -R -h system_u:object_r:httpd_sys_content_t /usr/share/camcops/server/static
- Restart Apache: ``sudo apachectl restart``.
- Ensure Apache restarts on boot.
- On Ubuntu, this should be automatic.
- On CentOS, run:
.. code-block:: bash
sudo chkconfig --level 2345 httpd on
Browse to the web site
-----------------------
If you have configured things correctly, the rest of the configuration should
be possible via the CamCOPS web site.
Assuming you used `/camcops` as the base URL path,
- Browse to `https://YOURHOST/camcops/webview`. This should work.
- Browse to `http://YOURHOST/camcops/webview`. This should *not* work; you
shouldn’t allow access via plain HTTP.
- Check that a tablet device can register with the server and upload some data
while using the URL `https://YOURHOST/camcops/database`.
Troubleshooting access to the web site
--------------------------------------
1. If something isn't working, begin by trying the following (as a user that
can definitely read the config file):
.. code-block:: bash
cat /PATH/TO/YOUR_CONFIG_FILE # can I read it?
camcops_server serve_pyramid --config /PATH/TO/YOUR_CONFIG_FILE
Note the URL and port, likely ``localhost`` on port 8000, and in a separate
command prompt, try:
.. code-block:: bash
wget http://127.0.0.1:8000
The server should report a "GET / HTTP" message and the ``wget`` command should
return HTML with a "login failed" message, but if so, this shows that CamCOPS
is reading the config file and serving data correctly.
2. If a UNIX socket method wasn't working, try a TCP/IP port method.
- If a TCP/IP method works and a Unix socket doesn't, with Apache, then
check the Apache config file and make sure the "internal" unique dummy
URL associated with the socket is using "http", not "https". See the
demo Apache config file.
3. If, when using Apache, you get errors like ``Page not found! //login``,
then there is a slash error; potentially you have an incorrect slash at
the end of the Unix domain socket "dummy" URL.
Configure backups
-----------------
Your backup strategy is up to you. However, one option is to use a script to
dump all MySQL databases. A tool, :ref:`camcops_backup_mysql_database
`, is provided to help you:
If you use this strategy, you will need to save this script and edit the copy.
Be sure your copy of the script is readable only by root and the backup user,
as it contains a password. You can then run your script regularly from
`/etc/crontab` (see ``man cron``, ``man crontab``).
Obviously, you will also need the dumped files to be backed up to a physically
secure location regularly.
If you want to keep daily backups for a few days, then only weekly or monthly
backups (etc.), you could use a script like this:
.. literalinclude:: prune_camcops_backups.sh
:language: bash
More than one CamCOPS instance
------------------------------
This is simple to set up, but fiddly to maintain. Try to avoid it! Using one
database and :ref:`groups ` is much better. But if you have to:
- Create a second CamCOPS database (from the MySQL command line) as above.
- **Be careful:** MySQL users are system-wide. So don’t think you can have a
user named `camcopsmaster` with password X for one database, and a user
named `camcopsmaster` with password Y for another database; attempting this
will merely change the password for that (single) user.
- Create a second CamCOPS configuration file, e.g. copying
`/etc/camcops/camcops.conf` to `/etc/camcops/camcops2.conf` and editing it to
point to the new database.
- Run ``camcops`` from the command line, pointing it to the new configuration
file, to create the tables and a superuser (as above).
- Add a second instance to the Apache configuration file and restart Apache.
Database performance tuning
---------------------------
Ignore this section unless you actually have performance problems.
MySQL/InnoDB commit
~~~~~~~~~~~~~~~~~~~
Network latency can be improved considerably by altering the MySQL/InnoDB
log-on-commit behaviour. This is governed by the
`innodb_flush_log_at_trx_commit` variable. The default is 1, which is the
safest; it is required for ACID compliance. However, setting it to 2 makes
database write operations much faster.
This can by done by editing the MySQL configuration file [#linuxflavours]_ to
add this line:
.. code-block:: ini
[mysqld]
innodb_flush_log_at_trx_commit = 2
after which you would need to restart MySQL [#linuxflavours]_. Alternatively
you can change it dynamically at the MySQL command line with:
.. code-block:: mysql
SET GLOBAL innodb_flush_log_at_trx_commit = 2;
# Use SHOW VARIABLES; to show the current values.
See also:
- http://stackoverflow.com/questions/14121464/mysql-is-slow-with-innodb-during-insert-compared-to-myisam
- http://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html
===============================================================================
.. rubric:: Footnotes
.. [#linuxflavours]
See :ref:`Linux flavours ` for a reminder of some common
differences between Linux operating systems.
.. [#lamp]
http://en.wikipedia.org/wiki/LAMP_(software_bundle)
.. [#snakeoil]
This is referred to as creating a “snake oil” certificate. See e.g.
https://en.wikipedia.org/wiki/Snake_oil_(cryptography);
http://www.akadia.com/services/ssh_test_certificate.html
.. [#pyramiddebugtoolbar]
https://docs.pylonsproject.org/projects/pyramid_debugtoolbar/
.. [#fork]
https://en.wikipedia.org/wiki/Fork_(system_call)
.. [#selinux]
See http://wiki.apache.org/httpd/13PermissionDenied and
https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Managing_Confined_Services/chap-Managing_Confined_Services-The_Apache_HTTP_Server.html
.. [#swlocation]
The exact intended location of third-party software under Ubuntu is a bit
debated. See e.g.
- https://www.linuxjournal.com/magazine/pointcounterpoint-opt-vs-usrlocal
- https://askubuntu.com/questions/722968/why-should-i-move-everything-into-opt/722972
-- "Second, /opt is used for third-party software, which in the context
of Ubuntu, means precompiled software that is not distributed via Debian
packages."
- https://unix.stackexchange.com/questions/11544/what-is-the-difference-between-opt-and-usr-local
-- including "The basic difference is that /usr/local is for software not
managed by the system packager, but still following the standard unix
deployment rules."
- CamCOPS is managed by the system package manager and follows e.g. `Debian
policy`_, checked by Lintian_.