Jump to content

Caddy: Difference between revisions

→‎Reverse proxy: Add example on forward real client ip
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 = {
{
  enable = true;
  # ...
  virtualHosts."localhost".extraConfig = ''
  services.caddy = {
    respond "Hello, world!"
    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 used ports ====
==== Check http connection ====


To check if Caddy is running and listening as configured you can run <code>netstat</code>:
You can use <code>curl</code> to test the http connections:
 
<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.
 
==== Check connection ====
 
You can use <code>curl</code> to test the http(s) connections:


<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
Connection: close
Location: https://localhost/
Location: https://localhost/
Server: Caddy
..
date: Sat, 08 Jul 2023 11:56:05 GMT
Content-Length: 0


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
server: Caddy
...
content-length: 15
date: Sat, 08 Jul 2023 11:56:05 GMT


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 = {
* [https://caddyserver.com/docs/quick-starts/reverse-proxy Caddy reverse proxy documentation]
  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}
   '';
   '';
     serverAlias = [ "old.example.org" ];
     serverAliases = [ "old.example.org" ];
};
};
</syntaxhighlight>
</syntaxhighlight>
Line 133: Line 147:
== Debugging ==
== Debugging ==


You can use curl to test http(s) calls. However, you must ensure that the "Host" header matches the virtualhost entry of Caddy. For example, when testing locally a config like  
=== 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:Web Servers]]
[[Category:Server]]
[[Category:Networking]]
62

edits