Skip to content

Installing trimus-server

Pick one. The one-line installer is the quickest — everything below it is the same install done more by hand.

Method When to use
One-command installer (get-trimus.sh, recommended) Fastest path: one line detects your platform, downloads + checksum-verifies the release, and runs the archive installer.
macOS installer (.pkg, double-click) macOS localhost demo / evaluation: a double-click installer that runs the same install.sh for you and drops a Desktop uninstaller. Needs Docker Desktop.
Release archive installer The same install done by hand: download the archive, then run its install.sh. Use when you want to see each step.
Binary-only install You want just the binaries on PATH and will wire up postgres, env, and service registration yourself.
Docker Compose You want postgres + Trimus + persistent volumes managed together as containers. Note: breaks claude_local / codex_local.
From source You're modifying Trimus, or you want to pin a non-released revision.

They all end with the same thing: a trimus-server process listening on a port (default 3100), talking to postgres, and ready for you to sign in.

get-trimus.sh automates the release-archive method below: it detects your OS/arch, downloads the matching archive, verifies its SHA-256 against the published checksums.txt, extracts it, and runs the bundled install.sh.

# Once the repo/release is public — anonymous, no auth:
curl -fsSL https://raw.githubusercontent.com/trimus-ai/trimus/main/scripts/get-trimus.sh | sh

# While the repo is private, authenticate one of two ways:

# a) GitHub CLI (cleanest — gh handles the token):
gh api /repos/trimus-ai/trimus/contents/scripts/get-trimus.sh \
  -H 'Accept: application/vnd.github.raw' | sh

# b) a token, no gh (the private asset lookup also needs jq):
export GITHUB_TOKEN=ghp_xxx
curl -fsSL -H "Authorization: Bearer $GITHUB_TOKEN" -H 'Accept: application/vnd.github.raw' \
  https://api.github.com/repos/trimus-ai/trimus/contents/scripts/get-trimus.sh | sh

Pass installer flags after sh -s --, and pin a release with TRIMUS_VERSION:

# system-wide install on a custom DB port:
gh api /repos/trimus-ai/trimus/contents/scripts/get-trimus.sh \
  -H 'Accept: application/vnd.github.raw' | sh -s -- --system --db-port 5544

# pin a specific release instead of "latest":
gh api /repos/trimus-ai/trimus/contents/scripts/get-trimus.sh \
  -H 'Accept: application/vnd.github.raw' | TRIMUS_VERSION=v4.12.0 sh

macOS installer (.pkg)

