Docker stacks for Coolify. Each service has a local compose file and a Coolify compose file. Images publish to ghcr.io/preservemygames/extra.
| Service | Folder | Coolify port | Image |
|---|---|---|---|
| Flarum | flarum/ |
ravenguard:8080 (forum), ravenguard-hub:8080 (WAF admin) |
ghcr.io/preservemygames/extra/flarum + .../ravenguard |
| MediaWiki | mediawiki/ |
8080 | ghcr.io/preservemygames/extra/mediawiki |
| Copyparty | copyparty/ |
3923 | ghcr.io/preservemygames/extra/copyparty |
| Forgejo | forgejo/ |
3000 | ghcr.io/preservemygames/extra/forgejo |
| cgit | cgit/ |
8080 | ghcr.io/preservemygames/extra/cgit |
| BugPin | bugpin/ |
7300 | ghcr.io/preservemygames/extra/bugpin |
| RavenGuard | ravenguard/ |
built for Flarum (and standalone smoke) | ghcr.io/preservemygames/extra/ravenguard |
Point your Coolify domain at the service port above. Coolify terminates HTTPS on the public URL.
Rootless forum image with bundled PreserveMyGames extensions. Coolify traffic goes through RavenGuard in fleet mode (WAF edge + separate hub):
Client -> Coolify TLS -> ravenguard :8080 -> flarum:8080
Client -> Coolify TLS -> ravenguard-hub :8080 (admin SPA)
Day one the edge runs with RG_MODE=all and admin disabled so the forum works without enrollment. The hub is a separate Coolify service on port 8080 only (avoids the dual-port warning). After login, enroll the edge from Proxies UI, then set on the ravenguard service:
RG_MODE=proxy
RG_AGENT_HUB_URL=http://ravenguard-hub:8080
RG_AGENT_TOKEN=...
RG_AGENT_HUB_PUBKEY=...
RG_AGENT_NAME=edge-1Redeploy. No custom Docker command is required (RG_MODE / RG_CONFIG are enough).
Required:
FLARUM_FORUM_TITLE=MeshChatX Forum
FLARUM_ADMIN_EMAIL=admin@example.comAttach Coolify domains like this (each service exposes only 8080):
| Domain | Service port |
|---|---|
Forum (https://forum.example.com) |
ravenguard:8080 |
Guard admin (https://waf.example.com) |
ravenguard-hub:8080 |
Do not attach domains to flarum. Coolify sets SERVICE_URL_RAVENGUARD_8080 (forum) and SERVICE_URL_RAVENGUARD_HUB_8080 (hub). Flarum uses:
FLARUM_BASE_URL=${FLARUM_BASE_URL:-$SERVICE_URL_RAVENGUARD_8080}Override FLARUM_BASE_URL only if you need a fixed origin. Do not use Coolify *.sslip.io URLs.
Coolify provides:
SERVICE_PASSWORD_FLARUMADMINSERVICE_PASSWORD_FLARUMDBSERVICE_PASSWORD_FLARUMROOTSERVICE_PASSWORD_RAVENGUARD(challenge HMAC, min 16 chars)SERVICE_PASSWORD_RAVENGUARDADMIN(hub bootstrap password)
Optional:
FLARUM_BASE_URL=https://forum.example.com
ALTCHA_HMAC_SECRET= # auto-generated if empty
SPAM_AI_API_KEY=
SPAM_AI_BASE_URL=https://openrouter.ai/api/v1
SPAM_AI_MODEL=openai/gpt-4o-mini
FLARUM_MAINTENANCE_MODE=off # off | banner | read_only | closed
RG_UI_BRAND=MeshChatX Forum
RG_UI_STATUS_TEXT=Checking your browser before accessing MeshChatX Forum.
RG_CHALLENGE_ENABLED=true
RG_TRUSTED_PROXIES=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16The entrypoint rewrites Flarum config.php url from FLARUM_BASE_URL on every start.
RavenGuard keeps its raven logo; challenge branding text comes from RG_UI_BRAND (default MeshChatX Forum). Change the hub admin password after first login.
AI spam protection (preservemygames-spam-protection)
OpenAI-compatible classifier (OpenRouter by default). Monitors new posts and registrations, then can hide posts, hide or lock discussions, and suspend users.
Configure under Admin → Extensions → AI Spam Protection, or seed from env on first boot:
SPAM_AI_API_KEY=sk-or-...
SPAM_AI_BASE_URL=https://openrouter.ai/api/v1
SPAM_AI_MODEL=openai/gpt-4o-miniAdmin settings for API key, base URL, and model override the environment once saved.
ALTCHA (preservemygames-altcha)
Self-hosted proof-of-work for registration (optional login / password reset). HMAC secret is auto-generated on first boot. Optional pin:
ALTCHA_HMAC_SECRET=$(openssl rand -hex 32)Maintenance (preservemygames-maintenance)
| Mode | Effect |
|---|---|
off |
Normal forum |
banner |
Notice banner only |
read_only |
Browse OK, posting blocked for non-admins |
closed |
Maintenance page for everyone except admins |
FLARUM_MAINTENANCE_MODE=closedOr set the mode under Admin → Extensions → Maintenance.
Delete users (preservemygames-delete-users)
Admins can permanently delete accounts from the admin users page (row action and bulk select) or the user editor. Content is soft-deleted first.
Bundled as flarum-backup in the image. Source is in flarum-backup-cli/.
docker compose exec flarum flarum-backup export -o /backups/forum.tar.gz
docker compose exec -T flarum flarum-backup restore -i /backups/forum.tar.gz --forceOfficial MediaWiki image, rootless wrapper, MariaDB backend.
MEDIAWIKI_SITE_NAME=PreserveMyGames Wiki
MEDIAWIKI_ADMIN_EMAIL=admin@example.com
MEDIAWIKI_ADMIN_PASSWORD=... # or Coolify SERVICE_PASSWORD_MEDIAWIKIADMINCoolify also provides SERVICE_PASSWORD_MEDIAWIKIDB and SERVICE_PASSWORD_MEDIAWIKIROOT.
Optional logo:
MEDIAWIKI_LOGO_URL=https://preservemygames.org/static/img/logo.svgLocalSettings.php and uploads live in the mediawiki_persist volume. Public URL :8080 is stripped automatically. Override with MEDIAWIKI_SITE_SERVER if needed.
Rootless copyparty file browser.
COPYPARTY_ADMIN_PASSWORD=... # or Coolify SERVICE_PASSWORD_COPYPARTYADMINPublic files go in the public folder at the site root. Uploads need admin login at /manage/.
Optional:
COPYPARTY_SITE_NAME=PreserveMyGames FilesTo refresh config defaults, delete copyparty.conf from the config volume and redeploy.
Official rootless Forgejo image with a small proxy/branding wrapper.
FORGEJO_DB_PASSWORD=... # or Coolify SERVICE_PASSWORD_FORGEJODBFinish setup in the web installer.
FORGEJO_APP_NAME=PreserveMyGames Git
FORGEJO_APP_SLOGAN=optional subtitle
FORGEJO_LOGO_URL=https://preservemygames.org/static/img/logo.svg
FORGEJO_FAVICON_URL=
FORGEJO_DEFAULT_THEME=forgejo-auto
FORGEJO_THEMES=forgejo-auto,forgejo-light,forgejo-dark
FORGEJO_CUSTOM_CSS_URL=Set FORGEJO_LOGO_URL=none for stock Forgejo branding. Logo and CSS are fetched into the data volume on each start.
Expose port 2222 if you want git@ clone URLs.
Forgejo does not support ALTCHA. Options:
# Built-in image captcha
FORGEJO_ENABLE_IMAGE_CAPTCHA=trueOr mCaptcha (proof-of-work):
docker compose -f docker-compose.yml -f docker-compose.captcha.yml up -dThen set FORGEJO_MCAPTCHA_URL, FORGEJO_MCAPTCHA_SITEKEY, and FORGEJO_MCAPTCHA_SECRET.
Forgejo and BugPin run as UID 1000. The other stacks use 10001.
Rootless cgit with nginx, fcgiwrap, git smart HTTP, and optional Git SSH.
Point Coolify at port 8080. Publish TCP 2222 for Git SSH. Bare repos live under /repos in the cgit_repos volume.
docker compose exec cgit entrypoint.sh init-repo myproject "My project"
git clone https://your-host/myproject.gitCGIT_SSH_AUTHORIZED_KEYS="ssh-ed25519 AAAA... user@host"
# or write keys to cfg volume: ssh/authorized_keys
CGIT_SSH_HOST=git.example.com
CGIT_SSH_ALLOW_PUSH=falsegit clone ssh://git@your-host:2222/myproject.gitHost keys are generated once into the cfg volume.
Browse and clone/fetch are enabled. HTTP push is off. Optional site-wide basic auth:
CGIT_AUTH_USER=reader
CGIT_AUTH_PASSWORD=...Optional index text:
CGIT_SITE_TITLE=PreserveMyGames Git
CGIT_ROOT_DESC=Public repositoriesDelete cgitrc from the cfg volume and redeploy to regenerate defaults.
Rootless wrapper around BugPin with a read-only rootfs.
- Log in with
admin@example.com/changeme123 - Change the password under Users
- Set the public App URL under Settings → General
- Enable Enforce HTTPS under Security once the proxy sends
X-Forwarded-Proto
Create a project, copy the API key, and embed the widget from your BugPin host. Restrict allowed domains per project for production.
Data (SQLite, session secret, screenshots, branding) lives in bugpin_data under /data.
BugPin runs as UID 1000 (same as Forgejo).
- Base images pinned by digest
- GitHub Actions pinned to commit SHAs
- CI uses
pull_requestwith read-only permissions - Publish only runs on
PreserveMyGames/extravia thepublishenvironment
Create a GitHub Environment named publish with required reviewers before the first release.