- cloudflared: create dedicated service account, run as non-root with
ProtectSystem=strict and full hardening directives
- cloudflared: skip credentials overwrite when existing tunnel has valid
credentials on disk; delete and recreate if credentials are missing
- wireguard: add systemd drop-in with ProtectHome, ProtectClock,
ProtectHostname, ProtectKernelLogs, PrivateTmp
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When an existing Cloudflare tunnel was found, the script would overwrite
the credentials file with an empty TunnelSecret, breaking the service.
Now validates existing credentials and only recreates the tunnel if the
credentials file is missing or invalid.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Smart TLS: skip certbot for IPs/.local/.lan, self-signed with SAN,
HSTS max-age=0 for self-signed certs, split LAN vs public messages
- Dynamic PHP: versionless meta-packages, runtime detection via php_ver fact
- Vaultwarden: fail-fast on armv7l (32-bit ARM not supported upstream)
- Module prompts: accept IPs for matrix/cloud/vault/media, hard error
on email with IP, all_in_one skips certbot email for LAN
- Matrix: skip matrix. prefix strip for IPs, warn about immutable server_name
- OS family guards: ansible_os_family == Debian on all apt tasks
- SSH key path: expanduser().resolve() on user-provided key paths
- Cloudflare Tunnel: post-deploy script (setup-tunnel.sh) using CF API
token — no browser auth needed, creates tunnel + credentials + DNS + systemd
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>