inputs: { lib, pkgs ? import <nixpkgs>, ... }:
let
 storeDirectory = dir:
    let
      dirName = builtins.baseNameOf dir;
      drv = derivation {
        name = dirName;
        src = dir;
        builder = pkgs.writeShellScript "builder.sh" ''
          ${pkgs.coreutils}/bin/mkdir -p $out/${dirName}
          ${pkgs.coreutils}/bin/cp -rf $src/* $out/${dirName}
          ${pkgs.coreutils}/bin/cp -rf $src/.* $out/${dirName}
        '';
        system = pkgs.system;
      };
    in
    "${drv}/${dirName}";
 # nixos oci-containers fucking suck, so we just do a one-shot 
  # systemd service that invokes docker-compose
  #
  # not very reproducible nor declarative, but compatible with pretty much
  # anything, which is (imo) more important for a home server
  mkDockerComposeContainer =
    { directory
    , name ? builtins.baseNameOf directory
    , autoStart ? true
    , extraConfig ? { }
    , env ? { }
    , envFiles ? [ ]
    , extraFlags ? [ ]
    }:
    let
      # referencing the file directly would make the service dependant
      # on the entire flake, resulting in the container being restarted
      # every time we change anything at all
      storeDir = storeDirectory directory;

      cmdline = [
        "--build"
        "--remove-orphans"
      ] ++ map (env: "--env-file ${env}") envFiles
      ++ map (name: "-e ${name}=${lib.escapeShellArg env.${name}}") (builtins.attrNames env)
      ++ extraFlags;
    in
    {
      systemd.services."docker-compose-${name}" = {
        wantedBy = if autoStart then [ "multi-user.target" ] else [ ];
        after = [ "docker.service" "docker.socket" ];
        serviceConfig = {
          WorkingDirectory = storeDir;
          ExecStart = "${pkgs.docker}/bin/docker compose up ${builtins.concatStringsSep " " cmdline}";
          ExecStopPost = "${pkgs.docker}/bin/docker compose down";
        } // (extraConfig.serviceConfig or { });
      } // (builtins.removeAttrs extraConfig [ "serviceConfig" ]);
    };
in
 mkDockerComposeContainer {
  directory = ./.;
 }