Skip to main content

Déploiement multi-machines avec NixOS

Gérer plusieurs machines NixOS

Lorsqu’on a plusieurs serveurs NixOS, il est pratique de centraliser les configurations dans un dépôt Git.

Structure recommandée

nixos-infra/
├── flake.nix
├── flake.lock
├── modules/
│   ├── base.nix           # Configuration commune
│   ├── docker.nix         # Module Docker réutilisable
│   └── monitoring.nix     # Module monitoring
├── machines/
│   ├── web-01/
│   │   ├── configuration.nix
│   │   └── hardware-configuration.nix
│   ├── db-01/
│   │   ├── configuration.nix
│   │   └── hardware-configuration.nix
│   └── ...
└── secrets/               # Fichiers secrets (optionnel, avec agenix/sops)

Module de base partagé

modules/base.nix :

{ config, pkgs, ... }:

{
  # Timezone et locale
  time.timeZone = "Europe/Zurich";
  i18n.defaultLocale = "en_US.UTF-8";

  # Paquets communs
  environment.systemPackages = with pkgs; [
    git vim htop curl wget tmux
  ];

  # SSH sécurisé
  services.openssh.enable = true;
  services.openssh.settings = {
    PermitRootLogin = "no";
    PasswordAuthentication = false;
  };

  # Firewall activé par défaut
  networking.firewall.enable = true;
  networking.firewall.allowedTCPPorts = [ 22 ];

  # Utilisateur admin
  users.users.admin = {
    isNormalUser = true;
    extraGroups = [ "wheel" ];
    openssh.authorizedKeys.keys = [
      "ssh-ed25519 AAAA... admin@workstation"
    ];
  };

  security.sudo.wheelNeedsPassword = false;
}

Configuration d’une machine

machines/web-01/configuration.nix :

{ config, pkgs, ... }:

{
  imports = [
    ./hardware-configuration.nix
    ../../modules/base.nix
  ];

  networking.hostName = "web-01";

  # Spécificités de cette machine
  services.nginx.enable = true;
  networking.firewall.allowedTCPPorts = [ 80 443 ];

  system.stateVersion = "24.05";
}

Flake pour multi-machines

flake.nix :

{
  description = "Infrastructure NixOS";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-24.05";
  };

  outputs = { self, nixpkgs }: {
    nixosConfigurations = {
      web-01 = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        modules = [ ./machines/web-01/configuration.nix ];
      };

      web-02 = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        modules = [ ./machines/web-02/configuration.nix ];
      };

      db-01 = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        modules = [ ./machines/db-01/configuration.nix ];
      };
    };
  };
}

Déploiement

Depuis la machine locale

Sur chaque machine, cloner le repo et appliquer :

git clone https://github.com/monuser/nixos-infra.git /etc/nixos
cd /etc/nixos
sudo nixos-rebuild switch --flake .#web-01

Déploiement distant avec nixos-rebuild

Depuis sa workstation, déployer sur une machine distante :

nixos-rebuild switch --flake .#web-01 \
  --target-host admin@web-01.example.com \
  --use-remote-sudo

Déploiement avec deploy-rs

Pour un déploiement plus robuste, utiliser deploy-rs :

# Dans flake.nix
{
  inputs.deploy-rs.url = "github:serokell/deploy-rs";

  outputs = { self, nixpkgs, deploy-rs }: {
    # ... nixosConfigurations ...

    deploy.nodes = {
      web-01 = {
        hostname = "web-01.example.com";
        profiles.system = {
          user = "root";
          path = deploy-rs.lib.x86_64-linux.activate.nixos
            self.nixosConfigurations.web-01;
        };
      };
    };
  };
}

Déployer :

nix run github:serokell/deploy-rs -- .#web-01

Workflow typique

  1. Modifier la configuration dans le repo Git
  2. Committer et pusher
  3. Sur la machine cible (ou à distance) :
cd /etc/nixos
git pull
sudo nixos-rebuild switch --flake .#$(hostname)

Automatisation avec CI/CD

Avec GitHub Actions, on peut vérifier que les configurations compilent :

name: Check NixOS configurations

on: [push, pull_request]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: cachix/install-nix-action@v25
        with:
          extra_nix_config: |
            experimental-features = nix-command flakes
      - run: nix flake check