{
  description = "every.channel development environment";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    flake-utils.url = "github:numtide/flake-utils";
    rust-overlay.url = "github:oxalica/rust-overlay";
    agenix.url = "github:ryantm/agenix";
  };

  outputs = { self, nixpkgs, flake-utils, rust-overlay, agenix }:
    let
      nixosModules = rec {
        ec-node = import ./nix/modules/ec-node.nix;
        ec-runner = import ./nix/modules/ec-runner.nix;
        ec-netboot = import ./nix/modules/ec-netboot.nix;
        ec-ipxe-qemu = import ./nix/modules/ec-ipxe-qemu.nix;
        ec-ethereum = import ./nix/modules/ec-ethereum.nix;
        ec-op-stack = import ./nix/modules/ec-op-stack.nix;
        ec-publisher-guest = import ./nix/modules/ec-publisher-guest.nix;
        default = ec-node;
      };
    in
    {
      inherit nixosModules;

      nixosConfigurations =
        let
          mkRunner = system: extraModules:
            nixpkgs.lib.nixosSystem {
              inherit system;
              specialArgs = { inherit self; };
              modules = [
                ./nix/nixos/ec-runner.nix
              ] ++ extraModules;
            };
          mkPublisher = system: extraModules:
            nixpkgs.lib.nixosSystem {
              inherit system;
              specialArgs = { inherit self; };
              modules = [
                ./nix/nixos/ec-runner.nix
                self.nixosModules.ec-publisher-guest
              ] ++ extraModules;
            };
        in
        {
          # Base runner system (for normal installs).
          ec-runner-aarch64 = mkRunner "aarch64-linux" [ ];
          ec-runner-x86_64 = mkRunner "x86_64-linux" [ ];
          ec-publisher-x86_64 = mkPublisher "x86_64-linux" [ ];

          # Sovereign forge host (git.every.channel) managed from every.channel.
          ecp-forge = nixpkgs.lib.nixosSystem {
            system = "x86_64-linux";
            specialArgs = { inherit self; };
            modules = [
              agenix.nixosModules.default
              self.nixosModules.ec-node
              self.nixosModules.ec-netboot
              self.nixosModules.ec-ipxe-qemu
              self.nixosModules.ec-ethereum
              self.nixosModules.ec-op-stack
              ./nix/nixos/ecp-forge.nix
            ];
          };

          # Netboot artifacts (iPXE/PXE).
          ec-runner-aarch64-netboot = mkRunner "aarch64-linux" [
            ({ modulesPath, ... }: {
              imports = [ (modulesPath + "/installer/netboot/netboot-minimal.nix") ];
            })
            ({ ... }: {
              services.every-channel.runner.overlayRoot.enable = false;
            })
            ({ config, pkgs, ... }: {
              # Convenience output dir: { kernel, initrd, netboot.ipxe }.
              system.build.netboot = pkgs.linkFarm "ec-runner-netboot" [
                {
                  name = "kernel";
                  path = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}";
                }
                {
                  name = "initrd";
                  path = "${config.system.build.netbootRamdisk}/initrd";
                }
                {
                  name = "netboot.ipxe";
                  path = "${config.system.build.netbootIpxeScript}/netboot.ipxe";
                }
              ];
            })
          ];
          ec-runner-x86_64-netboot = mkRunner "x86_64-linux" [
            ({ modulesPath, ... }: {
              imports = [ (modulesPath + "/installer/netboot/netboot-minimal.nix") ];
            })
            ({ ... }: {
              services.every-channel.runner.overlayRoot.enable = false;
            })
            ({ config, pkgs, ... }: {
              system.build.netboot = pkgs.linkFarm "ec-runner-netboot" [
                {
                  name = "kernel";
                  path = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}";
                }
                {
                  name = "initrd";
                  path = "${config.system.build.netbootRamdisk}/initrd";
                }
                {
                  name = "netboot.ipxe";
                  path = "${config.system.build.netbootIpxeScript}/netboot.ipxe";
                }
              ];
            })
          ];

          ec-publisher-x86_64-netboot = mkPublisher "x86_64-linux" [
            ({ modulesPath, ... }: {
              imports = [ (modulesPath + "/installer/netboot/netboot-minimal.nix") ];
            })
            ({ ... }: {
              services.every-channel.runner.overlayRoot.enable = false;
            })
            ({ config, pkgs, ... }: {
              system.build.netboot = pkgs.linkFarm "ec-publisher-netboot" [
                {
                  name = "kernel";
                  path = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}";
                }
                {
                  name = "initrd";
                  path = "${config.system.build.netbootRamdisk}/initrd";
                }
                {
                  name = "netboot.ipxe";
                  path = "${config.system.build.netbootIpxeScript}/netboot.ipxe";
                }
              ];
            })
          ];

          # Installer ISO (primarily for x86_64 bring-up).
          ec-runner-x86_64-iso = mkRunner "x86_64-linux" [
            ({ modulesPath, ... }: {
              imports = [ (modulesPath + "/installer/cd-dvd/installation-cd-minimal.nix") ];
            })
            ({ ... }: {
              services.every-channel.runner.overlayRoot.enable = false;
            })
          ];

          # aarch64 SD image (useful for quick ARM bring-up and as a "real image" build target).
          ec-runner-aarch64-sdimage = mkRunner "aarch64-linux" [
            ({ modulesPath, ... }: {
              imports = [ (modulesPath + "/installer/sd-card/sd-image-aarch64.nix") ];
            })
            ({ ... }: {
              services.every-channel.runner.overlayRoot.enable = false;
            })
          ];
        };
    }
    // flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = import nixpkgs {
          inherit system;
          overlays = [ (import rust-overlay) ];
        };
        rust = pkgs.rust-bin.stable.latest.default.override {
          targets = [ "wasm32-unknown-unknown" ];
        };
        agenixPkg =
          if pkgs ? agenix then pkgs.agenix
          else agenix.packages.${system}.default;
        webkitgtk =
          if pkgs ? webkitgtk_4_1 then pkgs.webkitgtk_4_1
          else if pkgs ? webkitgtk_4_0 then pkgs.webkitgtk_4_0
          else throw "nixpkgs is missing webkitgtk_4_1/webkitgtk_4_0 (required for tauri on Linux)";
        linuxTauriDeps = with pkgs; [
          gtk3
          webkitgtk
          librsvg
          libappindicator
          libsoup_3
          glib
          pango
          gdk-pixbuf
        ];
      in
      {
        packages = {
          agenix = agenixPkg;
          fj = pkgs.forgejo-cli;
          foundry = pkgs.foundry;
          solc = pkgs.solc;
          ec-node = pkgs.callPackage ./nix/pkgs/ec-node.nix { };
          ec-cli = pkgs.callPackage ./nix/pkgs/ec-cli.nix { };
        };

        devShells.default = pkgs.mkShell {
          buildInputs = with pkgs; [
            rust
            cargo
            cargo-tauri
            cargo-llvm-cov
            llvmPackages.llvm
            clang
            pkg-config
            openssl
            ffmpeg
            nodejs_22
            nodePackages.wrangler
            agenixPkg
            forgejo-cli
            foundry
            solc
            uv
            git
            just
            cargo-watch
            wasm-bindgen-cli
            trunk
          ] ++ lib.optionals stdenv.isLinux linuxTauriDeps;

          shellHook = ''
            # Ensure nix-provided tools win over any host-local installs (e.g. a wrong-arch trunk).
            export PATH=${pkgs.trunk}/bin:$PATH
            export FFMPEG_INCLUDE_DIR=${pkgs.ffmpeg.dev}/include
            export FFMPEG_LIB_DIR=${pkgs.ffmpeg.lib}/lib
            export LLVM_COV=${pkgs.llvmPackages.llvm}/bin/llvm-cov
            export LLVM_PROFDATA=${pkgs.llvmPackages.llvm}/bin/llvm-profdata
          '';
        };

        # Minimal shell for headless publishers/relays (e.g. remote boxes).
        # Avoid pulling in node/wrangler/trunk/tauri deps.
        devShells.rust = pkgs.mkShell {
          buildInputs = with pkgs; [
            rust
            cargo
            llvmPackages.llvm
            clang
            pkg-config
            openssl
            ffmpeg
            agenixPkg
            forgejo-cli
            foundry
            solc
            git
          ];

          shellHook = ''
            export FFMPEG_INCLUDE_DIR=${pkgs.ffmpeg.dev}/include
            export FFMPEG_LIB_DIR=${pkgs.ffmpeg.lib}/lib
            export LLVM_COV=${pkgs.llvmPackages.llvm}/bin/llvm-cov
            export LLVM_PROFDATA=${pkgs.llvmPackages.llvm}/bin/llvm-profdata
          '';
        };
      });
}
