206 lines
5.0 KiB
Markdown
206 lines
5.0 KiB
Markdown
# Caddy Reverse Proxy
|
|
|
|
- [Caddy Reverse Proxy](#caddy-reverse-proxy)
|
|
- [Custom Caddy Image](#custom-caddy-image)
|
|
- [Install Caddy](#install-caddy)
|
|
- [Ansible](#ansible)
|
|
- [Manual](#manual)
|
|
- [Adding a new Caddy Record](#adding-a-new-caddy-record)
|
|
- [Logs](#logs)
|
|
- [Caddy WAF](#caddy-waf)
|
|
|
|
## Custom Caddy Image
|
|
|
|
This repo builds a custom caddy image with route53 DNS certbot support.
|
|
|
|
```bash
|
|
podman image pull gitea.reeseapps.com/services/caddy:latest
|
|
```
|
|
|
|
To upgrade the image, check [the caddy-dns route53
|
|
project](https://github.com/caddy-dns/route53/tags) releases and update the
|
|
`Containerfile` with the new version.
|
|
|
|
## Install Caddy
|
|
|
|
### Ansible
|
|
|
|
You'll need a secrets/Caddyfile with your caddy config.
|
|
|
|
`secrets/Caddyfile` example:
|
|
|
|
```conf
|
|
https://something.reeseapps.com:443 {
|
|
reverse_proxy internal.reeselink.com:8000
|
|
}
|
|
|
|
https://something-else.reeseapps.com:443 {
|
|
reverse_proxy internal-other.reeselink.com:8080
|
|
}
|
|
```
|
|
|
|
Make sure to add [your route53 configuration](https://github.com/caddy-dns/route53?tab=readme-ov-file#configuration)
|
|
|
|
```conf
|
|
tls {
|
|
dns route53 {
|
|
access_key_id "..."
|
|
secret_access_key "..."
|
|
region "us-east-1"
|
|
wait_for_route53_sync true
|
|
skip_route53_sync_on_delete true
|
|
route53_max_wait 2m
|
|
max_retries 5
|
|
}
|
|
}
|
|
```
|
|
|
|
The playbook limits the installer to `hosts: caddy` so make sure you have a caddy
|
|
host in your inventory.
|
|
|
|
Now you can install the Caddy service with something like:
|
|
|
|
```bash
|
|
# Base Proxy
|
|
ansible-playbook \
|
|
-i ansible/inventory.yaml \
|
|
active/container_caddy/install_caddy_proxy.yaml
|
|
|
|
# Deskwork (AI) Proxy
|
|
ansible-playbook \
|
|
-i ansible/inventory.yaml \
|
|
active/container_caddy/install_caddy_deskwork.yaml
|
|
```
|
|
|
|
See ansible playbook [install_caddy.yaml](/active/container_caddy/install_caddy.yaml)
|
|
|
|
### Manual
|
|
|
|
As root
|
|
|
|
```bash
|
|
mkdir /etc/caddy
|
|
vim /etc/caddy/Caddyfile
|
|
```
|
|
|
|
Caddy will automatically provision certificates if the server DNS points to the correct IP
|
|
and is accessible on the ports specifified. All you need to do is put `https` in the caddy conf.
|
|
|
|
Example:
|
|
|
|
```conf
|
|
# Gitea
|
|
https://gitea.reeseapps.com:443 {
|
|
reverse_proxy podman.reeselink.com:3000
|
|
}
|
|
|
|
# Jellyfin
|
|
https://jellyfin.reeseapps.com:443 {
|
|
reverse_proxy podman.reeselink.com:8096
|
|
}
|
|
```
|
|
|
|
```bash
|
|
vim /etc/containers/systemd/caddy.container
|
|
```
|
|
|
|
```conf
|
|
[Unit]
|
|
Description=Caddy
|
|
|
|
[Container]
|
|
AddCapability=NET_ADMIN
|
|
ContainerName=caddy
|
|
Image=docker.io/caddy:2
|
|
Network=host
|
|
SecurityLabelDisable=true
|
|
Volume=/etc/caddy:/etc/caddy
|
|
Volume=caddy_data:/data
|
|
Volume=caddy_config:/config
|
|
|
|
[Service]
|
|
Restart=always
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
```
|
|
|
|
```bash
|
|
systemctl daemon-reload
|
|
systemctl restart caddy
|
|
```
|
|
|
|
## Adding a new Caddy Record
|
|
|
|
Before you can create a Caddyfile you need records that point to your server.
|
|
|
|
You can either create them manually in your DNS provider of choice or use the provided
|
|
ddns service:
|
|
|
|
1. Update the [ddns caddy records](/active/container_ddns/secrets/caddy_records.yaml)
|
|
2. (Optional) Update the Caddyfile at `active/container_caddy/secrets/Caddyfile`
|
|
3. Run the [caddy ansible playbook](/active/container_caddy/caddy.md#install-caddy)
|
|
|
|
## Logs
|
|
|
|
```bash
|
|
# Follow remote connections
|
|
podman logs -f caddy | grep -e '^{' | jq -c '.request | {remote_ip,host}'
|
|
|
|
# Filter out noisy hosts
|
|
podman logs -f caddy | grep -e '^{' | jq -c '.request | {remote_ip,host} | select(.host != "gitea.reeseapps.com")'
|
|
|
|
# Focus on user agents
|
|
podman logs -f caddy | grep -e '^{' | jq -c '
|
|
{
|
|
"User-Agent": .request.headers["User-Agent"],
|
|
remote_ip: .request.remote_ip,
|
|
host: .request.host,
|
|
status: .status
|
|
}
|
|
'
|
|
```
|
|
|
|
## Caddy WAF
|
|
|
|
<https://github.com/fabriziosalmi/caddy-waf>
|
|
|
|
1. Copy the rules.json to `/etc/caddy/rules.json`
|
|
2. Update the Caddyfile to something like this:
|
|
|
|
```Caddyfile
|
|
gitea.reeseapps.com:443 {
|
|
log {
|
|
output stdout
|
|
format json {
|
|
message_key msg # Key for the log message
|
|
level_key severity # Key for the log level
|
|
time_key timestamp # Key for the timestamp
|
|
name_key logger # Key for the logger name
|
|
caller_key function # Key for the caller information
|
|
stacktrace_key stack # Key for error stacktraces
|
|
time_format "2006-01-02 15:04:05 MST" # RFC3339-like format
|
|
time_local # Use local timezone
|
|
duration_format "ms" # Show durations in milliseconds
|
|
level_format "upper" # Uppercase log levels
|
|
}
|
|
}
|
|
route {
|
|
waf {
|
|
metrics_endpoint /waf_metrics
|
|
rule_file rules.json
|
|
}
|
|
|
|
@wafmetrics {
|
|
path /waf_metrics
|
|
}
|
|
|
|
handle @wafmetrics { } # empty → let the WAF serve the metrics
|
|
|
|
handle {
|
|
reverse_proxy gitea.reeselink.com:3000
|
|
}
|
|
}
|
|
}
|
|
```
|