895658a115
- zoraxy.md: fix arcane upstream to CT109 (192.168.1.8:10002), add SkipWebSocketOriginCheck column, note missing routes (dozzle, etc.) - arcane.md: reflect CT109 migration complete, expand agent table to all 8 environments, fix MANAGER_API_URL and DB paths - ct-inventory.md: CT103 RAM 512→4096+swap; CT109 footnote complete - proxmox-memory-audit.md: CT103 bump, add CT109+CT113 rows, fix sum - portmap.md: add Wetty row, fix arcane backend, WAL-G scrape target, homepage decommissioned, dozzle LAN-only note - mcp-gateway.md: add gitea/paperless/proxmox, count 26→29 servers - RESUME.md: check off WAL-G, Loki, Zoraxy audit; CT109 in key state table; session ×4 completed items block Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
124 lines
4.7 KiB
Markdown
124 lines
4.7 KiB
Markdown
# 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):
|
|
```bash
|
|
# 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:
|
|
```python
|
|
# 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**
|
|
|
|
```yaml
|
|
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**
|
|
|
|
```bash
|
|
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:
|
|
```sql
|
|
sqlite3 /rpool/data/subvol-109-disk-0/opt/stacks/arcane/data/arcane.db \
|
|
"DELETE FROM api_keys WHERE name='admin-cli';"
|
|
```
|