For a localhost demo or evaluation on a Mac, a double-click .pkg wraps the same install.sh: it generates secrets, brings up the Dockerized Postgres, starts the launchd trimus-server agent, runs migrations + seeds the admin, and drops a Trimus — open me.txt (URL + admin login) and an Uninstall Trimus.command on your Desktop. This is a temporary, single-user demo path — not a production deployment (see TLS & deployment).

  • Prerequisite: Docker Desktop installed and running (Trimus's Postgres runs in it). The installer stops with a clear message if it isn't.
  • Build it: make macos-pkg VERSION=4.1.0 (universal, unsigned) — or scripts/release/macos-pkg/build-pkg.sh --bin-dir <darwin release bins>.
  • Install it: the package is unsigned (v1), so Gatekeeper blocks a plain double-click — right-click → Open, or xattr -dr com.apple.quarantine Trimus-<version>.pkg first. You'll be asked for your password (the install needs admin rights).
  • Open: http://localhost:3100.
  • Uninstall (leaves the machine as found): double-click Uninstall Trimus.command, or run ~/.config/trimus/uninstall.sh --purge.

Full details — including the opt-in remote worker and Developer ID signing — are in scripts/release/macos-pkg/README.md.

Release archive installer (manual)

Every tagged release publishes platform archives containing the binaries, a Postgres‑only docker-compose.yml (ships pgvector/pgvector:pg16), service unit templates, and a one‑shot install.sh that wires everything up.

# Linux / amd64, v3.0.0 example — swap for your platform + release.
curl -L https://github.com/trimus-ai/trimus/releases/download/v3.0.0/trimus_3.0.0_linux_amd64.tar.gz | tar -xz
cd trimus_3.0.0_linux_amd64
./install.sh

The installer:

  • Generates a per-host Postgres password, session secret, and AES-256 encryption key. Each lives in ~/.config/trimus/ (chmod 600).
  • Prompts for an admin email and password (or auto-generates the password with --noninteractive).
  • Installs trimus-server, trimus-worker, and trimus-seed to ~/.local/bin.
  • Starts Postgres in Docker on 127.0.0.1:5432 (data persisted at ~/.trimus/pgdata).
  • Registers a systemd user unit (Linux) or launchd LaunchAgent (macOS) and starts it.
  • Waits for /api/health and prints the URL + admin credentials.

Two install modes

User-level (default) — no sudo, paths under $HOME, service runs as the invoking user. This is the mode you want if any agent uses the claude_local or codex_local adapters: those CLIs read OAuth state from ~/.claude and ~/.codex, which a system service running as a dedicated trimus user cannot reach.

./install.sh

Auto-start at boot without a login session requires sudo loginctl enable-linger $USER on Linux (one-time setup). On macOS, user LaunchAgents auto-start at login.

System-wide — paths under /etc/trimus, /var/lib/trimus, /usr/local/bin. Service runs as a dedicated trimus (Linux) or _trimus (macOS) user with hardening (ProtectHome=read-only, etc.). Auto-starts at boot via normal systemd / launchd semantics. Cannot use local-CLI adapters — choose this mode only when every agent uses cloud llm adapters. Running with sudo selects this mode automatically:

sudo ./install.sh

Useful flags

--system / --user     Force the mode (otherwise auto-detected: sudo →
                      system, normal user → user).
--db-url URL          Use an existing Postgres instead of the bundled one
                      (e.g. postgres://staple:pw@host:6543/staple). Implies
                      --skip-docker.
--db-port PORT        Host port for the bundled Postgres (default 5432).
--skip-docker         Don't start the bundled Postgres. Combine with
                      --db-url, or set DATABASE_URL by hand afterward.
--noninteractive      No prompts. Defaults email to admin@localhost,
                      auto-generates password if --admin-password not given.
--admin-email EMAIL   Pre-fill the admin email.
--admin-password PW   Pre-fill the admin password.
-h, --help            Show full help.

Idempotent re-runs

The installer is safe to re-run. On a re-run it:

  • Reuses existing secrets (so sessions don't invalidate and the secrets table stays decryptable).
  • Re-renders the service unit (so path changes take effect on systemctl restart).
  • Re-installs the binaries.

A fresh start is ./uninstall.sh --purge (full wipe) followed by ./install.sh.

Binary-only install

For development and partial installs (you'll wire up your own postgres, env, and service-manager registration), the repo includes a small fetcher at scripts/install.sh that downloads binaries from GitHub Releases without running the full setup:

./scripts/install.sh                # latest release
./scripts/install.sh v3.0.0         # a specific tag

The fetcher downloads trimus-server, trimus-worker, and trimus-seed for your platform and drops them in /usr/local/bin (or $HOME/.local/bin if that's not writable).

Auth: the fetcher needs GitHub credentials because the repo is private. It tries:

  1. gh if installed and gh auth status succeeds.
  2. GITHUB_TOKEN env var with curl.

If neither works it errors with instructions.

After the fetcher you still need to:

  • Stand up a reachable postgres ≥ 16 with pgvector (see database.md).
  • Set the env vars (DATABASE_URL minimum). See environment.md.
  • Run the server. Migrations apply automatically on startup; no separate trimus-seed step is required for migrations.
export DATABASE_URL='postgres://trimus:trimus@localhost:5432/trimus_dev?sslmode=disable'
trimus-server                # migrations run on first start

That's it. Open http://localhost:3100. (Most operators will prefer the full release-archive installer above — it handles the env file, secrets, Postgres, and service registration in one go.)

Docker Compose

The repo ships docker-compose.yml with a postgres-only service suited for local development. Trimus itself is not in the compose file by default — typical pattern is to run it on the host against the compose-managed postgres.

If you want a one-command "everything in containers" setup, add a service for trimus-server using the shipped Dockerfile:

# docker-compose.override.yml (example)
services:
  trimus:
    build: .
    environment:
      DATABASE_URL: postgres://trimus:trimus@postgres:5432/trimus_dev?sslmode=disable
      PORT: 3100
      TRIMUS_HOME: /data/home
      TRIMUS_STORAGE_DIR: /data/storage
      TRIMUS_PUBLIC_URL: http://localhost:3100
    ports:
      - "3100:3100"
    volumes:
      - trimus_data:/data
    depends_on:
      postgres:
        condition: service_healthy

volumes:
  trimus_data:

Then:

docker compose up -d                    # start postgres + trimus

Migrations apply automatically when trimus-server boots — no separate seed step is required. The shipped Dockerfile already configures trimus as the runtime user and /data as the persisted volume mount point.

From source

For development or pinned non-tag builds:

git clone https://github.com/trimus-ai/trimus.git
cd trimus
make devel-up        # starts postgres in docker
make migrate         # runs migrations
make seed            # creates default user + sample data
make run             # builds and runs trimus-server on :3100

Required: Go 1.26+, Docker (for postgres), make.

The full target list:

make build           # compiles server, worker, seed, trimus-cli into ./bin/
make test            # unit tests against the dev postgres
make test-integration   # testcontainers-based integration tests
make smoke           # runs the smoke script against a running server

Updating a running deploy in place

When you have the repo checked out on a host already running trimus-server under systemd (the typical pattern for --system installs), roll a new tag onto it without going through the release-archive installer:

git fetch --tags
git checkout v3.0.0
make deploy

make deploy chains:

  1. build-release — compiles trimus-{server,worker,seed,cli} with the same -ldflags GoReleaser uses (-X main.version, -X main.commit, -X main.date) and -s -w to strip the symbol table. CGO_ENABLED=0 produces statically linked binaries so they don't pick up libc surprises across hosts. Version is derived from git describe --tags --exact-match HEAD; on an untagged commit you get dev.
  2. install — atomically swaps each trimus-* binary in $(INSTALL_PREFIX) (default /usr/local/bin). The pattern is cp → mv on the same filesystem, so the directory entry updates to a new inode while the running daemon keeps its open inode. A plain cp to the running binary path fails with ETXTBSY ("Text file busy").
  3. systemctl restart $(SERVICE_NAME) (default trimus), waits 3s, then tails journalctl for the "server starting" JSON line and prints it. If no such line appears the target exits non-zero.

Overrides for non-default layouts:

# User-level systemd unit installed under ~/.local/bin
make deploy INSTALL_PREFIX=$HOME/.local/bin SERVICE_NAME=trimus SUDO=

# Multiple services on one host
make deploy SERVICE_NAME=trimus-prod

make install runs steps 1–2 only — useful on macOS where there is no systemctl and you want to refresh binaries before restarting the LaunchAgent by hand.

make build (no ldflags, fast, dev-friendly) still works for plain local hacking — build-release only kicks in when you ask for it.

This path is intentionally simpler than make dist (which wraps goreleaser release --clean to produce signed tarballs published to GitHub Releases). Use dist for new-host installs; use deploy for in-place updates.

What you get after install

  • trimus-server — the API + UI process. This is what users hit.
  • trimus-worker (optional) — a separate process that claims heartbeat tasks. The default trimus-server runs the worker pool in-process; you only need this binary if you're scaling out workers separately. See remote-workers.md.
  • trimus-seed — one-shot migration runner + dev seeder. Safe to run repeatedly; it's idempotent.

First-run checklist

If you used the release-archive installer (./install.sh) — steps 3 and 4 below are already done for you. The installer generated the encryption key and session secret automatically and wrote them into ~/.config/trimus/server.env. Skip to step 1.

After the server is running:

  1. Sign in. The installer's auto-seed creates a default user from the admin email/password you provided at install time. For binary-only / source installs, set TRIMUS_ADMIN_EMAIL / TRIMUS_ADMIN_PASSWORD before first run to provision a specific account (the server auto-seeds when no users exist).
  2. Create a company. From /companies+ New Company (a blank company), Create from template (a pre-wired industry org from the /get-started catalog, #368), or import a pre-built bundle via /portability/import (instance admin). Imported bundles can carry per-company LLM provider configuration (see providers.md).
  3. Set the encryption key. Only required when you didn't use the installer. Without TRIMUS_ENCRYPTION_KEY the encryption vault is not initialised and every encrypted‑write endpoint returns 503 — you cannot create secrets, provider keys, OAuth tokens, or signed triggers (SEC‑010). There is no plaintext fallback. See secrets-and-encryption.md.
  4. Set the session secret. Only required when you didn't use the installer. Without TRIMUS_SESSION_SECRET, sessions invalidate on every restart.
  5. Add a provider. Sidebar → Providers, or import a bundle that declares its own providers. See providers.md.
  6. Hire your first agent. See ../board/hiring-an-agent.md.

Where to next