Commit 4ae7351d authored by Dave Lane's avatar Dave Lane

provided relevant files and initial configuration documents. Need to add...

provided relevant files and initial configuration documents. Need to add Matomo install instructions and Let's Encrypt process
parent c4512b0a
# Matomo Docker Recipe
A quick recipe for firing up a Matomo instance (formerly Piwik) via Docker Compose.
\ No newline at end of file
A quick recipe for firing up a Matomo instance (formerly Piwik) via Docker Compose.
## Setup
The way we set up things for the OER Foundation, is that we tend to use Docker Compose to host containers on a virtual server. We usually run MariaDB on the Docker host rather than as a container, as it makes database backups easier, especially when we have lots of services that depend on MariaDB.
We usually put our Docker Compose configurations under /home/docker, in a directory with the domain name of the service. In this case, it's /home/docker/ In that directory, we often only have a docker-compose.yml file. It's where all Docker Compose commands are issued.
We store site-related data in /home/data - in this case in /home/data/ The source code for Matomo is in /home/data/ We also usually have /home/data/ for the generic NGINX configuration for the service (the files we use are held in the `nginx` director in this repo). We use another NGINX instance running on the host as a reverse proxy and as the endpoint for SSL (HTTPS). That simplifies maintenance of the Let's Encrypt certificates we use.
The only things you need to change are the [sitename] (we use the domain name of the site there) and the port you make the nginx instance visible on - if it's free, you can use 8080. Make sure the port specified in `docker-compose.yml` (create it from our sample via `cp docker-compose.yml-sample docker-compose.yml` in the git directory.
You can create a suitable database in your MariaDB with the following (you should be able to access the MariaDB command line via `sudo mysql` on any current Ubuntu Linux server) - just add your own password for [password]:
CREATE DATABASE matomo CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER "matomo"@"%" IDENTIFIED BY "[password]";
GRANT ALL ON matomo.* TO "matomo"@"%";
Note that your database will be available on from the perspective of your Docker containers.
You will also need to use the files in `reverse-proxy` (copy the include file to the right place: `sudo cp -a includes/letsencrypt.conf to /etc/nginx/` - and we would normally rename the matomo file to /etc/nginx/sites-available/[sitename], replacing the nginx port (if not 8080) and the [sitename] and then run `sudo ln -sf /etc/nginx/sites-available/[sitename] /etc/nginx/site-enabled` and then run `sudo nginx -t` to make sure there aren't any syntax errors, and finally `sudo service nginx reload` to restart the server.
version: '3'
image: matomo:fpm-alpine
restart: unless-stopped
- /home/data/[sitename]/src:/var/www/html
- MYSQL_USER=matomo
- /home/data/[sitename]/config/db.env
image: nginx:alpine
restart: unless-stopped
- /home/data/[sitename]/src:/var/www/html:ro
# see
- /home/data/[sitename]/nginx:/etc/nginx/conf.d
-[an available port, e.g. 8080]:80
server {
listen [::]:80; # remove this if you don't want Matomo to be reachable from IPv6
listen 80;
server_name default;
add_header Referrer-Policy origin always; # make sure outgoing links don't show the URL to the Matomo instance
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
root /var/www/html/; # replace with path to your matomo instance
index index.php;
## only allow accessing the following php files
location ~ ^/(index|matomo|piwik|js/index|plugins/HeatmapSessionRecording/configs)\.php {
#include fastcgi_param;
include conf.d/fastcgi-php.conf; # if your Nginx setup doesn't come with a default fastcgi-php config, you can fetch it from
try_files $fastcgi_script_name =404; # protects against CVE-2019-11043. If this line is already included in your snippets/fastcgi-php.conf you can comment it here.
#fastcgi_param HTTP_PROXY ""; # prohibit httpoxy:
fastcgi_pass app:9000; # uncomment if you are using PHP via TCP sockets (e.g. Docker container)
## deny access to all other .php files
location ~* ^.+\.php$ {
deny all;
return 403;
## serve all other files normally
location / {
try_files $uri $uri/ =404;
## disable all access to the following directories
location ~ ^/(config|tmp|core|lang) {
deny all;
return 403; # replace with 404 to not show these directories exist
location ~ /\.ht {
deny all;
return 403;
location ~ js/container_.*_preview\.js$ {
expires off;
add_header Cache-Control 'private, no-cache, no-store';
location ~ \.(gif|ico|jpg|png|svg|js|css|htm|html|mp3|mp4|wav|ogg|avi|ttf|eot|woff|woff2|json)$ {
allow all;
## Cache images,CSS,JS and webfonts for an hour
## Increasing the duration may improve the load-time, but may cause old files to show after an Matomo upgrade
expires 1h;
add_header Pragma public;
add_header Cache-Control "public";
location ~ ^/(libs|vendor|plugins|misc/user|node_modules) {
deny all;
return 403;
## properly display textfiles in root directory
location ~/(.*\.md|LEGALNOTICE|LICENSE) {
default_type text/plain;
# vim: filetype=nginx
# from
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REQUEST_SCHEME $scheme;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
# from
# Rule for legitimate ACME Challenge requests (like /.well-known/acme-challenge/xxxxxxxxx)
# We use ^~ here, so that we don't check other regexes (for speed-up). We actually MUST cancel
# other regex checks, because in our other config files have regex rule that denies access to files with dotted names.
location ^~ /.well-known/acme-challenge/ {
# Set correct content type. According to this:
# Current specification requires "text/plain" or no content header at all.
# It seems that "text/plain" is a safe option.
default_type "text/plain";
# This directory must be the same as in /etc/letsencrypt/cli.ini
# as "webroot-path" parameter. Also don't forget to set "authenticator" parameter
# there to "webroot".
# Do NOT use alias, use root! Target directory is located here:
# /var/www/common/letsencrypt/.well-known/acme-challenge/
root /var/www/letsencrypt;
# Hide /acme-challenge subdirectory and return 404 on all requests.
# It is somewhat more secure than letting Nginx return 403.
# Ending slash is important!
location = /.well-known/acme-challenge/ {
return 404;
# Set [sitename], YOUR_WPMS_DIR, and YOUR_PORT below to make this work
# HTTP does *soft* redirect to HTTPS
server {
# add [IP-Address:]80 in the next line if you want to limit this to a single interface
listen 80;
listen [::]:80;
server_name [sitename];
root /home/data/[sitename]/sc;
index index.php;
# change the file name of these logs to include your server name
# if hosting many services...
access_log /var/log/nginx/[sitename]_access.log;
error_log /var/log/nginx/[sitename]_error.log;
# for let's encrypt renewals!
include includes/letsencrypt.conf;
# redirect all HTTP traffic to HTTPS.
location / {
return 302 https://[sitename]$request_uri;
# This assumes you're using Let's Encrypt for your SSL certs (and why wouldn't
# you!?)...
server {
# add [IP-Address:]443 ssl in the next line if you want to limit this to a single interface
listen 443 ssl;
listen [::]:443 ssl;
ssl on;
# When starting nginx for the first time with this file, you need to use the default certificates
# to generate suitable Let's Encrypt certs for [sitename] - then you can uncomment the ones below,
# comment out the default certs, test nginx is happy via `sudo nginx -t` and then reload this
# configuration via `sudo service nginx reload`. Then your site should respond to https://[sitename]
#ssl_certificate /etc/letsencrypt/live/[sitename]/fullchain.pem;
#ssl_certificate_key /etc/letsencrypt/live/[sitename]/privkey.pem;
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# to create this, see
ssl_dhparam /etc/ssl/certs/dhparam.pem;
keepalive_timeout 20s;
server_name [sitename];
root /home/data/[sitename]/src;
index index.php;
# change the file name of these logs to include your server name
# if hosting many services...
access_log /var/log/nginx/[sitename]_access.log;
error_log /var/log/nginx/[sitename]_error.log;
location / {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Proto https;
proxy_connect_timeout 900;
proxy_send_timeout 900;
proxy_read_timeout 900;
send_timeout 900;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment