Skip to content

Commit

Permalink
Add custom matomo image
Browse files Browse the repository at this point in the history
  • Loading branch information
djbe committed Mar 23, 2024
1 parent d724f1c commit 7b5a8a8
Show file tree
Hide file tree
Showing 8 changed files with 399 additions and 0 deletions.
22 changes: 22 additions & 0 deletions .github/workflows/build-and-publish-matomo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
name: Build & Publish Matomo

on: # yamllint disable-line rule:truthy
schedule:
- cron: "0 0 1,15 * *" # Every 2 weeks
push:
branches:
- main
paths:
- .github/workflows/build-and-publish-matomo.yml
- .github/workflows/internal-build-and-publish.yml
- 'common/**'
- 'matomo/**'
workflow_dispatch:

jobs:
build-and-publish:
uses: ./.github/workflows/internal-build-and-publish.yml
with:
image: matomo
version: latest
26 changes: 26 additions & 0 deletions matomo/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
FROM matomo:fpm-alpine as final

# Install packages
# hadolint ignore=DL3018
RUN apk add --no-cache \
nginx \
supervisor

# Copy configuration files
# - nginx
COPY common/config/nginx/ /etc/nginx/
COPY matomo/config/nginx/http.d/ /etc/nginx/http.d/
# - supervisor
COPY common/config/supervisor/supervisord.conf /etc/supervisor/
COPY common/config/supervisor/conf.d/nginx.conf /etc/supervisor/conf.d/
COPY matomo/config/supervisor/conf.d/ /etc/supervisor/conf.d/
# - init
COPY matomo/scripts/ /

# Clean Up
WORKDIR /var/www/html
EXPOSE 80

# Start supervisord by default
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["serve"]
48 changes: 48 additions & 0 deletions matomo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Matomo Docker

🐳 Variant of the official Matomo docker image, tweaked to match our preferences.

Available images:
- `latest`: normal version.

## Commands

Docker will default to the `serve` command.

- `serve`: starts all services, such as `nginx`.
- `scheduler`: process scheduled tasks (cron jobs).
- `init`: initialize the project, such as executing migrations.
- fallback: execute the provided command.

# Initialization

Using an init container (that invokes `init` command above), the container will be prepared for use. This entails:

- Running through the Matomo onboarding wizard.
- Installing some plugins.
- Tweaking some base Matomo options.
- Applying the environment variables to the Matomo config.

# Configuration

This image can be configured using the following environment variables:

| Environment Key | Applied | Description |
------------------|---------|--------------
| MATOMO_USERNAME | Bootstrap only | Admin user username |
| MATOMO_PASSWORD | Bootstrap only | Admin user password |
| MATOMO_EMAIL | Bootstrap only | Admin user email address |
| MATOMO_HOST | Bootstrap only | Hostname of the first website that'll be created |
| MATOMO_WEBSITE_NAME | Bootstrap only | Name of the first website that'll be created |
| MATOMO_SMTP_HOST | Every run | SMTP server hostname |
| MATOMO_SMTP_PORT_NUMBER | Every run | SMTP server port number |
| MATOMO_SMTP_USER | Every run | SMTP server username |
| MATOMO_SMTP_PASSWORD | Every run | SMTP server password |
| MATOMO_SMTP_ENCRYPTION | Every run | SMTP server encryption |
| MATOMO_NOREPLY_NAME | Every run | Sender name for sent emails |
| MATOMO_NOREPLY_ADDRESS | Every run | Sender email address for sent emails |
| MATOMO_DATABASE_HOST | Every run | Database hostname |
| MATOMO_DATABASE_PORT_NUMBER | Every run | Database port number |
| MATOMO_DATABASE_NAME | Every run | Database name |
| MATOMO_DATABASE_USER | Every run | Database user |
| MATOMO_DATABASE_PASSWORD | Every run | Database password |
23 changes: 23 additions & 0 deletions matomo/config/nginx/http.d/default.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;

# Redirect root folder
location = /metrics {
access_log off;
log_not_found off;
return 302 /metrics/;
}

