262 lines
10 KiB
YAML

# Central YAML Source of Truth for Nathan's Lab (2026)
# Edit and commit this file; Ansible playbooks should read this as canonical.
lab_name: "nathan-lab-2026"
canonical_source: "ansible/group_vars/all.yml"
# The standard operational user created on every managed host.
# Override per-host in host_vars/ if a node uses a different login.
lab_ansible_user: "chester"
# Omada Open API credentials are sourced from the encrypted vault file.
omada_client_id: "{{ vault_omada_client_id }}"
omada_client_secret: "{{ vault_omada_client_secret }}"
omada_id: "{{ vault_omada_id }}"
omada_base_url: "{{ vault_omada_base_url }}"
networks:
main:
vlan: 1
cidr: "10.0.0.0/24"
dhcp_pool: "10.0.0.100-10.0.0.240"
gateway: "10.0.0.1"
purpose: "Family / wired / main SSID"
infra:
vlan: 10
cidr: "10.0.10.0/24"
reserved: "10.0.10.2-10.0.10.50"
purpose: "Management / Proxmox / NAS / Heimdall mgmt"
iot:
vlan: 50
cidr: "10.0.50.0/24"
dhcp_pool: "10.0.50.100-10.0.50.199"
purpose: "IoT devices (Omada)"
guest:
vlan: 30
cidr: "10.0.30.0/24"
dhcp_pool: "10.0.30.100-10.0.30.200"
purpose: "Guest WiFi (isolated)"
compute:
vlan: 200
cidr: "10.0.200.0/24"
purpose: "Swarm / AI grid / ephemeral compute"
lab_hosts:
er7212pc:
role: gateway
current_ip: "10.0.0.2"
desired_ip: "10.0.0.2"
note: "DHCP + Omada controller"
pve01:
physical_backing_host: "pve04"
role: proxmox
current_ip: "10.0.0.201"
desired_ip: "10.0.10.11"
pve02:
role: proxmox
current_ip: "10.0.0.202"
desired_ip: "10.0.10.12"
pve03:
role: proxmox
current_ip: "10.0.0.203"
desired_ip: "10.0.10.13"
pve04:
replacement_status: "retired-identity-now-backing-pve01"
role: retired_physical_alias
current_ip: "10.0.0.204"
desired_ip: "10.0.10.14"
swarm-manager-1:
current_ip: "10.0.0.211"
desired_ip: "10.0.200.11"
swarm-manager-2:
current_ip: "10.0.0.212"
desired_ip: "10.0.200.12"
swarm-manager-3:
current_ip: "10.0.0.213"
desired_ip: "10.0.200.13"
statler:
role: standalone_vm
current_ip: "10.0.0.210"
desired_ip: "10.0.0.210"
hypervisor_host: "pve02"
note: "Standalone Ubuntu 24.04 VM planned on pve02 with 2 vCPU, 10 GB RAM, and 32 GB disk."
swarm-worker-1:
current_ip: "10.0.0.221"
desired_ip: "10.0.200.21"
swarm-worker-2:
current_ip: "10.0.0.222"
desired_ip: "10.0.200.22"
swarm-worker-3:
current_ip: "10.0.0.223"
desired_ip: "10.0.200.23"
ai-lenovo:
current_ip: "10.0.0.220"
desired_ip: "10.0.200.20"
onboarding_status: "tbd-needs-onboarding-like-heimdall"
ansible_managed: false
note: "Pending onboarding workflow before inclusion in active automation and monitoring groups."
synology:
current_ip: "10.0.0.249"
desired_ip: "10.0.10.40"
terramaster:
current_ip: "10.0.0.250"
desired_ip: "10.0.10.41"
waldorf:
current_ip: "10.0.0.251"
desired_ip: "10.0.200.30"
lifecycle_status: "retired-shutdown"
ansible_managed: false
monitoring_enabled: false
note: "Retired host; excluded from active monitoring and deployment inventories."
watchtower:
current_ip: "10.0.0.200"
desired_ip: "10.0.10.200"
heimdall:
role: beelink
current_ip: null
desired_ip:
mgmt: "10.0.10.2"
lan: "10.0.0.50"
# === MONITORING INFRASTRUCTURE ===
# Environment-specific configuration for monitoring stack
monitoring:
stack_user: "chester"
heimdall_redis: "10.0.0.151:6379"
watchtower_ip: "10.0.0.200"
grafana_domain: "grafana.castaldifamily.com"
uptime_domain: "status.castaldifamily.com"
dozzle_domain: "logs.castaldifamily.com"
authentik_host: "https://sso.castaldifamily.com"
# grafana_admin_password: DEFINE IN VAULT
# === EDGE ROUTING TOPOLOGY ===
# Canonical ingress model: Traefik runs on a dedicated edge host outside Swarm.
# Swarm and standalone hosts publish routes through traefik-kop agents.
edge_routing:
ingress_mode: "external-traefik"
edge_host:
name: "heimdall"
ip: "10.0.0.151"
ssh_port: 22
http_port: 80
https_port: 443
integration:
# Watchtower-hosted traefik-kop instance (publishes Watchtower container routes)
agent_image: "ghcr.io/jittering/traefik-kop:latest"
redis_addr: "10.0.0.151:6379"
bind_ip: "10.0.0.200" # Watchtower IP — correct for routes originating on Watchtower
swarm:
# Swarm-hosted traefik-kop instance (publishes Swarm service routes)
# bind_ip MUST be a Swarm node IP — the Swarm routing mesh makes published
# ports available on ALL nodes, so Traefik routes inbound requests here.
bind_ip: "10.0.0.212" # swarm-manager-2 (current Leader; was swarm-manager-1 before it went down)
proxy_network: "proxy-net" # Swarm overlay network; separate from heimdall's bridge of same name
stack_deploy_target: "swarm-manager-2"
migration_rules:
deploy_traefik_in_swarm: false
use_external_proxy_network: true
notes:
- "Services should attach to swarm overlay proxy-net for east-west traffic."
- "Ingress is terminated by external Traefik at 10.0.0.151 via traefik-kop updates."
# Per-stack placement node overrides.
# Update when the deploy target node changes (e.g., after node replacement).
gitea_placement_node: "swarm-manager-2"
authentik_placement_node: "swarm-manager-2"
# === SERVICE SECRETS (set via: ansible-vault encrypt_string) ===
vault_gitea_db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
34623365623337336535656164623637656633356661373162356438646637333932663765323134
6261626565646166353966393366666434356434333263330a333666393765646233303663363738
65616665393235323132623462373435373637363262363539626163373061643930393730346633
3232373866663034310a343661306634313766313765623439626339353635626232663662323365
6666
vault_authentik_secret_key: !vault |
$ANSIBLE_VAULT;1.1;AES256
61373834613362356638303166376135613133616139613963333632613430636136623062373161
6335636331386565386139376234663362396361653463660a613834313263653039376363396264
62383166346563326630323734643462326438643436626565656633636234323835333033353130
3535306539626339320a323431666164353038323166633663656265613266366535623130323165
38353833393934393764376331333464663337616432623033303830393464303966643036656538
34396337363163663566383063396130616530633363636461343531636438303963653733343830
66636165656563653164383364643032373135666263316137623761656332316130313235623232
33623462343639366566
vault_authentik_postgres_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
37356530373764353038343038663662333535323436336663613239333234363036626462656130
3138313535353838306563663565663230646561313234390a313166623232383364623766383961
30363065373065353365616239663562333833313139636137616561616465656462613238323932
3630333538366430370a616263633263336436303662373530323161316534313737366633643535
30326636383131353265613463363431666536313966366364666564623637343737
vlan_defaults:
dns_domain: "home.lab"
ntp_servers:
- "10.0.10.2"
# Plex bootstrap claim token — used only on first server claim.
vault_plex_claim: !vault |
$ANSIBLE_VAULT;1.1;AES256
31373365323534353264373735363937623566646633653434613038396463303164396138306661
3130323134656463383835366130663632323561326265350a653162643064643563383738373637
36363135613735663037303036613637313431336139343430313963393930303532666366336365
3734386639393336310a323964386233346134616164656663393731376632643037313734323830
65366334356531623339643066373237306263323063383963363330346665316435
# Authentik outpost tokens for standalone arr services on statler.
vault_authentik_token_sonarr: !vault |
$ANSIBLE_VAULT;1.1;AES256
39303463306665356436626265653339663163613464366237663234376135306366303739343266
3762646230666263393330373833393037613165373337380a336663646161613534353232663761
65376666663063643066323831366265633337653630666235636234393130646361383032383032
3433393235633762390a376561303866373739613663333461643938353931626134336665383164
34346538376436313438313733393963303735646632323739313137626466356138636266396434
61363737636139386665616438646439366139303739646530316566373563306565623637363661
343938653662646132373565303836353030
vault_authentik_token_radarr: !vault |
$ANSIBLE_VAULT;1.1;AES256
32363735353663623031356362323765616232326234333564323839626236653634626263313765
6335653537656531396431366662616163366166633462390a346363633364363866373732373939
61666261616266333465393837383337313565613539303732396530333833666563653139353238
6537383336613933370a333662323339396463353134363635383430353133646331376533303861
30303765373566353633643261376430363837386239363261396235333033636563366231323564
35643564663866653831663633333436653330363130656631356166363731356639643238656530
643062636137396333383438623534346636
vault_authentik_token_sabnzbd: !vault |
$ANSIBLE_VAULT;1.1;AES256
30373635366337343236353866623234383665386461356637353534666461613466373463616531
3837646263643864636331343364663563666531333861660a626335393762353862663564656465
61373430336336373062623563633832383261333035353432666265313435363132316561383130
3236643962313765630a386634313331643639363035623663616166313532623932643162633762
64353335393764653031633033323862643732326434613564363935336166386239613932653765
32323335306634326133613334386262316464613166373031376362653266653937303131653165
376436643431366561323866383231343362
# Usage notes:
# - Treat this file as the single source of truth for IPs and VLANs.
# - Ansible playbooks should read `networks` and `lab_hosts` to render configs,
# update `inventory/hosts.ini`, and generate DHCP reservation templates.
#
# Discussion queue (2026-03-13):
# - Decide NAS + Ansible + Watchtower reporting model (agentless scrape, exporter sidecar, or API/blackbox only).
# - Decide Omada onboarding scope and what should be automated via Ansible versus documented/manual operations.