Accessing Multiple Servers via Domain on a Single Public IP with Caddy Reverse Proxy
You are setting up two computers at home (a Raspberry Pi and your PC) that both need to be accessed via domain names using ports 80 and 443. However, you cannot set up these ports on the same public IP to access different servers, because they will continuously conflict over that single public IP. So what is an effective solution?
Your ISP only provides one IP address at a time. In the case where you just need to expose a single server with ports 80 and 443, it is simple: you just set up NAT to open the ports. However, problems arise when you start setting up multiple servers on the same machine using the same ports, or different servers with different local IPs but the same ports. Your home network will not allow this. You need a mechanism in between that will route which domain, when accessing the public IP, will be forwarded to which corresponding local server IP to retrieve data. This concept is called a reverse proxy, and there are many tools that can implement it. Here I will introduce the simplest tool: Caddy.

Install Caddy with Docker
You can install Caddy in many ways by following the instructions here.
I chose to install it using Docker so that I can easily remove it when needed without affecting the system.
Create the compose.yml file
mkdir ~/caddy
cd ~/caddy
nano compose.ymlEnter the following content
services:
caddy:
image: caddy:2.7.6-alpine
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./html:/var/www/html
- ./caddy_data:/data
- ./caddy_config:/configCreate the Caddyfile file
nano Caddyfileand temporarily enter the following content
:80 {
respond "Hello, world!"
}Activate Caddy
docker compose up -dOpen your browser and go to http://<IP>. If you see the text Hello, world!, it means Caddy has been installed and activated successfully.
Configure Caddy as a Reverse Proxy
To configure Caddy as a reverse proxy for Portainer running at 192.168.0.50:9000, I edit the Caddyfile and add the following 3 lines
portainer.thuanbui.me {
reverse_proxy 192.168.0.50:9000
}Then restart Caddy with the command
docker compose exec -w /etc/caddy caddy caddy reloadWait 1–2 minutes for Caddy to complete the SSL certificate verification step, and now I can access Portainer via https://portainer.thuanbui.me
In case Portainer and Caddy are on the same server, you can refer to the article below to learn how to put the containers into the same Docker network and then modify the Caddyfile as follows
portainer.thuanbui.me {
reverse_proxy portainer
}P.S.: There are other tools to manage proxies via a UI; you can refer to this article: https://thuanbui.me/nginx-proxy-manager-reverse-proxy-openlitespeed-docker/