{ inputs = { nixpkgs.url = "nixpkgs/nixos-unstable"; flake-utils.url = "github:numtide/flake-utils"; rust-overlay.url = "github:oxalica/rust-overlay"; # Use separate channel for claude code. It always needs to be latest nixpkgs-claude.url = "nixpkgs/nixos-unstable"; nixpkgs-oapi-gen.url = "nixpkgs/2d068ae5c6516b2d04562de50a58c682540de9bf"; # openapi-generator-cli pin to 7.10.0 }; outputs = { self, nixpkgs, nixpkgs-claude, flake-utils, rust-overlay , nixpkgs-oapi-gen }: flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { inherit system; config.allowUnfree = true; overlays = [ (import rust-overlay) ]; }; claude-code = (import nixpkgs-claude { inherit system; config.allowUnfree = true; }).claude-code; openapi-generator-cli = (import nixpkgs-oapi-gen { inherit system; }).openapi-generator-cli; lib = pkgs.lib; stdenv = pkgs.stdenv; rust = pkgs.rust-bin.stable.latest.default.override { extensions = [ "rust-src" # for rust-analyzer "rust-analyzer" "rustfmt" ]; }; patchedClang = pkgs.llvmPackages_18.clang.overrideAttrs (oldAttrs: { postFixup = '' # Copy the original postFixup logic but skip add-hardening.sh ${oldAttrs.postFixup or ""} # Remove the line that substitutes add-hardening.sh sed -i 's/.*source.*add-hardening\.sh.*//' $out/bin/clang ''; }); buildInputs = with pkgs; [ openssl openssl.dev libxml2.dev xmlsec.dev libxslt.dev libclang.dev libffi # For deno_ffi libtool nodejs postgresql pkg-config clang cmake ]; coursier = pkgs.fetchFromGitHub { owner = "coursier"; repo = "launchers"; rev = "79d927f7586c09ca6d8cd01862adb0d9f9d88dff"; hash = "sha256-8E0WtDFc7RcqmftDigMyy1xXUkjgL4X4kpf7h1GdE48="; }; PKG_CONFIG_PATH = pkgs.lib.makeSearchPath "lib/pkgconfig" (with pkgs; [ openssl.dev libxml2.dev xmlsec.dev libxslt.dev ]); RUSTY_V8_ARCHIVE = let # NOTE: needs to be same as in Cargo.toml version = "130.0.7"; target = pkgs.hostPlatform.rust.rustcTarget; sha256 = { x86_64-linux = "sha256-pkdsuU6bAkcIHEZUJOt5PXdzK424CEgTLXjLtQ80t10="; aarch64-linux = pkgs.lib.fakeHash; x86_64-darwin = pkgs.lib.fakeHash; aarch64-darwin = pkgs.lib.fakeHash; }.${system}; in pkgs.fetchurl { name = "librusty_v8-${version}"; url = "https://github.com/denoland/rusty_v8/releases/download/v${version}/librusty_v8_release_${target}.a.gz"; inherit sha256; }; in { # Enter by `nix develop .#wasm` devShells."wasm" = pkgs.mkShell { # Explicitly set paths for headers and linker shellHook = '' export CC=${patchedClang}/bin/clang ''; buildInputs = buildInputs ++ (with pkgs; [ (rust-bin.nightly.latest.default.override { extensions = [ "rust-src" # for rust-analyzer "rust-analyzer" ]; targets = [ "wasm32-unknown-unknown" "wasm32-unknown-emscripten" ]; }) wasm-pack deno emscripten nushell # Needed for extra dependencies glibc_multi ]); }; devShells."cli" = pkgs.mkShell { shellHook = '' if command -v git >/dev/null 2>&1 && git rev-parse --is-inside-work-tree >/dev/null 2>&1; then export FLAKE_ROOT="$(git rev-parse --show-toplevel)" else # Fallback to PWD if not in a git repository export FLAKE_ROOT="$PWD" fi wm-cli-deps ''; buildInputs = buildInputs ++ [ pkgs.deno ]; packages = [ (pkgs.writeScriptBin "wm-cli" '' deno run -A --no-check $FLAKE_ROOT/cli/src/main.ts $* '') (pkgs.writeScriptBin "wm-cli-deps" '' pushd $FLAKE_ROOT/cli/ ${if pkgs.stdenv.isDarwin then "./gen_wm_client_mac.sh && ./windmill-utils-internal/gen_wm_client_mac.sh" else "./gen_wm_client.sh && ./windmill-utils-internal/gen_wm_client.sh"} popd '') ]; }; devShells.default = pkgs.mkShell { buildInputs = buildInputs ++ [ # To update run: `nix flake update nixpkgs-claude` claude-code # To update run: `nix flake update nixpkgs-oapi-gen` openapi-generator-cli ] ++ (with pkgs; [ # Essentials rust git sqlx-cli # Build/helper scripts jq gnused # other implementations are inconsistent on osx # Python flock python3 python3Packages.pip uv poetry pyright openapi-python-client # Other languages deno typescript nushell go bun dotnet-sdk_9 oracle-instantclient ansible ruby_3_4 cargo-sweep # We use it for rust # LSP/Local dev svelte-language-server taplo # Orchestration/Kubernetes minikube kubectl kubernetes-helm conntrack-tools # To run minikube without driver (--driver=none) cri-tools # Extra xcaddy cargo-watch nsjail sccache ]); packages = [ (pkgs.writeScriptBin "wm-caddy" '' cd ./frontend xcaddy build $* \ --with github.com/mholt/caddy-l4@145ec36251a44286f05a10d231d8bfb3a8192e09 \ --with github.com/RussellLuo/caddy-ext/layer4@ab1e18cfe426012af351a68463937ae2e934a2a1 '') (pkgs.writeScriptBin "wm-build" '' cd ./frontend npm install npm run ${ if pkgs.stdenv.isDarwin then "generate-backend-client-mac" else "generate-backend-client" } npm run build $* '') (pkgs.writeScriptBin "wm-migrate" '' cd ./backend sqlx migrate run '') (pkgs.writeScriptBin "wm-setup" '' sqlx database create wm-build wm-caddy wm-migrate '') (pkgs.writeScriptBin "wm-reset" '' sqlx database drop -f sqlx database create wm-migrate '') (pkgs.writeScriptBin "wm-bench" '' deno run -A benchmarks/main.ts -e admin@windmill.dev -p changeme $* '') (pkgs.writeScriptBin "wm" '' cd ./frontend npm install npm run generate-backend-client npm run dev $* '') (pkgs.writeScriptBin "wm-minio" '' set -e cd ./backend mkdir -p .minio-data/wmill ${pkgs.minio}/bin/minio server ./.minio-data --console-address ":9001" '') # Generate keys # TODO: Do not set new keys if ran multiple times (pkgs.writeScriptBin "wm-minio-keys" '' set -e cd ./backend # Set up MinIO alias ${pkgs.minio-client}/bin/mc alias set 'wmill-minio-dev' 'http://localhost:9000' 'minioadmin' 'minioadmin' # Check if secrets file exists and contains valid keys if [[ -f .minio-data/secrets.txt ]] && [[ -s .minio-data/secrets.txt ]]; then echo "Access keys already exist:" cat .minio-data/secrets.txt echo "" echo "Keys loaded from: ./backend/.minio-data/secrets.txt" else echo "Creating new access keys..." mkdir -p .minio-data ${pkgs.minio-client}/bin/mc admin accesskey create 'wmill-minio-dev' | tee .minio-data/secrets.txt echo "" echo 'New keys saved to: ./backend/.minio-data/secrets.txt' fi echo "bucket: wmill" echo "endpoint: http://localhost:9000" '') ]; inherit PKG_CONFIG_PATH RUSTY_V8_ARCHIVE; GIT_PATH = "${pkgs.git}/bin/git"; NODE_ENV = "development"; NODE_OPTIONS = "--max-old-space-size=16384"; # DATABASE_URL = "postgres://postgres:changeme@127.0.0.1:5432/"; DATABASE_URL = "postgres://postgres:changeme@127.0.0.1:5432/windmill?sslmode=disable"; REMOTE = "http://127.0.0.1:8000"; REMOTE_LSP = "http://127.0.0.1:3001"; # RUSTC_WRAPPER = "${pkgs.sccache}/bin/sccache"; DENO_PATH = "${pkgs.deno}/bin/deno"; GO_PATH = "${pkgs.go}/bin/go"; PHP_PATH = "${pkgs.php}/bin/php"; COMPOSER_PATH = "${pkgs.php84Packages.composer}/bin/composer"; BUN_PATH = "${pkgs.bun}/bin/bun"; NODE_PATH = "${pkgs.nodejs}/bin/node"; NODE_BIN_PATH = "${pkgs.nodejs}/bin/node"; UV_PATH = "${pkgs.uv}/bin/uv"; NU_PATH = "${pkgs.nushell}/bin/nu"; JAVA_PATH = "${pkgs.jdk21}/bin/java"; JAVAC_PATH = "${pkgs.jdk21}/bin/javac"; COURSIER_PATH = "${coursier}/coursier"; BASH_PATH = "bash"; RUBY_PATH = "${pkgs.ruby}/bin/ruby"; RUBY_BUNDLE_PATH = "${pkgs.ruby}/bin/bundle"; RUBY_GEM_PATH = "${pkgs.ruby}/bin/gem"; # for related places search: ADD_NEW_LANG FLOCK_PATH = "${pkgs.flock}/bin/flock"; CARGO_PATH = "${rust}/bin/cargo"; CARGO_SWEEP_PATH = "${pkgs.cargo-sweep}/bin/cargo-sweep"; DOTNET_PATH = "${pkgs.dotnet-sdk_9}/bin/dotnet"; DOTNET_ROOT = "${pkgs.dotnet-sdk_9}/share/dotnet"; ORACLE_LIB_DIR = "${pkgs.oracle-instantclient.lib}/lib"; ANSIBLE_PLAYBOOK_PATH = "${pkgs.ansible}/bin/ansible-playbook"; ANSIBLE_GALAXY_PATH = "${pkgs.ansible}/bin/ansible-galaxy"; # RUST_LOG = "debug"; # RUST_LOG = "kube=debug"; # See this issue: https://github.com/NixOS/nixpkgs/issues/370494 # Allows to build jemalloc on nixos CFLAGS = "-Wno-error=int-conversion"; # Need to tell bindgen where to find libclang LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib"; # LD_LIBRARY_PATH = "${pkgs.gcc.lib}/lib"; # Set C flags for Rust's bindgen program. Unlike ordinary C # compilation, bindgen does not invoke $CC directly. Instead it # uses LLVM's libclang. To make sure all necessary flags are # included we need to look in a few places. # See https://web.archive.org/web/20220523141208/https://hoverbear.org/blog/rust-bindgen-in-nix/ BINDGEN_EXTRA_CLANG_ARGS = # Prevent clang from using system headers - only use Nix headers "-nostdinc ${ builtins.readFile "${stdenv.cc}/nix-support/libc-crt1-cflags" } ${builtins.readFile "${stdenv.cc}/nix-support/libc-cflags"} ${ builtins.readFile "${stdenv.cc}/nix-support/cc-cflags" } ${ builtins.readFile "${stdenv.cc}/nix-support/libcxx-cxxflags" } -idirafter ${pkgs.libiconv}/include ${ lib.optionalString stdenv.cc.isClang "-idirafter ${stdenv.cc.cc}/lib/clang/${ lib.getVersion stdenv.cc.cc }/include" }${ lib.optionalString stdenv.cc.isGNU "-isystem ${stdenv.cc.cc}/include/c++/${ lib.getVersion stdenv.cc.cc } -isystem ${stdenv.cc.cc}/include/c++/${ lib.getVersion stdenv.cc.cc }/${stdenv.hostPlatform.config} -idirafter ${stdenv.cc.cc}/lib/gcc/${stdenv.hostPlatform.config}/${ lib.getVersion stdenv.cc.cc }/include" }"; }; packages.default = self.packages.${system}.windmill; packages.windmill-client = pkgs.buildNpmPackage { name = "windmill-client"; version = (pkgs.lib.strings.trim (builtins.readFile ./version.txt)); src = pkgs.nix-gitignore.gitignoreSource [ ] ./frontend; nativeBuildInputs = with pkgs; [ pkg-config ]; buildInputs = with pkgs; [ nodejs pixman cairo pango ]; doCheck = false; npmDepsHash = "sha256-NXk9mnf74+/k0i3goqU8Zi/jr5b/bmW+HWRLJCI2CX8="; npmBuild = "npm run build"; postUnpack = '' mkdir -p ./backend/windmill-api/ cp ${ ./backend/windmill-api/openapi.yaml } ./backend/windmill-api/openapi.yaml cp ${./openflow.openapi.yaml} ./openflow.openapi.yaml ''; preBuild = '' npm run ${ if pkgs.stdenv.isDarwin then "generate-backend-client-mac" else "generate-backend-client" } ''; installPhase = '' mkdir -p $out/build cp -r build $out ''; NODE_OPTIONS = "--max-old-space-size=8192"; }; packages.windmill = pkgs.rustPlatform.buildRustPackage { pname = "windmill"; version = (pkgs.lib.strings.trim (builtins.readFile ./version.txt)); src = ./backend; nativeBuildInputs = buildInputs ++ [ self.packages.${system}.windmill-client pkgs.perl ] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ # Additional darwin specific inputs can be set here pkgs.libiconv pkgs.darwin.apple_sdk.frameworks.SystemConfiguration ]; cargoLock = { lockFile = ./backend/Cargo.lock; outputHashes = { "php-parser-rs-0.1.3" = "sha256-ZeI3KgUPmtjlRfq6eAYveqt8Ay35gwj6B9iOQRjQa9A="; "progenitor-0.3.0" = "sha256-F6XRZFVIN6/HfcM8yI/PyNke45FL7jbcznIiqj22eIQ="; "tinyvector-0.1.0" = "sha256-NYGhofU4rh+2IAM+zwe04YQdXY8Aa4gTmn2V2HtzRfI="; }; }; buildFeatures = [ "enterprise" "enterprise_saml" "stripe" "embedding" "parquet" "prometheus" "openidconnect" "cloud" "jemalloc" "tantivy" "license" "http_trigger" "zip" "oauth2" "kafka" "otel" "dind" "websocket" "smtp" "static_frontend" "all_languages" ]; doCheck = false; inherit PKG_CONFIG_PATH RUSTY_V8_ARCHIVE; SQLX_OFFLINE = true; FRONTEND_BUILD_DIR = "${self.packages.${system}.windmill-client}/build"; }; }); }