../use-services-flake-devshell

services-flakeとかを使って開発環境を作る

この記事は Nix Advent Calendar 2024 の14日目の記事です。


NixOSには services という設定があります。この設定を書くことで、例えばollamaなどの設定をすることが出来ます。自分のdotfilesでも以下のような形でollamaが設定されています。


{
  services.ollama = {
    enable = true;
    openFirewall = true;
    loadModels = [
      "llama3.2"
      # ...
    ];
  };
}

他にもたくさんのソフトウェアservices を介して設定することが出来ます。

NixのFlakesの機能の一つにdevShells1というものがあります。これを使用することでグローバルの環境を汚すことなくプロジェクト専用のツール等をインストールすることが出来ます。

例えばこのブログは、Zolaという静的サイトジェネレーターで生成されているのですが、グローバルにzolaのCLIを入れることなく、以下のような flake.nix を使ってdevShellsでインストールしています。

{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
  };

  outputs =
    { nixpkgs }:
    let
      system = "x86_64-linux";
      pkgs = import nixpkgs { inherit system; };
    in
    {
      devShells.${system}.default = pkgs.mkShell {
        buildInputs = with pkgs; [
          zola
        ];
      };
    };
}

この記事で紹介する services-flake はこのdevShellsと同じような感覚でプロジェクトごとにservicesを設定しようというものです。 services-flakeはNixOS Modulesと同じようなことをするためのものである flake-parts に依存しているわけではありませんが、あると書きやすいので使用しています。

環境

この記事で使ったファイルなどは satler-git/sb-nix-services-flakeにあります。

またNixのバージョンは

❯ nix --version
nix (Nix) 2.24.10

nixpkgsとその他の inputs のバージョンはリポジトリの flake.lock を確認してください。

実践

ただのdevShells

まず適当な名前のディレクトリを作成し、そのディレクトリでflakeを初期化します。

❯ nix flake init

flake.nix を編集していきます。まずデフォルトで入っている outputs を消します。 そして inputsにflake-partsなどを追記して、flake-partsの inputs.flake-parts.lib.mkFlake を使い、flake.nixを以下のようにします。

{
  description = "A very basic flake";

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

    flake-parts.url = "github:hercules-ci/flake-parts";
    process-compose-flake.url = "github:Platonic-Systems/process-compose-flake";
    services-flake.url = "github:juspay/services-flake";
  };

  outputs =
    inputs:
    inputs.flake-parts.lib.mkFlake { inherit inputs; } {
      systems = [
        "aarch64-darwin"
        "aarch64-linux"
        "x86_64-darwin"
        "x86_64-linux"
      ];
      perSystem =
        {
          self',
          pkgs,
          config,
          lib,
          ...
        }:
        {
          devShells.default = pkgs.mkShell {
            inputsFrom = [ ];
            buildInputs = with pkgs; [
              hello
              # Add more packages!
            ];
          };
        };
    };
}

この状態で nix develop を実行するとシステムに hello が入っていなくても使用できるようになっているはずです。

❯ hello
Hello, world!

無のprocess-compose

flake-parts.lib.mkFlake の引数の importsperSystem の出力に process-compose を追加します。

+      imports = [
+        inputs.process-compose-flake.flakeModule
+      ];
       perSystem =

perSystem 周辺。

         {
+          process-compose."default-service" =
+            { config, ... }:
+            {
+              imports = [
+                inputs.services-flake.processComposeModules.default
+              ];
+
+              services = { };
+            };
+
           devShells.default = pkgs.mkShell {
-            inputsFrom = [ ];
+            inputsFrom = [
+              config.process-compose."default-service".services.outputs.devShell
+            ];
             buildInputs = with pkgs; [ hello ];
           };
         };

この時点では nix run .#default-service をしても何のサービスも起動されません。

サービスの追加

Redis

以下のような設定をすることでRedisを使うことが出来ます。この設定を書いた状態で nix run .#default-serviceを実行してみましょう。

また、ポートの6379はデフォルトですが例として書いてあります。

-              services = { };
+              services = {
+                redis."r1" = {
+                 enable = true;
+                  port = 6379; # port 6379 is the default
+                };
+              };
process-composeの画面
process-composeの画面

nix develop すれば、redis-cliも自動で追加されます。

❯ nix develop
❯ redis-cli
127.0.0.1:6379> SET test hello
OK
127.0.0.1:6379> GET test
"hello"

おわりに

redisしか紹介していませんが、他のサービスは ドキュメント に記載されています。DB等はかなり使えるようになっている印象です。また必要ならカスタムのサービスを作成したり、process-compose-flakeの機能を使ってプロセスが実行されるようにすることが可能です。

本当は今日はNixのTipsを投稿する予定でしたが、うまく記事がまとまらなかったため内容を変えました。

参照


1

shell.nixも同じような機能ではありますが、この記事で紹介するservices-flakeはFlakesにしか対応していないため焦点を絞っています

Tags /Nix/