Caddy: Difference between revisions

From NixOS Wiki
imported>Malteneuss
Fix content error in introduction
imported>Malteneuss
m Add code highlighting
Line 15: Line 15:
</syntaxhighlight>
</syntaxhighlight>


This snippet will let Caddy respond on http://localhost and https://localhost with a dummy text "Hello world!". When no port is mentioned on virtualhost like just "localhost" instead of "localhost:8080", Caddy listens on 80 and 443 by default and redirects requests on 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 used ports ====


To check if Caddy is running and listening as configured you can run netstat:
To check if Caddy is running and listening as configured you can run <code>netstat</code>:


<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
Line 35: Line 35:
==== Check connection ====
==== Check connection ====


You can use curl to test the http(s) connections:
You can use <code>curl</code> to test the http(s) connections:


<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
Line 57: Line 57:


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 "-k" 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.


== Typical configurations ==
== Typical configurations ==

Revision as of 12:09, 8 July 2023

Caddy is an efficient, HTTP/2 capable web server that can serve static and dynamic web pages. It can also be a reverse proxy to serve multiple web services under one server. Its main features are its simple config setup and automatic HTTPS: It will automatically request and renew a LetsEncrypt certificate so that users of your service get a Browser-trusted and secure connection.

Get started

To try out Caddy add the following minimal example to your NixOS module:

services.caddy = {
  enable = true;
  virtualHosts."localhost".extraConfig = ''
    respond "Hello, world!"
  '';
};

This snippet will let Caddy respond on http://localhost and https://localhost with a dummy text "Hello world!". When no port is mentioned on virtualhost like just localhost instead of localhost:8080, Caddy listens on 80 and 443 by default and redirects requests from port 80 (unsecured) to 443 (secured).

Check used ports

To check if Caddy is running and listening as configured you can run netstat:

$ 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

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 curl to test the http(s) connections:

$ curl localhost -i -L -k
HTTP/1.1 308 Permanent Redirect
Connection: close
Location: https://localhost/
Server: Caddy
date: Sat, 08 Jul 2023 11:56:05 GMT
Content-Length: 0

HTTP/2 200 
alt-svc: h3=":443"; ma=2592000
content-type: text/plain; charset=utf-8
server: Caddy
content-length: 15
date: Sat, 08 Jul 2023 11:56:05 GMT

Hello, world!

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 -k flag to ignore that.

Typical configurations

SSL

Caddy will automatically try to acquire SSL certificates for the specified domain, in this example example.org. This requires you to configure the DNS records of your domain correctly, which should point to the address of your Caddy server. The firewall ports 80 and 443 needs to be opened.

services.caddy = {
  enable = true;
  virtualHosts."example.org".extraConfig = ''
    encode gzip
    file_server
    root * ${
      pkgs.runCommand "testdir" {} ''
        mkdir "$out"
        echo hello world > "$out/example.html"
      ''
    }
  '';
}; 
networking.firewall.allowedTCPPorts = [ 80 443];

Reverse proxy

The following snippet creates a reverse proxy for the domain example.org, redirecting all requests to http://10.25.40.6

services.caddy = {
  enable = true;
  virtualHosts."example.org".extraConfig = ''
    reverse_proxy http://10.25.40.6
  '';
};

Redirect

Redirecting example.org and old.example.org to www.example.org

services.caddy = {
  enable = true;
  virtualHosts."example.org" = {
    extraConfig = ''
      redir https://www.example.org
   '';
    serverAlias = [ "old.example.org" ];
};

PHP FastCGI

Serving a PHP application in /var/www on http://localhost .

services.caddy = {
  enable = true;
  virtualHosts."http://localhost" = {
    extraConfig = ''
      root    * /var/www
      file_server
      php_fastcgi unix/var/run/phpfpm/localhost.sock
    '';
  };
};

You'll need a PHP-FPM socket listening on Unix socket path /var/run/phpfpm/localhost.sock.

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

services.caddy = {
  enable = true;
  virtualHosts."example.org".extraConfig = ''
    respond "Hello, world!"
  '';
};

you must send the request against "localhost" and manually override the host header to "example.org":

$ curl localhost -i -H "Host: example.org"
HTTP/1.1 308 Permanent Redirect
Connection: close
Location: https://example.org/
Server: Caddy
...

Above you also see the redirect from http://localhost to https://example.org; Caddy always redirects from the unsecure to the secure port of your virtualhost.

If the response is empty, try setting a port number like 80 and/or try a local TLS security certificate instead of global LetsEncrypt:

services.caddy = {
  enable = true;
  virtualHosts."example.org:80".extraConfig = ''
    respond "Hello, world!"
    tls internal
  '';
};

With "tls internal" Caddy will generate a local certificate, which is good when testing locally and/or you don't have internet access (e.g. inside a nixos-container).

See also