---
title: Install with Docker Compose
description: Run the Metis Suite Compose stack yourself, with databases you host elsewhere.
---

The bootstrap script is the simplest way to install. Use this page if you want to manage the Compose stack yourself, on any server with Docker and Docker Compose v2.

This page assumes your two databases are hosted outside the stack, on [Turso](https://turso.tech) or on a libSQL server (sqld) you already run. The bundled database server needs its two databases created before the first start, and the bootstrap script does that for you. If you want the bundled database server, use [the bootstrap script](/self-hosting/install/install-with-bootstrap).

1. **Create the install folder**

    Use `/opt/metis-suite`. The updater service expects the stack there unless
    you tell it otherwise.

    ```bash
    sudo mkdir -p /opt/metis-suite
    cd /opt/metis-suite
    ```

2. **Download the Compose file**

    ```bash
    sudo curl -fsSL https://raw.githubusercontent.com/trymetis/metis/main/compose.yml -o compose.yml
    ```

3. **Generate the secrets**

    Run this once for each secret you need: `BETTER_AUTH_SECRET`,
    `METIS_ENCRYPTION_KEY` and `METIS_DRIVE_RELAY_SECRET`.

    ```bash
    openssl rand -base64 32
    ```

    For the setup code, use any random value of at least 8 characters.

4. **Write the .env file**

    Create `/opt/metis-suite/.env`. Write each value as it is, without quotes.

    ```bash
    BETTER_AUTH_URL=http://localhost:3000
    BETTER_AUTH_SECRET=<secret>
    METIS_ENCRYPTION_KEY=<secret>
    METIS_DRIVE_RELAY_SECRET=<secret>
    METIS_DB_DRIVER=turso
    DATABASE_URL=libsql://<app database>.turso.io
    DATABASE_AUTH_TOKEN=<token>
    MASTRA_DATABASE_URL=libsql://<ai memory database>.turso.io
    MASTRA_DATABASE_AUTH_TOKEN=<token>
    METIS_SETUP_CODE=<setup code>
    METIS_OWNER_EMAIL=you@example.com
    ```

    For your own sqld server, set `METIS_DB_DRIVER=sqld` and use its
    `https://` addresses instead. `MASTRA_DATABASE_URL` is the AI memory
    database. It must be a separate database on the same driver.

    To install a specific release, add the four image pins, with your
    version in place of `X.Y.Z`:

    ```bash
    APP_IMAGE=ghcr.io/trymetis/metis:X.Y.Z
    PREFLIGHT_IMAGE=ghcr.io/trymetis/metis:X.Y.Z-preflight
    WORKER_IMAGE=ghcr.io/trymetis/metis:X.Y.Z-worker
    UPDATER_IMAGE=ghcr.io/trymetis/metis:X.Y.Z-updater
    ```

    Without them, the stack uses the newest images, and the dashboard shows
    the version as unknown until your first upgrade. Then protect the file:

    ```bash
    sudo chmod 600 /opt/metis-suite/.env
    ```

    :::warning[Back up the encryption key]
    Copy `METIS_ENCRYPTION_KEY` to a safe place. Losing it means every user
    has to reconnect every mailbox, calendar and drive.
    :::

5. **Start the stack**

    ```bash
    sudo docker compose --project-directory /opt/metis-suite up -d
    ```

    The preflight service runs first. The app starts only after it finishes
    without errors. If the app does not start, read the preflight log:

    ```bash
    sudo docker compose --project-directory /opt/metis-suite logs preflight
    ```

6. **Serve it on your domain**

    The app listens only on `127.0.0.1:3000`. To serve it over HTTPS, point
    your domain's DNS at the server, then set these two lines in `.env`:

    ```bash
    METIS_DOMAIN=mail.example.com
    BETTER_AUTH_URL=https://mail.example.com
    ```

    Start the stack with the `proxy` profile, which adds Caddy:

    ```bash
    sudo COMPOSE_PROFILES=proxy docker compose --project-directory /opt/metis-suite up -d
    ```

    Caddy gets the certificate on the first request. Ports 80 and 443 must
    be reachable. Then continue with
    [First run](/self-hosting/install/first-run).

See [Environment variables](/self-hosting/reference/environment-variables) for every other value you can put in `.env`.
