Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Compose runner

{
  lib,
  pkgs,
  config,
  ...
}:
let
  cfg = config.dr460nixed.compose-runner;
in
{
  options.dr460nixed.compose-runner = lib.mkOption (
    with lib;
    {
      type = types.attrsOf (
        types.submodule {
          options = {
            source = mkOption {
              default = null;
              description = "Folder containing a compose file.";
              type = types.path;
            };
            envfile = mkOption {
              default = null;
              description = "Direct path to a valid .env file";
              type = types.nullOr types.path;
            };
          };
        }
      );
      default = { };
    }
  );

  config = {
    systemd.services = lib.mapAttrs' (
      name: value:
      lib.nameValuePair ("compose-runner-" + name) (
        let
          output = derivation {
            builder = pkgs.writeShellScript "build" ''
              PATH="${pkgs.rsync}/bin:${pkgs.coreutils}/bin:${pkgs.gnused}/bin"
              set -e
              mkdir "$out"
              sed -r 's/(^\s+restart:\s*)(unless-stopped|always)(\s*($|#))/\1on-failure\3/g' "$src/compose.yml" > "$out/compose.yml"
              rsync -a "$src/" "$out"
            '';
            name = "compose-runner-" + name;
            src = value.source;
            inherit (pkgs.hostPlatform) system;
          };
          statepath = "/var/compose-runner/${name}";
        in
        {
          description = "Compose runner for ${name}";
          path = with pkgs; [
            rsync
            docker-compose
            podman
            bash
          ];
          serviceConfig = {
            ExecStart = pkgs.writeShellScript ("execstart-compose-runner-" + name) ''
              set -e
              mkdir -p "${statepath}"
              rsync -a --no-owner --size-only "${output}/" "${statepath}"
              ${lib.optionalString (value.envfile != null) ''
                cp "${value.envfile}" "${statepath}/.env"
                chmod 600 "${statepath}/.env"
              ''}
              cd "${statepath}"
              docker-compose up
            '';
            ExecStopPost = pkgs.writeShellScript ("execstop-compose-runner-" + name) ''
              set -e
              cd "${statepath}"
              docker-compose down
            '';
          };
          unitConfig = {
            After = "docker.socket";
            Requisite = "docker.socket";
            StopPropagatedFrom = "docker.socket";
          };
          wantedBy = [ "multi-user.target" ];
        }
      )
    ) cfg;
    environment.systemPackages = lib.mkIf (cfg != { }) [ pkgs.docker-compose ];
    virtualisation.docker.enable = lib.mkIf (cfg != { }) true;
  };
}