Ctrl K
ComunidadGuías…

mkdocs.yml

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
---
# The docs site. `uv run mkdocs build --strict` renders docs/ into site/; in production
# scripts/docs/build_docs.py runs the reference generators first and builds into the hostPath the
# `docs` k3s role serves.
#
# docs_dir points at the EXISTING docs/ tree and the nav names those files in place. Moving
# them to fit a navigation shape would break every reference to docs/secret-rotation.md and
# its siblings across CLAUDE.md, the role docs and the skills.
site_name: Homelab Docs
site_description: Reference and runbooks for the daniel-box / daniel-server / daniel-pi homelab
docs_dir: docs
site_dir: site
use_directory_urls: true

theme:
  name: material
  features:
    - navigation.top
    - navigation.indexes
    - search.highlight
    - content.code.copy
  palette:
    - media: "(prefers-color-scheme: light)"
      scheme: default
      toggle:
        icon: material/brightness-7
        name: Switch to dark mode
    - media: "(prefers-color-scheme: dark)"
      scheme: slate
      toggle:
        icon: material/brightness-4
        name: Switch to light mode

markdown_extensions:
  - admonition
  - attr_list
  - md_in_html
  - tables
  - toc:
      permalink: true
  - pymdownx.details
  - pymdownx.superfences
  - pymdownx.highlight:
      anchor_linenums: true
  # `--8<-- "assets/generated/fragments/<name>.md"` splices a generated fact table into a
  # hand-written page, so the prose stays prose and the tunables it sits beside are re-read
  # from the tree by scripts/docs/gen_doc_fragments.py on every docs-refresh run. check_paths
  # turns an include naming a fragment nobody generates into a strict-build failure; without
  # it the include line renders as text and the page reads as if the table were missing.
  - pymdownx.snippets:
      base_path: [docs]
      check_paths: true

plugins:
  - search

# Resolves the `<span class="fqdn">` placeholders the reference generators emit into links,
# using the domain of the URL the page was served from, and resolves the nav's sentinel hosts
# the same way. The generators cannot bake an FQDN in: they parse the tree statically and
# `domain` is SOPS-sourced. See the file's own header.
# Table overflow on the wide generated reference tables. The file's own header carries the
# mechanism; the short version is that Material's stock table rules clip long cells instead of
# wrapping them, and the scrollbar that would reach the clipped text sits several screens down.
extra_css:
  - assets/extra.css

extra_javascript:
  - assets/fqdn-links.js
  # A filter bar and sortable headers on the long tables. It runs in the browser because the
  # filter is the reader's choice, not a fact the build knows. The file's own header says
  # which tables get one; it sits after fqdn-links.js so a filter matches the resolved links.
  - assets/table-filter.js

# Turns a repo path written as a code span -- `scripts/docs/service_catalog.py`,
# `docs/secret-rotation.md` -- into a link to where this site documents it. Unlike the FQDN
# links above this resolves at build time, because a path -> URL map is fully known then; the
# file's own header carries what it links, what it deliberately does not, and why it injects
# the Scripts page's row anchors itself rather than asking the generator for them.
# The leading underscore keeps it out of the Scripts reference, which enumerates scripts/**.
hooks:
  - scripts/docs/_mkdocs_repo_links.py
  # Appends to every hand-written page the date of its last commit and which of the repo
  # files it names changed after that -- the freshness signal the generated pages get from
  # their frontmatter. Computed from git at build time, so nothing is committed;
  # reference/freshness.md is the same data as one ranked table.
  - scripts/docs/_mkdocs_freshness.py

