Docker Deployment
This page covers production deployment concerns for AsterYggdrasil as a Minecraft skin site and Yggdrasil authentication server.
If you have not mapped the launch checklist yet, start with Deployment Overview. This page focuses on what to mount and configure for Docker.
Persistent Data
Runtime state inside the container should be mounted at /data. Persist at least:
config.toml- SQLite database, or external database connection config.
- Local object storage directory.
- Runtime temp and log directories if enabled.
Example static config:
[server]
host = "0.0.0.0"
port = 3000
start_mode = "primary"
temp_dir = ".tmp"
[database]
url = "sqlite://asteryggdrasil.db?mode=rwc"
[object_storage]
backend = "local"
local_root = "storage"
[cache]
enabled = true
backend = "memory"If config.toml lives at /data/config.toml, local_root = "storage" resolves to /data/storage. Textures and uploaded user avatars are written through this object storage directory.
If you use S3 or MinIO, objects are not written to /data/storage, but the database and config.toml still must be persisted. Example:
[object_storage]
backend = "s3"
[object_storage.s3]
endpoint = "https://s3.example.com"
region = "auto"
bucket = "asteryggdrasil"
base_path = "production"
access_key_id = "..."
secret_access_key = "..."
force_path_style = falseTextures and uploaded avatars use the same object storage backend. S3/MinIO uploads are performed by server-side streaming and do not require browser presigned uploads.
Reverse Proxy
Production deployments usually expose HTTPS through Nginx, Caddy, or Traefik. Make sure the external path matches runtime config:
https://skin.example.com/api/yggdrasilmatching runtime config:
yggdrasil_public_base_url = ["https://skin.example.com/api/yggdrasil"]
yggdrasil_skin_domains = ["skin.example.com"]authlib-injector verifies that texture URL hosts are covered by skinDomains. If public base URL and skinDomains do not match, launchers or servers may reject textures.
If the S3 bucket or a frontend CDN is publicly readable, you can additionally configure runtime yggdrasil_texture_public_base_url so uploaded texture URLs point directly at object storage/CDN. In that mode, the bucket/CDN must allow anonymous GET/HEAD reads from the site origin; default skins still use the Yggdrasil API.
ALI
The site homepage returns:
X-Authlib-Injector-API-Location: /api/yggdrasil/Do not strip this response header in the reverse proxy. It lets users enter the site root in launchers and have the launcher discover the Yggdrasil API automatically.
trusted proxies
When running behind a reverse proxy, configure trusted proxies so the service does not trust forged forwarded headers from clients.
[network_trust]
trusted_proxies = ["127.0.0.1"]Use the real source address or CIDR used between the proxy and the application.
Multiple Instances
Periodic maintenance tasks should run on only one primary node:
[server]
start_mode = "primary"Other instances should use follower mode to avoid duplicate global cleanup, mail outbox, and background task dispatch work.
Signing Key
Startup ensures the Yggdrasil signing private key and public key exist. In production, rotate keys through the admin config action instead of editing private key values directly:
POST /api/v1/admin/config/yggdrasil/actionAfter rotation, clients and servers may need to fetch metadata again.
Backup
Back up at least:
- Database.
/data/storage.data/config.tomlor equivalent secret/config records.
Database and object storage must be backed up as a set. Restoring only one side can produce missing-object or orphan-object reports from the storage consistency check.