> ## Content Index
> Fetch the complete content index at: https://primerenaissance.xyz/llms.txt
> Use this file to discover other available public pages before exploring further.

# Setting up Caddy for pretty URLs and HTTPS
- URL: https://primerenaissance.xyz/setting-up-caddy-for-pretty-urls-and-https/
- Published: 2026-09-09T15:36:13.000Z
- Updated: 2026-09-09T15:36:13.000Z
- Author: Marcin

After I've installed the OS and set up AdGuard Home, the next step to take was to set up a reverse proxy. This is quite crucial, as nobody wants to access services via IP numbers and ports, and HTTPS would be quite useful too. 

There are several sensible options to choose from: Nginx Proxy Manager, Traefik, Caddy. So far, I have had experience with the former two, and just for the sake of self-development, I wanted to try something else.

Caddy is probably the easiest reverse proxy to set up. There is no complex boilerplate, configuration is very simple and concise. It is based on one config file named \`Caddyfile\`.

#### Set Caddy up and running

In order to start with Caddy, I ran the following docker-compose file:

```yaml
services:
  caddy:
    image: caddy:2.11.4-alpine
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./conf:/etc/caddy
      - ./site:/srv
      - caddy_data:/data
      - caddy_config:/config
    networks:
      - midgard-network

networks:
  midgard-network:
    external: true

volumes:
  caddy_data:
  caddy_config:
```

Caddy requires two volumes, one for data, and another one for config (where the Caddyfile resides).

Since at that stage I only had AdGuard Home as the only service, I put it into Caddyfile as the only entry:

```conf
adguard.home {
	tls internal
	reverse_proxy adguardhome:8080
}
```

The structure of the entry is quite simple. First, we need a specific URL for the service. I opted for `adguard.home`. Then I mapped it onto a specific Docker container name: in my case, it was `adguardhome`. It needs to have the port appended (`:8080`). This should be enough for the AdGuard Home dashboard to open in the browser under the requested URL.

#### Handling HTTPS

Another important directive for a homelab is `tls internal`, responsible for generating SSL/TLS certificates. With this setting, Caddy will not attempt to communicate with the external \`Let's Encrypt\` servers, but it will try to create a key on its own. This is usually sufficient for internal services. 

However, there is one more step which needs to be taken when we want to access homelab services via HTTPS on the client devices. The certificate generated by Caddy needs to be added to the keychain on the client device (in my case, MacOS).

First, I copied the file from the Caddy container to the current location:

```bash
docker cp caddy:/data/caddy/pki/authorities/local/root.crt .
```

Then, in other terminal window on the client (NOT on the server), I used \`scp\` to copy the certificate onto my MacOS machine:

```bash
scp marcin@192.168.88.10:/home/marcin/root.crt .
```

Thus, the certificate was available to me on my Mac. Finally, I needed to add it to the System Keychain. This can be easily done with GUI: open Keychain Access, drag the certificate onto it, choose \`Always Trust\` next to \`When using this certificate\` and... Voila! When you restart the browser and try to access `adguard.home`, the AdGuard dashboard should open with a secure connection!