Piwigo Image Gallery
Setup & Configuration
Piwigo runs as a two-container stack using the official piwigo/piwigo:latest image paired with a dedicated mariadb:lts database container. The stack is exposed via the Cloudflare tunnel on the frontend Docker network — no ports are published directly to the host.
INFO
The setup previously used the linuxserver.io community image. It has been replaced with the official Piwigo image for better standards compliance and maintained PHP extensions.
Containers
| Container | Image | Purpose |
|---|---|---|
piwigo | piwigo/piwigo:latest | Web application (Apache + PHP) |
piwigo-db | mariadb:lts | Dedicated database (separate from the main MySQL instance) |
The piwigo container waits for piwigo-db to pass its health check before starting.
Data directories
All persistent data lives under ~/docker/piwigo/piwigo-data/:
- 📁
piwigo/— Piwigo web root: configuration, plugins, themes, uploaded images- 📁
piwigo/upload/— images uploaded via the admin backend, organised asYYYY/MM/DD - 📁
piwigo/galleries/— images synchronised from folder structure (historic images) - 📁
piwigo/plugins/— installed Piwigo plugins - 📁
piwigo/themes/— installed themes - 📁
piwigo/local/— local CSS overrides for theming
- 📁
- 📁
mysql/— MariaDB data directory - 📁
backups/— output directory for database backups
Environment variables (.env)
Credentials and configuration are injected via an Ansible-templated .env file:
| Variable | Purpose |
|---|---|
TZ | Timezone (Europe/Berlin) |
PIWIGO_DATA_PATH | Base path for data volumes |
DB_NAME | MariaDB database name |
DB_USER | MariaDB application user |
DB_PASSWORD | MariaDB application password |
DB_ROOT_PASSWORD | MariaDB root password |
Sensitive values (DB_PASSWORD, DB_ROOT_PASSWORD) are stored in Ansible Vault.
Initial configuration
After first start, the Piwigo setup wizard is completed via the web UI. Ongoing configuration is managed through the Piwigo admin backend:
- Install plugins via Plugins → Installed Plugins
- Install and set Bootstrap Darkroom as the active theme
- Customise CSS for the KL Harriettes look and feel — the Ansible role automatically deploys
bootstrap_darkroom-rules.cssinto the piwigo data directory
CORS Configuration
The frontend fetches image thumbnails and album links directly from gallery.klharriettes.org via the Piwigo API. Because this is a cross-origin request, CORS headers must be added to responses.
This is handled by a Cloudflare HTTP Response Header Transform Rule named "Piwigo CORS Headers", applied to all requests matching (http.host eq "gallery.klharriettes.org"):
| Action | Header | Value |
|---|---|---|
| Add static | Access-Control-Allow-Origin | * |
| Set static | Access-Control-Allow-Methods | GET, POST, OPTIONS, HEAD |
| Add static | Access-Control-Allow-Headers | Authorization, Origin, X-Requested-With, Content-Type, Accept |
WARNING
These CORS headers are required for the frontend to consume the Piwigo API. Without them, browser security policies will block all cross-origin API calls and images will not load in the frontend.
Piwigo API
Besides serving as a standalone image gallery, the Piwigo API is used by the frontend to load image thumbnails and album links for individual runs. Requests are filtered by creation date to match images to a run date.
An interactive API explorer is available at gallery.klharriettes.org/tools/ws.htm.
INFO
The pwg.images.search endpoint is used for date-based image lookups. The preferred pwg.images.filteredSearch.create endpoint is not used as it requires the PHP cal_days_in_month() calendar function — verify whether this is available in the official image before switching.
Deployment
Deployment is managed by Ansible. The install-piwigo role writes the docker-compose.yml and .env to the server; the maintain.yml playbook handles pulling the latest image and restarting:
# Initial setup
ansible-playbook playbooks/install.yml -e target=piwigo_prod --tags piwigo
# Update to latest image
ansible-playbook playbooks/maintain.yml -e target=piwigo_prod --tags containersBackup & Restore
Piwigo generates large amounts of image data. The backup strategy is designed to minimise storage usage on Google Drive.
Database
The MariaDB database is backed up daily at 4:10am using ~/scripts/piwigo/backup_piwigo_db.sh. The backup file is stored in ~/docker/piwigo/piwigo-data/backups/.
Configuration & plugins
The Piwigo config directory (excluding the _data thumbnail cache) is backed up daily at 3:20am using ~/scripts/piwigo/backup_piwigo.sh.
Images
A split approach keeps Google Drive storage usage manageable:
Historic images (pre-2025-04) — backed up as a single tar archive outside the regular cycle, stored in
piwigo/galleries/. In case of data loss, restore by expanding the archive and synchronising via the Piwigo admin backend under Tools → Synchronize.Current images (2025-04+) — uploaded via the admin backend into
piwigo/upload/. Backed up weekly every Saturday at 3:05am usingrclone, copying only files newer than 8 days:
/usr/bin/rclone copy --max-age 8d ~/docker/piwigo/piwigo-data/piwigo/upload \
klhhh-google:/Backups/imagesIn case of data loss, copy the backup folder directly back to piwigo/upload/.
WARNING
The Ansible scripts do not include an automated restore procedure. Restores should be supervised manually due to the complexity of reconciling the database with the file system state.
