Simplify Caddy infrastructure to use file-based configuration instead of complex API registration system

This commit is contained in:
2025-11-15 00:11:46 +01:00
parent 7788410bfc
commit 8162e789ee
13 changed files with 706 additions and 216 deletions

View File

@@ -1,15 +1,16 @@
# Caddy Web Server Role
A comprehensive Ansible role for installing and configuring [Caddy](https://caddyserver.com/) web server with automatic HTTPS, DNS challenges, and production security hardening.
A modern Ansible role for installing and configuring [Caddy](https://caddyserver.com/) web server with automatic HTTPS, file-based service configuration, and security hardening.
## Features
- 🔐 **Automatic HTTPS** with Let's Encrypt certificates
- 🌐 **DNS Challenge Support** for wildcard certificates (Cloudflare provider)
- 📁 **File-Based Configuration** using sites-enabled directory pattern
- 🛡️ **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
- **Zero Downtime** configuration reloads without service restarts
- 🎯 **Simple Architecture** following nginx-like configuration patterns
- 🔄 **Git-Friendly** configuration files for version control
## Requirements
@@ -19,16 +20,9 @@ A comprehensive Ansible role for installing and configuring [Caddy](https://cadd
## Quick Start
### Basic Static Site Setup
### Infrastructure Setup (One-time)
```yaml
# host_vars/myserver/main.yml
caddy_tls_enabled: true
caddy_domain: "example.com"
caddy_tls_email: "admin@example.com"
```
### Production Setup with DNS Challenge
Configure core Caddy infrastructure in your host vars:
```yaml
# host_vars/myserver/main.yml
@@ -43,6 +37,40 @@ vault_caddy_tls_email: "admin@example.com"
vault_cloudflare_api_token: "your-api-token-here"
```
### Service Configuration (Per-Service)
Services deploy configuration files to the sites-enabled directory:
```yaml
# In your service role (e.g., roles/myapi/tasks/main.yml)
- name: Deploy API service
# ... your service deployment tasks ...
- name: Deploy Caddy configuration
template:
src: myapi.caddy.j2
dest: "{{ caddy_sites_enabled_dir }}/myapi.caddy"
owner: root
group: "{{ caddy_user }}"
mode: '0644'
notify: reload caddy
```
```caddyfile
# roles/myapi/templates/myapi.caddy.j2
{{ service_domain }} {
reverse_proxy {{ service_backend }}
}
```
### Service Role Dependencies
```yaml
# roles/myapi/meta/main.yml
dependencies:
- role: caddy
```
## Required Variables
### For HTTPS/TLS
@@ -60,6 +88,15 @@ vault_cloudflare_api_token: "your-api-token-here"
| `caddy_dns_provider` | DNS challenge | DNS provider | `"cloudflare"` |
| `cloudflare_api_token` | Cloudflare DNS | API token for DNS | `"{{ vault_token }}"` |
### For Service Configuration (Per-Service)
| Variable | Required | Description | Example |
|----------|----------|-------------|---------|
| `service_domain` | Yes | Domain for the service | `"api.example.com"` |
| `service_backend` | Yes | Backend address | `"localhost:8080"` |
These are typically set in service role defaults or passed as template variables.
## Optional Variables
### Service Configuration
@@ -68,6 +105,7 @@ vault_cloudflare_api_token: "your-api-token-here"
|----------|---------|-------------|
| `caddy_version` | `"latest"` | Caddy version to install |
| `caddy_config_file` | `"/etc/caddy/Caddyfile"` | Main config file path |
| `caddy_sites_enabled_dir` | `"/etc/caddy/sites-enabled"` | Service config directory |
| `caddy_service_enabled` | `true` | Enable systemd service |
| `caddy_service_state` | `"started"` | Service state |
| `caddy_admin_listen` | `"127.0.0.1:2019"` | Admin API endpoint |
@@ -93,7 +131,8 @@ vault_cloudflare_api_token: "your-api-token-here"
| Variable | Default | Description |
|----------|---------|-------------|
| `caddy_log_level` | `"INFO"` | Logging level (ERROR, WARN, INFO, DEBUG) |
| `caddy_log_format` | `"common"` | Log format (common, json) |
| `caddy_log_format` | `"json"` | Log format (common, json) |
| `caddy_log_credentials` | `false` | Log credentials in access logs |
### ACME Configuration
@@ -103,31 +142,84 @@ vault_cloudflare_api_token: "your-api-token-here"
| `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
## Service Configuration Patterns
### Multiple Sites
### Simple API Service
```caddyfile
# roles/simple-api/templates/simple-api.caddy.j2
api.example.com {
reverse_proxy localhost:3000
}
```
```yaml
caddy_sites:
# Static file serving
- domain: "static.example.com"
root: "/var/www/static"
dns_challenge: true
# Reverse proxy to backend service
- domain: "api.example.com"
backend: "localhost:8080"
dns_challenge: true
extra_config: |
header_up Host {upstream_hostport}
header_up X-Real-IP {remote_host}
# HTTP-only internal site
- domain: "internal.example.com"
root: "/var/www/internal"
tls: "off"
# roles/simple-api/tasks/main.yml
- name: Deploy API configuration
template:
src: simple-api.caddy.j2
dest: "{{ caddy_sites_enabled_dir }}/simple-api.caddy"
owner: root
group: "{{ caddy_user }}"
mode: '0644'
notify: reload caddy
```
### Load Balanced Service
```caddyfile
# roles/balanced-api/templates/balanced-api.caddy.j2
api.example.com {
reverse_proxy localhost:8080 localhost:8081 localhost:8082 {
lb_policy least_conn
health_timeout 5s
health_interval 30s
}
}
```
### Static File Service
```caddyfile
# roles/static-files/templates/static-files.caddy.j2
static.example.com {
root * /var/www/static
file_server browse
}
```
### Service Cleanup
```yaml
# Remove service when decommissioning
- name: Remove service configuration
file:
path: "{{ caddy_sites_enabled_dir }}/old-service.caddy"
state: absent
notify: reload caddy
```
## Available Handlers
This role provides Ansible handlers for service management:
### `reload caddy`
- Reloads Caddy configuration without restart
- Automatically triggered when .caddy files change
- Picks up new configurations from sites-enabled directory
- Safe to run multiple times
### `restart caddy`
- Fully restarts the Caddy service
- Used for major configuration changes or binary updates
- May cause brief downtime
### `reload systemd`
- Reloads systemd daemon configuration
- Used when service files are modified
## Advanced Configuration
### Custom Systemd Security
```yaml
@@ -169,15 +261,27 @@ This role implements production-grade security hardening:
roles/caddy/
├── defaults/main.yml # Default variables with documentation
├── tasks/main.yml # Installation and configuration tasks
├── handlers/main.yml # Service restart/reload handlers
├── handlers/main.yml # Service management handlers
├── templates/
│ ├── Caddyfile.j2 # Main Caddyfile template
│ ├── Caddyfile.j2 # Main config with import directive
│ ├── caddy.service.j2 # Systemd service for custom builds
│ ├── index.html.j2 # Default welcome page
│ └── systemd-override.conf.j2 # Security hardening overrides
├── meta/main.yml # Role metadata and dependencies
└── README.md # This file
```
## Directory Structure After Deployment
```
/etc/caddy/
├── Caddyfile # Main config with "import sites-enabled/*"
└── sites-enabled/ # Service configurations
├── api.caddy # API service config
├── dashboard.caddy # Dashboard service config
└── static.caddy # Static files config
```
## Example Playbooks
### Basic Deployment
@@ -190,25 +294,27 @@ roles/caddy/
- caddy
```
### Full Infrastructure
### Infrastructure with Services
```yaml
- name: Secure VPS Setup
- name: Deploy Infrastructure and Services
hosts: production
become: yes
roles:
- security # Firewall, SSH hardening, etc.
- caddy # Web server with HTTPS
- caddy # Core web server infrastructure
- myapi # API service (deploys .caddy config automatically)
- mydashboard # Dashboard service (deploys .caddy config automatically)
```
## Dependencies
This role automatically handles Caddy installation, including:
This role automatically handles Caddy installation and configuration:
- 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
- Systemd service configuration with security hardening
- Sites-enabled directory structure for service configurations
## Compatibility
@@ -216,21 +322,40 @@ This role automatically handles Caddy installation, including:
- **Should work**: CentOS/RHEL 8+, Ubuntu 18.04+, Debian 10+
- **Requires**: systemd, curl/wget
## Contributing
## Troubleshooting
When modifying this role:
### List Service Configurations
```bash
ls -la /etc/caddy/sites-enabled/
```
1. Update defaults in `defaults/main.yml` with clear documentation
2. Use host-specific overrides in `host_vars/` for sensitive values
3. Leverage Ansible Vault for secrets (`vault_*` variables)
4. Test changes against the security hardening requirements
### Check Configuration Files
```bash
cat /etc/caddy/sites-enabled/myservice.caddy
```
## Security Considerations
### Validate Configuration
```bash
caddy validate --config /etc/caddy/Caddyfile
```
- **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
### View Caddy Logs
```bash
journalctl -u caddy -f
```
### Reload Configuration
```bash
systemctl reload caddy
```
## Examples
See other roles associated with the rick-infra project
## Additional Documentation
- [Caddy Service Configuration Guide](../../docs/caddy-service-configuration.md) - Comprehensive usage guide
- [Caddy Official Documentation](https://caddyserver.com/docs/) - Official Caddy documentation
## License