Anyone deployed a portableService with caddy inside?

Greetings!

I am building my own website, and would like to make deploying it painless, whether it is for development or production, whether it is for NixOS or non-NixOS.

Backstory which shows how to use portable services.

I found out about pkgs.portableService, which exports a systemd portable service.

I wrote a minimal example of a Flake which does just that:

{
  description = "Minimal example of a Nix flake exporting a `systemd` unit";

  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";

  outputs =
    inputs@{ self, ... }:
    let
      pkgs = inputs.nixpkgs.legacyPackages.x86_64-linux;
    in
    {
      packages.x86_64-linux.default = self.packages.x86_64-linux.portableService;
      packages.x86_64-linux.portableService =
        let
          example-website-service = pkgs.writeText "example-website.service" ''
            [Unit]
            Description=Example service for my website

            [Service]
            ExecStart=${pkgs.lib.getExe pkgs.caddy} file-server
          '';
        in
        pkgs.portableService {
          pname = "example-website";
          version = "0.1";
          units = [ example-website-service ];
        };
    };
}

Running this service requires someone to use sudo portablectl attach --profile=trusted result/example-website_0.1.raw, before being able to sudo systemctl start example-website like a real service. If I don’t use --profile=trusted, the user running Caddy doesn’t have the permissions to bind to ports 80 and 443.

My actual website tries to make use of the official caddyfile.service, the only modification being that I’m trying to use DynamicUser=yes instead of manually giving the service a particular user and group.

The problem?

Well, for once, I think that using --profile=trusted like I did in my backstory is wrong. I think the systemd defaults should be fine, and that giving permissions to bind to lower ports and create sockets, in AmbiantCapabilities, should make it so that Caddy doesn’t show an error when it tries to serve websites on ports 80 and 443.

But also, I’m thinking that this manual way of managing a “personal website service” is bad in production. Is there any way to attach a portable service to some NixOS config? I haven’t seen any option for that.

And, lastly, I think that Caddy’s official systemd unit file is not good enough for NixOS – it gives warnings related to read-only filesystems, lack of a $HOME directory, things like that.

So…

Currently, my website’s flake exports a filesystem with a /etc/caddy/Caddyfile for Caddy’s configuration, a /var/www/ directory with the website’s contents, and expects the end user (myself, or anyone wanting to run my website locally) to run Caddy on their own.

Is there a better way to distribute a website, including the webserver itself?

In a way that makes it easy to run without installing anything (with nix run), but also installable as a service if needed? How to do it in such a way that it’s possible to be deployed on a non-NixOS server?

I think my “portable service” solution was a nice idea, but Caddy doesn’t seem to like it very much.

Thank you kindly!

Is there a better way to distribute a website, including the webserver itself?

Arguably, the best way to distribute a website is by making it fully static and then it can be easily served with almost anything. Then you can use literally any tiny webserver which just serves a directory or many free services like github pages.

In a way that makes it easy to run without installing anything (with nix run), but also installable as a service if needed? How to do it in such a way that it’s possible to be deployed on a non-NixOS server?

You can bundle it up using nix bundle but then it is gigantic and takes a few seconds to start.