StackPanel

Quick Start

Get started with stackpanel in under 5 minutes

Overview

stackpanel is an infrastructure toolkit that provides a reproducible development environment using Nix and flake-parts. It gives you:

  • Zero-config dev environments - Automatic setup for popular stacks
  • Secrets management - Team-based encrypted secrets with age
  • IDE integration - Auto-generated VS Code settings
  • Global services - PostgreSQL, Redis, Minio with deterministic ports
  • AWS integration - Passwordless AWS access via certificate authentication

Prerequisites

Before starting, you'll need:

  • Nix with flakes enabled
  • direnv (recommended)

If you're new to Nix, we recommend using the Determinate Nix Installer which enables flakes by default.

Installation

Create a new project with a template

nix flake init -t github:darkmatter/stackpanel

This creates:

  • flake.nix - Main flake with flake-parts
  • .stack/config.nix - Stackpanel options
nix flake init -t github:darkmatter/stackpanel#minimal

This creates:

  • flake.nix - Standard flake without flake-parts
  • .stack/config.nix - Stackpanel options

Simpler but less modular.

Or add to an existing project manually:

{
  description = "My project";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    flake-parts.url = "github:hercules-ci/flake-parts";
    stackpanel.url = "github:darkmatter/stackpanel";
    nix2container.url = "github:nlewo/nix2container";
    nix2container.inputs.nixpkgs.follows = "nixpkgs";
    mk-shell-bin.url = "github:rrbutani/nix-mk-shell-bin";
  };

  outputs = inputs @ {self, stackpanel, ...}:
    stackpanel.lib.mkFlake {
      inherit inputs self;

      perSystem = {pkgs, ...}: {
        packages.hello = pkgs.hello;
      };
    };
}

Set up direnv

Create a .envrc file in your project root:

use flake .

Then allow direnv:

direnv allow

Enter the dev shell

If using direnv, the shell activates automatically when you cd into the project.

Otherwise, manually enter the shell:

nix develop

You should see the stackpanel welcome message with available commands.

Configuration

Stackpanel Options

Configuration lives in .stack/config.nix, which stackpanel loads automatically. Use the stackpanel.* option namespace:

# .stack/config.nix
{
  enable = true;

  name = "my-project";

  # Packages to add to the devshell (string names are resolved from nixpkgs)
  packages = [
    "git"
    "jq"
    pkgs.nodejs
    pkgs.bun
  ];

  # Language toolchains (native stackpanel implementations)
  languages = {
    javascript = {
      enable = true;
      bun.enable = true;
      bun.install.enable = true;
    };
    typescript.enable = true;
    # go.enable = true;
  };

  # Environment variables
  devshell.env = {
    DATABASE_URL = "postgres://localhost:5432/myapp";
    NODE_ENV = "development";
  };

  # Shell hooks
  devshell.hooks.main = [
    ''
      echo "Welcome to the dev environment!"
      bun install
    ''
  ];

  # Starship prompt theme
  theme.enable = true;

  # IDE integration
  ide.enable = true;
  ide.vscode.enable = true;

  # MOTD customization
  motd.enable = true;
  motd.commands = [
    { name = "dev"; description = "Start development server"; }
  ];

  # AWS certificate authentication (uncomment to enable)
  # aws.roles-anywhere = {
  #   enable = true;
  #   region = "us-west-2";
  #   account-id = "123456789012";
  #   role-name = "dev-role";
  #   trust-anchor-arn = "arn:aws:rolesanywhere:...";
  #   profile-arn = "arn:aws:rolesanywhere:...";
  # };

  # Step CA for internal certificates (uncomment to enable)
  # step-ca = {
  #   enable = true;
  #   ca-url = "https://ca.internal:443";
  #   ca-fingerprint = "...";
  # };

  # Global services (uncomment to enable)
  # globalServices = {
  #   enable = true;
  #   project-name = "myapp";
  #   postgres.enable = true;
  #   redis.enable = true;
  # };
}

Common Tasks

Adding Packages

# .stack/config.nix
{
  packages = with pkgs; [
    nodejs
    bun
    go
    jq
    git
  ];
}

Configuring Languages

# .stack/config.nix
{
  languages = {
    javascript = {
      enable = true;
      bun.enable = true;
      bun.install.enable = true;
    };
    typescript.enable = true;
    go.enable = true;
    python = {
      enable = true;
      # Use the python module's option set if available
    };
  };
}

Environment Variables

# .stack/config.nix
{
  devshell.env = {
    DATABASE_URL = "postgres://localhost:5432/myapp";
    NODE_ENV = "development";
  };
}

Shell Hooks

# .stack/config.nix
{
  devshell.hooks.main = [
    ''
      echo "Welcome to the dev environment!"
      bun install
    ''
  ];
}

Development Processes

stackpanel uses process-compose to run apps and services. Define an app and its dev command:

# .stack/config.nix
{
  apps.web = {
    path = "apps/web";
    bun.enable = true;
  };
}

Then start all processes:

dev

Or define custom process-compose processes:

# .stack/config.nix
{
  process-compose.processes = {
    api = {
      command = "go run ./cmd/api";
      working_dir = "apps/api";
    };
  };
}

Next Steps

Troubleshooting

Flake evaluation fails with missing attribute

Stackpanel evaluates purely by default. Make sure you are running commands from inside the project repository so the flake can locate .stack/config.nix and compute outputs relative to the git root.

nix develop
nix flake check

If you see a missing-attribute error, check that:

  1. The project is initialized in a git repository.
  2. .stack/config.nix exists and is valid Nix.
  3. Required flake inputs are present and unlocked.

direnv not activating

  1. Ensure direnv is installed and hooked into your shell
  2. Run direnv allow in the project directory
  3. Check .envrc exists with use flake .

On this page