# Pass along to matomo server block
location ^~/metrics/ {
access_log off;
log_not_found off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Forwarded-Uri /metrics;
proxy_pass http://127.0.0.1:26059/;
}
}
64 changes: 64 additions & 0 deletions matomo/config/nginx/http.d/matomo.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
server {
listen 127.0.0.1:26059;

# Paths
root /var/www/html;
index index.php;

# Security
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;

# serve PHP files
location ~ ^/(index|matomo|piwik|js/index|plugins/HeatmapSessionRecording/configs)\.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass 127.0.0.1:9000;
}

## 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;
}

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|node_modules) {
deny all;
return 403;
}

## properly display textfiles in root directory
location ~/(.*\.md|LEGALNOTICE|LICENSE) {
default_type text/plain;
}
}
10 changes: 10 additions & 0 deletions matomo/config/supervisor/conf.d/php-fpm.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[program:php-fpm]
command=php-fpm -F

stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

autorestart=false
startretries=0
173 changes: 173 additions & 0 deletions matomo/scripts/bootstrap.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#!/usr/bin/env sh

set -euo pipefail

config_file="/var/www/html/config/config.ini.php"

start_server() {
echo "Booting up temporary server…"

# Start services
/entrypoint.sh php-fpm &
nginx
sleep 2
}

