Files
matomo-bootstrap/README.md

310 lines
6.7 KiB
Markdown
Raw Normal View History

2025-12-23 10:19:37 +01:00
# matomo-bootstrap
2025-12-23 22:05:52 +01:00
Headless bootstrap tooling for **Matomo**. Automates **first-time installation** and **API token provisioning** for fresh Matomo instances.
---
## Features
2025-12-23 22:05:52 +01:00
- 🚀 **Fully headless Matomo installation**
- Drives the official Matomo web installer using **Playwright**
- Automatically skips the installer if Matomo is already installed
- 🔐 **API token provisioning**
- Creates an **app-specific token** via an authenticated Matomo session
- Compatible with **Matomo 5.3.x** Docker images
- 🧪 **E2E-tested**
- Docker-based end-to-end tests included
- ❄️ **First-class Nix support**
- Flake-based packaging and pinned `flake.lock`
- Uses `nixpkgs` browsers via `playwright-driver` (no Playwright downloads)
- 🧼 **Token-only stdout contract**
- **stdout contains only the token** (safe for scripting)
- Logs go to **stderr**
---
## Requirements
2025-12-23 22:05:52 +01:00
- A running Matomo instance (e.g. via Docker)
- For fresh installs:
- Chromium (provided by Playwright or by the Playwright base container image)
---
## Installation
2025-12-23 22:05:52 +01:00
### Nix (recommended)
2025-12-23 22:05:52 +01:00
Run directly from the repository:
```bash
nix run github:kevinveenbirkenbach/matomo-bootstrap
```
2025-12-23 22:05:52 +01:00
In Nix mode, browsers are provided via `nixpkgs` (`playwright-driver`) and Playwright downloads are disabled.
---
2025-12-23 22:05:52 +01:00
### Python / pip
2025-12-23 22:05:52 +01:00
Requires **Python ≥ 3.10**:
```bash
pip install matomo-bootstrap
2025-12-23 22:05:52 +01:00
python -m playwright install chromium
```
2025-12-23 22:05:52 +01:00
---
### Docker image (GHCR)
Pull the prebuilt image:
```bash
2025-12-23 22:05:52 +01:00
docker pull ghcr.io/kevinveenbirkenbach/matomo-bootstrap:stable
# or:
docker pull ghcr.io/kevinveenbirkenbach/matomo-bootstrap:latest
```
---
## Usage
### CLI
```bash
matomo-bootstrap \
--base-url http://127.0.0.1:8080 \
--admin-user administrator \
2025-12-23 22:05:52 +01:00
--admin-password 'AdminSecret123!' \
--admin-email administrator@example.org \
--token-description my-ci-token
```
2025-12-23 22:05:52 +01:00
On success, the command prints **only the token** to stdout:
```text
6c7a8c2b0e9e4a3c8e1d0c4e8a6b9f21
```
---
2025-12-23 22:05:52 +01:00
### Environment variables
All options can be provided via environment variables:
```bash
export MATOMO_URL=http://127.0.0.1:8080
export MATOMO_ADMIN_USER=administrator
2025-12-23 22:05:52 +01:00
export MATOMO_ADMIN_PASSWORD='AdminSecret123!'
export MATOMO_ADMIN_EMAIL=administrator@example.org
export MATOMO_TOKEN_DESCRIPTION=my-ci-token
matomo-bootstrap
```
---
2025-12-23 22:05:52 +01:00
### Debug mode
2025-12-23 22:05:52 +01:00
Enable verbose logs (**stderr only**):
```bash
matomo-bootstrap --debug
```
---
2025-12-23 22:05:52 +01:00
## Docker Compose integration (one-shot bootstrap)
### Why “one-shot”?
The bootstrap container is meant to:
1. Run once,
2. Print the token to stdout,
3. Exit with code `0`.
You should **not** start it automatically on every `docker compose up`.
Instead, start Matomo normally, then run the bootstrap via `docker compose run`.
The cleanest Compose pattern is to put `bootstrap` behind a **profile**.
---
### Example `docker-compose.yml` (recommended: `profiles`)
```yaml
services:
db:
image: mariadb:11
container_name: matomo-db
restart: unless-stopped
environment:
MARIADB_DATABASE: matomo
MARIADB_USER: matomo
MARIADB_PASSWORD: matomo_pw
MARIADB_ROOT_PASSWORD: root_pw
volumes:
- mariadb_data:/var/lib/mysql
healthcheck:
test: ["CMD-SHELL", "mariadb-admin ping -uroot -proot_pw --silent"]
interval: 5s
timeout: 3s
retries: 60
matomo:
image: matomo:5.3.2
container_name: matomo
restart: unless-stopped
depends_on:
db:
condition: service_healthy
ports:
- "${MATOMO_PORT:-8080}:80"
environment:
MATOMO_DATABASE_HOST: db
MATOMO_DATABASE_ADAPTER: mysql
MATOMO_DATABASE_USERNAME: matomo
MATOMO_DATABASE_PASSWORD: matomo_pw
MATOMO_DATABASE_DBNAME: matomo
volumes:
- matomo_data:/var/www/html
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1/ >/dev/null || exit 1"]
interval: 10s
timeout: 5s
retries: 60
bootstrap:
# This prevents automatic startup during a normal `docker compose up`
profiles: ["bootstrap"]
# Option A: use the published image (recommended)
image: ghcr.io/kevinveenbirkenbach/matomo-bootstrap:1.0.1
# Option B: build locally from the repository checkout
# build:
# context: .
# dockerfile: Dockerfile
# image: matomo-bootstrap:local
container_name: matomo-bootstrap
depends_on:
matomo:
condition: service_started
environment:
# inside the compose network, Matomo is reachable via the service name
MATOMO_URL: "http://matomo"
MATOMO_ADMIN_USER: "administrator"
MATOMO_ADMIN_PASSWORD: "AdminSecret123!"
MATOMO_ADMIN_EMAIL: "administrator@example.org"
MATOMO_TOKEN_DESCRIPTION: "docker-compose-bootstrap"
# Values used by the recorded installer flow
MATOMO_SITE_NAME: "Matomo (docker-compose)"
MATOMO_SITE_URL: "http://127.0.0.1:${MATOMO_PORT:-8080}"
MATOMO_TIMEZONE: "Germany - Berlin"
# Optional stability knobs
MATOMO_TIMEOUT: "30"
MATOMO_PLAYWRIGHT_HEADLESS: "1"
MATOMO_PLAYWRIGHT_NAV_TIMEOUT_MS: "60000"
MATOMO_PLAYWRIGHT_SLOWMO_MS: "0"
restart: "no"
volumes:
mariadb_data:
matomo_data:
```
---
### Commands
Start DB + Matomo **without** bootstrap:
```bash
docker compose up -d db matomo
```
Run bootstrap once (prints token to stdout):
```bash
docker compose --profile bootstrap run --rm bootstrap
```
Re-run bootstrap (creates a new token by default):
```bash
docker compose --profile bootstrap run --rm bootstrap
```
---
## Idempotency / avoiding new tokens on every run
By default, `UsersManager.createAppSpecificTokenAuth` creates a new token each time.
If you want strictly idempotent runs in automation, you can provide an existing token
and make the bootstrap return it instead of creating a new one:
```bash
export MATOMO_BOOTSTRAP_TOKEN_AUTH="0123456789abcdef..."
matomo-bootstrap
```
> This is useful for CI re-runs or configuration management tools.
---
## How it works
1. **Reachability check**
2025-12-23 22:05:52 +01:00
* waits until Matomo responds via HTTP (any status is considered “reachable”)
2. **Installation (if needed)**
2025-12-23 22:05:52 +01:00
* uses a recorded Playwright flow to complete the Matomo web installer
3. **Authentication**
2025-12-23 22:05:52 +01:00
* logs in using Matomos `Login.logme` controller (cookie session)
4. **Token creation**
2025-12-23 22:05:52 +01:00
* calls `UsersManager.createAppSpecificTokenAuth`
5. **Output**
2025-12-23 22:05:52 +01:00
* prints the token to stdout (token-only contract)
---
2025-12-23 22:05:52 +01:00
## End-to-end tests
Run the full E2E cycle locally:
```bash
make e2e
```
This will:
1. Start Matomo + MariaDB via Docker
2. Install Matomo headlessly
3. Create an API token
2025-12-23 22:05:52 +01:00
4. Validate the token via the Matomo API
5. Tear everything down again
---
2025-12-23 10:19:37 +01:00
## Author
**Kevin Veen-Birkenbach**
2025-12-23 22:05:52 +01:00
[https://www.veen.world/](https://www.veen.world/)
---
## License
2025-12-23 22:05:52 +01:00
MIT — see [LICENSE](LICENSE)