Skip to main content

Caddy

Caddy is the recommended starting point when you do not already run a reverse proxy. Its normal public-hostname flow obtains and renews certificates automatically, and Jiandu needs only a short Caddyfile.

This guide assumes:

  • users open https://documents.example.net;
  • Caddy can reach Jiandu at jiandu:8077; and
  • Jiandu sees Caddy's direct connection from 172.30.0.2.

Replace all three values for your deployment. The trusted address must be the address Jiandu actually observes, not merely the address in this example.

1. Configure Jiandu​

/etc/jiandu/jiandu.json
{
"schema_version": 1,
"server": {
"bind": "0.0.0.0:8077",
"request_timeout_seconds": 30,
"ingress": {
"mode": "https_reverse_proxy",
"public_origin": "https://documents.example.net",
"trusted_proxy_cidrs": ["172.30.0.2/32"]
}
}
}

For two host processes, replace the bind address with 127.0.0.1:8077 and the trusted CIDR with 127.0.0.1/32. In a container network, pinning Caddy to a dedicated /32 prevents an unrelated container on the same subnet from becoming a trusted proxy.

2. Add the Caddy route​

Caddyfile
documents.example.net {
header Strict-Transport-Security "max-age=31536000"

reverse_proxy jiandu:8077 {
header_up Host {http.request.host}
header_up X-Forwarded-Proto https
header_up X-Forwarded-For {http.request.remote.host}

header_up -X-Jiandu-Proxy-Secret
header_up -X-Auth-Subject
header_up -X-Auth-Name
header_up -X-Auth-Groups
}
}

Do not add tls internal for a public hostname. With DNS pointing to Caddy and ports 80/443 reachable as required by the selected ACME challenge, Caddy's default automation obtains a public certificate. See Caddy's automatic HTTPS requirements.

For a private lab where every client can trust your private CA, add:

tls internal

Export and install the Caddy root CA on each test client. Clicking through a browser warning does not establish a sound production boundary.

Why each directive is present​

DirectivePurpose
documents.example.netSelects the only host this site block serves and activates HTTPS certificate management. It must equal Jiandu's public_origin host.
header Strict-Transport-Security ...Tells browsers to return over HTTPS for one year. It intentionally omits subdomains and preload.
reverse_proxy jiandu:8077Sends traffic to the private Jiandu listener. This address must not be publicly routable.
header_up Host ...Preserves the external host and any non-default port so Jiandu can compare it with public_origin.
header_up X-Forwarded-Proto httpsReplaces any client value with the scheme established by this TLS edge.
header_up X-Forwarded-For ...Replaces, rather than appends to, browser-controlled forwarding data. Jiandu can then apply client-aware rate limits behind the trusted hop.
header_up -X-...Deletes identity assertions and proxy secrets supplied by an untrusted client. Extend this list if trusted-proxy authentication uses different header names.

Caddy's reverse proxy supports streaming bodies without a whole-request buffering directive. Do not add a short response_header_timeout or request-body limit unless you have sized it for slow uploads, downloads, and Jiandu's resumable upload requests. Caddy's reverse_proxy reference describes the transport controls if your network requires explicit timeouts.

3. Isolate the backend network​

In Compose, publish only Caddy and keep the backend internal:

compose.yaml
services:
jiandu:
expose:
- "8077"
networks:
backend:
ipv4_address: 172.30.0.10

caddy:
image: caddy:2.10.2-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
- caddy-config:/config
networks:
edge: {}
backend:
ipv4_address: 172.30.0.2

networks:
edge: {}
backend:
internal: true
ipam:
config:
- subnet: 172.30.0.0/24

volumes:
caddy-data: {}
caddy-config: {}

Persist both Caddy volumes: /data contains certificate state and /config contains runtime configuration. Do not publish Jiandu's port with ports:. The repository's examples/docker-compose directory contains the complete runnable topology.

4. Validate the boundary​

caddy validate --config /etc/caddy/Caddyfile
curl --fail --silent https://documents.example.net/api/v1/health/ready
curl --silent --show-error --head https://documents.example.net/ | grep -i strict-transport-security

Also confirm that http://<server>:8077 is unreachable from another machine. If Jiandu returns 421 ingress_not_allowed, inspect the Caddy address on the backend network and update the /32; do not widen it to the entire private address space as a shortcut.