Skip to main content
Install Mill with Docker Compose. These steps include PostgreSQL; you can also use an existing database.

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, use http://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:
Choose another published tag to install a different version. The Compose file already selects matching public API and UI images; no GitHub login, registry token, Node.js or source build is needed.

2. Set your domains and secrets

Run this command twice to generate separate values for the application secret and database password:
Open .env and set these values:
Use the same generated database password in 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

Compose pulls the images and starts PostgreSQL, API and UI. The API applies its packaged database migrations automatically. PostgreSQL data lives in a persistent Docker volume and has no published port. Use the same project name and both -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:
Forward the entire API origin, including /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 labelled Mill installation setup secret in the API startup log:
Open your Mill URL, enter that setup secret, and create your team and first administrator. The setup secret is separate from 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:
Then verify sign-in and task creation through your public HTTPS URLs. Continue with your first board and task, Configuration for email or attachments, and Backup and recovery.

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 in DATABASE_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:
Continue with domain routing and team setup above. Use the same command without the overlay when managing this installation.

Pin images by digest

For immutable image references, use the API and UI image digests published with your chosen release. Replace both Compose image 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.