mirror of
https://github.com/multica-ai/multica.git
synced 2026-06-17 11:48:42 +02:00
Adds a value (default true for backward compatibility) that gates the uploads PersistentVolumeClaim, the backend container's volumeMount, and the pod-spec volume. Operators who serve uploads from S3 (S3_BUCKET set) can now set backend.uploads.persistence.enabled=false to drop the PVC entirely, removing the ReadWriteOnce Multi-Attach barrier on the storage side for replicas > 1. Also makes the PVC accessModes configurable (default [ReadWriteOnce]) so operators with a ReadWriteMany-capable StorageClass can share the uploads volume across replicas without object storage. Documentation: values.yaml comments and the SELF_HOSTING.md resource list are updated to describe the new toggle. Refs: https://github.com/multica-ai/multica/issues/3646 Co-authored-by: multica-agent <github@multica.ai>
489 lines
21 KiB
Markdown
489 lines
21 KiB
Markdown
# Self-Hosting Guide
|
|
|
|
Deploy Multica on your own infrastructure in minutes.
|
|
|
|
## Architecture
|
|
|
|
| Component | Description | Technology |
|
|
|-----------|-------------|------------|
|
|
| **Backend** | REST API + WebSocket server | Go (single binary) |
|
|
| **Frontend** | Web application | Next.js 16 |
|
|
| **Database** | Primary data store | PostgreSQL 17 with pgvector |
|
|
|
|
Each user who runs AI agents locally also installs the **`multica` CLI** and runs the **agent daemon** on their own machine.
|
|
|
|
## Quick Install (Recommended)
|
|
|
|
Two commands to set up everything — server, CLI, and configuration:
|
|
|
|
```bash
|
|
# 1. Install CLI + provision the self-host server
|
|
curl -fsSL https://raw.githubusercontent.com/multica-ai/multica/main/scripts/install.sh | bash -s -- --with-server
|
|
|
|
# 2. Configure CLI, authenticate, and start the daemon
|
|
multica setup self-host
|
|
```
|
|
|
|
This installs the `multica` CLI, checks out the latest self-host assets, pulls the official Multica images from GHCR, and configures everything for localhost.
|
|
|
|
Open http://localhost:3000. To log in, configure `RESEND_API_KEY` in `.env` for email-based codes (recommended), or leave Resend unset and copy the generated code from the backend logs. See [Step 2 — Log In](#step-2--log-in) for details.
|
|
|
|
> **Prerequisites:** Docker and Docker Compose must be installed. The script checks for this and provides install links if missing.
|
|
>
|
|
> **CLI only?** If the self-host server is already running and you only need the CLI on a macOS/Linux machine, install it with Homebrew:
|
|
>
|
|
> ```bash
|
|
> brew install multica-ai/tap/multica
|
|
> ```
|
|
|
|
---
|
|
|
|
## Step-by-Step Setup (Alternative)
|
|
|
|
If you prefer to run each step manually:
|
|
|
|
### Step 1 — Start the Server
|
|
|
|
**Prerequisites:** Docker and Docker Compose.
|
|
|
|
```bash
|
|
git clone https://github.com/multica-ai/multica.git
|
|
cd multica
|
|
make selfhost
|
|
```
|
|
|
|
`make selfhost` automatically creates `.env` from the example, generates a random `JWT_SECRET`, and starts all services via Docker Compose.
|
|
|
|
By default it pulls the latest stable release images from GHCR. To build the backend/web from your current checkout instead, run `make selfhost-build`.
|
|
If the selected GHCR tag has not been published yet, `make selfhost` now tells you to fall back to `make selfhost-build`.
|
|
`make selfhost-build` uses local `multica-backend:dev` / `multica-web:dev` tags, so it does not overwrite the pulled `:latest` images.
|
|
|
|
Once ready:
|
|
|
|
- **Frontend:** http://localhost:3000
|
|
- **Backend API:** http://localhost:8080
|
|
|
|
> **Note:** If you prefer to run the Docker Compose steps manually, see [Manual Docker Compose Setup](#manual-docker-compose-setup) below.
|
|
|
|
### Step 2 — Log In
|
|
|
|
Open http://localhost:3000 in your browser. The Docker self-host stack defaults to `APP_ENV=production` (set in `docker-compose.selfhost.yml`), and there is no fixed verification code by default. Pick one of the following to log in:
|
|
|
|
- **Recommended (production):** configure `RESEND_API_KEY` in `.env`, then restart the backend. Real verification codes will be sent to the email address you enter. See [Advanced Configuration → Email](SELF_HOSTING_ADVANCED.md#email-required-for-authentication).
|
|
- **Without email configured:** the verification code is generated server-side and printed to the backend container logs (look for `[DEV] Verification code for ...:`). Useful for one-off testing on a single machine.
|
|
- **Deterministic local/private testing:** set `APP_ENV=development` and `MULTICA_DEV_VERIFICATION_CODE=888888` in `.env`, then restart the backend. This fixed code is ignored when `APP_ENV=production`.
|
|
|
|
Changes to `ALLOW_SIGNUP`, `DISABLE_WORKSPACE_CREATION`, and `GOOGLE_CLIENT_ID` also take effect after restarting the backend / compose stack. The web UI reads all three from `/api/config` at runtime, so no web rebuild is needed. See [Advanced Configuration → Signup Controls](SELF_HOSTING_ADVANCED.md#signup-controls-optional) for the recommended sequence to lock down workspace creation.
|
|
|
|
> **Warning:** do **not** set `MULTICA_DEV_VERIFICATION_CODE` on a publicly reachable instance — anyone who knows an email address can then log in with that fixed code.
|
|
|
|
### Step 3 — Install CLI & Start Daemon
|
|
|
|
The daemon runs on your local machine (not inside Docker). It detects installed AI agent CLIs, registers them with the server, and executes tasks when agents are assigned work.
|
|
|
|
Each team member who wants to run AI agents locally needs to:
|
|
|
|
### a) Install the CLI and an AI agent
|
|
|
|
```bash
|
|
brew install multica-ai/tap/multica
|
|
```
|
|
|
|
You also need at least one AI agent CLI installed:
|
|
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (`claude` on PATH)
|
|
- [Codex](https://github.com/openai/codex) (`codex` on PATH)
|
|
- [GitHub Copilot CLI](https://docs.github.com/en/copilot) (`copilot` on PATH)
|
|
- [OpenClaw](https://github.com/openclaw/openclaw) (`openclaw` on PATH)
|
|
- [OpenCode](https://github.com/anomalyco/opencode) (`opencode` on PATH)
|
|
- [Hermes](https://github.com/NousResearch/hermes) (`hermes` on PATH)
|
|
- Gemini (`gemini` on PATH)
|
|
- [Pi](https://pi.dev/) (`pi` on PATH)
|
|
- [Cursor Agent](https://cursor.com/) (`cursor-agent` on PATH)
|
|
- Kimi (`kimi` on PATH)
|
|
- Kiro CLI (`kiro-cli` on PATH)
|
|
|
|
### b) One-command setup
|
|
|
|
```bash
|
|
multica setup self-host
|
|
```
|
|
|
|
This automatically:
|
|
1. Configures the CLI to connect to `localhost` (ports 8080/3000)
|
|
2. Opens your browser for authentication
|
|
3. Discovers your workspaces
|
|
4. Starts the daemon in the background
|
|
|
|
For on-premise deployments with custom domains:
|
|
|
|
```bash
|
|
multica setup self-host --server-url https://api.example.com --app-url https://app.example.com
|
|
```
|
|
|
|
To verify the daemon is running:
|
|
|
|
```bash
|
|
multica daemon status
|
|
```
|
|
|
|
> **Alternative:** If you prefer manual steps, see [Manual CLI Configuration](#manual-cli-configuration) below.
|
|
|
|
### Step 4 — Verify & Start Using
|
|
|
|
1. Open your workspace in the web app at http://localhost:3000
|
|
2. Navigate to **Settings → Runtimes** — you should see your machine listed
|
|
3. Go to **Settings → Agents** and create a new agent
|
|
4. Create an issue and assign it to your agent — it will pick up the task automatically
|
|
|
|
---
|
|
|
|
## Kubernetes Deployment (Alternative)
|
|
|
|
If you already run a Kubernetes cluster, you can deploy Multica there instead of Docker Compose using the released OCI Helm chart at `oci://ghcr.io/multica-ai/charts/multica` or the source chart at [`deploy/helm/multica/`](deploy/helm/multica/). It targets a typical k3s / k8s setup with an Ingress controller and a default `ReadWriteOnce` StorageClass — authored against k3s + Traefik + `local-path`, and should work on any cluster with minor tweaks.
|
|
|
|
The chart creates the following resources in the target namespace:
|
|
|
|
- `multica-postgres` — `pgvector/pgvector:pg17` backed by a 10Gi PVC
|
|
- `multica-backend` — Go API/WS server. Backed by a 5Gi `ReadWriteOnce` uploads PVC by default; set `backend.uploads.persistence.enabled=false` when you have configured S3 (`backend.config.s3Bucket`) and don't want the chart to declare the PVC at all.
|
|
- `multica-frontend` — Next.js standalone server
|
|
- Two `Ingress` resources: one for the web host, one for the backend host
|
|
- `multica-config` ConfigMap (rendered from `values.yaml`)
|
|
|
|
The `multica-secrets` Secret is **not** managed by the chart — you create it once with `kubectl` so real values never need to land in git.
|
|
|
|
> **One release per namespace:** the prebuilt `multica-web` image bakes `REMOTE_API_URL=http://backend:8080` at build time, so the chart ships an ExternalName Service literally named `backend`. Because that name is unprefixed, you can run only one Multica release per namespace, and `helm install` will fail if a `Service/backend` already exists there (pass `--take-ownership`, or use a dedicated namespace). If you build a web image with a patched `REMOTE_API_URL`, set `frontend.compatibility.backendAlias: false` to drop the alias.
|
|
|
|
> **Prerequisites:** `kubectl` and `helm` (v3.13+ for `--take-ownership`, or v4+) configured for the target cluster, an Ingress controller (Traefik / NGINX), and a default StorageClass.
|
|
|
|
### Step 1 — Point hostnames at the cluster
|
|
|
|
The chart defaults to `multica.dev.lan` (web) and `api.multica.dev.lan` (backend). Pick one of:
|
|
|
|
- **`/etc/hosts`** on every machine that needs access (developer laptops + the machine running the daemon):
|
|
|
|
```text
|
|
192.168.1.206 multica.dev.lan api.multica.dev.lan
|
|
```
|
|
|
|
Replace `192.168.1.206` with any node IP where your Ingress controller's Service is reachable.
|
|
|
|
- **Local DNS** (Pi-hole, Unbound, etc.): add A records for both hostnames pointing at the cluster Ingress IP.
|
|
|
|
To use different hostnames, override the matching values at install time (see [Step 4](#step-4--install-the-chart)) — `ingress.frontend.host`, `ingress.backend.host`, plus `backend.config.appUrl`, `backend.config.frontendOrigin`, `backend.config.localUploadBaseUrl`, and `backend.config.googleRedirectUri`.
|
|
|
|
### Step 2 — Create the namespace
|
|
|
|
```bash
|
|
kubectl create namespace multica
|
|
```
|
|
|
|
### Step 3 — Create the `multica-secrets` Secret
|
|
|
|
The chart references this Secret by name. Create it once with random values:
|
|
|
|
```bash
|
|
kubectl -n multica create secret generic multica-secrets \
|
|
--from-literal=JWT_SECRET="$(openssl rand -hex 32)" \
|
|
--from-literal=POSTGRES_PASSWORD="$(openssl rand -hex 16)" \
|
|
--from-literal=RESEND_API_KEY="" \
|
|
--from-literal=GOOGLE_CLIENT_SECRET="" \
|
|
--from-literal=CLOUDFRONT_PRIVATE_KEY="" \
|
|
--from-literal=MULTICA_DEV_VERIFICATION_CODE=""
|
|
```
|
|
|
|
Leave optional values empty for now — you can fill them in later (see [Step 5 — Log In](#step-5--log-in)).
|
|
|
|
### Step 4 — Install the chart
|
|
|
|
```bash
|
|
helm install multica oci://ghcr.io/multica-ai/charts/multica \
|
|
--version <chart-version> \
|
|
-n multica
|
|
```
|
|
|
|
Released chart versions strip the leading `v` from the Git tag. For example, release tag `v0.3.5` publishes chart version `0.3.5`; the chart defaults the backend and frontend image tags to `v0.3.5`.
|
|
|
|
To override defaults, export the chart values, edit them, and pass them with `-f`:
|
|
|
|
```bash
|
|
helm show values oci://ghcr.io/multica-ai/charts/multica \
|
|
--version <chart-version> > my-values.yaml
|
|
# edit my-values.yaml — e.g. change ingress hosts, image tags, resource limits
|
|
helm install multica oci://ghcr.io/multica-ai/charts/multica \
|
|
--version <chart-version> \
|
|
-n multica \
|
|
-f my-values.yaml
|
|
```
|
|
|
|
When developing from a checkout, use the local chart path instead:
|
|
|
|
```bash
|
|
helm install multica deploy/helm/multica -n multica
|
|
```
|
|
|
|
Watch the pods come up:
|
|
|
|
```bash
|
|
kubectl -n multica get pods -w
|
|
```
|
|
|
|
On a cold cluster the backend can sit `Running` but not `Ready` for a few minutes while it waits on PostgreSQL and runs migrations — a startupProbe absorbs this, so the pod should not restart. Once the backend reports `Ready`, migrations have completed and `/healthz` returns OK:
|
|
|
|
```bash
|
|
curl -H "Host: api.multica.dev.lan" http://<ingress-ip>/healthz
|
|
# {"status":"ok","checks":{"db":"ok","migrations":"ok"}}
|
|
```
|
|
|
|
Then open http://multica.dev.lan in your browser.
|
|
|
|
### Step 5 — Log In
|
|
|
|
The chart defaults to `APP_ENV=production` (set in `values.yaml` under `backend.config.appEnv`), and there is no fixed verification code by default. Pick one of the following to log in — the same three options as the Docker setup:
|
|
|
|
- **Recommended (production):** patch the Secret with a real Resend key, then restart the backend:
|
|
|
|
```bash
|
|
kubectl -n multica patch secret multica-secrets --type=merge \
|
|
-p '{"stringData":{"RESEND_API_KEY":"re_xxx"}}'
|
|
kubectl -n multica rollout restart deploy/multica-backend
|
|
```
|
|
|
|
Real verification codes will be sent to the email address you enter. See [Advanced Configuration → Email](SELF_HOSTING_ADVANCED.md#email-required-for-authentication).
|
|
|
|
- **Without email configured:** the verification code is generated server-side and printed to the backend pod logs (look for `[DEV] Verification code for ...:`). Useful for one-off testing.
|
|
|
|
```bash
|
|
kubectl -n multica logs -f deploy/multica-backend | grep "Verification code"
|
|
```
|
|
|
|
- **Deterministic local/private testing:** set `backend.config.appEnv: development` in your values file and `MULTICA_DEV_VERIFICATION_CODE=888888` in the Secret, then `helm upgrade` and restart. This fixed code is ignored when `APP_ENV=production`.
|
|
|
|
```bash
|
|
helm upgrade multica oci://ghcr.io/multica-ai/charts/multica \
|
|
--version <chart-version> \
|
|
-n multica \
|
|
-f my-values.yaml --set backend.config.appEnv=development
|
|
kubectl -n multica patch secret multica-secrets --type=merge \
|
|
-p '{"stringData":{"MULTICA_DEV_VERIFICATION_CODE":"888888"}}'
|
|
kubectl -n multica rollout restart deploy/multica-backend
|
|
```
|
|
|
|
`ALLOW_SIGNUP`, `DISABLE_WORKSPACE_CREATION`, and `GOOGLE_CLIENT_ID` likewise live under `backend.config.*` in `values.yaml` (as `allowSignup`, `disableWorkspaceCreation`, and `googleClientId`). After `helm upgrade`, the backend pod will roll automatically because the ConfigMap hash changes; the web UI reads all three from `/api/config` at runtime, so no web rebuild is needed.
|
|
|
|
> **Warning:** do **not** set `MULTICA_DEV_VERIFICATION_CODE` on a publicly reachable instance — anyone who knows an email address can then log in with that fixed code.
|
|
|
|
### Step 6 — Install CLI & Start Daemon
|
|
|
|
The daemon runs on your local machine, not in the cluster. Install the CLI and an AI agent as in [Step 3](#step-3--install-cli--start-daemon) above, then point the CLI at your Ingress hostnames:
|
|
|
|
```bash
|
|
multica setup self-host \
|
|
--server-url http://api.multica.dev.lan \
|
|
--app-url http://multica.dev.lan
|
|
```
|
|
|
|
Make sure the machine running the daemon has the same `/etc/hosts` (or DNS) entries from [Step 1](#step-1--point-hostnames-at-the-cluster).
|
|
|
|
### Updating
|
|
|
|
To pull the latest images without changing the chart version when your values still use the mutable `latest` image tag:
|
|
|
|
```bash
|
|
kubectl -n multica rollout restart deploy/multica-backend deploy/multica-frontend
|
|
```
|
|
|
|
To upgrade to a specific Multica release, upgrade to the matching chart version. The released chart defaults its app images to the matching Git tag:
|
|
|
|
```bash
|
|
helm upgrade multica oci://ghcr.io/multica-ai/charts/multica \
|
|
--version <chart-version> \
|
|
-n multica \
|
|
-f my-values.yaml
|
|
```
|
|
|
|
If you need to override the app images independently from the chart version, set the image tags in your values file:
|
|
|
|
```yaml
|
|
images:
|
|
backend:
|
|
tag: v0.2.4
|
|
frontend:
|
|
tag: v0.2.4
|
|
```
|
|
|
|
Then run the same upgrade command with `-f my-values.yaml`:
|
|
|
|
```bash
|
|
helm upgrade multica oci://ghcr.io/multica-ai/charts/multica \
|
|
--version <chart-version> \
|
|
-n multica \
|
|
-f my-values.yaml
|
|
```
|
|
|
|
To roll back if an upgrade goes sideways:
|
|
|
|
```bash
|
|
helm -n multica rollback multica
|
|
```
|
|
|
|
> **Upgrading from `v0.3.4` to `v0.3.5+` fails with `refusing to drop legacy daily rollups: ...`?** Same migration guard as the Docker path — see [Usage Dashboard Rollup → Option C](#option-c--backfill-history-first-then-schedule). Run the backfill against the same database the chart is using (`kubectl -n multica exec deploy/multica-backend -- ./backfill_task_usage_hourly --sleep-between-slices=2s`), then restart the backend deployment to re-apply migrations.
|
|
|
|
### Tearing down
|
|
|
|
```bash
|
|
# Remove the workloads but keep the PVCs and the Secret
|
|
helm -n multica uninstall multica
|
|
|
|
# Wipe everything, including PostgreSQL data and uploads
|
|
kubectl delete namespace multica
|
|
```
|
|
|
|
---
|
|
|
|
## Usage Dashboard Rollup (Required)
|
|
|
|
Starting with `v0.3.5`, the Usage / Runtime dashboards read from a derived `task_usage_hourly` table rather than directly from `task_usage`. Raw `task_usage` rows are written by the backend on every task, but the dashboard only sees data after `rollup_task_usage_hourly()` runs and aggregates them into `task_usage_hourly`.
|
|
|
|
**The bundled `pgvector/pgvector:pg17` image does NOT include `pg_cron`.** If nothing schedules the rollup, the dashboard will stay at zero forever even though `task_usage` is populated. You have three supported options — pick one before relying on the dashboard.
|
|
|
|
> **Upgrading from `v0.3.4` to `v0.3.5+`** with existing `task_usage` history: migration `103` is fail-closed and will abort `migrate up` with `refusing to drop legacy daily rollups: …`. Run `backfill_task_usage_hourly` first (Option C below), then re-run the upgrade. **Fresh installs** are exempted by that guard and migrate cleanly — but the dashboard will still stay at zero until you pick Option A or Option B.
|
|
|
|
### Option A — External cron / systemd-timer (simplest)
|
|
|
|
Schedule a 5-minute job that calls `rollup_task_usage_hourly()`. It is idempotent and watermark-driven, so a missed tick catches up on the next run.
|
|
|
|
```bash
|
|
# /etc/cron.d/multica-rollup — every 5 minutes
|
|
*/5 * * * * root docker compose -f /path/to/multica/docker-compose.selfhost.yml \
|
|
exec -T postgres psql -U multica -d multica \
|
|
-c "SELECT rollup_task_usage_hourly();" >/dev/null
|
|
```
|
|
|
|
Or as a systemd timer + service if you prefer that surface. The function returns the number of (upserted + deleted-empty) rows; it's safe to call concurrently with itself (an advisory lock makes overlapping runs no-op) and safe to call alongside `backfill_task_usage_hourly`.
|
|
|
|
### Option B — Swap Postgres for an image that ships `pg_cron`
|
|
|
|
If you'd rather have Postgres schedule itself, replace `pgvector/pgvector:pg17` in `docker-compose.selfhost.yml` with an image that bundles both `pgvector` and `pg_cron` (e.g. `supabase/postgres`, or your own build of `pgvector/pgvector` with `pg_cron` added and `shared_preload_libraries=pg_cron` set on the server). Then, once:
|
|
|
|
```sql
|
|
CREATE EXTENSION IF NOT EXISTS pg_cron;
|
|
SELECT cron.schedule(
|
|
'rollup_task_usage_hourly',
|
|
'*/5 * * * *',
|
|
$$SELECT rollup_task_usage_hourly()$$
|
|
);
|
|
```
|
|
|
|
`shared_preload_libraries` requires a Postgres restart to take effect — set it in `postgresql.conf` (or via the image's documented mechanism) before bringing the container up.
|
|
|
|
### Option C — Backfill history first, then schedule
|
|
|
|
If you're upgrading from `v0.3.4 → v0.3.5+` and already have `task_usage` rows (or you just want the dashboard to show historical data on a fresh install that you've been running for a while), run the bundled backfill command once before scheduling the rollup:
|
|
|
|
```bash
|
|
# Backfills task_usage_hourly from all historical task_usage rows and stamps
|
|
# the rollup watermark. Idempotent — safe to re-run.
|
|
docker compose -f docker-compose.selfhost.yml exec backend \
|
|
./backfill_task_usage_hourly --sleep-between-slices=2s
|
|
```
|
|
|
|
On a database with years of data this can scan tens of millions of rows; `--sleep-between-slices=2s` throttles the read pressure. Use `--months-back N` (plus `--force-partial`) if you only want the last N months. Once it finishes, set up Option A or Option B so new buckets keep flowing.
|
|
|
|
After upgrading, re-run `migrate up` (or restart the backend container — migrations run automatically on startup) to apply migration `103` cleanly.
|
|
|
|
## Stopping Services
|
|
|
|
If you installed via the install script:
|
|
|
|
```bash
|
|
curl -fsSL https://raw.githubusercontent.com/multica-ai/multica/main/scripts/install.sh | bash -s -- --stop
|
|
```
|
|
|
|
If you cloned the repo manually:
|
|
|
|
```bash
|
|
# Stop the Docker Compose services (backend, frontend, database)
|
|
make selfhost-stop
|
|
|
|
# Stop the local daemon
|
|
multica daemon stop
|
|
```
|
|
|
|
## Switching to Multica Cloud
|
|
|
|
If you've been self-hosting and want to switch your CLI to [Multica Cloud](https://multica.ai):
|
|
|
|
```bash
|
|
multica setup
|
|
```
|
|
|
|
This reconfigures the CLI for multica.ai, re-authenticates, and restarts the daemon. You will be prompted before overwriting the existing configuration.
|
|
|
|
> Your local Docker services are unaffected. Stop them separately if you no longer need them.
|
|
|
|
## Upgrading
|
|
|
|
```bash
|
|
docker compose -f docker-compose.selfhost.yml pull
|
|
docker compose -f docker-compose.selfhost.yml up -d
|
|
```
|
|
|
|
Pin `MULTICA_IMAGE_TAG` in `.env` to an exact version like `v0.2.4` if you want to stay on a specific release. Migrations run automatically on backend startup.
|
|
If the selected GHCR tag has not been published yet, fall back to `make selfhost-build` or `docker compose -f docker-compose.selfhost.yml -f docker-compose.selfhost.build.yml up -d --build`.
|
|
|
|
> **Upgrading from `v0.3.4` to `v0.3.5+` fails with `refusing to drop legacy daily rollups: ...`?** That's migration `103`'s fail-closed guard: it requires `task_usage_hourly` to be seeded before the legacy daily rollups are dropped. Run `backfill_task_usage_hourly` first, then re-run the upgrade. Full instructions in [Usage Dashboard Rollup → Option C](#option-c--backfill-history-first-then-schedule).
|
|
|
|
---
|
|
|
|
## Manual Docker Compose Setup
|
|
|
|
If you prefer running Docker Compose steps manually instead of `make selfhost`:
|
|
|
|
```bash
|
|
git clone https://github.com/multica-ai/multica.git
|
|
cd multica
|
|
cp .env.example .env
|
|
```
|
|
|
|
Edit `.env` — at minimum, change `JWT_SECRET`:
|
|
|
|
```bash
|
|
JWT_SECRET=$(openssl rand -hex 32)
|
|
```
|
|
|
|
Then start everything:
|
|
|
|
```bash
|
|
docker compose -f docker-compose.selfhost.yml pull
|
|
docker compose -f docker-compose.selfhost.yml up -d
|
|
```
|
|
|
|
## Manual CLI Configuration
|
|
|
|
If you prefer configuring the CLI step by step instead of `multica setup`:
|
|
|
|
```bash
|
|
# Point CLI to your local server
|
|
multica config set server_url http://localhost:8080
|
|
multica config set app_url http://localhost:3000
|
|
|
|
# Login (opens browser)
|
|
multica login
|
|
|
|
# Start the daemon
|
|
multica daemon start
|
|
```
|
|
|
|
For production deployments with TLS:
|
|
|
|
```bash
|
|
multica config set app_url https://app.example.com
|
|
multica config set server_url https://api.example.com
|
|
multica login
|
|
multica daemon start
|
|
```
|
|
|
|
## Advanced Configuration
|
|
|
|
For environment variables, manual setup (without Docker), reverse proxy configuration, database setup, and more, see the [Advanced Configuration Guide](SELF_HOSTING_ADVANCED.md).
|