Nix & NixOS | Declarative builds and deployments

ℹ️
Watch a short
overview of Nix
, Nix in 100 Seconds, by influencer Fireship on YouTube.
NixOS (https://nixos.org/) was created by Eelco Dolstra in 2003
https://youtu.be/DMQWirkx5EY?si=gETDKa9G9OpztgHZ
https://youtu.be/RoMArT8UCKM?si=S-44eBCPDK8_aVfb
NixOS has a VS Code Extension
NixOS has a User Forum

AI Explains Docker and NixOS combo.

Docker and Nix serve complementary purposes, even though there's some overlap. Here are the key benefits of using Docker alongside Nix:

- Application Distribution

  • Docker: Provides a standardized way to package and distribute applications with their exact runtime environment
  • Nix: Focuses on reproducible development environments and system configurations

- Isolation Levels

  • Docker: Offers stronger runtime isolation through containerization (separate network namespaces, process spaces, etc.)
  • Nix: Provides isolation at the package dependency level but runs processes directly on the host
- Ecosystem Compatibility
  • Docker: Has become the de facto standard for distributing cloud-native applications
  • Many services (like Chroma) are primarily distributed as Docker images
  • Integration with orchestration tools (Kubernetes, Docker Compose) is seamless

- State Management

  • Docker: Better at managing stateful applications through volume mounts and container lifecycle
  • Nix: Primarily focused on managing immutable software builds and environments

- Development vs Production

  • Nix: Excellent for ensuring consistent development environments
  • Docker: Better suited for production deployments and scaling
Using both tools lets you leverage the strengths of each: Nix for development environment reproducibility and Docker for application isolation and distribution.

NixOS has its own Programming Language, which declares the Ephemeral Environments

Nix
#!/bin/bash

# Exit on error
set -e

# Source the utils file
source "$(dirname "${BASH_SOURCE[0]}")/utils.sh"

# Get the directory where the script is located
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

# Change to parent directory (project root)
cd "$SCRIPT_DIR/.."

# Create flake.nix
cat > flake.nix << 'EOL'
{
  description = "Data Augmentation Flow - React Micro-frontend Project";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    flake-utils.url = "github:numtide/flake-utils";
    rust-overlay.url = "github:oxalica/rust-overlay"; # For tools like SWC
    surrealdb.url = "github:surrealdb/surrealdb";
    outerbase = {
      url = "github:outerbase/outerbase";
      flake = false;
    };
    nix-vscode-extensions.url = "github:nix-community/nix-vscode-extensions";
  };

  outputs = { self, nixpkgs, flake-utils, rust-overlay, surrealdb, outerbase }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        overlays = [ (import rust-overlay) ];
        pkgs = import nixpkgs { 
          inherit system overlays; 
          config.allowUnfree = true;  # For tools like VS Code
        };
        outerbasePkg = pkgs.buildGoModule {
          pname = "outerbase";
          version = "0.1.0";
          src = outerbase;
          vendorHash = null;
        };
      in
      {
        devShells.default = pkgs.mkShell {
          buildInputs = with pkgs; [
            # Node.js ecosystem
            nodejs_20
            nodePackages.pnpm
            nodePackages.typescript
            nodePackages.typescript-language-server
            nodePackages.npm-check-updates  # For dependency updates

            # IDE and Editor Support
            vscode
            neovim
            nodePackages.prettier
            nodePackages.eslint
            nodePackages.stylelint

            # Performance and Analysis
            chromium  # For headless testing
            nodePackages.lighthouse
            nodePackages.webpack-bundle-analyzer

            # Development Tools
            deno
            git
            watchman
            jq
            mkcert
            ngrok  # For sharing local builds
            localtunnel  # Alternative to ngrok

            # Build Tools
            pkg-config
            cmake
            gnumake
            (rust-bin.stable.latest.default)  # For native addons

            # Container Tools
            docker
            docker-compose
            colima

            # Database Tools
            postgresql_15
            redis
            mongodb
            surrealdb
            duckdb      # Analytics DB
            litestream  # DB replication
            rqlite      # Distributed SQLite
            questdb     # Time-series DB
            edgedb     # Graph-relational DB
            outerbasePkg

            # Database Management & Monitoring
            dbeaver    # Universal DB tool
            pgadmin4
            mongodb-compass
            redis-desktop-manager

            # Monitoring & Debugging
            netcat
            lsof
            htop
            curl
            httpie  # Better curl

            # Documentation
            nodePackages.typedoc
            graphviz  # For dependency graphs
            nixpkgs-fmt  # or alejandra
            nil  # Nix Language Server

            # VS Code Extensions
            vscode-extensions.jnoortheen.nix-ide
            vscode-extensions.mkhl.direnv
            vscode-extensions.arrterian.nix-env-selector
            vscode-extensions.ms-azuretools.vscode-docker
            vscode-extensions.ms-vscode.makefile-tools
            vscode-extensions.donjayamanne.githistory
            vscode-extensions.eamodio.gitlens
            vscode-extensions.esbenp.prettier-vscode
            vscode-extensions.dbaeumer.vscode-eslint
            vscode-extensions.mblode.pretty-formatter
            vscode-extensions.christian-kohler.npm-intellisense
            vscode-extensions.rooveterinaryinc.roo-cline
          ];

          shellHook = ''
            # Environment variables
            export DOCKER_BUILDKIT=1
            export COMPOSE_DOCKER_CLI_BUILD=1
            
            # Node.js settings
            export NODE_ENV=development
            export PATH="$PWD/node_modules/.bin:$PATH"
            
            # Browser settings for testing
            export CHROME_BIN=${pkgs.chromium}/bin/chromium
            
            # Ensure local certificates
            if ! test -d "~/.local/share/mkcert"; then
              mkcert -install
              mkcert localhost
            fi

            # Create .npmrc if it doesn't exist
            if [ ! -f .npmrc ]; then
              echo "node-linker=hoisted" > .npmrc
            fi

            # VS Code settings
            if [ ! -d .vscode ]; then
              mkdir .vscode
              echo '{
                "typescript.tsdk": "node_modules/typescript/lib",
                "editor.formatOnSave": true,
                "editor.defaultFormatter": "esbenp.prettier-vscode"
              }' > .vscode/settings.json
            fi

            # Database initialization
            export SURREALDB_PATH="$PWD/.data/surrealdb"
            export DUCKDB_PATH="$PWD/.data/duckdb"
            export OUTERBASE_PATH="$PWD/.data/outerbase"
            
            # Create data directories
            mkdir -p $SURREALDB_PATH
            mkdir -p $DUCKDB_PATH
            mkdir -p $OUTERBASE_PATH

            # Database service helpers
            function start_surrealdb() {
              surreal start --log debug --user root --pass root file:$SURREALDB_PATH
            }

            function start_outerbase() {
              outerbase serve --data-dir $OUTERBASE_PATH
            }

            # Start Chroma DB if not already running
            if ! docker ps | grep -q chromadb; then
              docker run -d -p 8000:8000 -v $(pwd)/chroma_data:/chroma/chroma --name chromadb chromadb/chroma
            fi

            echo "🚀 Development environment ready!"
            echo "📦 Run 'pnpm install' to install dependencies"
            echo "🏃 Run 'pnpm dev' to start all services"
            echo "🧪 Run 'pnpm test' to run tests"
            echo "📊 Available Databases:"
            echo "  - PostgreSQL: pg_ctl"
            echo "  - MongoDB: mongod"
            echo "  - Redis: redis-server"
            echo "  - SurrealDB: start_surrealdb"
            echo "  - DuckDB: duckdb"
            echo "  - Outerbase: start_outerbase"
          '';

          # Environment variables
          RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";
        };
      }
    );
}
EOL

echo "flake.nix created successfully."