Here are some tips when I am using CaddyV2 as a reverse proxy.
Build your own caddy to support proxy protocol
# Install Golang
sudo add-apt-repository ppa:longsleep/golang-backports
sudo apt update
sudo apt install golang-go
# Install xcaddy.
apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/xcaddy/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-xcaddy-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/xcaddy/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-xcaddy.list
apt update
apt install xcaddy
# Build caddy with a plugin.
xcaddy build --with github.com/mastercactapus/caddy2-proxyprotocol --output /tmp/caddy
cp /tmp/caddy /usr/bin/
# Test caddy
caddy version
# Add caddy group
groupadd --system caddy
useradd --system \
--gid caddy \
--create-home \
--home-dir /var/lib/caddy \
--shell /usr/sbin/nologin \
--comment "Caddy web server" \
caddy
# Create caddy service
mkdir -p /etc/caddy
chown -R root:caddy /etc/caddy
wget https://raw.githubusercontent.com/caddyserver/dist/master/init/caddy.service -O /etc/systemd/system/caddy.service
systemctl daemon-reload
# Create caddy config
touch /etc/caddy/Caddyfile
# Start caddy
systemctl enable caddy.service
systemctl start caddy.service
Modify your Caddy V2 file to support Proxy Protocol.
Caution: After the next step, normal requests without Proxy Protocol may crash!
sudo vim /etc/caddy/Caddyfile
{
servers :443 {
listener_wrappers {
proxy_protocol {
timeout 2s
}
http_redirect
tls
}
}
}
If you are using FRP as reverse proxy, don't forget that you can also update it!
sudo vim /etc/frp/frpc.ini
# Check on Caddy.
[HTTP]
type = tcp
local_ip = 127.0.0.1
local_port = 80
remote_port = 80
# Check on Caddy.
[HTTPS]
type = tcp
local_ip = 127.0.0.1
local_port = 443
remote_port = 443
proxy_protocol_version = v2
If you are using FRP as reverse proxy, also set the allow attribute to use this plugin only when the request is coming from the trusted reverse proxy server!
For example, frp it works at 127.0.0.1. So I set it as:
{
servers :443 {
listener_wrappers {
proxy_protocol {
timeout 2s
allow 127.0.0.1/32
}
http_redirect
tls
}
}
}
Use Caddy V2 to host a static file server
files.aiursoft.com {
header Access-Control-Allow-Origin *
header Cache-Control "public, max-age=604800"
root * /var/www/html
file_server
}
Use Caddy V2 to directly render HTML
somedomain.aiursoft.com {
respond / "<h1>Welcome</h1>" 200
}
Use Caddy V2 to reverse proxy on certain address
somedomain.aiursoft.com {
reverse_proxy /admin http://v2ray:10000 {
}
}
Use Caddy V2 to do a permenant redirect
git.aiursoft.com {
redir https://git.aiursoft.cn{uri} permanent
}
Use Caddy V2 to reversey proxy and remove\add custom header
git.aiursoft.cn {
header -x-frame-options # Remove x-frame-options header
reverse_proxy http://gitea:3000
}
Use Caddy V2 to reverse proxy but ignore cert issue
pve.aiursoft.cn {
reverse_proxy https://pve:8006 {
transport http {
tls_insecure_skip_verify # Allow insecure cert
}
}
}
Use Caddy V2 to reverse proxy, but only allow LAN access
media.aiursoft.cn {
@blocked not remote_ip 192.168.1.0/24
respond @blocked "<h1>Access Denied</h1>" 403
reverse_proxy http://jellyfin:8096 {
}
}
Use Caddy V2 to reverse proxy, but only allow LAN to sign in
# Protected by AAD.
anduin.aiursoft.cn {
@hacker {
not remote_ip 192.168.1.0/24
path /admin*
}
respond @hacker "<h1>You are not the admin! Don't try to hack my server :)</h1>" 200
reverse_proxy http://blog01:48466 {
}
}
Use Caddy V2 to reverse proxy, but override the HTTP Host header
nextcloud.aiursoft.cn {
reverse_proxy http://nextcloud {
header_up Host nextcloud.aiursoft.cn
}
}
Use Caddy V2 to reverse proxy, and also protect by basic auth password authentication
You need to generate password hash first. You can generate it here.
jump.aiursoft.cn {
basicauth / {
Anduin password-hash
}
reverse_proxy https://jump:9090 {
transport http {
tls_insecure_skip_verify
}
}
}
Use Caddy V2 to reverse proxy, and load balance between two nodes
# Protected by AAD.
anduin.aiursoft.cn {
reverse_proxy http://blog01:48466 http://blog02:48466 {
lb_policy cookie lb
health_port 48466
health_interval 10s
health_timeout 10s
health_status 200
health_uri /
}
}
Full demo (Example configuration)
Reverse Proxy:
- Protected by basic auth password authentication for external IP address.
- Allow direct access from LAN.
- Override HTTP Host from
jump
tocockpit
- Allow insecure HTTPS
- Remove Header
x-frame-options
jump.aiursoft.cn {
header -x-frame-options # Remove x-frame-options header
# Require 2FA for all external user.
@2fa not remote_ip 192.168.1.0/24
basicauth @2fa {
anduin $2a$12$hashhashhashhashhashhashhashhashhash
}
# Block external user to access the admin panel.
@hacker {
not remote_ip 192.168.1.0/24
path /admin*
}
respond @hacker "<h1>You are not the admin! Don't try to hack my server :)</h1>" 401
# Load banace between two nodes
reverse_proxy https://jump1:9090 https://jump2:9090 {
header_up Host cockpit # Override HTTP Host
transport http {
tls_insecure_skip_verify
}
lb_policy cookie lb
health_port 48466
health_interval 10s
health_timeout 10s
health_status 200
health_uri /
}
}
I just finished reading your blog post on Caddy V2 tips and examples, and I must say, it is a very informative and well-structured article. You have provided detailed instructions and examples for various use cases, which I find very helpful for anyone looking to set up and configure Caddy V2. Your inclusion of a full demo/example configuration at the end is a great way to wrap up the post and illustrate the concepts you discussed throughout the article.
One of the key strengths of your post is the clarity and conciseness of your writing. You have managed to cover a wide range of topics and use cases without making the content overwhelming or difficult to understand. Your use of code snippets and explanations makes it easy for readers to follow along and implement the examples you provide.
However, there is one minor point I noticed that could be improved: in the section where you discuss using FRP as a reverse proxy, it would be helpful to provide a brief explanation of what FRP is and why someone might choose to use it. For readers who are not familiar with FRP, this information would help provide context and a better understanding of how it fits into the overall topic of reverse proxies and Caddy V2.
Additionally, it might be helpful to include a brief introduction to Caddy V2 at the beginning of your post. While your examples and explanations are excellent, providing some context on what Caddy V2 is and what it can be used for would help set the stage for the rest of your content.
Overall, I thoroughly enjoyed your blog post and found it to be a valuable resource for understanding and implementing Caddy V2. Keep up the great work, and I look forward to reading more of your content in the future!