# Pages that are BUILT unless named here. mkdocs serves everything under docs_dir whether or
# not the nav links it, and it logs an unlinked page at INFO — so `--strict` does not catch
# one, and neither does reading the nav.
#
# `superpowers/` is 11 design plans kept on disk and deliberately gitignored (.gitignore:5-6).
# Untracked is not unpublished: the cron builds from the host's working tree, so they were
# being served from an internet-facing site. They are the only pages here with a real exposure
# delta — this repo is PUBLIC, so everything tracked is world-readable already and excluding it
# protects nothing. `adr/template.md` is a fill-in-the-blanks stub, not a decision.
exclude_docs: |
  superpowers/
  adr/template.md
  # Snippet bodies, not pages: each is spliced into a page above by `--8<--`, and mkdocs
  # would otherwise build every one as an orphan page of one table. Excluding a file from
  # the build does not hide it from the snippets extension, which reads base_path from disk.
  assets/generated/fragments/
  # M6's per-batch status records, hand-written and spliced into m6-retire-kuma.md the same
  # way. One file per batch so parallel PRs do not conflict over one status block (#6656).
  target-architecture/monitoring/m6-status/

# Built and served on purpose, but deliberately absent from the nav. `archive/` is the
# historical record of executed work — other docs and CLAUDE.md link INTO it, so excluding it
# would 404 those links, while listing every superseded planning doc in the nav would bury the
# live pages. Its README is the one exception: the nav's History section names it, as the
# index a reader browses the archive from. Declaring it here is what separates "decided to
# leave unlinked" from "nobody noticed", which is the distinction the nav coverage test now
# enforces.
#
# DECIDED: docs/archive stays; size was never the concern, and a PR number is not greppable
# offline the way the linked record is. Deleting the archive in favour of PR numbers was
# re-examined on 2026-09-28 (#2808) and kept.
#
# `reference/backlog.md` is the same case for a different reason: `findings.py list` is the
# open register, this page is only its rendering, and `issue-claiming-and-fanout.md` and
# CLAUDE.md link INTO it directly — so it stays built and reachable, just off the nav.
not_in_nav: |
  archive/
  reference/backlog.md

