diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 55cbc0d1..98dacd41 100755 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -117,7 +117,7 @@ Repo IDs: infra=1, Website=2, finance=3, health=4, travel_blog=5, webhook-handle - **Rate limiting**: Return 429 (not 503). Per-service tuning: Immich/Nextcloud need higher limits. - **Retry middleware**: 2 attempts, 100ms — in default ingress chain. - **HTTP/3 (QUIC)**: Enabled cluster-wide via Traefik. -- **IPAM & DNS auto-registration**: pfSense Kea DHCP serves all 3 subnets (VLAN 10, VLAN 20, 192.168.1.x). Kea DDNS auto-registers every DHCP client in Technitium (RFC 2136, A+PTR). CronJob `phpipam-pfsense-import` (5min) pulls Kea leases + ARP into phpIPAM via SSH (passive, no scanning). CronJob `phpipam-dns-sync` (15min) bidirectional sync phpIPAM ↔ Technitium. 42 MAC reservations for 192.168.1.x. +- **IPAM & DNS auto-registration**: pfSense Kea DHCP serves all 3 subnets (VLAN 10, VLAN 20, 192.168.1.x). Kea DDNS auto-registers every DHCP client in Technitium (RFC 2136, A+PTR). CronJob `phpipam-pfsense-import` (hourly) pulls Kea leases + ARP into phpIPAM via SSH (passive, no scanning). CronJob `phpipam-dns-sync` (15min) bidirectional sync phpIPAM ↔ Technitium. 42 MAC reservations for 192.168.1.x. ## Service-Specific Notes | Service | Key Operational Knowledge | @@ -129,7 +129,7 @@ Repo IDs: infra=1, Website=2, finance=3, health=4, travel_blog=5, webhook-handle | Authentik | 3 replicas, PgBouncer in front of PostgreSQL, strip auth headers before forwarding | | Kyverno | failurePolicy=Ignore to prevent blocking cluster, pin chart version | | MySQL Standalone | Raw `kubernetes_stateful_set_v1` with `mysql:8.4` (migrated from InnoDB Cluster 2026-04-16). `skip-log-bin`, `innodb_flush_log_at_trx_commit=2`, `innodb_doublewrite=ON`. ConfigMap `mysql-standalone-cnf`. PVC `data-mysql-standalone-0` (15Gi, `proxmox-lvm-encrypted`). Service `mysql.dbaas` unchanged. Anti-affinity excludes k8s-node1. Old InnoDB Cluster + operator still in TF (Phase 4 cleanup pending). Bitnami charts deprecated (Broadcom Aug 2025) — use official images. | -| phpIPAM | IPAM — no active scanning. `pfsense-import` CronJob (5min) pulls Kea leases + ARP via SSH. `dns-sync` CronJob (15min) bidirectional sync with Technitium. Kea DDNS on pfSense handles all 3 subnets. API app `claude` (ssl_token). | +| phpIPAM | IPAM — no active scanning. `pfsense-import` CronJob (hourly) pulls Kea leases + ARP via SSH. `dns-sync` CronJob (15min) bidirectional sync with Technitium. Kea DDNS on pfSense handles all 3 subnets. API app `claude` (ssl_token). | ## Monitoring & Alerting - Alert cascade inhibitions: if node is down, suppress pod alerts on that node. diff --git a/docs/architecture/dns.md b/docs/architecture/dns.md index 97e609f3..eec99830 100644 --- a/docs/architecture/dns.md +++ b/docs/architecture/dns.md @@ -377,7 +377,7 @@ Devices get automatic DNS registration without manual intervention. See [network Summary: 1. **Kea DHCP** on pfSense assigns IP (53 reservations across 3 subnets). DHCP option 6 (DNS servers) is pushed with two IPs per internal subnet: internal resolver + AdGuard public fallback (`94.140.14.14`) — clients survive an internal DNS outage. 2. **Kea DDNS** sends **TSIG-signed** RFC 2136 dynamic update to Technitium (A + PTR records) — immediate. Key `kea-ddns` (HMAC-SHA256); Technitium enforces both source-IP ACL and TSIG signature on `viktorbarzin.lan` + reverse zones. -3. **phpipam-pfsense-import** CronJob (5min) pulls Kea leases + ARP table into phpIPAM +3. **phpipam-pfsense-import** CronJob (hourly) pulls Kea leases + ARP table into phpIPAM 4. **phpipam-dns-sync** CronJob (15min) pushes named phpIPAM hosts → Technitium A + PTR, pulls Technitium PTR → phpIPAM hostnames ## Automation CronJobs @@ -389,7 +389,7 @@ Summary: | `technitium-split-horizon-sync` | `15 */6 * * *` | technitium | Split Horizon + DNS Rebinding Protection on all 3 instances | | `technitium-dns-optimization` | `30 */6 * * *` | technitium | Min cache TTL 60s, emrsn.org stub zone | | `phpipam-dns-sync` | `*/15 * * * *` | phpipam | Bidirectional phpIPAM ↔ Technitium DNS sync | -| `phpipam-pfsense-import` | `*/5 * * * *` | phpipam | Import Kea DHCP leases + ARP from pfSense | +| `phpipam-pfsense-import` | `0 * * * *` | phpipam | Import Kea DHCP leases + ARP from pfSense | ### Password Rotation Flow diff --git a/docs/architecture/networking.md b/docs/architecture/networking.md index 3c75e4fd..e7959589 100644 --- a/docs/architecture/networking.md +++ b/docs/architecture/networking.md @@ -104,7 +104,7 @@ flowchart LR end subgraph K8s["Kubernetes"] - Import[CronJob
pfsense-import
every 5min] + Import[CronJob
pfsense-import
hourly] Sync[CronJob
dns-sync
every 15min] IPAM[phpIPAM
Web UI + API] MySQL[(MySQL
InnoDB)] @@ -338,7 +338,7 @@ Containerd on all K8s nodes uses `hosts.toml` to redirect pulls to the local cac - Stack: `stacks/phpipam/` - Web UI: `phpipam.viktorbarzin.me` (Authentik-protected) - Database: MySQL InnoDB cluster (`mysql.dbaas.svc.cluster.local`) -- Device import: CronJob `phpipam-pfsense-import` every 5min — queries Kea DHCP leases + pfSense ARP table via SSH (no active scanning) +- Device import: CronJob `phpipam-pfsense-import` hourly — queries Kea DHCP leases + pfSense ARP table via SSH (no active scanning) - DNS sync: CronJob `phpipam-dns-sync` every 15min — bidirectional sync between phpIPAM and Technitium DNS (push named hosts → A+PTR, pull DNS hostnames → unnamed phpIPAM entries) - Subnets tracked: 10.0.10.0/24, 10.0.20.0/24, 192.168.1.0/24, 10.3.2.0/24, 192.168.8.0/24, 192.168.0.0/24 - API: REST API enabled (app `claude`, ssl_token auth), MCP server available for agent access diff --git a/stacks/phpipam/main.tf b/stacks/phpipam/main.tf index c277ba21..9fce6c14 100644 --- a/stacks/phpipam/main.tf +++ b/stacks/phpipam/main.tf @@ -386,7 +386,7 @@ resource "kubernetes_cron_job_v1" "phpipam_pfsense_import" { namespace = kubernetes_namespace.phpipam.metadata[0].name } spec { - schedule = "*/5 * * * *" + schedule = "0 * * * *" successful_jobs_history_limit = 1 failed_jobs_history_limit = 3 concurrency_policy = "Forbid"