# Deploy to LXC One script deploys everywhere: [`scripts/deploy.sh`](../scripts/deploy.sh). It SSHes to the LXC host, does `git fetch + reset --hard origin/main`, rebuilds and restarts the service, then hits the health check. It never keeps secrets in the repo — configuration comes from env vars, a gitignored `deploy.env`, or Gitea secrets. ## Target host (one-time setup on the LXC) ```bash # as root on the LXC container: apt install -y git # plus docker+compose, or node 22 for systemd mode useradd -m -s /bin/bash deploy || true # checkout (read-only deploy key tied to this repo, no push rights): sudo -u deploy bash -c ' git clone git@git.omniagency.ru:2222/a.andreev/AI-Rendezvous.git /opt/ai-rendezvous' chown -R deploy:deploy /opt/ai-rendezvous ``` Generate a read-only deploy key on the LXC (`sudo -u deploy ssh-keygen -t ed25519`) and add the public key as a **read-only** deploy key in Gitea (repo Settings → Deploy keys, *without* write access). Choose how the service runs: - **docker mode (default):** `docker compose up -d` is used on every deploy. Prepare `.env` with `BASE_URL=https://rendezvous.example` next to `docker-compose.yml` on the LXC. - **systemd mode:** install [`ai-rendezvous.service`](../contrib/ai-rendezvous.service) and set `DEPLOY_MODE=systemd`. ## Option A — Gitea Actions (recommended) Add repository secrets (Settings → Actions → Secrets): | Secret | Example | Notes | |---|---|---| | `DEPLOY_HOST` | `deploy@10.0.0.42` | user@lxc-container | | `DEPLOY_PORT` | `22` | | | `DEPLOY_DIR` | `/opt/ai-rendezvous` | | | `DEPLOY_MODE` | `docker` | or `systemd` | | `DEPLOY_SERVICE` | `ai-rendezvous` | systemd mode only | | `DEPLOY_HEALTH_URL` | `http://127.0.0.1:3000/health` | checked via SSH on the LXC | | `DEPLOY_SSH_KEY` | *(private key)* | key of a user allowed to deploy (not the read-only one) | | `DEPLOY_KNOWN_HOSTS` | output of `ssh-keyscan -p 22 10.0.0.42` | | `.gitea/workflows/deploy.yml` runs `scripts/deploy.sh` on every push to `main`. Needs one act runner registered in Gitea (can run anywhere with SSH access to the LXC — including the LXC itself). ## Option B — Gitea webhook If you don't want an act runner: add a webhook (Settings → Webhooks) pointing to a minimal receiver on the LXC (e.g. `webhook`/` webhookd`/a 20-line HTTP server) that verifies the shared secret and executes: ```bash sudo -u deploy env SSH_HOST=deploy@localhost DEPLOY_MODE=docker \ /opt/ai-rendezvous/scripts/deploy.sh ``` Gitea → webhook → receiver → `deploy.sh`. Same script, no CI needed. ## Option C — manual / from a dev machine (or the agent's shell) ```bash ./scripts/deploy.sh # reads deploy.env (gitignored) if present ``` `deploy.env` example: ```bash SSH_HOST=deploy@lxc42.internal SSH_PORT=22 DEPLOY_DIR=/opt/ai-rendezvous DEPLOY_MODE=docker HEALTH_URL=http://127.0.0.1:3000/health ``` ## Deploy flow for the agent 1. Make changes, `npm test` locally. 2. Commit and push to `main` on Gitea. 3. Gitea Actions (or webhook) runs `scripts/deploy.sh`. 4. The health check must pass; the action fails loudly otherwise. 5. Human verifies on the deployed instance.