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.
One-command installer (get-trimus.sh) — recommended¶
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) — orscripts/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>.pkgfirst. 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, andtrimus-seedto~/.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/healthand 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.
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:
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:
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:
ghif installed andgh auth statussucceeds.GITHUB_TOKENenv 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_URLminimum). See environment.md. - Run the server. Migrations apply automatically on startup; no
separate
trimus-seedstep 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:
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:
make deploy chains:
build-release— compilestrimus-{server,worker,seed,cli}with the same-ldflagsGoReleaser uses (-X main.version,-X main.commit,-X main.date) and-s -wto strip the symbol table.CGO_ENABLED=0produces statically linked binaries so they don't pick up libc surprises across hosts. Version is derived fromgit describe --tags --exact-match HEAD; on an untagged commit you getdev.install— atomically swaps eachtrimus-*binary in$(INSTALL_PREFIX)(default/usr/local/bin). The pattern iscp → mvon the same filesystem, so the directory entry updates to a new inode while the running daemon keeps its open inode. A plaincpto the running binary path fails withETXTBSY("Text file busy").systemctl restart $(SERVICE_NAME)(defaulttrimus), waits 3s, then tailsjournalctlfor 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 defaulttrimus-serverruns 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:
- 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_PASSWORDbefore first run to provision a specific account (the server auto-seeds when no users exist). - Create a company. From
/companies→ + New Company (a blank company), Create from template (a pre-wired industry org from the/get-startedcatalog, #368), or import a pre-built bundle via/portability/import(instance admin). Imported bundles can carry per-company LLM provider configuration (see providers.md). - Set the encryption key. Only required when you didn't use the
installer. Without
TRIMUS_ENCRYPTION_KEYthe 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. - Set the session secret. Only required when you didn't use the
installer. Without
TRIMUS_SESSION_SECRET, sessions invalidate on every restart. - Add a provider. Sidebar → Providers, or import a bundle that declares its own providers. See providers.md.
- Hire your first agent. See ../board/hiring-an-agent.md.
Where to next¶
- environment.md — full env-var reference.
- database.md — postgres details.
- security.md — TLS, OAuth, rate limits before you expose this to the public internet.