This document explains how to manage runtimes in your self-hosted Stormkit instance using the Admin Dashboard.
Stormkit’s runtime management system allows you to control which programming languages, package managers, and tools are available during your app deployments.
You can:
latestflake.nix file to provide system-level tools via NixNote: You have to be an administrator to access this area.
node, go, npm, npm:@angular/cli24, 1.24) or latestTip: Refer to the mise documentation for a complete list of supported tools.
× icon next to the runtime you want to remove.When Auto install is enabled, Stormkit automatically installs required runtimes during deployment based on your app’s version configuration files.
To toggle:
The following files are recognized automatically:
| Runtime | Files |
|---|---|
| go | .go-version |
| node | .nvmrc, .node-version |
| python | .python-version, .python-versions |
| ruby | .ruby-version, Gemfile |
If your repository contains a flake.nix file, Stormkit will automatically run nix develop during the install runtimes step to bootstrap the Nix development shell. The packages defined in the flake are then available for all subsequent build commands — no additional configuration required — and, as described under Availability at runtime below, to your deployed server as well.
A typical flake.nix that provides ffmpeg and imagemagick during builds:
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
outputs = { self, nixpkgs }: let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
in {
devShells.${system}.default = pkgs.mkShell {
packages = [ pkgs.ffmpeg pkgs.imagemagick ];
};
};
}
flake.nix and mise.toml can coexist — mise handles language runtimes while the flake covers system-level tools.
The flake is not a build-only feature. flake.nix and flake.lock are copied into
the server artifact, and when your environment has a Start command, Stormkit wraps
that command in nix develop before spawning the process. Your server therefore starts
inside the same shell your build commands ran in, so every package in the flake is on
PATH — system binaries such as headless-browser dependencies can be launched from your
application at request time, not only from build commands.
This also explains why /nix has to be mounted on the hosting (serving) service and
not only on the workerserver (builds, periodic jobs): the store has to be there when
the app runs, too. Give each service its own volume rather than sharing one — see
Persisting the Nix Store below.
Two conditions apply:
nix develop wrapper is skipped when it is off.node process with no Nix shell around them, so flake packages are
not on PATH there. If your code needs system binaries, run it behind a start
command.The first request after a deployment may take a while, or briefly show a "dependencies are being installed" page, while Nix realises the shell. Subsequent requests reuse the warm store.
A flake.nix providing headless Chromium to a start-command server:
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
outputs = { self, nixpkgs }: let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
in {
devShells.${system}.default = pkgs.mkShell {
packages = [ pkgs.playwright-driver.browsers pkgs.chromium ];
shellHook = ''
export PLAYWRIGHT_BROWSERS_PATH=${pkgs.playwright-driver.browsers}
export PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=true
'';
};
};
}
Stormkit relies on the mise open-source tool for runtime management. Current version is displayed in the Mise section.
mise.Note: Upgrading
misedoes not automatically upgrade installed runtimes. You’ll need to update those manually.
Stormkit uses Nix as a backend for maintaining system level dependencies. By default, the Nix store lives at /nix inside the container. Without a persistent volume at that path, packages are re-downloaded every time the container restarts.
As of April 2026, the official docker-compose.yaml mounts a named nix volume at /nix for both the workerserver and hosting services. If you set up Stormkit before this date, add the following to your docker-compose.yaml to benefit from cached Nix packages:
1. Declare the volumes at the top-level volumes section:
volumes:
workerserver_nix:
hosting_nix:
2. Mount them in the respective service definitions:
# workerserver
- workerserver_nix:/nix
# hosting
- hosting_nix:/nix
After updating, run docker compose up -d to recreate the containers with the new mount. The Nix store will be populated on first use and reused on subsequent restarts.
Existing installations: If you see an error like failed to mkdir .../nix/_data/store/...: file exists on startup, it means both services raced to seed the same volume simultaneously. Use separate named volumes to avoid this:
volumes:
workerserver_nix:
hosting_nix:
Then mount them individually:
# workerserver
- workerserver_nix:/nix
# hosting
- hosting_nix:/nix
latest only for development or experimental environments.