exec_sql_query() {
php -r "
\$conn = new PDO(\"mysql:host=${MATOMO_DATABASE_HOST}:${MATOMO_DATABASE_PORT_NUMBER};dbname=${MATOMO_DATABASE_NAME}\", \"${MATOMO_DATABASE_USER}\", \"${MATOMO_DATABASE_PASSWORD}\");
\$conn->exec(\"$1\");"
}

# Run through the installation wizard
matomo_pass_wizard() {
local wizard_url cookie_file curl_output curl_opts curl_data_opts

# Start wizard
wizard_url="http://127.0.0.1:26059/"
cookie_file="/tmp/cookie$RANDOM"
curl_opts="--location --silent --cookie $cookie_file --cookie-jar $cookie_file -o /dev/null"
curl $curl_opts $wizard_url

echo "Step 1: System check"
curl_data_opts="--data-urlencode action=systemCheck"
curl $curl_opts $curl_data_opts $wizard_url

echo "Step 2: Database setup"
curl_data_opts="--data-urlencode action=databaseSetup\
--data-urlencode host=${MATOMO_DATABASE_HOST}:${MATOMO_DATABASE_PORT_NUMBER}\
--data-urlencode username=${MATOMO_DATABASE_USER}\
--data-urlencode password=${MATOMO_DATABASE_PASSWORD}\
--data-urlencode dbname=${MATOMO_DATABASE_NAME}\
--data-urlencode tables_prefix=matomo_\
--data-urlencode adapter=PDO\\MYSQL"
curl $curl_opts $curl_data_opts $wizard_url

echo "Step 3: Create tables (SKIP)"

echo "Step 4: Setup super-user"
curl_data_opts="--data-urlencode action=setupSuperUser\
--data-urlencode module=Installation\
--data-urlencode login=${MATOMO_USERNAME}\
--data-urlencode password=${MATOMO_PASSWORD}\
--data-urlencode password_bis=${MATOMO_PASSWORD}\
--data-urlencode email=${MATOMO_EMAIL}"
curl $curl_opts $curl_data_opts $wizard_url

echo "Step 5: Setup first tracking website"
curl_data_opts="--data-urlencode action=firstWebsiteSetup\
--data-urlencode module=Installation\
--data-urlencode siteName=${MATOMO_WEBSITE_NAME}\
--data-urlencode url=${MATOMO_HOST}\
--data-urlencode timezone=UTC"
curl $curl_opts $curl_data_opts $wizard_url

echo "Step 6: Tracking code"
curl_data_opts="--data-urlencode action=trackingCode\
--data-urlencode module=Installation"
curl $curl_opts $curl_data_opts $wizard_url

echo "Step 7: Finish installation"
curl_data_opts="--data-urlencode action=finished\
--data-urlencode module=Installation"
curl $curl_opts $curl_data_opts $wizard_url
}

# Install & activate the given plugin
matomo_install_plugin() {
echo "Installing plugin '$1'…"

# Download plugin
curl --location --silent -o "/tmp/$1.zip" "https://plugins.matomo.org/api/2.0/plugins/$1/download/latest"
unzip -q "/tmp/$1.zip" -d /var/www/html/plugins
chown -R www-data:www-data "/var/www/html/plugins/$1"
rm "/tmp/$1.zip"

# Activate plugin
./console plugin:activate $1
}

# Adapt some general settings (stored in the DB) to match our preferences
matomo_tweak_options() {
echo "Tweak some options…"

# General settings
exec_sql_query "REPLACE INTO matomo_option VALUES
('enableBrowserTriggerArchiving', '0', 1),
('PrivacyManager.ipAddressMaskLength', '2', 0),
('PrivacyManager.ipAnonymizerEnabled', '1', 0),
('PrivacyManager.useAnonymizedIpForVisitEnrichment', '1', 0),
('PrivacyManager.anonymizeOrderId', '1', 0),
('PrivacyManager.anonymizeUserId', '1', 0),
('PrivacyManager.doNotTrackEnabled', '1', 0),
('delete_logs_enable', '1', 0),
('delete_logs_older_than', '180', 0),
('delete_reports_enable', '1', 0),
('delete_reports_keep_basic_metrics', '1', 0),
('delete_reports_keep_month_reports', '1', 0),
('delete_reports_keep_year_reports', '1', 0),
('delete_reports_older_than', '12', 0);"

# Configure ProtectTrackID
exec_sql_query "INSERT INTO matomo_plugin_setting VALUES
('ProtectTrackID', 'baseSetting', 'ABCDEFGHIJKLMNOPijklmnopqrstuvxwyz12345', 0, '', DEFAULT),
('ProtectTrackID', 'saltSetting', '$(openssl rand -hex 20)', 0, '', DEFAULT),
('ProtectTrackID', 'lengthSetting', '20', 0, '', DEFAULT);"

# Configure TrackingSpamPrevention
exec_sql_query "INSERT INTO matomo_plugin_setting VALUES
('TrackingSpamPrevention', 'block_clouds', '1', 0, '', DEFAULT),
('TrackingSpamPrevention', 'block_headless', '1', 0, '', DEFAULT);"
}

# Update configuration settings stored in the config.ini.php file
# Will always be run, to reflect changes to the ENV
matomo_update_config() {
# Database settings
./console config:set \
"database.host=\"$MATOMO_DATABASE_HOST:$MATOMO_DATABASE_PORT_NUMBER\"" \
"database.username=\"$MATOMO_DATABASE_USER\"" \
"database.password=\"$MATOMO_DATABASE_PASSWORD\"" \
"database.dbname=\"$MATOMO_DATABASE_NAME\"" \
"General.enable_load_data_infile=0"

# Handle proxy correctly
./console config:set \
'General.force_ssl=1' \
'General.assume_secure_protocol=1' \
'General.proxy_uri_header=1' \
'General.enable_trusted_host_check=0' \
'General.trusted_hosts=[]' \
'General.proxy_client_headers=[]' \
'General.proxy_client_headers[]="HTTP_X_FORWARDED_FOR"' \
'General.proxy_host_headers=[]' \
'General.proxy_host_headers[]="HTTP_X_FORWARDED_HOST"'

# Email settings
./console config:set \
"General.noreply_email_address=\"$MATOMO_NOREPLY_ADDRESS\"" \
"General.noreply_email_name=\"$MATOMO_NOREPLY_NAME\"" \
'mail.transport="smtp"' \
"mail.port=\"$MATOMO_SMTP_PORT_NUMBER\"" \
"mail.host=\"$MATOMO_SMTP_HOST\"" \
'mail.type="Login"' \
"mail.username=\"$MATOMO_SMTP_USER\"" \
"mail.password=\"$MATOMO_SMTP_PASSWORD\"" \
"mail.encryption=\"$MATOMO_SMTP_ENCRYPTION\""
}

# Only initialize if we do NOT have a config file
if [ ! -f "$config_file" ]; then
start_server
matomo_pass_wizard
matomo_install_plugin BotTracker
matomo_install_plugin JsTrackerForceAsync
matomo_install_plugin Provider
matomo_install_plugin ProtectTrackID
matomo_install_plugin TrackingSpamPrevention
matomo_install_plugin TreemapVisualization
matomo_tweak_options
fi

# Always update general config
matomo_update_config
Loading

0 comments on commit 7b5a8a8

Please sign in to comment.