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>
software-properties-common removed — dropped from Debian 13 (trixie).
unattended-upgrades and apt-listchanges moved to optional task with
ignore_errors so missing packages don't fail the entire deployment.