Operating Modes
depends.cc runs in self-hosted (default) or hosted mode, auto-detected at startup via process.env.LEGENDUM_API_KEY. Self-hosted mode (no key set) bypasses auth, billing, and signup—ideal for local development, private networks, or trusted infrastructure. Hosted mode (key set) enables multi-tenant bearer-token auth, Legendum billing, and SMTP email delivery.
The core model (nodes, edges, effective states, TTL, notifications) is identical across modes. See project-invariants.md for key behaviors like lazy TTL evaluation and no server-side polling.
Mode Detection
// src/server/middleware.ts (excerpt)
export function isByLegendum(): boolean {
return !!process.env.LEGENDUM_API_KEY;
}
export function isSelfHosted(): boolean {
return !isByLegendum();
}
Restart required to switch modes.
Self-Hosted Mode
No LEGENDUM_API_KEY. Requests map to well-known LOCAL_TOKEN = "dep_local" (token ID 0); namespaces auto-create on first access. Authorization header optional/ignored. Rate limiting skips localhost (127.0.0.1, ::1): 120 requests/minute per IP otherwise.
Quickstart (Local Development)
Install CLI (includes server):
curl -fsSL https://depends.cc/install.sh | sh
depends serve # http://localhost:3000 (data/depends.db created)
Or directly:
bun install
bun run dev # Watch mode
bun run start # Production; override PORT=8080
CLI auto-detects local mode (no DEPENDS_TOKEN):
depends init # Scaffold depends.yml
depends push # Sync graph
depends status # View states
depends set myproject/api-server red
Explicit: DEPENDS_API_URL=http://localhost:3000/v1 depends status.
Events auto-purge hourly (older than 30 days; see data-purging.md). Admin: depends admin tokens.
Database and Logs
- SQLite:
data/depends.db(WAL mode: concurrent reads, hot backups safe). Schema auto-applies (database-schema.md). - Backup:
cp data/depends.db data/depends.db.backup. - Logs: JSON-line
log/YYYY-MM-DD.log(access, webhook/email failures).
tail -f log/$(date -u +%F).log
grep '"kind":"webhook_failed"' log/$(date -u +%F).log
Hosted Mode (Production)
Set LEGENDUM_API_KEY (Legendum service key). Enforces Authorization: Bearer dep_... (per-account, namespace-scoped via ownership). Signup required.
Deployment Steps
- Clone:
git clone./opt/depends && cd /opt/depends bun install.- Set env vars (minimum:
LEGENDUM_API_KEY). - Start:
bun run src/server.ts. - Reverse proxy for HTTPS.
Reverse Proxies
Nginx:
server {
listen 443 ssl;
server_name depends.cc;
ssl_certificate /etc/letsencrypt/live/depends.cc/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/depends.cc/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Caddy:
depends.cc {
reverse_proxy localhost:3000
}
Systemd
[Unit]
Description=depends.cc
After=network.target
[Service]
ExecStart=/usr/bin/bun run /opt/depends/src/server.ts
WorkingDirectory=/opt/depends
EnvironmentFile=/etc/depends/env
Restart=always
User=depends
[Install]
WantedBy=multi-user.target
Signup and Tokens
depends signup you@example.com lak_... # lak_... from legendum.co.uk/account
Token emailed. Tokens hash-stored (SHA-256), own namespaces:
-- src/db.ts (excerpt)
CREATE TABLE tokens (
id INTEGER PRIMARY KEY AUTOINCREMENT,
token_hash TEXT NOT NULL UNIQUE,
email TEXT,
legendum_token TEXT,
...
);
CREATE TABLE namespaces (
ns_id INTEGER PRIMARY KEY AUTOINCREMENT,
id TEXT NOT NULL,
token_id INTEGER NOT NULL REFERENCES tokens(id) ON DELETE CASCADE,
UNIQUE(token_id, id)
);
CLI config (~/.config/depends/config.yml or DEPENDS_TOKEN):
token: dep_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
default_namespace: myproject
api_url: https://depends.cc/v1
See cli.md.
Billing
Legendum credits per action (self-hosted skips):
| Action | Cost |
|---|---|
| Node create | 1 |
| State write | 0.1 |
| Webhook/Email | 2 |
GET /usage/{ns} stats (api-reference.md). 402 on insufficient funds.
Emails via SMTP (notifications.md).
Key Differences
| Aspect | Self-Hosted | Hosted |
|---|---|---|
LEGENDUM_API_KEY | Unset | Set |
| Auth | dep_local (auto) | Bearer dep_... (signup) |
| Namespaces | Auto-create | Token-owned (POST /namespaces) |
| Billing | None | Legendum |
| Emails | Skipped | SMTP |
| Rate Limiting | Skip localhost | All IPs |
Environment Variables
Server:
| Variable | Default | Description |
|---|---|---|
PORT | 3000 | Listen port |
LEGENDUM_API_KEY | Unset | Enables hosted mode |
BASE_URL | https://depends.cc | Ack URLs (notifications.md) |
SMTP_HOST | Unset | SMTP hostname |
SMTP_PORT | 465 | SMTP port (TLS) |
SMTP_USER | Unset | SMTP user |
SMTP_PASS | Unset | SMTP password |
SMTP_FROM | notifications@depends.cc | From address |
CLI (ignored by server):
| Variable | Description |
|---|---|
DEPENDS_TOKEN | Bearer token |
DEPENDS_NAMESPACE | Default namespace |
DEPENDS_API_URL | API base (e.g. http://localhost:3000/v1) |
DEPENDS_CONFIG | Config path |
Upgrading
CLI:
depends update # git pull + bun install in ~/.config/depends/src
Server:
- Backup:
cp data/depends.db data/depends.db.backup. git pull && bun install.- Restart:
systemctl restart depends.
Schema auto-applies new tables/indexes. For column changes:
- Stop server.
- Backup DB.
sqlite3 data/depends.db < migration.sql.- Update code, restart.
No migrations needed currently. Events purge after 30 days (data-purging.md).
Recent changes
- Merged: deployment.md, docs/UPDATES.md → operating-modes.md
- Merged: authentication.md, self-hosted-mode.md, hosted-mode.md → operating-modes.md