Install with the bootstrap script
Deploy Metis Suite on an Ubuntu server with one script, then find the setup code for the first account.
In this tutorial you install a complete Metis Suite instance on a fresh Ubuntu server. The bootstrap script installs Docker, generates every secret, picks the newest release and starts the services. By the end, the app is running and you have the setup code that creates the first account.
The stack the script starts has these services:
- sqld: the database server. It holds the app database and the AI memory database, in the
metis_sqldDocker volume. - preflight: a one-time check that runs before the app starts on every deploy. It prepares the database and checks your settings.
- app: Metis Suite itself.
- updater: applies upgrades and rollbacks that you start from the owner dashboard.
- caddy: serves the app over HTTPS. It runs only once you set a domain.
Everything is installed in /opt/metis-suite. Your settings go in /opt/metis-suite/.env, which only root can read.
Decide on the owner email
The owner is the one account that can open the owner dashboard, where you change settings and apply updates. Pick the email address you will sign in with.
If you leave the owner email empty, the first account can use any email
address, and the owner dashboard is turned off for everyone. You can set
it later, but that needs an edit to .env and a restart.
Download the script
Sign in to the server and download the script:
curl -fsSLO https://raw.githubusercontent.com/trymetis/metis/main/bootstrap.shRun it
Run the script in interactive mode. It asks for anything you have not exported as an environment variable:
sudo -E bash bootstrap.sh --interactivePress Enter to accept a default. The script asks for:
- METIS_DOMAIN: your domain. Leave it blank if DNS does not point at the server yet; you can add it later.
- BETTER_AUTH_URL: the address people use to reach the app. It
defaults to
https://<your domain>, or tohttp://localhost:3000without a domain. - BETTER_AUTH_SECRET and the other secrets: leave them blank and the script generates them.
- METIS_DB_DRIVER:
sqld(the default) runs the bundled database server. Choosetursoonly if your databases are hosted on Turso (see below). - DATABASE_URL and MASTRA_DATABASE_URL: press Enter to use the bundled database server.
- METIS_SETUP_CODE: leave it blank to generate one.
- METIS_OWNER_EMAIL: the owner email from step 1.
The script also generates METIS_ENCRYPTION_KEY, which protects every
password and token users store when they connect accounts.
To run without prompts, for example from cloud-init, export the values
you want first and run sudo -E bash bootstrap.sh. Anything you do not
export is generated or left at its default.
Back up the encryption key
Copy METIS_ENCRYPTION_KEY from /opt/metis-suite/.env to a safe place,
such as a password manager.
Read the summary
When the stack is up, the script prints:
- The address the app runs at.
- Two commands for later: one shows the status of the services, the other follows the app’s log.
- Without a domain, an SSH tunnel command for reaching the app.
- Create the first account at: the setup page address.
- Setup code: the code that creates the first account. It is also
kept in
/opt/metis-suite/.env.
The status and log commands are:
docker compose --project-directory /opt/metis-suite ps
docker compose --project-directory /opt/metis-suite logs -f appOpen the app
With a domain, open https://<your domain>/setup.
Without a domain, the app listens only on the server itself. Open a tunnel from your own computer:
ssh -L 3000:127.0.0.1:3000 <user>@<your server>Then open http://localhost:3000/setup in your browser. Continue with
First run.
Optional settings for the script
Export any of these before you run the script:
| Variable | What it does | Default |
|---|---|---|
METIS_VERSION |
Installs a specific release, such as 1.2.3. A leading v is ignored. |
The newest release |
INSTALL_DIR |
Where the stack and .env are installed. |
/opt/metis-suite |
APP_PORT |
The port the app listens on, on 127.0.0.1. If you change it, also add APP_PORT=<port> to .env so later docker compose commands keep it. |
3000 |
COMPOSE_REF |
The branch or tag the Compose file is downloaded from. | main |
COMPOSE_URL |
A full URL to download the Compose file from instead. | |
APP_IMAGE, PREFLIGHT_IMAGE, WORKER_IMAGE, UPDATER_IMAGE |
Use these exact images instead of a release. |
Provider, AI, mail, background work, sign-up and legal variables can be exported too. The script copies each one you export into .env, and the instance uses it as the starting value for that setting. After the first start, you change those settings in the owner dashboard. See How configuration works.
Use Turso instead of the bundled database
To keep both databases on Turso, export these before you run the script:
export METIS_DB_DRIVER=turso
export DATABASE_URL=libsql://<app database>.turso.io
export DATABASE_AUTH_TOKEN=<token>
export MASTRA_DATABASE_URL=libsql://<ai memory database>.turso.io
export MASTRA_DATABASE_AUTH_TOKEN=<token>
The bundled database server then does not start. Both databases must use the same driver.
Run the script again
You can run the script again at any time, for example to pick up a new Compose file:
- An existing
.envis kept. In interactive mode the script asks “Re-configure .env? (y/N)” first. - Every run pins the release again: the newest one, or the one in
METIS_VERSION. So running the script also upgrades the app.
Troubleshooting the install
| Message | What to do |
|---|---|
| “Run as root (or with sudo)” | Run the script with sudo -E bash bootstrap.sh. |
| “openssl could not generate an Ed25519 key for sqld (OpenSSL 3 is required)” | Install OpenSSL 3, or use a newer Ubuntu release. |
| “Could not download” the Compose file | Check that the server can reach raw.githubusercontent.com, or point COMPOSE_URL at a copy of the Compose file. |
| “sqld did not become healthy” | Look at the database server’s log: docker compose --project-directory /opt/metis-suite logs sqld. |
| “The stack did not start” | Look at the preflight log: docker compose --project-directory /opt/metis-suite logs preflight. It names the setting that is wrong. |