Infrastructure/docs/homeserver.md

112 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Homeserver — Dell OptiPlex 3000
The OptiPlex (`192.168.30.20`, Servers VLAN) is the homeserver. It runs the
Omada controller, Pi-hole, Nginx Proxy Manager and Home Assistant in Docker;
all web UIs are served over HTTPS under `*.home.staffenberger.at`. Set up on
2026-10-04.
| Service | Runs on | Internal address | Name (via NPM, HTTPS) |
|---|---|---|---|
| Omada controller | OptiPlex (Docker, host network) | https://192.168.30.20:8043 | omada.home.staffenberger.at |
| Pi-hole | OptiPlex (Docker) | http://192.168.30.20:8081/admin | pihole.home.staffenberger.at |
| Nginx Proxy Manager | OptiPlex (Docker) | http://192.168.30.20:81 | (not proxied yet) |
| Home Assistant | OptiPlex (Docker, host network) | http://192.168.30.20:8123 | ha.home.staffenberger.at |
| OctoPrint | Raspberry Pi | Pi IP, port 80 | octoprint.home.staffenberger.at |
| Old Pi-hole | Synology NAS | 192.168.30.10 | to be switched off |
Compose files live in `~/omada`, `~/pihole`, `~/npm` and `~/homeassistant` on
the OptiPlex; copies with notes are in [`../docker/`](../docker/). SSH from the
PC: `ssh optiplex`.
## Hardware check
Dell OptiPlex 3000: Core i3-12300T (12th gen, 35 W "T" part), 16 GB DDR4, 512 GB NVMe SSD, genuine Dell 65 W power supply — matched the listing.
| Check | Result |
|---|---|
| Memtest86+ | 2 passes, 0 errors (needs Secure Boot off to boot) |
| CPU stress test (stress-ng, 10 min) | Max 88 °C, no throttling |
| Dell ePSA diagnostics | Passed |
| Network link | 1000 Mb/s |
| USB ports | All working |
| SSD SMART | ~15,400 power-on hours, 0 media errors, extended self-test passed twice |
The Windows key was read with ShowKeyPlus before wiping. An OEM key in the
firmware stays there after installing Linux and only reactivates Windows on
this machine.
## SSD problem and fix
The system froze under disk load because the NVMe link threw fatal PCIe
errors. Stable since adding a thermal pad and the kernel option `pcie_aspm=off`.
**The drive:** Toshiba XG4 THNSN5512GPUK (512 GB NVMe), an HP OEM part (HP P/N
902944-002, made 2017), fitted by a refurbisher — not the original Dell drive.
**Symptoms:** load average around 37 with idle CPU, commands hanging, kernel
log entries `PCIe Bus Error: severity=Uncorrectable (Fatal)` followed by
controller resets.
**Findings:**
- The board's "M.2 SSD THERMAL PAD AREA" under the SSD was bare. The drive
reached 81 °C (warning 78 °C, critical 82 °C). With a thermal pad (two
stacked), idle dropped from 68 °C to ~46 °C, ~70 °C under sustained writes.
- The errors persisted at low temperature, so heat was not the root cause. The
SSD's AER registers show an FCP error (flow-control protocol, classified
fatal), most likely triggered by the L1.2 link power state the BIOS enables.
- The BIOS declares ASPM unsupported (FADT), so the kernel never controls ASPM.
`pcie_aspm=off` makes the kernel leave AER and LTR to the BIOS, which
tolerates the error. With kernel control (`pcie_aspm.policy=performance`) the
fatal errors returned every 30–60 seconds.
- The link trains at full speed (8 GT/s, x4). fio: ~1,380 MB/s read, ~500 MB/s write.
**Current setting:** `GRUB_CMDLINE_LINUX_DEFAULT="pcie_aspm=off"` in
`/etc/default/grub`. The APST option (`nvme_core.default_ps_max_latency_us=0`)
was removed again — it only made the drive run hotter.
**Health checks:**
```bash
sensors | grep -A1 Composite
sudo smartctl -a /dev/nvme0n1 | grep -iE "temp|media"
sudo lspci -vv -s 01:00.0 | grep -E "UESta|CESta"
```
Baseline: Warning Comp. Temperature Time = 5 minutes. A new 500 GB NVMe
(~€30–40) would remove the workaround entirely.
## Ubuntu Server and SSH
Ubuntu Server 26.04 LTS, headless, no disk encryption, SSH key logins only.
- **Install choices:** full disk via LVM, OpenSSH server, no featured snaps, no
encryption (so it boots unattended after power cuts).
- **BIOS:** Secure Boot on, AC Recovery set to Power On.
- **SSH key:** `~/.ssh/id_ed25519_homelab` (same per-client key as for the Pi),
copied with `ssh-copy-id`. Entry in `~/.ssh/config` on the PC:
```
Host optiplex
HostName 192.168.30.20
User david
IdentityFile ~/.ssh/id_ed25519_homelab
IdentitiesOnly yes
```
- **Password login disabled** in `/etc/ssh/sshd_config.d/00-no-password.conf`
(`PasswordAuthentication no`, `KbdInteractiveAuthentication no`). The `00-`
prefix makes it win over Ubuntu's `50-cloud-init.conf`.
- **Port 53 freed for Pi-hole:** `DNSStubListener=no` in
`/etc/systemd/resolved.conf.d/no-stub.conf`, and `/etc/resolv.conf` linked to
`/run/systemd/resolve/resolv.conf`.
## Docker
Installed from Docker's official apt repository (`docker-ce`,
`docker-compose-plugin`); user `david` is in the `docker` group. Service
details: [omada](../docker/omada/README.md), [pihole](../docker/pihole/README.md),
[npm](../docker/npm/README.md), [homeassistant](../docker/homeassistant/README.md).
All of the above was done by hand. Turning it into an Ansible playbook is
tracked in [todo.md](todo.md).