Records the host's service inventory, setup runbook, mail account list, sync plan, package diff vs. clean install, and hardening TODOs, including today's SSH hardening (key-only, no root login) and the fail2ban sshd findtime fix for a low-and-slow brute-force evasion pattern. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RdTyvEJkfNLDVAWt8WQ6X9
12 KiB
alpha.jayfield.org — Diff vs. a Clean Ubuntu 22.04 Install
Generated 2026-07-19. Methodology and caveats up front; findings below, organized in three tiers of decreasing mechanical certainty and increasing manual judgment.
Update, same day: three of the findings below (RTMP/nginx, the
wireguard tunnel, and samba/cifs-utils) were removed shortly after
this diff was run — see the annotations inline and README.md's known
quirks for the current state. Left in place here as a record of what was
found and why it was removed; this file is a point-in-time investigation,
not a live inventory (README.md is the live inventory).
Baseline used: the official jammy-server-cloudimg-amd64 manifest
(cloud-images.ubuntu.com/jammy/current/) for package comparisons, and
freshly-downloaded .debs from the exact same Ubuntu archive this host
uses (matching installed versions exactly — e.g. bind9 9.18.39-0ubuntu0.22.04.4,
postfix 3.6.4-1ubuntu1.4) for config-file comparisons. One honest caveat:
several signs suggest this host was actually provisioned from the
interactive Server ISO installer, not the cloud image (installation-report,
tasksel, popularity-contest, and language-pack-en are all manually
installed — none of these appear on a cloud-init-provisioned instance).
The cloud image manifest is still the best available reference point, but
treat tier 1's line count as approximate, not exact.
Tier 1 — Package diff
968 packages installed vs. 600 in the baseline manifest. Most of that gap
is transitive dependencies (installing apache2 alone pulls in a dozen
supporting libraries nobody explicitly chose). Filtering to packages that
are both (a) not in the baseline and (b) marked apt-mark showmanual
(i.e. an actual administrative decision, not a dependency) gives 122
packages — the real, meaningful list. Grouped by what they're for:
| Purpose | Packages |
|---|---|
| DNS | bind9 |
postfix, postfix-mysql, dovecot-core, dovecot-imapd, dovecot-lmtpd, dovecot-managesieved, dovecot-mysql, dovecot-sieve, rspamd, mailutils, libmailutils6 |
|
| Database | mariadb-server (+ mariadb-server-10.3/galera-3 — stale leftovers, see note below) |
| Web | apache2, php8.0 + extensions, libapache2-mod-php7.4, libapache2-mod-php8.0, nginx |
| TLS | certbot, python3-certbot-apache |
| Docker | docker-ce, docker-ce-cli, docker-buildx-plugin, docker-compose-plugin, containerd.io |
| Security | fail2ban |
| File sharing | samba, cifs-utilsvlda-01 CIFS mount; removed same day along with the dead tunnel below) |
| VPN — not previously documented | wireguard/root/removed-configs-backup/) |
| Utilities | at, net-tools, unzip, lz4, ltrace, bsdmainutils, resolvconf, qemu-guest-agent |
| ISO-installer artifacts | installation-report, tasksel, popularity-contest, language-pack-en, language-selector-common |
Stale/leftover packages worth a cleanup pass: mariadb-server-10.3,
mariadb-client-10.3, galera-3, libssl1.1, libicu66, php8.0 (vs.
the active php7.4 module), libperl5.30 — all remnants of the
18.04→20.04→22.04 upgrade history already noted in README.md (same
lineage as the python3.8/certbot issue documented there). Not actively
harmful, just disk/attack-surface bloat from packages no longer in active
use. Candidate for a future apt autoremove pass — worth checking what's
actually still linked against before purging.
24 packages "missing" vs. baseline are not removals — they're
expected absences for a BIOS-booted QEMU VM with no physical hardware:
grub-efi-*, shim-signed, mokutil, efibootmgr (this host boots via
legacy BIOS/bios_grub, confirmed in the disk-resize work — never needed
EFI tooling), plus libtss2-* (TPM), fuse3/libntfs-3g89 (physical
filesystem drivers), systemd-hwe-hwdb (hardware enablement) — none of
this is relevant to a cloud VM regardless of who administers it.
Tier 2 — Config file diff (live file vs. pristine package default)
Real diff -u output against genuinely pristine files pulled from the
matching package version in Ubuntu's archive — not reconstructed from
memory. Only the files with a real static default to diff against are
listed; Postfix's main.cf/master.cf and Dovecot's dovecot.conf are
not static conffiles (Postfix generates them via debconf at install
time; Dovecot's shipped file is a first-install template only), so "diff"
for those is a semantic comparison, covered in SETUP.md instead.
/etc/bind/named.conf.options
Exactly what's documented in TODO.md/README.md — version "unknown",
the rate-limit block, and the forwarders block removed in favor of
full recursion (with an inline comment explaining why). Plus pre-existing
(2022) additions: allow-transfer, allow-query { any; },
allow-recursion { trusted; }, querylog yes, the trusted ACL.
/etc/ssh/sshd_config
Port 10022(from#Port 22)PasswordAuthentication yesandPermitRootLogin yesexplicitly set — the shipped default leaves both commented out (relying on OpenSSH's own safer compiled-in defaults). Flagged already inSETUP.md§1 as a hardening gap worth reconsidering.ChallengeResponseAuthentication no— uses the pre-8.7 directive name; current templates useKbdInteractiveAuthentication. Cosmetic, but a dating signal (this file predates a later OpenSSH directive rename).- New finding: an entire
Match Group sftpblock — chrooted, no-shell SFTP-only access (ChrootDirectory /var/sftp/%u, tunneling and forwarding all disabled). Three accounts use it:ftpuser,ftp_jens,ftp_alex(/var/sftp/{ftpuser,ftp_jens,ftp_alex}/). This is a legitimate, separate access mechanism fromjens's full shell account — not documented anywhere before this diff.
/etc/systemd/resolved.conf
Exactly the DNS=127.0.0.1 change documented in README.md's resolver
section, plus pre-existing DNSSEC=allow-downgrade, LLMNR=no, etc.
/etc/apache2/apache2.conf
<Directory /var/www>:AllowOverride all(default:None) — permits.htaccessfiles to override server config anywhere under/var/www. Broader than the stock posture; worth checking whether any.htaccessfiles actually exist and rely on this before tightening it.- A custom
fail2banLogFormat— ties into theapache-authjail. - New finding, worth a closer look: a global block appended at the
end of the file —
The regex
<FilesMatch "\.*"> SetHandler application/x-httpd-php </FilesMatch>\.*(zero or more literal dots, unanchored) matches nearly any filename, including ones with zero dots. Applied globally (outside any<Directory>scope), this routes essentially all requests through the PHP handler, not just.phpfiles. Whether this has real consequences depends on what mod_php does with non-PHP content (likely passes it through as literal text), but it's a broad, unusual, and previously-undocumented directive — worth understanding the original intent before deciding whether to scope it down to\.php$.
/etc/fail2ban/jail.conf
This host edits jail.conf directly rather than using jail.local for
overrides — the intended pattern is to leave the vendor file untouched
and override in jail.local so future package upgrades don't silently
clobber local changes. Real customizations found: bantime 10m→4h,
findtime 10m→30m, maxretry 5→3, port = 10022 on the
sshd/dropbear/selinux-ssh jails (matching the moved SSH port),
sender = root@jayfield.org, and several jails explicitly enabled = true
(sshd, postfix, postfix-rbl, dovecot, sieve, pam-generic, and
others) that ship disabled by default. The remaining diff noise (action-
syntax %(banaction)s[...] reformatting, comment typo fixes) is from
fail2ban's own upstream template evolving between minor releases, not a
local change.
/etc/nginx/nginx.conf — removed 2026-07-19, same day as this diff
Confirmed Tier 1's finding cleanly: the entire http {} block from the
stock config was removed — no web serving capability at all — and
include /etc/nginx/rtmp.conf; was the only addition. This nginx instance
existed solely to run libnginx-mod-rtmp as a live-streaming ingest server
(rtmp.conf: listen 1935; application live { live on; record off; },
no publish authentication configured). Entirely separate from the
Docker web (nginx) container and from Apache — no overlap, no conflict,
just a second, unrelated nginx process that had gone uncatalogued. No
active connections or recent use found before removal; purged
(nginx nginx-core nginx-common libnginx-mod-rtmp) along with /etc/nginx.
/etc/apache2/ports.conf
No diff — matches stock exactly (Apache's own Listen 80/mod_ssl's
Listen 443 addition).
Tier 3 — Changes with no package-level "default" to diff against
Not mechanically diffable — either data (not config), or infrastructure this host's package manager doesn't track at all.
- Disk partitioning: root partition was 9.7GB of a 172GB disk for
years (see
README.md) — grown to 157GB this session viagrowpart/resize2fs. No "default" partition layout to diff against; this is provisioning-time state. - DNS zone content (
/etc/bind/db.jayfield.org): all records — there's no baseline zone file to diff against, it's 100% custom data. - MySQL
vmaildatabase: schema + data for mail accounts/aliases/domains (seeSETUP.md§3 for the schema). Data, not config. - TLS certificates: 7 Let's Encrypt certs, all custom to this domain.
- Docker layer:
portainer,web(nginx), and the Nextcloud stack (nextcloud,nextcloud-db,nextcloud-redis) — none of this exists in a base install; it's entirely additive infrastructure documented inREADME.md. - WireGuard — removed 2026-07-19, same day as this diff
(
/etc/wireguard/alpha_at_moon.conf): a client tunnel named "alpha at moon" —Address = 10.8.0.8/24, peer endpointvpn.dyndns.jayfield.org:51820,AllowedIPs = 10.8.0.0/24, 192.168.22.0/24. Was inactive (wg-quick@wg0not running) at the time of this diff. Almost certainly why themnt-vlda-01.mountfailure documented inREADME.mdhappened —vlda-01(the CIFS target) was presumably only reachable via this same192.168.22.0/24range. Decision made: rather than reviving the tunnel, removed it along with the dead CIFS mount and unused Samba packages. Config backed up to/root/removed-configs-backup/alpha_at_moon.conf.bakon the server (600 root:root) in case the tunnel is wanted again later. - SFTP chroot jail (
/var/sftp/): three accounts (ftpuser,ftp_jens,ftp_alex) in thesftpgroup, each chrooted to their own directory with no shell — a controlled file-drop mechanism separate fromjens's admin SSH access. Purpose/owners of these accounts not established from config alone. - Users, groups, sudoers: not diffed — no baseline "clean install"
user set to compare against beyond the default
ubuntu/first-boot user, which this host doesn't appear to still have. - Cron jobs:
certbot renew(weekly), Nextcloud'scron.php(every 5 min) — both documented inREADME.md, both additive, no baseline.
Summary: what this diff actually surfaced
Beyond confirming the changes already tracked in README.md/TODO.md,
this exercise found four previously-undocumented things:
A live RTMP streaming server (— removed same day; unused, no auth on the publish endpoint, no reason found to keep it.nginx+libnginx-mod-rtmpon:1935)A dormant WireGuard tunnel to a home network— removed same day, along with the CIFS mount it was almost certainly gating and the Samba packages that supported it. Config backed up first.- A chrooted SFTP-only access path for three accounts, separate from the main admin login. Left as-is — appears to be legitimate, ongoing infrastructure, not a stray leftover.
- Two Apache config items worth a second look:
AllowOverride allon/var/www, and a broad<FilesMatch "\.*">PHP handler that's wider than it probably needs to be. Still open — not yet addressed.