{
  description = "CI-OS - the Continuous Integration OS";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    flake-utils.url = "github:numtide/flake-utils";
    git-sv.url = "git+https://code.252.no/tommy/git-sv";
  };

  outputs = { self, nixpkgs, flake-utils, git-sv, ... }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = import nixpkgs { inherit system; };
        lib = nixpkgs.lib;

        # imports from flakes
        gitSvPkg = git-sv.defaultPackage.${system};

        # include a few helper functions
        pkgs-local = import ./packages { inherit pkgs lib; };

        # Define a path to the templates directory
        templates = builtins.path { path = ./templates; };

      in
      {
        # Define the flake apps
        apps = {
          flux-local = flake-utils.lib.mkApp { drv = pkgs-local.flux-local; };
          flux-diff = flake-utils.lib.mkApp { drv = pkgs-local.flux-diff; };
          forgejo-comment = flake-utils.lib.mkApp { drv = pkgs-local.forgejo-comment; };
          forgejo-release = flake-utils.lib.mkApp { drv = pkgs-local.forgejo-release; };
        };

        packages = {
          build-image = pkgs.dockerTools.buildImageWithNixDb {
            name = "code.252.no/tommy/ci-os";
            tag = "latest";
            copyToRoot = pkgs.buildEnv {
              name = "image-root";
              pathsToLink = ["/bin" "/etc"];
              ignoreCollisions = true;
              paths = with pkgs; [
                # kubernetes
                chart-testing
                kubernetes-helm
                kubernetes-polaris
                fluxcd
                pluto
                skopeo
                pkgs-local.flux-local
                pkgs-local.flux-diff
                pkgs-local.forgejo-comment
                pkgs-local.forgejo-release

                # repository tooling
                gitSvPkg

                gnupg
                coreutils-full
                gnugrep
                findutils
                python312Full
                docker
                bash
                cacert
                coreutils
                curl
                jq
                yq
                jo
                gawk
                gitFull
                git-lfs
                gnused
                gnutar
                gzip
                nixVersions.stable
                nodejs
                openssh
                sudo
                wget
                xz
                zstd
                (pkgs.writeTextFile {
                  name = "nix.conf";
                  destination = "/etc/nix/nix.conf";
                  text = ''
                    accept-flake-config = true
                    experimental-features = nix-command flakes
                  '';
                })
              ];
            };

            extraCommands = ''
              # for /usr/bin/env
              mkdir usr
              ln -s ../bin usr/bin

              # make sure /tmp exists
              mkdir -m 1777 tmp

              # need a HOME
              mkdir -vp root

              # Copy templates into the image at /templates
              mkdir -p var/ci-os/templates
              cp -r ${templates} var/ci-os/templates
            '';

            config = {
              Cmd = ["/bin/bash"];
              Env = [
                "NIX_PATH=nixpkgs=${nixpkgs}"
                "LANG=en_GB.UTF-8"
                "ENV=/etc/profile.d/nix.sh"
                "BASH_ENV=/etc/profile.d/nix.sh"
                "NIX_BUILD_SHELL=/bin/bash"
                "PAGER=cat"
                "PATH=/usr/bin:/bin"
                "SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
                "USER=root"
              ];
            };
          };
        };
      }
    );
}