# ENFORCED by scripts/tests/test_mkdocs_config.py, in both directions: every entry below must
# resolve to a file, and every docs/**.md must appear here OR be matched by exclude_docs above.
# A document absent from the nav is still built and served, but nothing links to it — which is
# indistinguishable from it not existing.
nav:
  - Home: index.md
  # A nav heading that is only a link, off the site to the artifacts browser. The host is a
  # sentinel: `domain` is SOPS-sourced, so nothing static can name the real one, and
  # assets/fqdn-links.js rewrites this href to the domain and tier the reader is already on
  # — the same derivation it does for the reference pages' `<span class="fqdn">` spans.
  #
  # The degradation differs from those spans and is worse. A span that is never rewritten
  # still reads as its placeholder text; a nav anchor is a live link or a dead one, so a
  # JavaScript failure leaves this entry pointing at an unresolvable host. Accepted: the
  # same failure already costs every service link on the reference pages.
  - Artifacts: https://artifacts.local.invalid/
  - Reference:
      - Services: reference/services.md
      - Hosts: reference/hosts.md
      - Secrets: reference/secrets.md
      - Scheduled jobs: reference/crons.md
      - State of the lab: reference/state.md
      - Networking: reference/networking.md
      - Scripts: reference/scripts.md
      - Topology: reference/topology.md
      - Doc freshness: reference/freshness.md
      - Decision markers: reference/decisions.md
  # template.md is deliberately absent — it is a form, not a document. The nav test only
  # checks docs/*.md, not subdirectories, so leaving it out costs nothing.
  - Decisions:
      - Index: adr/index.md
      - "ADR-0001 MkDocs site with generated reference": adr/0001-mkdocs-site-with-generated-reference.md
      - "ADR-0002 k3s over Docker Compose": adr/0002-k3s-over-docker-compose-for-the-cluster-nodes.md
      - "ADR-0003 SOPS with age for secrets": adr/0003-sops-with-age-for-secrets-at-rest.md
      - "ADR-0004 Authelia as the SSO layer": adr/0004-authelia-is-the-single-sign-on-layer.md
      - "ADR-0005 Traefik as the edge": adr/0005-traefik-is-the-edge-with-ingressroute-crds.md
      - "ADR-0006 Longhorn for cluster storage": adr/0006-longhorn-for-cluster-storage.md
      - "ADR-0007 Backup tiering: R2 daily, B2 weekly": adr/0007-backup-tiering-r2-daily-b2-weekly.md
      - "ADR-0008 16 MiB Longhorn blocks": adr/0008-16-mib-longhorn-blocks.md
      - "ADR-0009 NetworkPolicy default-deny": adr/0009-networkpolicy-default-deny-ingress.md
      - "ADR-0010 Pull-based GitOps over Argo and Flux": adr/0010-pull-based-gitops-over-argo-and-flux.md
      - "ADR-0011 One lock serialises every deploy path": adr/0011-one-lock-serialises-every-deploy-path.md
      - "ADR-0012 Zero-downtime rollout gates": adr/0012-zero-downtime-deploys-gate-on-rollout-and-restarts.md
      - "ADR-0013 daniel-pi stays on Docker": adr/0013-daniel-pi-stays-on-docker.md
      - "ADR-0014 Kopia retired, Longhorn owns B2": adr/0014-kopia-retired-longhorn-owns-the-b2-credentials.md
      - "ADR-0015 D2 for hand-authored diagrams": adr/0015-d2-for-hand-authored-diagrams.md
      - "ADR-0016 Code scanning stays on default setup": adr/0016-code-scanning-stays-on-default-setup.md
      - "ADR-0017 The tree lock guards the tree": adr/0017-the-tree-lock-guards-the-tree-not-the-cluster.md
      - "ADR-0018 The repository stays public, CI stays hosted": adr/0018-the-repository-stays-public-and-ci-stays-hosted.md
      - "ADR-0019 Fact support stops at the repo store": adr/0019-fact-support-stops-at-the-repo-store.md
      - "ADR-0020 Flux applies the cluster from a promoted artifact": adr/0020-flux-applies-the-cluster-from-a-promoted-artifact.md
      - "ADR-0021 The host-package builder trusts master plus green CI": adr/0021-the-host-package-builder-trusts-master-plus-green-ci.md
      - "ADR-0022 The cluster decrypts its own file with its own key": adr/0022-the-cluster-decrypts-its-own-file-with-its-own-key.md
      - "ADR-0023 Fact support is a diff notice": adr/0023-fact-support-is-a-diff-notice.md
      - "ADR-0024 Code scanning is off": adr/0024-code-scanning-is-off.md
      - "ADR-0025 SUC upgrades k3s, and homelab-k3s-restart restarts it": adr/0025-suc-upgrades-k3s-and-homelab-k3s-restart-restarts-it.md
      - "ADR-0026 One alert plane on Prometheus and Alertmanager; Uptime Kuma retired": adr/0026-one-alert-plane-on-prometheus-and-alertmanager.md
      - "ADR-0027 Fan-out batches stay on host cgroups": adr/0027-fanout-batches-stay-on-host-cgroups.md
      - "ADR-0028 The cluster render supports a closed Jinja subset": adr/0028-the-renderer-supports-a-closed-jinja-subset.md
      # The long-form documents three of the records above compress. They sit under Decisions
      # rather than in a section of their own: each one is the working-out behind a single
      # ADR, and a reader who wants that depth arrives from the record, not from a
      # top-level heading.
      - Background:
          - "Longhorn backup tiering (ADR-0007)": longhorn-backup-tiering.md
          - "NetworkPolicy default-deny (ADR-0009)": networkpolicy-default-deny.md
          # The per-slice record. It is
          # the answers each deploy settled by observation, and slice 5's four decisions govern
          # how the baseline selects pods — live content, not archive material.
          - "NetworkPolicy — what each slice settled": networkpolicy-slice-answers.md
          - "Argo and Flux evaluation (ADR-0010)": archive/gitops-argo-flux-evaluation.md
          # The measurement #3734 needs before initial_setup.yml loops over a setup_roles list.
          - "Looped include_role measurement (#3734)": setup-role-loop-measurement.md
  # Six groups, ordered day-to-day first and recovery last. An upgrade is both a driving and
  # a recovery procedure, so the upgrades sit with recovery, where a reader looking for "how do
  # I get the cluster back" finds them. A group is a nav heading only: every page keeps its
  # path, so moving one between groups breaks no link.
  - Operations:
      - Deploy and land:
          - Deploying by hand: deploying.md
          # The long form behind the `land-after-merge` skill. The skill carries the invocation
          # and the verdict decoder; this page carries the measurement behind each rule, which
          # keeps the skill short.
          - Landing a merged PR: landing.md
          - The GitOps pipeline: gitops-pipeline.md
          - Host packages: host-packages.md
          - The Flux deploy plane: flux-deploy-plane.md
          - The homelab-render renderer: homelab-render.md
          - Secret rotation: secret-rotation.md
      - Monitoring and alerting:
          - Healthchecks.io deadman: healthchecks-io-deadman.md
          - Uptime Robot monitors: uptime-robot-monitors.md
          # internals holds the module table, prerequisites and gate sets; the check record
          # holds one entry per live check. check.py and cli.py cite the internals path.
          - monitor-bridge internals: monitor-bridge-internals.md
          - monitor-bridge check record: monitor-bridge-checks.md
          - uptime-kuma and AutoKuma record: uptime-kuma-autokuma-record.md
          - observability record: observability-dashboards.md
          - autofix-bridge actuators: autofix-bridge-actuators.md
      - Access and host security:
          - WireGuard private access: wireguard-private-homelab-access.md
          - Security tools: security-tools.md
      - Claude tooling:
          - Claude tooling reference: claude-tooling.md
          - Claude shell permissions: claude-shell-permissions.md
          - Claude as its own UNIX user: claude-agent-user.md
          - claude-rc caps: claude-code-rc-caps.md
          - Claude memory store copy: claude-memory-sync.md
          - Alert-triggered diagnosis (no-go): alert-triggered-diagnosis.md
          - Issue claiming and fan-out: issue-claiming-and-fanout.md
          - Failure classes: failure-classes.md
          - Python code organization: python-code-organization.md
      # Each page below takes the working-out of one role CLAUDE.md: drill records, measured
      # traps, board provenance and design records. The role doc keeps the operating rules,
      # within the inject hook's character budget, and a session reads the page only when it
      # edits that code.
      - Role records:
          - Edge:
              - Traefik record: traefik-plugins-and-startup.md
              - CrowdSec record: crowdsec-waf-record.md
              - Authelia sessions record: authelia-sessions-and-crowdsec-init.md
              - Pi-hole DNS continuity record: pihole-dns-continuity-record.md
          - Hosts:
              - Host baseline record: host-baseline-record.md
              - Pi host tuning record: pi-host-tuning-record.md
              - k3s node-plane crons and incidents: k3s-node-plane-crons-and-incidents.md
              - hypervisor libvirt internals: hypervisor-libvirt-internals.md
              - Docker engine pins and runtime: docker-engine-pins-and-runtime.md
          - Storage:
              - volume-snapshot drill record: volume-snapshot-drills.md
              - volume-revert drill and sizing: volume-revert-drill-and-sizing.md
          - Renovate:
              - renovate_notify internals: renovate-notify-internals.md
              - renovate_agent bounds and digest: renovate-agent-bounds-and-digest.md
          - Services:
              - headlamp plugins and OIDC record: headlamp-oidc-and-plugins.md
              - homepage widgets and layout: homepage-widgets-and-layout.md
              - Jellyfin plugins: jellyfin-plugins.md
              - Jellyfin font attachment latency: jellyfin-attachment-latency.md
              - qbittorrent VPN and prefs: qbittorrent-vpn-and-prefs.md
              - n8n community node packages: n8n-community-packages.md
              - game-stats internals: game-stats-internals.md
              - Valheim modding: valheim-modding.md
              - Email to RSS: email-to-rss.md
              - artifacts star list: artifacts-star-list.md
      - Recovery and upgrades:
          - k3s control-plane upgrade: k3s-upgrade.md
          - Longhorn upgrade: longhorn-upgrade.md
          - Ubuntu 26.04 upgrade plan: ubuntu-26.04-upgrade-plan.md
          - Longhorn disaster recovery: longhorn-disaster-recovery.md
          - k3s etcd restore: k3s-etcd-restore.md
          - Registry push store collection: registry-push-store-gc.md
          # The last stop on the recovery ladder — total loss of daniel-box or the author's own
          # access. It is the entry point that links to every runbook above rather than one more
          # subsystem-specific procedure, so it sits after all of them.
          - Break glass: break-glass.md
  # The planned migration to Flux, one alert plane, per-host packages and generated facts.
  # Every page is a plan with Status: PLANNED, not a description of what runs. A slice moves
  # to archive/ once it ships, the way the k3s migration's slices did.
  - Target architecture:
      - Design: target-architecture/design.md
      - Contracts: target-architecture/contracts.md
      - Renderer:
          - R1 Shadow render: target-architecture/render/r1-shadow-render.md
          - R2 Secret placeholders: target-architecture/render/r2-secret-placeholders.md
          - R3 Remove live reads: target-architecture/render/r3-remove-live-reads.md
          - R4 Delete the k8s Ansible path: target-architecture/render/r4-delete-k8s-ansible-path.md
      - Cluster deploy plane:
          - D1 Flux installed: target-architecture/deploy/d1-flux-installed.md
          - D2 First leaf: target-architecture/deploy/d2-first-leaf.md
          - D3 Secrets: target-architecture/deploy/d3-secrets.md
          - D4 Ordering: target-architecture/deploy/d4-ordering.md
          - D5 Bulk move: target-architecture/deploy/d5-bulk-move.md
          - D6 Delete the old path: target-architecture/deploy/d6-delete-old-path.md
          - D7 Superseding promotions: target-architecture/deploy/d7-superseding-promotions.md
      - Monitoring:
          - M1 Alertmanager: target-architecture/monitoring/m1-alertmanager.md
          - M2 First bridge family: target-architecture/monitoring/m2-first-bridge-family.md
          - M3 Textfile timer: target-architecture/monitoring/m3-textfile-timer.md
          - M4 Blackbox ingress probes: target-architecture/monitoring/m4-blackbox-ingress.md
          - M5 Loki ruler: target-architecture/monitoring/m5-loki-ruler.md
          - M6 Retire Kuma: target-architecture/monitoring/m6-retire-kuma.md
          - Alertmanager UI and readers: target-architecture/monitoring/alertmanager-ui-and-readers.md
      - Host plane:
          - H1 Cluster config to Flux: target-architecture/host/h1-cluster-config-to-flux.md
          - H2 Shrink the host plane: target-architecture/host/h2-shrink-host-plane.md
          - H3 Pi pilot: target-architecture/host/h3-pi-pilot.md
          - H4 Secrets unit: target-architecture/host/h4-secrets-unit.md
          - H5 Pi Compose: target-architecture/host/h5-pi-compose.md
          - H6 k3s upgrades: target-architecture/host/h6-k3s-suc.md
          - H7 Delete Ansible: target-architecture/host/h7-delete-ansible.md
      - Docs guard:
          - G1 Diff notice: target-architecture/docs-guard/g1-diff-notice.md
          - G2 Retire the lock: target-architecture/docs-guard/g2-retire-lock.md
          - G3 Freshness reviewer: target-architecture/docs-guard/g3-freshness-reviewer.md
          - G4 Drop the size test: target-architecture/docs-guard/g4-drop-size-test.md
          - G5 Shrink root CLAUDE.md: target-architecture/docs-guard/g5-shrink-root-claude-md.md
  # Work that shipped, a spike that concluded and an incident that closed: kept as the record,
  # not as instructions. Operations holds only pages that describe the lab as it runs.
  # The archive index lists every archived plan and names where its live documentation went,
  # and the pages under it stay off the nav (see not_in_nav above). So this heading is the
  # index alone.
  - History:
      - Archive index: archive/README.md