Die Neuronen Schmiede setzt sich in erster Linie mit Themen im Bereich Software Entwicklung auseinander. Ein Fokus dabei sind robuste Web-Anwendungen.

Reproduzierbare Entwicklungsumgebung mit nix-shell

Permalink

Wenn du schon einmal Zeit und Nerven aufgewendet hast die Entwicklungsumgebung für ein Projekt auf einem neuen Computer aufzusetzen, ist nix-shell eventuell das richtige. Ich verwende es seit Anfang 2020 und habe mir bisher viel Zeit und Nerven gespart. Es ermöglicht mir pro Projekt eine Sandbox zu starten in welcher die richtige Version von Node, Ruby, PostgreSQL, PHP, MariaDB installiert ist.

Konkret hat mich nix-shell aus folgenden Situationen gerettet, die ich mit meinem bisherigen Ansatz nicht meistern konnte.

  • Ein Projekt mit alter Ruby Version lauffähig bekommen das nach einem automatischen Update von OpenSSL durch Homebrew nicht mehr funktioniert hat.
  • Alte Node Versionen installiert um angestaubte Ember.js Projekte weiterzuentwickeln.
  • gnuplot Graphen repariert, die nach einem macOS Update Artefakte enthalten haben.
  • Einen LAMP Stack unter macOS aufsetzen ohne XAMPP oder Ähnliches installieren zu müssen.
  • Eine unter Homebrew nicht mehr installierbare Ansible Version verwenden.
  • Eine identische Entwicklungsumgebung unter macOS und Ubuntu haben.

Tipps

  • Nix ist ein Package Manager, ein Betriebssystem und eine Programmiersprache. Ich verwende nur den Package Manager und notgedrungen die Programmiersprache für die Definition meiner Entwicklungsumgebung.
  • Die Definition der Entwicklungsumgebung kommt in die Datei shell.nix im Projektverzeichnis.
  • Installationsanleitung.
  • Um Festplattenspeicher freizubekommen kannst du die Garbage Collection mit nix-collect-garbage laufen lassen.
  • Du solltest die verwendete Version von nixpkgs selbst möglichst genau definieren. Ansonsten bekommst du in einem Jahr andere Packages installiert als heute. Die meisten Anleitungen machen diesen Fehler, am Ende des Tages ist es somit erst Recht wieder nicht reproduzierbar.

Workflow

  1. Terminal öffnen
  2. In Projektordner wechseln
  3. Sandbox mit nix-shell starten
  4. Entwickeln

Beispiele

Ein kleines Projekt mit der aktuellsten Ruby und cURL Version.

{
  pkgs ? import (fetchGit {
    url = https://github.com/NixOS/nixpkgs-channels;
    ref = "nixos-20.03";
  }) {}
}:

pkgs.mkShell {
  buildInputs = with pkgs; [
    curl
    ruby
  ];

  shellHook = ''
    mkdir -p .nix-gems
    export GEM_HOME=$PWD/.nix-gems
    export GEM_PATH=$GEM_HOME
    export PGHOST="$PWD/.local-data/postgresql/sockets"
    unset SSL_CERT_FILE
    unset NIX_SSL_CERT_FILE
  '';
}

Verwaltung meiner Finanzen mit hledger und gnuplot.

{
  pkgs ? import (fetchGit {
    url = https://github.com/NixOS/nixpkgs-channels;
    ref = "nixos-20.03";
  }) {}
}:

pkgs.mkShell {
  buildInputs = with pkgs; [
    hledger
    gnuplot
    gnumeric
  ];

  shellHook = ''
    export FONTCONFIG_FILE=${pkgs.fontconfig.out}/etc/fonts/fonts.conf
  '';
}

Dieses Projekt benötigt eine alte Ruby Version die sonst nicht mehr installierbar ist.

{
  pkgs ? import (fetchGit {
    url = https://github.com/NixOS/nixpkgs-channels;
    ref = "nixos-20.03";
  }) {},
  oldpkgs ? import (fetchGit {
    url = https://github.com/NixOS/nixpkgs-channels;
    ref = "nixos-19.03";
  }) {},
  ruby ? oldpkgs.ruby_2_3,
  bundler ? oldpkgs.bundler.override { inherit ruby; }
}:

pkgs.mkShell {
  buildInputs = with pkgs; [
    ruby
    bundler
    which
    git
    postgresql_9_6
    parallel
  ];

  shellHook = ''
    mkdir -p .local-data/gems
    export GEM_HOME=$PWD/.local-data/gems
    export GEM_PATH=$GEM_HOME
    export PGHOST="$PWD/.local-data/postgresql/sockets"
  '';
}

Infrastruktur die mit Ansible verwaltet wird.

{
  pkgs ? import (fetchGit {
    url = https://github.com/NixOS/nixpkgs-channels;
    ref = "nixos-20.03";
  }) {}
}:

pkgs.mkShell {
  buildInputs = with pkgs; [
    ansible_2_9
    git-crypt
    sshpass
  ];
}

Weiteres Projekt mit einer bestimmten Ruby Version.

{
  pkgs ? import (fetchGit {
    url = https://github.com/NixOS/nixpkgs-channels;
    ref = "nixos-20.03";
  }) {},
  oldpkgs ? import (fetchGit {
    url = https://github.com/NixOS/nixpkgs-channels;
    ref = "nixos-19.03";
  }) {}
}:

pkgs.mkShell {
  buildInputs = with pkgs; [
    oldpkgs.ruby_2_5
    oldpkgs.bundler
    tychus
    git
    postgresql_9_6
    parallel
  ];

  shellHook = ''
    mkdir -p .nix-gems
    export GEM_HOME=$PWD/.nix-gems
    export GEM_PATH=$GEM_HOME
    export PGHOST="$PWD/.local-data/postgresql/sockets"
    unset SSL_CERT_FILE
    unset NIX_SSL_CERT_FILE
  '';
}

Ember.js Projekt mit Ember CLI

{ pkgs ? import (fetchGit {
  url = https://github.com/NixOS/nixpkgs-channels;
  ref = "nixos-20.03";
}) {} }:

pkgs.mkShell {
  buildInputs = with pkgs; [
    yarn
    nodejs-12_x
    git
  ];

  shellHook = ''
  '';
}

Projekt mit sehr alten Ember CLI Version sowie anderen Abhängigkeiten.

{
  pkgs ? import (fetchGit {
    url = https://github.com/NixOS/nixpkgs-channels;
    ref = "nixos-19.03";
  }) {}
}:

pkgs.mkShell {
  buildInputs = with pkgs; [
    nodejs-8_x
    git
    rsync
    openssh
    python
  ];

  shellHook = ''
  '';
}

PHP 7.3, MariaDB und Caddy als Webserver sowie eine Erhöhung der maximalen Upload Größe von PHP.

{
  pkgs ? import (fetchGit {
    url = https://github.com/NixOS/nixpkgs;
    ref = "nixos-20.09";
  }) {},
  php73 ? pkgs.php73.buildEnv {
    extraConfig = "upload_max_filesize = 20M";
  }
}:

pkgs.mkShell {
  buildInputs = with pkgs; [
    php73
    php73Packages.composer
    php73Packages.php-cs-fixer
    mariadb
    parallel
    caddy
  ];

  shellHook = ''
  '';
}