Arcane¶
Web-based Docker management IDE. Main instance on CT 109 (192.168.1.8:10002, arcane.nuclide.systems). Manages containers on all Docker hosts via edge agents. Migrated from CT 104 → CT 109 on 2026-05-23.
Stack: /opt/stacks/arcane/docker-compose.yml on CT 109.
Image: ghcr.io/getarcaneapp/arcane:latest
Auth: OIDC via Pocket ID, admin: fkrebs@nucli.de
Edge agents¶
An edge agent (ghcr.io/getarcaneapp/arcane-headless:latest) runs inside each remote CT and connects outbound to the main Arcane server via gRPC poll. The main server then manages that CT's Docker.
Currently deployed agents¶
| CT | Hostname | Environment | Compose path | Status |
|---|---|---|---|---|
| CT 101 | shepard | shepard | /opt/stacks/ops-agents/docker-compose.yml |
online |
| CT 104 | docker | docker | /opt/stacks/ops-agents/docker-compose.yml |
online |
| CT 105 | nextcloud | nextcloud | /opt/stacks/ops-agents/docker-compose.yml |
online |
| CT 110 | id | id | /opt/stacks/ops-agents/docker-compose.yml |
online |
| CT 111 | dev | dev | /opt/stacks/ops-agents/docker-compose.yml |
online |
| CT 112 | secrets | secrets | /opt/stacks/ops-agents/docker-compose.yml |
online |
| CT 113 | db | db | /opt/stacks/db/docker-compose.yml |
online |
| nuc | nuc | NUC (built-in) | (built-in environment) | online |
Adding an edge agent to a new CT¶
Step 1 — Create the environment in Arcane (requires Arcane API or UI access)
With the admin CLI API key (stored in Arcane DB, regenerate if needed):
# Get or create an admin API key — see "Admin API key" section below
API_KEY="arc_..."
curl -s -X POST -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
"http://192.168.1.40:10002/api/environments" \
-d '{"name":"<ctname>","apiUrl":"edge://<ctname>","isEdge":true}'
# Note the environment id from the response
Step 2 — Generate and wire the AGENT_TOKEN
Arcane stores the raw AGENT_TOKEN in environments.access_token. Insert it via:
# On PVE host, run: python3 /tmp/arcane-bootstrap.py
import argon2, secrets, sqlite3, uuid
from datetime import datetime, timezone
db_path = "/rpool/data/subvol-109-disk-0/opt/stacks/arcane/data/arcane.db"
env_id = "<id from step 1>" # paste the environment UUID here
conn = sqlite3.connect(db_path)
raw_token = "arc_" + secrets.token_hex(32)
key_prefix = "arc_" + raw_token[4:12]
ph = argon2.PasswordHasher(memory_cost=65536, time_cost=3, parallelism=2)
key_hash = ph.hash(raw_token)
key_id = str(uuid.uuid4())
now = datetime.now(timezone.utc).isoformat()
conn.execute(
"INSERT INTO api_keys (id, name, description, key_hash, key_prefix, environment_id, managed_by, created_at, updated_at)"
" VALUES (?,?,?,?,?,?,?,?,?)",
(key_id, f"Environment Bootstrap Key - {env_id[:8]}",
"Auto-generated key for environment pairing",
key_hash, key_prefix, env_id, "system", now, now))
conn.execute("UPDATE environments SET access_token=? WHERE id=?", (raw_token, env_id))
conn.commit()
conn.close()
print("AGENT_TOKEN:", raw_token)
Step 3 — Add the agent to the CT's compose
arcane-agent:
image: ghcr.io/getarcaneapp/arcane-headless:latest
container_name: arcane-agent
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./arcane-agent:/app/data
environment:
EDGE_AGENT: "true"
EDGE_TRANSPORT: poll
AGENT_TOKEN: ${ARCANE_AGENT_TOKEN}
MANAGER_API_URL: http://192.168.1.8:10002
deploy:
resources:
limits:
cpus: "0.5"
memory: 256M
Add ARCANE_AGENT_TOKEN=<raw_token> to the CT's .env.
Step 4 — Start and verify
docker compose up -d arcane-agent
docker logs arcane-agent 2>&1 | grep "Edge gRPC tunnel"
# Expected: Edge gRPC tunnel connected to manager environment_id=<uuid>
The environment should flip to online in environments.status within ~5 seconds.
Migration to CT 109 — completed 2026-05-23¶
Arcane migrated from CT 104 → CT 109. All edge agents updated with MANAGER_API_URL: http://192.168.1.8:10002. Zoraxy upstream updated to 192.168.1.8:10002. SQLite DB at /opt/stacks/arcane/data/ on CT 109.
Admin API key (non-OIDC access)¶
Arcane doesn't store plaintext API keys — use the DB-insert method above when a new admin key is needed. The python3-argon2 package must be installed on the PVE host (apt install python3-argon2).
The key inserted for CLI use during CT 113 provisioning (arc_a9695182...) is linked to fkrebs user in the api_keys table. Rotate it after provisioning work is complete by deleting the row: