Self-Hosting Lycato

Status: alpha, single tenant, source install. Lycato currently ships the local lycato serve supervisor, but it does not ship a Docker image, Compose file, or Caddy configuration. The public npm install is also blocked until the Lycato workspace packages are published together.

Scope

This runbook covers one company repo on one trusted host:

The cockpit has no application authentication. Keep it on loopback and use an authenticated reverse proxy, SSH tunnel, Tailscale, or another private-network control if it must be reached remotely.

Prerequisites

First boot from source

Build Lycato once, outside the company repo:

git clone https://github.com/axysar/lycato.git /opt/lycato
cd /opt/lycato
corepack enable
pnpm install --frozen-lockfile
pnpm build

Create a company repo in a separate directory. init is interactive and must run inside the target directory:

mkdir -p /srv/lycato/company
cd /srv/lycato/company
node /opt/lycato/apps/cli/bin/run.js init
node /opt/lycato/apps/cli/bin/run.js doctor

Start the supervisor from that company repo:

cd /srv/lycato/company
node /opt/lycato/apps/cli/bin/run.js serve --interval 900

The cockpit and API share http://127.0.0.1:3001/. lycato serve:

  1. starts the built cockpit UI, Fastify API, and WebSocket endpoint;
  2. runs sync immediately and then at the requested interval;
  3. checks scheduled agents every minute, replaying elapsed minute slots after timer drift or host suspension;
  4. appends run evidence to .founder/runs/YYYY-MM.jsonl.

Use --skip-cockpit, --skip-sync, or --skip-agents when a separate process owns that responsibility.

daily-digest does not write unattended company truth. Approve or deny its action digest explicitly:

node /opt/lycato/apps/cli/bin/run.js agent approvals
node /opt/lycato/apps/cli/bin/run.js agent approve <digest>

Running under a service manager

Use /srv/lycato/company as the working directory and this executable:

/usr/bin/node /opt/lycato/apps/cli/bin/run.js serve --interval 900

Configure the service manager to restart on failure and stop it with SIGINT or SIGTERM. Keep .founder/keys.env mode 0600; Lycato loads it when the supervisor starts.

Upgrades

Stop the supervisor before upgrading:

cd /opt/lycato
git pull --ff-only
pnpm install --frozen-lockfile
pnpm build

cd /srv/lycato/company
node /opt/lycato/apps/cli/bin/run.js migrate
node /opt/lycato/apps/cli/bin/run.js doctor

Then restart the supervisor. Migrations are forward-only and idempotent.

Backup and restore drill

node /opt/lycato/apps/cli/bin/run.js backup --out /backups/lycato-$(date +%F).lycatobak
node /opt/lycato/apps/cli/bin/run.js restore \
  --from /backups/lycato-YYYY-MM-DD.lycatobak \
  --to /tmp/lycato-restore-drill

The company directory is also a Git repo. A private remote is a useful second backup tier, but it does not replace a tested .lycatobak restore.

Operational checks

Run these from /srv/lycato/company:

node /opt/lycato/apps/cli/bin/run.js doctor
node /opt/lycato/apps/cli/bin/run.js logs --kind agent --since 2026-05-01
curl --fail http://127.0.0.1:3001/api/health

/api/health reports the repository root, bind host and port, authentication mode, and network posture.

Hardening

Not included

The source-hosted path does not include Docker packaging, TLS automation, passkeys/SSO, Stripe billing, KMS-backed secrets, multi-tenant orchestration, or managed off-host backups. Those are separate hosted-product work, not implied by this runbook.