Hello I’m switching from nginx to caddy
1. The problem I’m having:
I’m almost done switching from nginx to caddy and it works great. The only thing i don’t manage to get working is my vmware vcenter that i ran behind nginx to get valid certificates.
The two main problems are:
- Header modification to hide from vcenter that there is a proxy in front of it
- Whitelist to allow only specific IPs and subnets (I haven’t tried to fix that yet but that is next in line after the first problem).
In the configuration files i have replaced the domain as the adress is not ment for the public.
2. Error messages and/or full log output:
When i visit the adress for the vcenter i get a redirected to the internal adress.
I haven’t managed to transfer all header modifications from nginx to caddy and that is what i need help with. It isn’t visible with curl in a only web browser.
3. Caddy version:
v2.8.4 h1:q3pe0wpBj1OcHFZ3n/1nl4V4bxBrYoSoab7rL9BMYNk=
4. How I installed and ran Caddy:
Caddy runs in a docker container on the same server as nginx that i’m replacing (and yes. nginx is not running and is disabled)
a. System environment:
Docker compose on ubuntu 24.04
b. Command:
PASTE OVER THIS, BETWEEN THE ``` LINES.
Please use the preview pane to ensure it looks nice.
c. Service/unit/compose file:
services:
caddy:
image: serfriz/caddy-crowdsec:latest # replace with the desired Caddy build name
container_name: caddy # feel free to choose your own container name
restart: "unless-stopped" # run container unless stopped by user (optional)
ports:
- "80:80" # HTTP port
- "443:443" # HTTPS port
- "443:443/udp" # HTTP/3 port (optional)
- "8443:8443" #unifi
volumes:
- caddy-data:/data # volume mount for certificates data
- caddy-config:/config # volume mount for configuration data
- $PWD/Caddyfile:/etc/caddy/Caddyfile # to use your own Caddyfile
# - $PWD/log:/var/log # bind mount for the log directory (optional)
- /var/log/caddy:/var/log/caddy
- $PWD/srv:/srv \ # bind mount to serve static sites or files (optional)
environment:
# - CLOUDFLARE_API_TOKEN=<token-value> # Cloudflare API token (if applicable)
# - DUCKDNS_API_TOKEN=<token-value> # DuckDNS API token (if applicable)
- CROWDSEC_API_KEY=<REDACED>
# - NETCUP_CUSTOMER_NUMBER=<number-value> \ # Netcup customer number (if applicable)
# - NETCUP_API_KEY=<key-value> \ # Netcup API key (if applicable)
# - NETCUP_API_PASSWORD=<password-value> \ # Netcup API password (if applicable)
volumes:
caddy-data:
external: true
caddy-config:
d. My Caddy config:
debug # makes Caddy logs more detailed (optional)
order crowdsec first # forces the CrowdSec directive to be executed first
crowdsec {
api_url http://REDACTED:8080 # it should point to your CrowdSec API (it can be a remote URL)
api_key {env.CROWDSEC_API_KEY}
}
log {
output file /var/log/caddy/access.log {
roll_size 10mb
roll_keep 20
roll_keep_for 720h
}
}
}
#Other servers not relevant and redacted
vc.public.tld {
crowdsec
log
reverse_proxy https://vc.private.local {
header_up Host vc.private.local
header_up Origin vc.private.local
transport http {
tls_insecure_skip_verify
}
}
}
5. Links to relevant resources:
Old nginx configuration:
server {
location / {
include /etc/nginx/conf.d/dynamicips;
include /etc/nginx/conf.d/staticips;
deny all;
proxy_set_header Host "vc.private.local";
proxy_set_header Origin "vc.private.local";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Authorization "";
proxy_set_header Origin "";
proxy_pass_header X-XSRF-TOKEN;
proxy_ssl_verify off;
proxy_pass https://vc.private.local;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_buffering off;
proxy_send_timeout 300;
proxy_read_timeout 300;
send_timeout 300;
client_max_body_size 1000m;
proxy_redirect https://vc.private.local/ https://vc.public.tld/;
}
location /websso/SAML2 {
include /etc/nginx/conf.d/dynamicips;
include /etc/nginx/conf.d/staticips;
deny all;
sub_filter "vc.private.local" "vc.public.tld";
proxy_set_header Host vc.private.local;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Authorization "";
proxy_set_header Origin "";
proxy_pass_header X-XSRF-TOKEN;
proxy_ssl_verify off;
proxy_pass https://vc.private.local;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
proxy_send_timeout 300;
proxy_read_timeout 300;
send_timeout 300;
client_max_body_size 1000m;
proxy_ssl_session_reuse on;
proxy_redirect https://vc.private.local/ https://vc.public.tld/;
}
server_name vc.public.tld;
listen 443 http2 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/vc.public.tld/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/vc.public.tld/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = vc.public.tld) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name vc.public.tld;
listen 80;
return 404; # managed by Certbot
}