Operations

Deployment and recovery

Run the production or staging stack, monitor health, and recover AlphaLedger safely.

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.4
  • migrate: applies the immutable baseline and forward migrations, then exits
  • web: PHP/Apache application
  • cron: durable PA delivery and reconciliation daemon

Required values are written directly in docker-compose.yml as obvious placeholders:

  • APP_URL: public application URL
  • MYSQL_PASSWORD: MySQL application-user password
  • MYSQL_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

  1. Stop web and cron.
  2. Extract database.sql.gz and encryption_key from the selected archive.
  3. Restore the SQL into a clean AlphaLedger database.
  4. Place the key at /var/www/data/.encryption_key with mode 0600.
  5. Start migrate, then web and cron.
  6. Verify /readyz, login, a report, and PA connection status.