Caddy: Difference between revisions
imported>Malteneuss m Add code highlighting |
→Reverse proxy: Add example on forward real client ip |
||
(13 intermediate revisions by 7 users not shown) | |||
Line 4: | Line 4: | ||
== Get started == | == Get started == | ||
To try out Caddy add the following minimal example to your NixOS module: | To try out Caddy add the following minimal example to your [[NixOS modules | NixOS module]]: | ||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
services.caddy = { | { | ||
# ... | |||
services.caddy = { | |||
enable = true; | |||
virtualHosts."localhost".extraConfig = '' | |||
}; | respond "Hello, world!" | ||
''; | |||
}; | |||
} | |||
</syntaxhighlight> | </syntaxhighlight> | ||
This snippet will let Caddy respond on <code>http://localhost</code> and <code>https://localhost</code> with a dummy text "Hello world!". When no port is mentioned on virtualhost like just <code>localhost</code> instead of <code>localhost:8080</code>, Caddy listens on <code>80</code> and <code>443</code> by default and redirects requests from port 80 (unsecured) to 443 (secured). | This snippet will let Caddy respond on <code>http://localhost</code> and <code>https://localhost</code> with a dummy text "Hello world!". When no port is mentioned on virtualhost like just <code>localhost</code> instead of <code>localhost:8080</code>, Caddy listens on <code>80</code> and <code>443</code> by default and redirects requests from port 80 (unsecured) to 443 (secured). | ||
==== Check | ==== Check http connection ==== | ||
You can use <code>curl</code> to test the http connections: | |||
You can use <code>curl</code> to test the http | |||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
$ curl localhost -i -L -k | $ curl localhost -i -L -k | ||
HTTP/1.1 308 Permanent Redirect | HTTP/1.1 308 Permanent Redirect | ||
Location: https://localhost/ | Location: https://localhost/ | ||
.. | |||
HTTP/2 200 | HTTP/2 200 | ||
alt-svc: h3=":443"; ma=2592000 | alt-svc: h3=":443"; ma=2592000 | ||
content-type: text/plain; charset=utf-8 | content-type: text/plain; charset=utf-8 | ||
... | |||
Hello, world! | Hello, world! | ||
Line 58: | Line 40: | ||
Here you can see that Caddy automatically redirects from an unsecure http://localhost to a secure https://localhost call. | Here you can see that Caddy automatically redirects from an unsecure http://localhost to a secure https://localhost call. | ||
For local addresses like "localhost" Caddy always generates and uses a self-signed certificate, which curl correctly doesn't trust; use the <code>-k</code> flag to ignore that. | For local addresses like "localhost" Caddy always generates and uses a self-signed certificate, which curl correctly doesn't trust; use the <code>-k</code> flag to ignore that. | ||
==== Check http(s) connection ==== | |||
When virtualhost and "real" host aren't the same it gets complicated with HTTPS, so the following curl command works: | |||
<syntaxhighlight lang="bash"> | |||
$ curl --connect-to <virtualhost>:443:<realhost>:443 https://<virtualhost> -k | |||
Hello, world! | |||
</syntaxhighlight> | |||
Curl will set <code>Host</code> header and TLS <code>SNI</code> in the request to <code><virtualhost></code> as desired by Caddy, but will make the actual request against the <code><realhost></code>, e.g. a load-balancer or ingress-controller. | |||
Alternatively with http and automatic redirects to https you can extend that call: | |||
<syntaxhighlight lang="bash"> | |||
$ curl --connect-to <virtualhost>:80:<realhost>:80 --connect-to <virtualhost>:443:<realhost>:443 https://<virtualhost> -k -L | |||
Hello, world! | |||
</syntaxhighlight> | |||
* [https://curl.se/docs/manpage.html#--connect-to curl connect-to documentation] | |||
* [https://www.claudiokuenzler.com/blog/693/curious-case-of-curl-ssl-tls-sni-http-host-header Curl on HTTPS, SNI, Host] | |||
* [https://github.com/caddyserver/caddy/issues/2656#issuecomment-1627342466 curl to Caddy over HTTPS] | |||
== Typical configurations == | == Typical configurations == | ||
Line 91: | Line 95: | ||
virtualHosts."example.org".extraConfig = '' | virtualHosts."example.org".extraConfig = '' | ||
reverse_proxy http://10.25.40.6 | reverse_proxy http://10.25.40.6 | ||
''; | |||
virtualHosts."another.example.org".extraConfig = '' | |||
reverse_proxy unix//run/gunicorn.sock | |||
''; | ''; | ||
}; | }; | ||
</syntaxhighlight> | </syntaxhighlight>In case you would like to forward the real client IP of the request to the backend, add following headers<syntaxhighlight lang="nix"> | ||
services.caddy = { | |||
virtualHosts."example.org".extraConfig = '' | |||
reverse_proxy http://10.25.40.6 { | |||
header_down X-Real-IP {http.request.remote} | |||
header_down X-Forwarded-For {http.request.remote} | |||
} | |||
''; | |||
}; | |||
</syntaxhighlight>Fur further reverse proxy configuration, see [https://caddyserver.com/docs/quick-starts/reverse-proxy upstream documentation]. | |||
=== Redirect === | === Redirect === | ||
Line 106: | Line 120: | ||
virtualHosts."example.org" = { | virtualHosts."example.org" = { | ||
extraConfig = '' | extraConfig = '' | ||
redir https://www.example.org | redir https://www.example.org{uri} | ||
''; | ''; | ||
serverAliases = [ "old.example.org" ]; | |||
}; | }; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 133: | Line 147: | ||
== Debugging == | == Debugging == | ||
=== Check used ports === | |||
To check if Caddy is running and listening as configured you can run <code>netstat</code>: | |||
<syntaxhighlight lang="bash"> | |||
$ netstat -tulpn | |||
Active Internet connections (only servers) | |||
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name | |||
tcp 0 0 127.0.0.1:2019 0.0.0.0:* LISTEN 1202/caddy | |||
tcp6 0 0 :::80 :::* LISTEN 1202/caddy | |||
tcp6 0 0 :::443 :::* LISTEN 1202/caddy | |||
udp6 0 0 :::443 :::* 1202/caddy | |||
</syntaxhighlight> | |||
The tcp (ipv4) socket port 2019 is Caddy's management endpoint, for when you want manage its config via web REST calls instead of Nix (ignore). | |||
The tcp6 (an ipv6 socket that also listens on ipv4) socket on port 80 (HTTP) and 443 (HTTPS) indicate that our virtualhost config was used. | |||
=== Virtualhost and real host not identical === | |||
When you connect to Caddy must ensure that the "Host" header matches the virtualhost entry of Caddy. For example, when testing locally a config like | |||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
Line 181: | Line 213: | ||
[[Category:Applications]] | [[Category:Applications]] | ||
[[Category: | [[Category:Server]] | ||
[[Category:Networking]] |