# pfv-netboot — Reference Network Infrastructure (READ-ONLY reference)

> **Status:** REFERENCE SOURCE ONLY. This node is production infrastructure.
> Do **not** modify it. This document describes it as audited so its services can
> be replicated to `pfv-netinfra-01` / `pfv-netinfra-02`. All data below was
> collected by **read-only** audit scripts (`audit-netboot.sh`,
> `deep-audit-netboot.sh`, `gather-configs.sh`) on 2026-07-27/28.

## 1. Host

| Item | Value |
|---|---|
| Hostname / FQDN | `pfv-netboot` / `pfv-netboot.knel.net` |
| OS | Debian GNU/Linux 12 (bookworm), kernel 6.1.0-44-amd64 |
| Hardware | 2 vCPU, ~1.9 GiB RAM, 491 GB disk (18 GB used) |
| Timezone | `America/Chicago` (US/Central) |
| LAN | `eth0` static `192.168.3.250/22`, gw `192.168.3.254` (`/etc/network/interfaces`) |
| Tailscale | `100.103.64.82` (`tailscale0`) |
| DNS resolver | Tailscale MagicDNS — `/etc/resolv.conf` → `100.100.100.100` |
| Docker | Docker Engine 29.6.2 (containerd v2.2.6, runc 1.3.6) |
| Access | `localuser` has passwordless sudo; **not** in `docker` group (uses `sudo docker`) |

`eth1` is up but unconfigured; many docker bridges exist (`pihole_default`,
`ntp_default`, `dns_default`, and several stale ones).

## 2. Services overview

| Service | Form | Running? |
|---|---|---|
| **Pi-hole** (DNS sinkhole, recursive resolver) | Docker container `pihole` | ✅ healthy |
| **NTP** — overlay on Tailscale IP | Docker container `tsys-ntp` (`dockurr/chrony`) | ✅ healthy |
| **NTP** — system clock + LAN serving | bare-metal `ntpsec` (`ntpd`) | ✅ active, enabled |
| **Technitium DNS** (authoritative for `knel.net`) | Docker container | ❌ **not running**; config preserved in orphaned volume |

## 3. Pi-hole (container)

- **Compose:** `/root/pihole/docker-compose.yml` (compose project `pihole`)
- **Image:** `pihole/pihole:latest` — Core **v6.1.2**, Web v6.2.1, FTL v6.2.2
- **Container:** `pihole`, `restart: always`, `cap_add: [SYS_NICE]`, network `pihole_default`
- **Ports (host):**

  | Host | Container | Purpose |
  |---|---|---|
  | `53/tcp`, `53/udp` | 53 | DNS |
  | `10002/tcp` | 80 | Web admin (HTTP) |
  | `10003/tcp` | 443 | Web admin (HTTPS, self-signed) |

- **Environment:** `TZ=America/Chicago`, `FTLCONF_webserver_api_password=REDACTED_PASSWORD`, `FTLCONF_dns_listeningMode=all`
- **Data:** bind mount `/root/pihole/etc-pihole:/etc/pihole` (dir owned by `localuser`; files by container `pihole` uid)
- **Config (Pi-hole v6 TOML):** `pihole.toml`. Key settings:
  - Upstream DNS: `192.168.3.16`, `8.8.8.8`, `2001:4860:4860::8888`
  - `listeningMode = "ALL"`, `interface = "eth0"`, `dns.port = 53`, `dns.domain = "lan"`
  - `queryLogging = true`, DNSSEC off
- **Adlists:** one entry — `https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts` (in `gravity.db`/`adlists.list`)
- **Gravity DB:** `/etc/pihole/gravity.db` (~5.5 MB) holds adlists/domainlists/clients/groups
- **Web admin:** `http://pfv-netboot:10002/admin/` (password `REDACTED_PASSWORD`)
- Note: query history `pihole-FTL.db` (~2.5 GB) is transient and **excluded** from replication.

## 4. NTP (two layers)

