Container architecture
Production Compose exposes port 1630; staging exposes 1631. Both use separate named volumes for MySQL, encrypted application data, and backup archives.
Services:
db: MySQL 8.4migrate: applies the immutable baseline and forward migrations, then exitsweb: PHP/Apache applicationcron: durable PA delivery and reconciliation daemon
Required values are written directly in docker-compose.yml as obvious placeholders:
APP_URL: public application URLMYSQL_PASSWORD: MySQL application-user passwordMYSQL_ROOT_PASSWORD: MySQL administrative password used by verified backups
Search for changeme and replace every match before starting. No .env file is required. Optional operational settings include AL_PORT (default 1630), SESSION_IDLE_SECONDS (default 900), and AL_SYNC_INTERVAL_SECONDS (default 30).
The default published port listens only on host loopback and uses internal container port 8080. Place web behind HTTPS and set APP_URL to the public https:// URL. With COOKIE_SECURE=auto, AlphaLedger enables Secure cookies and HSTS from that URL and refuses non-loopback HTTP configurations. Never expose MySQL publicly.
Both application images run as the unprivileged www-data user. Named volumes are initialized with that ownership; bind-mounted data or backup directories must also be writable by UID/GID 33.
Database authentication after changing passwords
The official MySQL image applies MYSQL_PASSWORD and MYSQL_ROOT_PASSWORD only when its data directory is initialized. Editing those values later does not alter accounts stored in an existing alphaledger_db volume.
For a disposable test installation, reset the stack and its data with:
docker compose down -v
docker compose up -d --build
This permanently removes the database, time records, application encryption key, and backups stored in Compose volumes. For an installation containing real data, do not remove the volumes—restore the original passwords or perform a controlled MySQL password rotation instead.
Prebuilt container images
The publishing workflow produces multi-architecture images in GitHub Container Registry:
docker pull ghcr.io/ledgetoptechnologies/alpha-ledger:latest
docker pull ghcr.io/ledgetoptechnologies/alpha-ledger:cron-latest
Tags created from main include latest, cron-latest, and immutable sha-* variants. A tag such as v2.1.0 additionally creates semantic-version tags for both targets.
GitHub may create the package as private on its first publication. To support anonymous pulls, open the package settings in the ledgetoptechnologies organization and change its visibility to Public. Private-package users can authenticate with a token that has read:packages:
echo "$GHCR_TOKEN" | docker login ghcr.io -u USERNAME --password-stdin
Backup
Run a verified backup with docker compose exec web alphaledger-backup. The script takes a transactionally consistent dump, restores it into a temporary database, runs mysqlcheck, and archives the dump with .encryption_key.
The backup contains the database and its encryption key. Treat the complete archive as a production secret and restrict access accordingly.
Restore
- Stop
webandcron. - Extract
database.sql.gzandencryption_keyfrom the selected archive. - Restore the SQL into a clean AlphaLedger database.
- Place the key at
/var/www/data/.encryption_keywith mode0600. - Start
migrate, thenwebandcron. - Verify
/readyz, login, a report, and PA connection status.