This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
# Hardware
|
||||
|
||||
Physical inventory.
|
||||
|
||||
| Item | Model | Serial | Purchased | Warranty | Notes |
|
||||
|---|---|---|---|---|---|
|
||||
| Gateway | UniFi UDR7 | _redact on public_ | | | |
|
||||
| _add yours_ | | | | | |
|
||||
@@ -0,0 +1,17 @@
|
||||
# Frostlabs Homelab
|
||||
|
||||
Operational documentation and disaster-recovery runbooks.
|
||||
|
||||
!!! info "How this site works"
|
||||
The source of truth is the Markdown in this repository on `git.frostlabs.me`.
|
||||
On every push to `main`, Gitea Actions rebuilds and redeploys this site. The
|
||||
rendered page you're reading is disposable — if it's ever lost, it rebuilds
|
||||
from the repo. The repo itself lives in three independent places (Gitea VPS,
|
||||
homelab, laptop), which is what makes this survive a total system failure.
|
||||
|
||||
## Start here
|
||||
|
||||
- [Network](network/index.md) — topology, VLAN/subnet plan, firewall policy
|
||||
- [Runbooks](runbooks/index.md) — step-by-step recovery procedures
|
||||
- [Services](services/index.md) — what runs where
|
||||
- [Hardware](hardware/index.md) — physical inventory
|
||||
@@ -0,0 +1,21 @@
|
||||
# Firewall
|
||||
|
||||
Zone-based policy on the UDR7. Document the **intent** first, then the rules
|
||||
that implement it — future-you (mid-outage) needs the reasoning, not just a
|
||||
rule dump.
|
||||
|
||||
## Policy matrix
|
||||
|
||||
| From \ To | Management | Trusted | IoT | Guest | WAN |
|
||||
|---|---|---|---|---|---|
|
||||
| Management | — | allow | allow | allow | allow |
|
||||
| Trusted | deny | — | allow | deny | allow |
|
||||
| IoT | deny | deny | — | deny | allow* |
|
||||
| Guest | deny | deny | deny | — | allow |
|
||||
|
||||
\* IoT to WAN often restricted to specific destinations. Document exceptions.
|
||||
|
||||
## Rationale
|
||||
|
||||
Explain each non-obvious allow/deny: why IoT can't reach Trusted, which
|
||||
management exceptions exist, and any per-device carve-outs.
|
||||
@@ -0,0 +1,8 @@
|
||||
# Network
|
||||
|
||||
The homelab runs on a UniFi UDR7 with a segmented VLAN design and a
|
||||
zone-based firewall policy. This section is the reference for that design.
|
||||
|
||||
- [Topology](topology.md) — physical + logical layout
|
||||
- [VLANs & Subnets](vlans.md) — the segmentation plan
|
||||
- [Firewall](firewall.md) — inter-zone policy and rationale
|
||||
@@ -0,0 +1,27 @@
|
||||
# Topology
|
||||
|
||||
!!! note "Template"
|
||||
The diagram below is a scaffold. Replace the nodes/edges with your actual
|
||||
layout. It renders automatically — Material draws ` ```mermaid ` blocks.
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
WAN[Internet] --> UDR7[UniFi UDR7]
|
||||
UDR7 --> SW[Aggregation Switch]
|
||||
SW --> AP[Access Points]
|
||||
SW --> VLAN_MGMT[VLAN 10 · Management]
|
||||
SW --> VLAN_TRUST[VLAN 20 · Trusted]
|
||||
SW --> VLAN_IOT[VLAN 30 · IoT]
|
||||
SW --> VLAN_GUEST[VLAN 40 · Guest]
|
||||
```
|
||||
|
||||
## Physical
|
||||
|
||||
| Device | Model | Location | Notes |
|
||||
|---|---|---|---|
|
||||
| Gateway | UniFi UDR7 | _rack_ | _replace with real detail_ |
|
||||
| Switch | _model_ | _location_ | _uplinks / PoE_ |
|
||||
|
||||
## Logical
|
||||
|
||||
Describe uplinks, tagged/untagged ports, and where each VLAN is trunked.
|
||||
@@ -0,0 +1,18 @@
|
||||
# VLANs & Subnets
|
||||
|
||||
!!! warning "Fill in real values"
|
||||
The rows below are an **example format**, not your live plan. Replace them
|
||||
with your actual VLAN IDs, subnets, and gateways. On the private site this
|
||||
is fine; keep the [public portfolio version](../index.md) sanitized.
|
||||
|
||||
| VLAN | Name | Subnet | Gateway | DHCP | Purpose |
|
||||
|---|---|---|---|---|---|
|
||||
| 10 | Management | 10.0.10.0/24 | 10.0.10.1 | reserved | Switches, APs, UDR7 UI |
|
||||
| 20 | Trusted | 10.0.20.0/24 | 10.0.20.1 | yes | Workstations, phones |
|
||||
| 30 | IoT | 10.0.30.0/24 | 10.0.30.1 | yes | Smart-home, Matter/Thread |
|
||||
| 40 | Guest | 10.0.40.0/24 | 10.0.40.1 | yes | Isolated guest access |
|
||||
|
||||
## Notes
|
||||
|
||||
- Reserved (static) leases: document them per device.
|
||||
- mDNS / service discovery across VLANs: note where it's allowed and how.
|
||||
@@ -0,0 +1,45 @@
|
||||
# Disaster Recovery: Git + Docs stack
|
||||
|
||||
Goal: restore `git.frostlabs.me` and the docs sites after losing the VPS.
|
||||
|
||||
## What state actually matters
|
||||
|
||||
| Thing | Where | Rebuildable? |
|
||||
|---|---|---|
|
||||
| Gitea data (repos, DB, config) | `/opt/gitea/gitea/` (SQLite + repos) | **No — back this up** |
|
||||
| Runner registration | `/opt/gitea/runner/.runner` | No (but re-registerable in minutes) |
|
||||
| Built sites | `/srv/www/` | Yes — rebuilt on next push |
|
||||
| Tunnel / nginx / compose config | `/opt/gitea/*.yml`, `.env`, `nginx.conf` | Keep a copy off-box |
|
||||
|
||||
The docs repos themselves are safe as long as one clone survives (VPS, homelab,
|
||||
laptop). This runbook is about restoring the **server**.
|
||||
|
||||
## Backup (do this on a schedule)
|
||||
|
||||
```bash
|
||||
# Off-box snapshot of everything stateful on the VPS
|
||||
rsync -aP /opt/gitea/ backup-target:/backups/gitea/
|
||||
```
|
||||
|
||||
!!! tip
|
||||
A `gitea dump` is the "proper" way, but for a single-user SQLite instance an
|
||||
rsync of `/opt/gitea` while the stack is stopped is simplest and complete.
|
||||
|
||||
## Restore onto a fresh VPS
|
||||
|
||||
1. Provision the box, install Docker + compose.
|
||||
2. Recreate `/opt/gitea/` and restore the backup into it.
|
||||
3. Recreate `.env` with `TUNNEL_TOKEN` and (optionally) `RUNNER_TOKEN`.
|
||||
4. `mkdir -p /srv/www/docs-public /srv/www/docs-private`
|
||||
5. `docker compose up -d`
|
||||
6. In Cloudflare Zero Trust, point the tunnel at the new box (token is the same
|
||||
tunnel, so hostnames just reattach). Confirm `git.frostlabs.me` loads.
|
||||
7. If the runner didn't reconnect, re-register it (Site Admin → Actions → Runners).
|
||||
8. Push any repo (or hit **Run workflow**) to rebuild both sites into `/srv/www`.
|
||||
|
||||
## Verify
|
||||
|
||||
- [ ] `git.frostlabs.me` reachable, repos present
|
||||
- [ ] `runbook.frostlabs.me` rebuilt and gated by CF Access
|
||||
- [ ] `docs.frostlabs.me` rebuilt and public
|
||||
- [ ] a test push triggers a green Actions run
|
||||
@@ -0,0 +1,6 @@
|
||||
# Runbooks
|
||||
|
||||
Step-by-step procedures for when something is on fire. Written to be followed
|
||||
under stress — imperative steps, exact commands, no ambiguity.
|
||||
|
||||
- [Disaster Recovery](disaster-recovery.md) — rebuild the docs/Git stack from nothing
|
||||
@@ -0,0 +1,12 @@
|
||||
# Services
|
||||
|
||||
What runs where, and how to reach it.
|
||||
|
||||
| Service | Host | VLAN | URL / Port | Notes |
|
||||
|---|---|---|---|---|
|
||||
| Gitea | VPS (Linode) | — | git.frostlabs.me | via Cloudflare Tunnel |
|
||||
| Docs (this site) | VPS (Linode) | — | runbook.frostlabs.me | nginx + CF Access |
|
||||
| _add yours_ | | | | |
|
||||
|
||||
For each service, link to its own page with config location, backup method,
|
||||
and restore steps.
|
||||
Reference in New Issue
Block a user