262 lines
10 KiB
YAML
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. |