### 4a. chrony container (`tsys-ntp`) — overlay on the Tailscale IP
- **Compose:** `/root/NTP/docker-compose.yml` (project `ntp`)
- **Image:** `dockurr/chrony`
- **Env:** `NTP_SERVERS=pool.ntp.org`
- **Ports:** `100.103.64.82:123:123/udp` — bound specifically to the **Tailscale IP**
- `restart: always`
- chrony.conf (generated): `server pool.ntp.org iburst`, `allow all`, `rtcsync`
- On netboot this coexists with bare-metal ntpsec because ntpsec here does **not** pre-bind the specific Tailscale-IP socket, letting Docker claim it.

### 4b. bare-metal `ntpsec`
- Unit `ntpsec.service` — active, enabled; `/usr/sbin/ntpd -c /etc/ntpsec/ntp.conf -g -N -u ntpsec:ntpsec`
- **Config** (`/etc/ntpsec/ntp.conf`):
  ```
  driftfile /var/lib/ntp/ntp.drift
  leapfile /usr/share/zoneinfo/leap-seconds.list
  server pfvsvrpi.knel.net
  restrict 127.0.0.1
  restrict ::1
  ```
- Listens on all local addresses (incl. Tailscale) for UDP/123; serves LAN clients.

## 5. Technitium DNS (currently stopped)

- **Not running** — no container and **no compose file** exists for it.
- A previous deployment left an **orphaned Docker volume** `dns_tsys-dns-config`
  (mountpoint `/var/lib/docker/volumes/dns_tsys-dns-config/_data`) whose contents
  are intact (last activity 2025-06-23). A second typo'd volume
  `dns_tyss-dns-config` is empty.
- Config files are **binary** (Technitium's own serialization), but copy verbatim:
  `dns.config`, `auth.config`, `log.config`, `scopes/Default.scope`,
  `self-signed-cert.pfx`, `cache.bin`, `zones/`, `stats/`, `logs/`.
- **Zones present** (12 reverse + 1 forward):
  - `knel.net.zone` — forward zone; SOA `dns.knel.net. hostadmin.knel.net.` (serial `2025062313`). A-records for the internal fleet, including: `tsys1`, `rr-middleware`, `pfv-netboot`, `pfv-k8s-cnode1`…`cnode5`, `pfv-k8s-wnode3`, `tsys-k8scloud-netcup-1`, `tsys-kali-vptechops`, `tsys-kali-dev`; NS `dns.knel.net`.
  - Reverse zones for Tailscale CGNAT ranges (`100.x.in-addr.arpa`): `199.86`, `145.105`, `181.103`, `184.108`, `194.67`, `2.108`, `211.114`, `46.96`, `64.103`, `75.110`, `97.82`, `119.127`.
- **Auth:** `auth.config` defines user `admin` (Administrators group) with a stored password hash; the plaintext password is whatever was set on the original Technitium instance.
- The compose project name historically was `dns` (network `dns_default` still exists).

## 6. Firewall / misc

- nftables/iptables: mostly Docker + Tailscale chains (`ts-input`, `ts-forward`,
  `DOCKER`, `DOCKER-FORWARD`); default `INPUT ACCEPT`, `FORWARD DROP`,
  `OUTPUT ACCEPT`. No UFW / firewalld.
- Also runs (out of scope for this replication): Samba (137/138/139, 445), NFS
  (2049), rpcbind (111), Postfix (25), Cockpit (9090), Beszel agent, webmin/
  usermin (10000/10002/20000), Tailscale (41641).
- SELinux absent; AppArmor default docker profile.

## 7. How it was audited (no changes made)

```bash
ssh localuser@pfv-netboot 'bash -s' < audit-netboot.sh        # broad read-only sweep
ssh localuser@pfv-netboot 'bash -s' < deep-audit-netboot.sh   # docker inspect + compose
ssh localuser@pfv-netboot 'bash -s' < gather-configs.sh       # pihole.toml + technitium
```

Artifacts: `netboot-audit.txt`, `netboot-deep-audit.txt`, `netboot-configs.txt`.
