Caddy Web Server Role
A comprehensive Ansible role for installing and configuring Caddy web server with automatic HTTPS, DNS challenges, and production security hardening.
Features
- 🔐 Automatic HTTPS with Let's Encrypt certificates
- 🌐 DNS Challenge Support for wildcard certificates (Cloudflare provider)
- 🛡️ Security Hardening with systemd restrictions and capability bounds
- 🔧 Flexible Configuration for static sites and reverse proxies
- 📝 Production Ready with proper logging and monitoring
- 🎯 Role-Based Architecture with host-specific overrides
Requirements
- Systemd-based Linux distribution (tested on Arch Linux)
- Ansible 2.9+
- For DNS challenges: Cloudflare account with API token
Quick Start
Basic Static Site Setup
Production Setup with DNS Challenge
Required Variables
For HTTPS/TLS
| Variable |
Required When |
Description |
Example |
caddy_tls_enabled |
Always for HTTPS |
Enable TLS/HTTPS |
true |
caddy_tls_email |
HTTPS enabled |
Email for Let's Encrypt |
"admin@example.com" |
caddy_domain |
HTTPS enabled |
Primary domain |
"example.com" |
For DNS Challenge (Wildcard Certificates)
| Variable |
Required When |
Description |
Example |
caddy_dns_provider |
DNS challenge |
DNS provider |
"cloudflare" |
cloudflare_api_token |
Cloudflare DNS |
API token for DNS |
"{{ vault_token }}" |
Optional Variables
Service Configuration
| Variable |
Default |
Description |
caddy_version |
"latest" |
Caddy version to install |
caddy_config_file |
"/etc/caddy/Caddyfile" |
Main config file path |
caddy_service_enabled |
true |
Enable systemd service |
caddy_service_state |
"started" |
Service state |
caddy_admin_listen |
"127.0.0.1:2019" |
Admin API endpoint |
Directory Configuration
| Variable |
Default |
Description |
caddy_config_dir |
"/etc/caddy" |
Configuration directory |
caddy_data_dir |
"/var/lib/caddy" |
Data/state directory |
caddy_log_dir |
"/var/log/caddy" |
Log directory |
caddy_web_root |
"/var/www" |
Web root directory |
Security Configuration
| Variable |
Default |
Description |
caddy_systemd_security |
true |
Enable systemd security restrictions |
caddy_firewall_ports |
[80, 443] |
Ports to open in firewall |
Logging Configuration
| Variable |
Default |
Description |
caddy_log_level |
"INFO" |
Logging level (ERROR, WARN, INFO, DEBUG) |
caddy_log_format |
"common" |
Log format (common, json) |
ACME Configuration
| Variable |
Default |
Description |
caddy_acme_ca |
Let's Encrypt Prod |
ACME CA directory URL |
caddy_dns_resolvers |
["1.1.1.1:53", "1.0.0.1:53"] |
DNS resolvers |
caddy_dns_propagation_timeout |
120 |
DNS propagation timeout (seconds) |
Advanced Configuration
Multiple Sites
Custom Systemd Security
Staging Environment
Security Features
This role implements production-grade security hardening:
Systemd Security Restrictions
- NoNewPrivileges: Prevents privilege escalation
- CapabilityBoundingSet: Limits to
CAP_NET_ADMIN and CAP_NET_BIND_SERVICE
- ProtectSystem=strict: Read-only filesystem protection
- ProtectKernelLogs/Modules/Tunables: Kernel protection
- RestrictAddressFamilies: Limits to IPv4, IPv6, and Unix sockets
- RestrictNamespaces/Realtime/SUIDSGID: Additional restrictions
- MemoryDenyWriteExecute: Prevents code injection
- SystemCallFilter=@system-service: Whitelist system calls
File System Security
- Dedicated
caddy user and group
- Proper directory permissions
- Read-only configuration binding
- Isolated temporary files
File Structure
Example Playbooks
Basic Deployment
Full Infrastructure
Dependencies
This role automatically handles Caddy installation, including:
- Standard Caddy binary for HTTP-only setups
- Custom build with Cloudflare DNS plugin when DNS challenge is enabled
- System user and directory creation
- Systemd service configuration
Compatibility
- Tested: Arch Linux
- Should work: CentOS/RHEL 8+, Ubuntu 18.04+, Debian 10+
- Requires: systemd, curl/wget
Contributing
When modifying this role:
- Update defaults in
defaults/main.yml with clear documentation
- Use host-specific overrides in
host_vars/ for sensitive values
- Leverage Ansible Vault for secrets (
vault_* variables)
- Test changes against the security hardening requirements
Security Considerations
- Secrets: Always use Ansible Vault for API tokens and sensitive data
- Firewall: Role opens ports 80 and 443; ensure firewall is configured
- DNS: DNS challenge requires API access to your DNS provider
- Monitoring: Monitor certificate expiration and renewal
License
This role is part of the rick-infra project infrastructure configuration.