mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
- RUNBOOK.md: k3s/FPGA/Tailscale/GPU/DNS ops procedures - FPGA_PROGRAMMING_GUIDE.md: SUBLEQ format, memory map, 3 examples - DISASTER_RECOVERY.md: backup/restore for all components - API_DOCS.md: dashboard, credential, registry, jobs, blobs APIs
6.9 KiB
6.9 KiB
Disaster Recovery — Research Stack
Last updated: 2026-05-29
Procedures for backing up and restoring all Research Stack components.
k3s Cluster
Backup etcd
# Snapshot etcd (on control plane node — nixos)
sudo k3s etcd-snapshot save \
--name researchstack-backup \
--dir /var/lib/rancher/k3s/server/db/snapshots
# List snapshots
sudo ls -la /var/lib/rancher/k3s/server/db/snapshots/
# Copy snapshot off-node
scp /var/lib/rancher/k3s/server/db/snapshots/researchstack-backup-* \
user@backup-host:/backups/k3s/
Restore from Snapshot
# On control plane (nixos):
sudo systemctl stop k3s
# Restore
sudo k3s server \
--cluster-reset \
--cluster-reset-restore-path=/var/lib/rancher/k3s/server/db/snapshots/researchstack-backup-<timestamp>
# Restart
sudo systemctl start k3s
# Verify
export KUBECONFIG=/tmp/researchstack-kubeconfig.yaml
kubectl get nodes
kubectl get pods -A
Backup Manifests
All Kubernetes manifests are in the git repo. The source of truth is:
cd ~/Research\ Stack
git push origin main
Automated Backup Schedule
Create a cron job on nixos:
# /etc/cron.d/k3s-backup
0 3 * * * root k3s etcd-snapshot save --name researchstack-backup --dir /var/lib/rancher/k3s/server/db/snapshots && \
find /var/lib/rancher/k3s/server/db/snapshots/ -mtime +7 -delete
FPGA — Tang Nano 9K
Backup Bitstream
The bitstream source and compiled output are in the git repo:
cd ~/Research\ Stack
# Source
ls 4-Infrastructure/hardware/*.v
# Compiled bitstream
ls 4-Infrastructure/hardware/research_stack_top.fs
Re-flash from Git
cd ~/Research\ Stack
# Rebuild if needed
cd 4-Infrastructure/hardware && bash build_research_stack.sh
# Flash
openFPGALoader -b tangnano9k research_stack_top.fs
# Verify
openFPGALoader -b tangnano9k --verify research_stack_top.fs
Backup SRAM Contents
SRAM contents are volatile (lost on power cycle). To preserve runtime state:
# Dump memory via UART before power-off
import serial, struct
ser = serial.Serial('/dev/ttyUSB0', 115384, timeout=10)
# Trigger memory dump (send HALT with dump flag)
# ... protocol-specific ...
# Read and save
with open('fpga_memory_dump.bin', 'wb') as f:
data = ser.read(8192) # 4K words = 8K bytes
f.write(data)
ser.close()
Tailscale
Re-authenticate Node
# On the node that lost auth:
sudo systemctl restart tailscaled
tailscale up --authkey=<TS_AUTH_KEY>
# Or interactive
tailscale up
Re-join Tailnet
# Check current status
tailscale status
# If node is missing from tailnet:
# 1. Generate new auth key at https://login.tailscale.com/admin/settings/keys
# 2. On the node:
sudo tailscale up --authkey=tskey-auth-<key>
# Verify connectivity
tailscale ping nixos-laptop
tailscale ping qfox-1
Backup Tailscale State
Tailscale state is stored at /var/lib/tailscale/:
# Backup state directory
sudo tar czf /backups/tailscale-state-$(date +%Y%m%d).tar.gz \
/var/lib/tailscale/
# Restore
sudo systemctl stop tailscaled
sudo tar xzf /backups/tailscale-state-*.tar.gz -C /
sudo systemctl start tailscaled
Git Repository
Backup
The canonical backup is the remote origin. Ensure all changes are pushed:
cd ~/Research\ Stack
# Check for unpushed commits
git log --oneline origin/main..HEAD
# Push everything
git push origin main --tags
# Verify clean state
git status --branch --short --untracked-files=all
Restore from Remote
# Clone fresh
cd ~
git clone <remote-url> "Research Stack"
# Or reset to remote state
cd ~/Research\ Stack
git fetch origin
git reset --hard origin/main
Backup Remotes
# List remotes
cd ~/Research\ Stack
git remote -v
# Add backup remote
git remote add backup <backup-url>
git push backup main --tags
Secrets (sops-nix / age)
Backup age Keys
# age key location (NixOS)
cat /etc/age/keys.txt
# Backup
cp /etc/age/keys.txt /backups/age-keys-$(date +%Y%m%d).txt
chmod 600 /backups/age-keys-*.txt
# Or from home directory
cat ~/.config/sops/age/keys.txt
Restore age Keys
# Restore key file
cp /backups/age-keys-*.txt /etc/age/keys.txt
chmod 600 /etc/age/keys.txt
# Verify sops can decrypt
sops -d secrets.enc.yaml
Backup sops Configuration
# The .sops.yaml config is in the repo
cat ~/Research\ Stack/.sops.yaml
# Encrypted secrets are also in the repo
find ~/Research\ Stack -name '*.enc.yaml' -o -name '*.enc.json'
Regenerate age Key (Last Resort)
# Generate new key pair
age-keygen -o /etc/age/keys.txt
# Get public key
age-keygen -y /etc/age/keys.txt
# Re-encrypt all secrets with new key
# (requires old key or plaintext backup)
sops updatekeys secrets.enc.yaml
DNS — Porkbun
Backup API Key
# From k8s secret
kubectl get secret porkbun-credentials -n services \
-o jsonpath='{.data.api-key}' | base64 -d
# Back up securely
echo "<api-key>" | age -r <backup-age-pubkey> > /backups/porkbun-api.age
# Or store in password manager
Recover API Key
- Log in to Porkbun
- Navigate to Account → API Access
- Regenerate or copy existing API key
- Update k8s secret:
kubectl create secret generic porkbun-credentials \
-n services \
--from-literal=api-key=<new-key> \
--dry-run=client -o yaml | kubectl apply -f -
# Restart Caddy to pick up new key
kubectl rollout restart deployment/caddy -n services
Verify DNS Records
dig researchstack.info +short
dig auth.researchstack.info +short
dig registry.researchstack.info +short
# Test Porkbun API
curl -X POST https://api.porkbun.com/api/json/v3/ping \
-H "Content-Type: application/json" \
-d '{"apikey": "<key>", "secretapikey": "<secret>"}'
Recovery Priority Order
When restoring from a total failure, follow this order:
| Step | Component | Depends On |
|---|---|---|
| 1 | Tailscale | Auth key (from password manager or backup) |
| 2 | Git repo | Network connectivity (Tailscale or direct) |
| 3 | age keys | Backup location |
| 4 | k3s cluster | etcd snapshot + age keys for secrets |
| 5 | DNS/Porkbun | API key (from backup or Porkbun account) |
| 6 | FPGA | Git repo (source + bitstream) |
| 7 | Services | k3s cluster + secrets + DNS |
Full System Checklist
After recovery, verify each component:
- Tailscale:
tailscale statusshows all 5 nodes - k3s:
kubectl get nodesshows all nodes Ready - Pods:
kubectl get pods -A— all Running/Succeeded - DNS:
dig researchstack.inforesolves correctly - TLS: cert valid (
openssl s_client) - Auth:
auth.researchstack.infoloads Authentik - Funnel:
361395-1.tail4e7094.ts.netresponds - Ollama:
curl http://100.88.57.96:31434/api/tagsreturns models - FPGA:
openFPGALoader --detectsees Tang Nano 9K - Dashboard:
https://researchstack.infoshows Homer