Caddy: Difference between revisions

Onny (talk | contribs)
Add section on uWSGI usage with Caddy
Fenhl (talk | contribs)
the version of Caddy in nixpkgs stable has HTTP/3 enabled by default
 
(12 intermediate revisions by 3 users not shown)
Line 1: Line 1:
[https://caddyserver.com/ Caddy] is an efficient, HTTP/2 capable web server that can serve static and dynamic web pages.
[https://caddyserver.com/ Caddy] is an efficient, HTTP/2 and HTTP/3 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.
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.


Line 9: Line 9:
   enable = true;
   enable = true;
   virtualHosts."localhost".extraConfig = ''
   virtualHosts."localhost".extraConfig = ''
    tls internal
     respond "Hello, world!"
     respond "Hello, world!"
   '';
   '';
Line 14: Line 15:


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).
Use <code>curl -iLk localhost</code> to verify the configuration.


For SSL to work, just supply a public domain and ensure HTTP and HTTPS ports are accessible. Caddy will automatically configure TLS:
For SSL to work, just supply a public domain and ensure HTTP and HTTPS ports are accessible. Caddy will automatically configure TLS:
Line 86: Line 89:


You'll need a [[Phpfpm|PHP-FPM]] socket listening on Unix socket path <code>/var/run/phpfpm/localhost.sock</code>.
You'll need a [[Phpfpm|PHP-FPM]] socket listening on Unix socket path <code>/var/run/phpfpm/localhost.sock</code>.
=== PHP support using FrankenPHP plugin ===
Instead of Caddy, the FrankenPHP package can be defined as drop-in replacement for the Caddy-service which will  allow serving PHP applications without additional external process managers. In case you want to use FrankenPHP as an additional Caddy plugin, you can try this modifications
<syntaxhighlight lang="nix">
nixpkgs.overlays = [
  (self: super: {
    phpWithEmbed = super.php.override {
      embedSupport = true;
      ztsSupport = true;
      staticSupport = super.stdenv.hostPlatform.isDarwin;
      zendSignalsSupport = false;
      zendMaxExecutionTimersSupport = super.stdenv.hostPlatform.isLinux;
    };
    caddy = super.caddy.overrideAttrs (oldAttrs: {
      buildInputs =
        (oldAttrs.buildInputs or [ ])
        ++ [
          self.watcher
          self.phpWithEmbed.unwrapped
          self.brotli
        ]
        ++ self.phpWithEmbed.unwrapped.buildInputs;
      preBuild = ''
        export CGO_CFLAGS="$(${self.phpWithEmbed.unwrapped.dev}/bin/php-config --includes)"
        export CGO_LDFLAGS="-DFRANKENPHP_VERSION=${self.frankenphp.version} \
          $(${self.phpWithEmbed.unwrapped.dev}/bin/php-config --ldflags) \
          $(${self.phpWithEmbed.unwrapped.dev}/bin/php-config --libs)"
      '';
    });
  })
];
services.caddy = {
  enable = true;
  package = pkgs.caddy.withPlugins {
    plugins = [
      "github.com/dunglas/frankenphp/caddy@v1.12.1"
    ];
    hash = "sha256-WWUg717C7VcW7hNDpyoMdNE37JXgyvEU0vmMtZQXFSY=";
  };
  virtualHosts."localhost".extraConfig = ''
    tls internal
    respond "Hello, world!"
  '';
};
</syntaxhighlight>


=== Plug-ins ===
=== Plug-ins ===
Line 143: Line 194:


</syntaxhighlight>This example will serve a [[uWSGI]] app, provided by a unix socket file, on the host <code>myapp.example.org</code>.
</syntaxhighlight>This example will serve a [[uWSGI]] app, provided by a unix socket file, on the host <code>myapp.example.org</code>.
=== Caching ===
Caching can be enabled by adding the official [https://github.com/caddyserver/cache-handler cache-handler plugin]. Note that the corresponding hash and upstream version can change.<syntaxhighlight lang="nix">
services.caddy = {
  package = pkgs.caddy.withPlugins {
    plugins = [ "github.com/caddyserver/cache-handler@v0.16.0" ];
    hash = "sha256-XTFwYo3o7il3UfnE2QuJM+UoGTu0Yw+8ka0p9czdgEM=";
  };
  globalConfig = ''
    cache
  '';
  virtualHosts = {
    "example.org" = {
      extraConfig = ''
        cache
        reverse_proxy your-app:8080
      '';
  };
};
</syntaxhighlight>If you need to add caching to an existing virtual host entry, which was created by a module, you can prepend it by using <code>lib.mkBefore</code><syntaxhighlight lang="nix">
services.caddy = {
  [...]
  virtualHosts."dokuwiki.example.org".extraConfig = lib.mkBefore ''
    cache {
      ttl 30m
      stale 1h
    ]
  '';
};
</syntaxhighlight>See [https://github.com/caddyserver/cache-handler upstream documentation] for further configuration options.


=== Passing environment variable secrets/configuring acme_dns ===
=== Passing environment variable secrets/configuring acme_dns ===
Line 164: Line 247:


=== Check used ports ===
=== Check used ports ===
To check if Caddy is running and listening as configured you can run <code>netstat</code>:
To check if Caddy is running and listening as configured you can run <code>ss</code>:


<syntaxhighlight lang="bash">
<syntaxhighlight lang="console">
$ netstat -tulpn
$ sudo ss --listening --no-queues --numeric --processes --tcp --udp | grep 'Process\|caddy'
Active Internet connections (only servers)
Netid State      Local Address:Port  Peer Address:Port Process
Proto Recv-Q Send-Q Local Address           Foreign Address         State      PID/Program name   
tcp   LISTEN          127.0.0.1:2019       0.0.0.0:*   users:(("caddy",pid=1000,fd=10))
tcp       0      0 127.0.0.1:2019         0.0.0.0:*               LISTEN      1202/caddy          
tcp  LISTEN                  *:80               *:*    users:(("caddy",pid=1000,fd=11))
tcp6      0      0 :::80                   :::*                    LISTEN      1202/caddy        
tcp  LISTEN                  *:443             *:*    users:(("caddy",pid=1000,fd=12))
tcp6      0      0 :::443                 :::*                    LISTEN      1202/caddy        
udp  UNCONN                  *:443             *:*    users:(("caddy",pid=1000,fd=13))
udp6      0      0 :::443                 :::*                                1202/caddy          
</syntaxhighlight>
</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 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).