Files
homelab-infra/apps/netbox/values.yaml
T
panxiao81 88a02ababa
lint / yaml (push) Has been cancelled
lint / ansible (push) Has been cancelled
lint / terraform (push) Has been cancelled
Establish clean homelab infrastructure baseline
Reorganize the brownfield repository, remove retired and generated artifacts, harden ignore rules, and record the GitOps/IaC redesign.
2026-09-09 16:47:20 +00:00

191 lines
8.8 KiB
YAML

# NetBox — IPAM + DCIM, candidate "source of truth for network facts".
# THIS IS AN EVALUATION DEPLOYMENT (see CONTEXT.md §1: adoption is not decided).
# Nothing else in the repo reads from NetBox yet; it is safe to delete outright.
#
# Chart: netbox/netbox 8.3.38 (app v4.6.5)
# helm repo add netbox https://netbox-community.github.io/netbox-chart/
#
# Shape mirrors the other k3s services here: external shared Postgres, private
# exposure over the Tailscale ingress, authentication delegated to Authelia OIDC.
# Pin the app image; the chart default matches but drifts on every chart bump.
image:
tag: v4.6.5
# --- Local break-glass superuser -------------------------------------------
# Deliberately kept, exactly like Grafana's local admin: NetBox's SSO group->
# superuser mapping does not exist (that feature is LDAP-only, see README), so
# the first SSO login lands as an ordinary user and needs promoting BY someone.
# Password is generated by the chart and preserved in the netbox-superuser Secret.
superuser:
name: admin
email: [email protected]
# NetBox refuses writes via any hostname not listed here. The pod IP is appended
# automatically (allowedHostsIncludesPodIP) for the k8s probes.
allowedHosts:
- netbox.ad.ddupan.top
- netbox.netbox.svc.cluster.local
- localhost
# Envoy terminates TLS and forwards plain HTTP, so Django sees an http:// request
# carrying an https:// Origin header. Without this, every POST (including the login
# form) fails CSRF verification — it presents as "login is broken", not "config is
# missing". Same requirement behind any TLS-terminating proxy.
csrf:
trustedOrigins:
- https://netbox.ad.ddupan.top
# It is an infrastructure source of truth on a private tailnet, but "on the
# tailnet" is not authentication — require a login for read access too.
#
# This logs a benign FutureWarning at startup ("LOGIN_REQUIRED is deprecated ...
# can be removed from your configuration file"): NetBox v5.0 drops the setting and
# makes login mandatory, i.e. true is the direction of travel. The warning is
# unavoidable via this chart — the ConfigMap always emits the key, and NetBox warns
# on false as well ("unauthenticated access will no longer be supported").
loginRequired: true
# Everything else in this homelab is UTC (the node is Etc/UTC); stay consistent
# so timestamps line up with VictoriaLogs.
timeZone: UTC
# Version check phones home to api.github.com. The WAN flaps (CONTEXT.md §6) and
# a blocking outbound call on page render is exactly what we don't want.
releaseCheck:
url: ""
# --- Authentication: Authelia forward-auth (trusted headers) --------------
# Authelia authenticates + enforces 2FA at the GATEWAY (securitypolicy.yaml); by the
# time a request arrives here it is already authenticated, and Envoy has attached
# Remote-* headers describing who the user is.
#
# WHY NOT OIDC (which this used to be): NetBox has NO SSO group -> role mapping.
# REMOTE_AUTH_SUPERUSER_GROUPS and AUTH_LDAP_USER_FLAGS_BY_GROUP are LDAP-only; the
# social-auth pipeline only runs user_default_groups_handler, so an OIDC user landed
# as an ordinary member of one static group and had to be promoted BY HAND, and AD
# group changes never propagated. With header auth, REMOTE_AUTH_GROUP_SYNC_ENABLED
# re-evaluates group membership on EVERY request — the same declarative AD-group
# pattern already used by Grafana and Proxmox.
#
# ⚠⚠ THIS SETTING IS ONLY SAFE BEHIND THE GATEWAY. RemoteUserBackend trusts the
# header unconditionally — NetBox has no trusted-proxy allowlist. Two things keep
# that honest, and BOTH must stay true:
# 1. Envoy sets these headers from Authelia's response, and Envoy Gateway's
# headersToBackend OVERRIDES any client-supplied value ("coexisting headers
# will be overridden"), so a spoofed Remote-User cannot survive the hop.
# 2. networkpolicy.yaml restricts pod ingress to the gateway namespace, so nothing
# in-cluster can bypass Envoy and talk to :8080 directly.
# Removing either one turns `Remote-User: admin` into an instant superuser.
remoteAuth:
enabled: true
backends:
- netbox.authentication.RemoteUserBackend
# Authelia's header names. NetBox's defaults assume HTTP_REMOTE_USER_GROUP, but
# Authelia emits Remote-Groups -> HTTP_REMOTE_GROUPS, and joins values with a
# COMMA where NetBox defaults to "|". Both must be overridden or group sync
# silently yields one group literally named "a,b,c".
header: HTTP_REMOTE_USER
groupHeader: HTTP_REMOTE_GROUPS
groupSeparator: ","
# Authelia sends Remote-Email and Remote-Name (a single display name); it has no
# split given/family name, so the first/last-name headers are left unmapped.
userEmail: HTTP_REMOTE_EMAIL
autoCreateUser: true
autoCreateGroups: true # mirror AD groups into NetBox groups as they appear
groupSyncEnabled: true # re-evaluate membership on every request
# AD group -> NetBox role. Managed in ../../infrastructure/samba-ad (samba_ad_groups).
superuserGroups:
- netbox-admins
staffGroups:
- netbox-admins # is_staff => access to the Django admin site
# The OIDC client config that used to live here (SOCIAL_AUTH_OIDC_*) is gone; the
# netbox-secrets Secret now only carries the database password.
extraConfig: []
# --- Postgres: the shared CNPG cluster ------------------------------------
# Dedicated role + database, no shared superuser — same as Authelia and Gitea.
postgresql:
enabled: false
externalDatabase:
host: shared-postgresql-rw.shared-db.svc.cluster.local
port: 5432
database: netbox
username: netbox
existingSecretName: netbox-secrets
existingSecretKey: postgresql-password
# --- Valkey (Redis) for the RQ task queue + caching -----------------------
# Bundled subchart rather than a shared instance: nothing else in the cluster
# runs Redis, and NetBox wants two logical databases of its own.
#
# ⚠ Bitnami's public catalog no longer serves versioned tags (only `latest`,
# versioned images moved to the `bitnamilegacy` repo), which is why the chart
# ships `tag: latest`. `latest` is not reproducible, so pin the DIGEST instead —
# resolved 2026-07-25 for bitnami/valkey:latest.
valkey:
image:
digest: sha256:5d43ca8bb57aa263ef78d1684dbf1e4b4f63844727eafdd5ea2b0e102a25b141
# Single node: the chart default is primary+replica, which buys nothing here
# (one k8s node, no HA anywhere in this cluster — CONTEXT.md §6).
architecture: standalone
primary:
persistence:
enabled: true
storageClass: localpv-zfs-ceph
size: 1Gi
resourcesPreset: micro
# --- Storage --------------------------------------------------------------
# Media = uploaded images/attachments only; the real data is in Postgres.
#
# ⚠ NOT localpv-zfs-ceph, unlike every other PVC here. The chart mounts this ONE
# RWO claim into BOTH Deployments (web and worker — the worker writes files the web
# serves), and the OpenEBS ZFS class provisions a **zvol**: a block device with xfs
# on it, which cannot be mounted twice. Whichever pod won the race mounted it and
# the other stuck in Init forever with
# verifyMount: device already mounted at [...]
# from the CSI node plugin. local-path is hostPath-based, so kubelet can bind-mount
# the same directory into both pods. (localpv-zfs-ceph stays correct for the valkey
# PVC below — single StatefulSet pod, no sharing.)
persistence:
enabled: true
storageClass: local-path
size: 2Gi
# --- LAN exposure via the Contour gateway ---------------------------------
# https://netbox.ad.ddupan.top — reachable from any LAN host, no Tailscale client
# needed, and it does not traverse the WAN. Deliberately NOT on the cloudflared
# tunnel: a full inventory of the network is not something to publish.
#
# Gateway API, not Ingress. The shared gateway lives in ../../platform/envoy-gateway and already
# terminates TLS with the *.ad.ddupan.top wildcard from ../../platform/cert-manager — so this
# service needs no cert of its own, just this route plus a DNS A record on the DC
# (../../infrastructure/samba-ad). Authentication is enforced at the gateway by the SecurityPolicy in
# securitypolicy.yaml, before a request ever reaches this pod.
ingress:
enabled: false
httpRoute:
enabled: true
parentRefs:
- name: eg
namespace: envoy-gateway-system
sectionName: https # the :443 listener; :80 is for ACME/redirects only
hostnames:
- netbox.ad.ddupan.top
# --- Resource budget ------------------------------------------------------
# The laptop is the single k3s node and already runs everything (CONTEXT.md §6);
# at survey time it had ~4 GiB RAM headroom. Keep this deployment modest.
resourcesPreset: medium # 500m/1Gi requests, 750m/1.5Gi limits
worker:
resourcesPreset: small # 500m/512Mi requests — one worker, no bulk jobs yet
# Nightly changelog/job pruning. Retentions are the chart defaults (90 days).
housekeeping:
enabled: true
schedule: "17 4 * * *"