2026-03-27 02:28:51 +01:00
|
|
|
# Railiance Stack — Full Deploy Runbook
|
|
|
|
|
|
|
|
|
|
> **When to use this:** Starting from a bare server (post-OS install) or rebuilding
|
|
|
|
|
> after a catastrophic failure. For day-to-day operations use the individual layer
|
|
|
|
|
> repos. See ADR-003 for layer boundaries and ADR-004 for connectivity posture.
|
|
|
|
|
|
|
|
|
|
## Pre-conditions checklist
|
|
|
|
|
|
|
|
|
|
Before starting, verify you have:
|
|
|
|
|
|
2026-08-22 12:34:25 +02:00
|
|
|
- [ ] SSH access to the selected inventory host. `Railiance01` is the current
|
|
|
|
|
primary; `CoulombCore` is legacy/frozen and is not a default deployment target.
|
2026-03-27 02:28:51 +01:00
|
|
|
- [ ] SOPS age private key available (`~/.config/sops/age/keys.txt` or `SOPS_AGE_KEY` env)
|
|
|
|
|
- [ ] ops-bridge running on the workstation (needed for state hub MCP): `make mcp-http` in `~/the-custodian/state-hub/`
|
2026-07-09 10:34:44 +02:00
|
|
|
- [ ] Forgejo accessible (git pull on remote): SSH via `forgejo-remote:coulomb/<repo>.git`
|
|
|
|
|
- [ ] Gitea on coulombcore remains read-only fallback only (`gitea-remote` for emergency rollback)
|
2026-03-27 02:28:51 +01:00
|
|
|
- [ ] If re-provisioning from scratch: Hetzner/HostEurope API credentials decryptable via SOPS
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## S1 — Infrastructure Substrate (`railiance-infra`)
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# On workstation
|
|
|
|
|
cd ~/railiance-infra
|
|
|
|
|
|
|
|
|
|
# Provision server (skip if server already exists)
|
|
|
|
|
make tf-plan # review Terraform plan
|
|
|
|
|
make tf-apply # create/update server
|
|
|
|
|
|
2026-08-22 12:34:25 +02:00
|
|
|
# Converge OS baseline on the selected inventory host
|
|
|
|
|
ssh -i ~/.ssh/id_ops tegwick@92.205.62.239 \
|
2026-03-27 02:28:51 +01:00
|
|
|
'cd ~/railiance-infra && git pull && \
|
|
|
|
|
cd ansible && ansible-playbook playbooks/bootstrap.yaml \
|
2026-08-22 12:34:25 +02:00
|
|
|
-c local --become -l Railiance01'
|
2026-03-27 02:28:51 +01:00
|
|
|
|
|
|
|
|
# Verify OS baseline
|
|
|
|
|
make verify
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**Checkpoint:** UFW active, fail2ban running, swap enabled, nproc limits in place,
|
|
|
|
|
SOPS/age installed.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## S2 — Cluster Runtime (`railiance-cluster`)
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-08-22 12:34:25 +02:00
|
|
|
# On the selected cluster host (Railiance01 for the current primary)
|
|
|
|
|
ssh -i ~/.ssh/id_ops tegwick@92.205.62.239
|
2026-03-27 02:28:51 +01:00
|
|
|
|
|
|
|
|
cd ~/railiance-cluster
|
2026-08-22 12:34:25 +02:00
|
|
|
make converge # installs k3s, Helm, cert-manager, Traefik, cnpg operator
|
2026-03-27 02:28:51 +01:00
|
|
|
make smoke # runs cluster health assertions
|
|
|
|
|
```
|
|
|
|
|
|
2026-08-22 12:34:25 +02:00
|
|
|
**Checkpoint:** k3s running, Helm available, cert-manager and Traefik pods Running,
|
2026-03-27 02:28:51 +01:00
|
|
|
cnpg-system namespace active.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## S3 — Platform Services (`railiance-platform`)
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-08-22 12:34:25 +02:00
|
|
|
# On the current primary (kubectl available after S2)
|
2026-03-27 02:28:51 +01:00
|
|
|
cd ~/railiance-platform && git pull
|
|
|
|
|
|
2026-07-09 10:34:44 +02:00
|
|
|
# Deploy Forgejo database cluster (production on railiance01)
|
|
|
|
|
# Credentials via SOPS — see railiance-platform docs/forgejo-backup.md
|
|
|
|
|
make forgejo-db-deploy
|
|
|
|
|
make forgejo-db-status
|
2026-03-27 02:28:51 +01:00
|
|
|
|
2026-07-09 10:34:44 +02:00
|
|
|
# Legacy coulombcore Gitea DB (read-only fallback — retain until T12 retires Gitea)
|
|
|
|
|
# make db-deploy && make db-status
|
2026-03-27 02:28:51 +01:00
|
|
|
|
2026-08-22 12:34:25 +02:00
|
|
|
# Deploy an optional cache only when a named workload requirement and custody
|
|
|
|
|
# path exist. Cache installation is not an unconditional S3 baseline step.
|
2026-03-27 02:28:51 +01:00
|
|
|
```
|
|
|
|
|
|
2026-08-22 12:34:25 +02:00
|
|
|
**Checkpoint:** `kubectl get cluster -n databases` shows `forgejo-db` healthy
|
|
|
|
|
on Railiance01; optional services are present only when explicitly required.
|
2026-03-27 02:28:51 +01:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## S4 — Developer Enablement (`railiance-enablement`)
|
|
|
|
|
|
2026-08-22 12:34:25 +02:00
|
|
|
Validate the consumer-facing paved paths; S4 does not deploy the forge runtime:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
cd ~/railiance-enablement && git pull
|
|
|
|
|
make check
|
|
|
|
|
make test
|
|
|
|
|
```
|
2026-03-27 02:28:51 +01:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## S5 — Workloads & Experience (`railiance-apps`)
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-08-22 12:34:25 +02:00
|
|
|
# Verify the forge through its operational owner.
|
|
|
|
|
cd ~/railiance-forge && git pull
|
|
|
|
|
make gitea-status
|
2026-03-27 02:28:51 +01:00
|
|
|
|
2026-08-22 12:34:25 +02:00
|
|
|
# Deploy each application through its owning rapp/release runbook. S5 does not
|
|
|
|
|
# own the forge runtime or generic rail/template behavior.
|
2026-03-27 02:28:51 +01:00
|
|
|
```
|
|
|
|
|
|
2026-07-09 10:34:44 +02:00
|
|
|
**Checkpoint:** `https://forgejo.coulomb.social` serves HTTPS; git clone/push via
|
|
|
|
|
`forgejo-remote`; state-hub `/state/health` returns 200.
|
2026-03-27 02:28:51 +01:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## ops-bridge tunnel setup (workstation)
|
|
|
|
|
|
|
|
|
|
After S2 is up, establish the persistent tunnels from the workstation:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
bridge up state-hub-coulombcore # state-hub HTTP (port 18000 remote)
|
|
|
|
|
bridge up state-hub-mcp-coulombcore # state-hub MCP (port 18001 remote)
|
2026-08-15 15:41:59 +02:00
|
|
|
bridge up k3s-api-coulombcore # CoulombCore k3s API (port 16443 local)
|
|
|
|
|
bridge up k3s-api-railiance01 # Railiance01 k3s API (port 16444 local)
|
2026-03-27 02:28:51 +01:00
|
|
|
```
|
|
|
|
|
|
2026-08-22 12:34:25 +02:00
|
|
|
Verify: `bridge status` shows the tunnels needed for the selected host connected.
|
2026-03-27 02:28:51 +01:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Recovery pointers
|
|
|
|
|
|
2026-07-09 10:34:44 +02:00
|
|
|
- **Forgejo backup/restore:** `railiance-platform/docs/forgejo-backup.md`, `docs/forgejo-restore-drill-evidence.md`
|
|
|
|
|
- **Cutover rollback:** `docs/forgejo-cutover-rollback.md`
|
2026-03-27 02:28:51 +01:00
|
|
|
- **Node overload / SSH unresponsive:** See `the-custodian/ops/runbooks/gitea-coulombcore.md` Issue #3
|
|
|
|
|
- **Incident report:** `the-custodian/ops/incidents/2026-03-26-coulombcore-runaway-agent-overload.md`
|
|
|
|
|
- **Cluster backup restore:** `railiance-cluster/tools/cmd/railiance-restore-s2`
|
2026-07-09 10:34:44 +02:00
|
|
|
- **Forgejo SSH:** NodePort `30022` on railiance01 (`forgejo-ssh-nodeport` in `forgejo` namespace)
|
2026-03-27 02:28:51 +01:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Layer dependency chain
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
S1 (infra) → S2 (cluster) → S3 (platform) → S4 (enablement) → S5 (workloads)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Each layer must be fully converged and verified before starting the next.
|
|
|
|
|
Never configure S2 concerns from S3+ repos (ADR-003 boundary rule).
|