v1.0.1. Choose a release only after its GitHub release and both public images have been published.
1. Download the installation files
Choose a version from Mill releases. Downloaddocker-compose.yml and .env.example from that release’s source tag into an empty directory. You can use your browser or these commands:
.env automatically; --env-file /path/to/your.env is available if you store it elsewhere. Image versions are already set in the release’s Compose file.
2. Set three environment values
Edit.env:
localhost inside that container refers to the container itself.
Generate MILL_SECRET with a password manager or openssl rand -hex 32. Keep it private and preserve it across upgrades and restores: Mill uses it to protect authentication data. Leave MILL_BASE_URL as shown for local use, or use your final HTTPS origin for remote access.
3. Start Mill
Optional: run PostgreSQL with Compose
If you do not have a database, downloaddocker-compose.postgres.yml from the same release:
openssl rand -hex 32. Add POSTGRES_PASSWORD to .env and use the same value in DATABASE_URL:
MILL_SECRET and MILL_BASE_URL values. Start all three services with the optional overlay:
-f options for subsequent commands on this installation. The overlay creates persistent PostgreSQL storage, waits for database readiness before starting the API, and publishes no database port. Use --project-name mill consistently so Compose reuses the same volume. down stops the containers and leaves the volume intact; down --volumes permanently removes it.
Host Mill with HTTPS
SetMILL_BASE_URL to the exact browser origin, for example https://tasks.example.com, and recreate the services using your installation’s Compose command. The default UI port binds to 127.0.0.1:4321, ready for a reverse proxy on the same host. For example, a Caddy configuration can use:
web:4322 instead. Preserve the public host, support streaming HTTP at /mcp, and do not cache /api, /mcp or OAuth responses. Keep the database and API private. To change the local port or bind address, edit the web service’s ports entry in Compose and keep MILL_BASE_URL aligned with the browser URL.
The public origin is used for cookies, passkeys, links and OAuth. Set it correctly before people register passkeys; changing it later requires a recovery plan. Remote access requires HTTPS. Local HTTP OAuth works automatically only when MILL_BASE_URL is an exact loopback origin; no extra switch is needed.
Use a deployment platform
Images read runtime environment variables directly. A platform or secret manager can supply them without an.env file:
Use your PostgreSQL instance’s connection URL as
DATABASE_URL. Keep the API and UI at the same release version, and route the public HTTPS hostname to the UI. Optional email settings are covered in configuration.
Optional: pin images by digest
If your deployment policy requires immutable references, downloadmill-images.json from the matching GitHub release. Replace the two services’ image fields in Compose with its images.api and images.web values:
Protect your installation
Take a first backup, keep an encrypted copy of the environment settings, and preserve the originalMILL_SECRET. Before changing versions, read upgrades. Troubleshooting covers startup, authentication and connectivity issues. Source builds are for contributors; see package registry setup.
In the app
Team setup
- Desktop
- Mobile
