The trojan-go service runs as the trojan user (non-root) and needs to: (1) read TLS cert/key files from /etc/letsencrypt/, (2) bind to port 443. Currently, cert files are owned by root with restrictive permissions, and the systemd unit only uses AmbientCapabilities without CapabilityBoundingSet.
Goals:
trojan user can read the TLS certificate and key filesCAP_NET_BIND_SERVICE is properly granted to the trojan-go processNon-Goals:
Copy cert files to a trojan-owned directory instead of changing /etc/letsencrypt permissions
Changing the entire /etc/letsencrypt tree to be readable by the trojan user is a security concern. Instead, copy the cert and key to /etc/trojan-go/tls/ owned by the trojan user after each certbot renewal. This keeps the Let's Encrypt directory locked down while giving trojan exactly what it needs.
Add CapabilityBoundingSet alongside AmbientCapabilities
AmbientCapabilities alone may not be sufficient on all systems. Adding CapabilityBoundingSet ensures the capability is available to the process even when the bounding set is restricted.
--deploy-hook copies certs after renewal, so there's a brief window where trojan serves the old cert. Mitigation: the hook reloads trojan after copying.