Infrastructure Status — Research Stack
Last verified: 2026-05-23
Scope: All live nodes, services, and storage in the Tailscale mesh.
Tailscale Mesh
All nodes route through Tailscale. No public ports are open on any node except microvm-racknerd (ports 80/443 for Caddy).
| Node |
Tailscale IP |
Hostname |
Role |
OS |
SSH |
| qfox-1 |
100.88.57.96 |
QFox |
Garage primary, S3 endpoint, GPU compute, build host |
Arch Linux 7.0.9-cachyos |
local |
| nixos-laptop |
100.102.173.61 |
nixos |
Authentik SSO, k3s control plane, storage node |
NixOS 26.05 (Yarara) |
key OK |
| 361395-1 |
100.110.163.82 |
361395 |
Netcup VPS, Garage storage node |
Debian 13 |
key OK |
| microvm-racknerd |
100.101.247.127 |
MicroVM-Racknerd |
Caddy reverse proxy, public edge |
Debian (microVM) |
root password OK |
| nixos-steamdeck-1 |
100.85.244.73 |
steamdeck |
GPU compute, planned edge LLM (3B-7B) |
NixOS |
just onboarded |
| dracocomp |
100.100.140.27 |
— |
offline / unreachable |
— |
unreachable 3+ days |
Public Edge: Caddy on microvm-racknerd
Caddy v2.11.3 with Porkbun DNS plugin handles all public HTTPS traffic.
Wildcard TLS
- Certificate:
*.researchstack.info + researchstack.info
- Issuer: Let's Encrypt E7
- Challenge: DNS-01 via Porkbun API
- Valid: 2026-05-21 → 2026-08-19
- Renewal: automatic
Domains & Routing
| Domain |
Caddy Action |
Upstream (Tailscale) |
Notes |
researchstack.info |
forward_auth + reverse_proxy |
100.102.173.61:30803 |
Homer dashboard (landing page) |
chat.researchstack.info |
forward_auth + file_server |
100.102.173.61:9000 (auth only) |
Placeholder HTML |
dash.researchstack.info |
forward_auth + reverse_proxy |
100.102.173.61:30802 |
Heimdall (k3s NodePort) |
status.researchstack.info |
forward_auth + reverse_proxy |
100.102.173.61:30801 |
Uptime Kuma (k3s NodePort) |
auth.researchstack.info |
reverse_proxy (direct) |
100.102.173.61:9000 |
Authentik SSO (no forward_auth loop) |
Caddy Service
- Config:
/etc/caddy/Caddyfile
- Service:
caddy.service (systemd)
- Status: active
- Env: Porkbun credentials via systemd drop-in (
/etc/systemd/system/caddy.service.d/override.conf)
- Disk: 9.1G total, 6.4G free
Identity: Authentik on nixos-laptop
Authentik runs as standalone Podman containers (not k3s). The k3s Helm migration is pending.
Containers
| Container |
Image |
Port |
Status |
authentik_postgresql_1 |
postgres:16-alpine |
5432/tcp |
Up, healthy |
authentik_valkey_1 |
valkey/valkey:8-alpine |
6379/tcp |
Up, healthy |
authentik_server_1 |
ghcr.io/goauthentik/server:2026.2.3 |
0.0.0.0:9000→9000, 0.0.0.0:9443→9443 |
Up |
authentik_worker_1 |
ghcr.io/goauthentik/server:2026.2.3 |
— |
Up |
Compose
- Path:
/home/allaun/authentik/docker-compose.yml
- Network:
authentik_authentik (bridge)
- Volumes:
database, redis, media, custom-templates, certs
Valkey Migration
Redis was replaced with Valkey 8 (Alpine) on 2026-05-22. The redis volume was wiped during migration because Valkey does not read Redis RDB format version 13. Authentik cache/session data was lost but rebuilds automatically on first use.
k3s on nixos-laptop
k3s v1.35.4+k3s1 runs as a single-node control plane. Authentik was not successfully migrated to k3s.
Running Services (services namespace)
| Pod |
Service |
NodePort |
Status |
uptime-kuma |
uptime-kuma |
30801 |
Running |
heimdall |
heimdall |
30802 |
Running |
homer |
homer |
30803 |
Running |
pulse-receiver |
pulse-receiver |
30804 |
Running |
Blocked / Broken
| Pod |
Status |
Blocker |
authentik-postgresql-0 |
CrashLoopBackOff |
Bitnami PostgreSQL subchart: read-only filesystem on /var/run/postgresql |
authentik-redis-master-0 |
ImagePullBackOff |
Bitnami Redis image tags no longer exist |
authentik-server-* |
Running (0/1) |
Waiting for PostgreSQL |
authentik-worker-* |
CrashLoopBackOff |
Waiting for PostgreSQL |
helm-install-authentik-* |
Error |
Helm revision failures cascade |
Decision: Keep Authentik on standalone Podman. Decommission or fix the k3s Authentik HelmChart when time permits.
Storage: Garage S3
Garage v2.3.0 provides a self-hosted, replicated S3-compatible object store.
Cluster Topology
| Node ID |
Hostname |
Address |
Zone |
Capacity |
Usable |
DataAvail |
3e08a71b73fa2b10 |
QFox |
100.88.57.96:3901 |
local |
780.4 GiB |
68.9 GiB |
1.5 TiB (83.5%) |
75fac43bc53eb201 |
361395 |
100.110.163.82:3901 |
fra |
68.9 GiB |
68.9 GiB |
65.2 GiB (52.3%) |
a7e6c283056a4d77 |
nixos |
100.102.173.61:3901 |
ord |
346.5 GiB |
68.9 GiB |
393.5 GiB (85.8%) |
- Replication factor: 3
- Zone redundancy: maximum
- Effective capacity: 68.9 GiB (bottlenecked by 361395-1)
- Layout version: 1
Ports
| Port |
Purpose |
Binding |
| 3900 |
S3 API |
qfox-1 only (localhost + Tailscale) |
| 3901 |
RPC (inter-node) |
all nodes, Tailscale |
| 3903 |
Admin API |
loopback only |
Buckets
| Alias |
Purpose |
research-stack |
Primary project objects |
db-scratch |
Active SQLite scratch databases |
rds-overflow |
pg_dump / COPY TO exports |
snap-zone |
ZFS send/receive snapshots |
gdrive-mirror |
Mirror of gdrive:research-stack |
Nodes
qfox-1
- Garage runs as systemd service (
garage.service) under dedicated garage user
- S3 API bound to localhost:3900 (forwarded via SSH tunnel for remote access)
- NixOS-style persistence not needed (native Arch)
361395-1
- Garage runs as systemd service
- zram enabled: 2G zstd swap
- Disk: 125G total, 66G free
nixos-laptop
- Garage runs as systemd service via NixOS module
- zram enabled in
/etc/nixos/configuration.nix
- Disk: 459G NVMe, 394G free
- Binary path: not in default
$PATH; managed by NixOS
Backups: restic + rclone
Primary restic repo
- Backend:
s3:http://localhost:3900/research-stack (Garage)
- Password file:
/etc/garage/restic-password
Scripts
All scripts live in 4-Infrastructure/storage/restic/:
| Script |
Purpose |
backup.sh snap [tag] |
Snapshot repo tree → Garage |
backup.sh snap-db [dir] |
Snapshot SQLite scratch DBs |
backup.sh snap-rds <table> |
Stream pg_dump | zstd → restic stdin |
backup.sh cold-copy |
rclone copy Garage → gdrive:restic-mirror |
backup.sh sync-gdrive |
rclone sync gdrive:research-stack → Garage:gdrive-mirror |
backup.sh forget |
Retention prune (7d/4w/6m) |
backup.sh verify |
restic check --read-data-subset=5% |
backup.sh full |
snap + cold-copy + sync-gdrive + forget |
Schedule
- Daily timer:
restic-backup.timer fires at 03:00 ±30 min
- Post-commit hook:
.git/hooks/post-commit runs db-consolidate.sh offload + consolidate in background
Secrets
SOPS/age is used for all secrets.
- Age key:
~/.config/sops/age/keys.txt
- Public key:
age1tp4vr565zkmvnyulatpyaj6z8zrz7q9mpaypz85yz8rty99crdasualxyr
- Config:
.sops.yaml (repo root) + 4-Infrastructure/k3s-flake/.sops.yaml
Encrypted files (selection)
| File |
Contents |
4-Infrastructure/infra/secrets/credentials.json |
Provider API keys |
4-Infrastructure/infra/secrets/appflowy.env |
AppFlowy secrets |
4-Infrastructure/deploy/cupfox/pre-infect-backup/porkbun.env |
Porkbun API key + secret |
4-Infrastructure/storage/restic/restic.env |
Restic + Garage credentials |
API KEYS/racknerd_510bd9c_root.txt |
Racknerd credentials |
Porkbun DNS
- API key + secret stored in SOPS-encrypted
porkbun.env
- Used by Caddy for DNS-01 wildcard certificate challenges
- Verified working:
/ping and /dns/retrieve/researchstack.info
Post-Quantum Cryptography
| Layer |
Status |
| Tailscale |
X25519Kyber768 hybrid key exchange active (v1.98+) |
| SSH (all nodes) |
mlkem768x25519-sha256 preferred in sshd_config and ssh_config |
| Garage RPC |
Tailscale transport only (no direct PQ on RPC layer) |
Node Details
qfox-1
| Spec |
Value |
| OS |
Arch Linux, kernel 7.0.9-1-cachyos |
| CPU |
AMD Ryzen (GPU compute available) |
| Disk |
1.8 TB NVMe |
| Memory |
— |
| Tailscale |
100.88.57.96 |
| Garage |
primary node, S3 endpoint |
| SSH config |
~/.ssh/config entry qfox-1 (local) |
nixos-laptop
| Spec |
Value |
| OS |
NixOS 26.05.20260521.f83fc3c (Yarara) |
| Disk |
459G NVMe, 394G free |
| Memory |
14 GiB total |
| Tailscale |
100.102.173.61 |
| k3s |
v1.35.4+k3s1, single-node control plane |
| Authentik |
Podman, port 9000 |
| Garage |
storage node (ord zone) |
| zram |
enabled in NixOS config |
361395-1 (Netcup VPS)
| Spec |
Value |
| OS |
Debian 13 (OpenSSH_10.0p2) |
| Public IP |
46.232.249.226 |
| Disk |
125G, 66G free |
| Memory |
— |
| Tailscale |
100.110.163.82 |
| Garage |
storage node (fra zone) |
| zram |
2G zstd (manual zramctl) |
| APT issues |
enterprise.proxmox.com returns 401; pve-no-subscription repo duplicated |
microvm-racknerd
| Spec |
Value |
| OS |
Debian (microVM) |
| Public IP |
172.245.19.182 |
| Disk |
9.1G, 6.4G free |
| Tailscale |
100.101.247.127 |
| Role |
Caddy reverse proxy, public edge |
| Ports |
80, 443 open to internet |
nixos-steamdeck-1
| Spec |
Value |
| OS |
NixOS |
| Tailscale |
100.85.244.73 |
| Hostname |
steamdeck |
| Role |
GPU compute, planned edge LLM (3B-7B) |
| GPU |
RDNA 2 |
| Status |
just onboarded |
Open Issues
| # |
Issue |
Node |
Priority |
Notes |
| 1 |
k3s Authentik PostgreSQL read-only filesystem |
nixos-laptop |
Low |
Using standalone Podman instead |
| 2 |
k3s Authentik Redis image pull failure |
nixos-laptop |
Low |
Bitnami tags removed; Valkey already in use |
| 3 |
361395-1 APT 401 + duplicate repos |
361395-1 |
Low |
Cleanup sources.list when convenient |
| 4 |
dracocomp offline |
— |
Low |
Unreachable 3+ days |
| 5 |
Garage S3 API only on qfox-1 localhost |
qfox-1 |
Low |
Remote access via SSH tunnel or Tailscale funnel |
| 6 |
Caddy admin API returns null certs JSON |
racknerd |
Info |
Cert is functional; API introspection mismatch |
Access Cheat Sheet
# SSH shortcuts (from ~/.ssh/config)
ssh nixos-laptop
ssh racknerd # alias for microvm-racknerd
ssh 361395-1
ssh steamdeck # nixos-steamdeck-1 (100.85.244.73)
# Tailscale direct
ssh -o StrictHostKeyChecking=accept-new root@100.110.163.82
# Authentik (local on nixos-laptop)
curl http://127.0.0.1:9000
# Caddy reload (on racknerd)
systemctl reload caddy
# Garage status
sudo /usr/local/bin/garage -c /etc/garage/garage.toml status
# Decrypt secrets
cd "/home/allaun/Research Stack"
sops --decrypt 4-Infrastructure/infra/secrets/credentials.json
# k3s on nixos-laptop
kubectl get pods -n services
kubectl get svc -n services
# restic backup (from qfox-1)
bash 4-Infrastructure/storage/restic/backup.sh full
Changelog
| Date |
Change |
| 2026-05-22 |
Redis replaced with Valkey in Authentik compose |
| 2026-05-22 |
Caddy upstreams switched from k3s NodePort 30800 to standalone Podman 9000 |
| 2026-05-23 |
infra-controller deployed on 361395-1 (Netcup); systemd timer every 5 min |
| 2026-05-23 |
nixos-steamdeck-1 onboarded (100.85.244.73, NixOS, RDNA 2 GPU) |
| 2026-05-22 |
nixos-laptop Tailscale IP changed 100.119.165.120 → 100.102.173.61 |
Automation: infra-controller on 361395-1
The infra-controller is the central health orchestration daemon running on the Netcup VPS (361395-1). It probes all nodes every 5 minutes via SSH over the Tailscale mesh.
Architecture
361395-1 (Netcup) — CONTROL PLANE
├── infra-controller.timer (systemd, every 5 min)
├── infra-controller.service (oneshot)
├── Receipts: ~/.cache/infra-controller.jsonl (hash-chained)
└── Alerting: local postfix → admin@researchstack.info
Probes (SSH → each node):
qfox-1 → system, restic, garage, garage_buckets, gdrive_offload
nixos-laptop → system, k3s
microvm-racknerd → system, caddy
nixos-steamdeck-1 → system
361395-1 (local) → system, garage, garage_buckets
Roles (affects alert severity):
CRITICAL: microvm-racknerd, nixos-laptop → alert on down
OPTIONAL: qfox-1, nixos-steamdeck-1 → log only
Receipts
- Schema:
infra_controller_receipt_v1
- Format: JSONL hash-chain, one entry per cycle
- Local:
~/.cache/infra-controller.jsonl (always available)
- S3 backup: planned (s3://research-stack/agent-receipts/)
Commands
# Manual run
ssh 361395-1 "cd '/home/allaun/Research Stack' && python3 4-Infrastructure/auto/infra_controller.py --probe-only"
# View latest receipt
ssh 361395-1 "tail -1 ~/.cache/infra-controller.jsonl | python3 -m json.tool"
# Watch journal
ssh 361395-1 "journalctl -u infra-controller.service -f"
# Timer status
ssh 361395-1 "systemctl status infra-controller.timer"
Code location
4-Infrastructure/auto/infra_controller.py — main daemon
4-Infrastructure/auto/lib/probe.py — SSH probe runner
4-Infrastructure/auto/lib/receipt.py — receipt schema + hash-chain
4-Infrastructure/auto/lib/alerting.py — email/webhook/dashboard dispatch
4-Infrastructure/auto/lib/config.py — YAML config loader
4-Infrastructure/auto/config/nodes.yaml — node inventory + thresholds
4-Infrastructure/auto/nodes/*.sh — per-probe collector scripts (bash)
| 2026-05-21 | Wildcard TLS *.researchstack.info deployed via Porkbun DNS-01 |
| 2026-05-21 | Porkbun API keys regenerated and re-encrypted |
| 2026-05-20 | Garage cluster bumped to replication_factor=3 across all nodes |
| 2026-05-20 | zram enabled cluster-wide |
| 2026-05-19 | NixOS flake conversion + k3s bootstrap on nixos-laptop |
| 2026-05-18 | Garage buckets created: research-stack, db-scratch, rds-overflow, snap-zone, gdrive-mirror |