Before you start
You need Docker with Compose v2. For remote access, prepare two HTTPS domains under the same site: one for Mill and one for its API. A reverse proxy routes each domain to its container. For a local installation, usehttp://localhost:4322 for the UI and http://localhost:4321 for the API instead.
1. Download the installation files
Create a directory and download all three files from the same published release:2. Set your domains and secrets
Run this command twice to generate separate values for the application secret and database password:.env and set these values:
POSTGRES_PASSWORD and DATABASE_URL. Hexadecimal passwords from the command above need no URL encoding. If you use another password format, percent-encode special characters in the connection URL.
Keep .env private. Preserve MILL_SECRET across upgrades and restores, and store an encrypted copy with your backup records.
3. Start Mill
-f options for subsequent commands. down leaves the database volume intact; down --volumes permanently removes it.
4. Route your domains
For remote access, configure a reverse proxy on the Docker host:
Enable HTTPS for both domains and set their DNS records to your server. For example, with Caddy:
/api, /mcp, /oauth, /.well-known and /health. Preserve streaming responses and avoid caching API, OAuth or MCP responses. The UI’s no-store /runtime-config.js supplies the public API origin to browsers.
Set the final origins before people register passkeys or connect MCP clients. See Configuration before changing an established installation’s URLs.
5. Create your team
Find the line labelledMill installation setup secret in the API startup log:
MILL_SECRET; do not enter the application secret in the form. Keep the setup secret and startup logs private.
There is no default account. The first administrator is email-verified automatically and signed in. Setup closes after the workspace is created; existing installations keep their sign-in flow.
Check readiness on the Docker host:
Choose your database
The steps above use bundled PostgreSQL. To use an existing or managed database, omit the PostgreSQL overlay. Use a dedicated PostgreSQL database reachable from the API container. Put its full connection URL inDATABASE_URL, including any required TLS settings. The database user must be able to create and modify Mill’s tables. localhost inside a container refers to that container, not the Docker host.
Set MILL_SECRET, MILL_WEB_URL and MILL_API_URL as above. Omit POSTGRES_PASSWORD and start without the PostgreSQL overlay:
Pin images by digest
For immutable image references, use the API and UI image digests published with your chosen release. Replace both Composeimage values with those digest-pinned references. Keep the pair from the same release and record them with your installation settings.
Read Upgrades before changing versions. Troubleshooting covers startup, sign-in and connectivity problems; contributors can use the source-build instructions in Package registry setup.