バージョン管理された人

subversionで管理されてます

Magic: the Gathering の統率者戦用ランダム統率者表示アプリを作成した

Magic: the Gathering における統率者戦1における統率者をランダムに表示するアプリをつくった。

izzet-mtg.github.io

友人とランダムに統率者を決定して遊ぶのを目的として作成した。 是非使ってみてほしい。

何かあれば以下の GitHub リポジトリーで Issue をたててほしい。

github.com

NetBox の デフォルトで所属するグループ

NetBox はデフォルトで所属するグループを REMOTE_AUTH_DEFAULT_GROUPS で指定できる

netboxlabs.com

NetBox を直接 VM で動かしている場合、設定ファイルとなる Python のリストを設定すれば動くのだが、 Docker 版 NetBox だと指定方法が少し違う。 指定方法はどこにも書いてなくてコード読まないとわからない1。 コード読むと次のように _AS_LIST と指定してリスト形式で読み込むことがわかる。

REMOTE_AUTH_DEFAULT_GROUPS = _environ_get_and_map('REMOTE_AUTH_DEFAULT_GROUPS', '', _AS_LIST)

github.com

では _AS_LIST は環境設定値をどのように読み込んでいるか。 これは _environ_get_and_map 関数の中を見てもすぐにはわからない。

def _environ_get_and_map(variable_name: str, default: str | None = None, map_fn: Callable[[str], Any | None] = None) -> Any | None:
    env_value = environ.get(variable_name, default)

    if env_value == None:
        return env_value

    if not map_fn:
        return env_value
    
    return map_fn(env_value)

github.com

実際に重要なのはこの関数の第3引数である map_fn で、この定義は実はトップ変数で定義している。

_AS_BOOL = lambda value : value.lower() == 'true'
_AS_INT = lambda value : int(value)
_AS_LIST = lambda value : list(filter(None, value.split(' ')))

github.com

つまり、半角スペースを区切り文字としている。 そのため、複数グループを追加するよう Docker 版 NetBox に環境変数で指定する場合は次のようにする。

# デフォルトで group1 と group2 に新規ユーザーを追加する
REMOTE_AUTH_DEFAULT_GROUPS="group1 group2"

注意点として単純に半角スペースで区切っているだけなので、たとえば group 1 のようにスペースが混じると駄目。 本当に素朴に半角スペースで区切っているだけなので、よくあるバックスラッシュ (\) によるエスケープとか効かないことに注意。

まとめ

  • Docker 版 NetBox で複数個の値を設定できる環境変数は半角スペース区切りで指定する
  • エスケープとかないので、グループの名前に空白とか含めない方がいい
    • そもそも空白が含めないのかもしれないが

  1. というかそもそも Docker 版 NetBox の設定値はコード読まないとわからないことが多い。

NetBox のバージョニングとアップデート

NetBox のアップデートについてはここで述べる制約がある。 詳細は公式にあるからそっちを読んで欲しい。 あとは英語で読める人には蛇足。

For example, NetBox v2.11.8 can be upgraded to version 3.3.2 following the steps below. However, a deployment of NetBox v2.10.10 or earlier must first be upgraded to any v2.11 release, and then to any v3.x release. (This is to accommodate the consolidation of database schema migrations effected by a major version change).

netboxlabs.com

用はアップグレードするのにまず現在のメジャーバージョン (vX.Y.ZX の部分) におけるマイナーバージョン (vX.Y.ZY の部分) を最新になるようにアップグレードする。 たとえば 2024/11/30 時点で v3 の最新マイナーバージョン版は v3.7.X であり、自分の NetBox が v3.4.X であればまずは v3.7.X へ NetBox を上げる必要がある。 そこから v4.X.Y にアップグレードするという手法をとる。 こうしないと DB のマイグレーションスクリプトが動かないためアップグレードができない。

つまり、 v3.4.X や v3.0.X から v4.X.Y へ直接のアップグレードはできず、必ず v3 における最終マイナーバージョンである v3.7.X を経由しなければならない。 これは v4.X.Y から v5 へアップグレードするときも v2.X.Y から v3.X.Y にアップグレードするときも同じ。

NetBox の HA 構成

NetBox 自体は HA 構成に特段考慮事項や設定は必要ない。
そのまま必要な分だけ NetBox インスタンスをたててあげれば NetBox 自体は HA 構成できる。

github.com

つまり、手前に LB 置いて各 NetBox インスタンスにロードバランシングするようにしてあげても何か HA 構成となって動く。
そのためリクエストがロードバランシングで別 NetBox インスタンスにいってしまっても問題ない。

それよりはバックエンドの PostgreSQL や Redis の HA 構成が大変か。
まぁクラウドで最近は簡単に HA 構成できてしまうけども。

Docker 版 NetBox と Azure Active Directory (あるいは Entra ID)

NetBox と Azure Active Directory (というか Entra ID。以下 Azure AD と呼ぶことにする) の連携方法自体はある。

netboxlabs.com

これを NetBox を Docker 化した netboxcommunity/docker で動かそうとして次のように環境変数を指定してみてログインしようとするとログインができない。

docker run \
    -e REMOTE_AUTH_BACKEND='social_core.backends.azuread.AzureADOAuth2' \
    -e SOCIAL_AUTH_AZUREAD_OAUTH2_KEY='{Azure AD に登録した App Registration の Overview で表示される Application ID}' \
    -e SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET='{Azure AD に登録した App Registration に対して登録したクライアントのシークレット値}' \
    netboxcommunity/netbox:latest

実は netboxcommunity/netbox Docker イメージは REMOTE_AUTH_BACKEND の環境変数を設定できるようにはしているが、

REMOTE_AUTH_BACKEND = _environ_get_and_map('REMOTE_AUTH_BACKEND', 'netbox.authentication.RemoteUserBackend', _AS_LIST)

github.com

SOCIAL_AUTH_AZUREAD_OAUTH2_KEYSOCIAL_AUTH_AZUREAD_OAUTH2_SECRET は設定してくれない。

この2つで上記 GitHub リポジトリを検索すると実際に上記環境変数名が引っ掛からないことが確認できる。

SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET が netboxcommunity/netbox Docker イメージで定義されていない様子

幸いにも netboxcommunity/netbox Docker イメージでは /etc/netbox/config に Python コードを *.py という名前で書いておくと設定を Python コードを通して読み込んでくれる。

def read_configurations(config_module, config_dir, main_config):
    loaded_configurations = []

    main_config_path = abspath(f"{config_dir}/{main_config}.py")
    if isfile(main_config_path):
        _import(f"{config_module}.{main_config}", main_config_path, loaded_configurations)
    else:
        print(f"⚠️ Main configuration '{main_config_path}' not found.")

    with scandir(config_dir) as it:
        for f in sorted(it, key=_filename):
            if not f.is_file():
                continue

            if f.name.startswith("__"):
                continue

            if not f.name.endswith(".py"):
                continue

            if f.name == f"{main_config}.py":
                continue

            if f.name == f"{config_dir}.py":
                continue

            module_name = f"{config_module}.{f.name[:-len('.py')]}".replace(".", "_")
            _import(module_name, f.path, loaded_configurations)

    if len(loaded_configurations) == 0:
        print(f"‼️ No configuration files found in '{config_dir}'.")
        raise ImportError(f"No configuration files found in '{config_dir}'.")

    return loaded_configurations


## Specific Parts
# This section's code actually loads the various configuration files
# into the module with the given name.
# It contains the logic to resolve arbitrary configuration options by
# levaraging dynamic programming using `__getattr__`.


_loaded_configurations = read_configurations(
    config_dir="/etc/netbox/config/",
    config_module="netbox.configuration",
    main_config="configuration",
)

github.com

なので、たとえば extra-configuration.py というような名前で追加のコンフィグを読み込む Python コードを書いて

from os import environ

SOCIAL_AUTH_AZUREAD_OAUTH2_KEY = environ.get("SOCIAL_AUTH_AZUREAD_OAUTH2_KEY")
SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET = environ.get("SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET")

/etc/netbox/config に入れておくように Docker イメージを編集し、

ARG TAG=latest
FROM netboxcommunity/netbox:${TAG}
COPY ./extra-configuration.py /etc/netbox/config

ビルドする。

docker build -t netbox:latest .

走らせると Azure AD ログインができるようになる。

docker run \
    -e REMOTE_AUTH_BACKEND='social_core.backends.azuread.AzureADOAuth2' \
    -e SOCIAL_AUTH_AZUREAD_OAUTH2_KEY='{Azure AD に登録した App Registration の Overview で表示される Application ID}' \
    -e SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET='{Azure AD に登録した App Registration に対して登録したクライアントのシークレット値}' \
    netbox:latest

まとめ

  • 素の netboxcommunity/netbox Docker イメージには Azure AD との連携に必要な変数を定義できるようにしていない
  • 拡張子が .py な名前のファイルに Azure AD との連携に必要な変数を環境変数から読み込むように定義してあげる
  • 追加した .py ファイルを /etc/netbox/config に配置するように Dockerfile を書く
  • Azure AD と連携するには素の netboxcommunity/netbox Docker イメージではなく自分でつくった Docker イメージを利用する

【NTT Communications Advent Calendar 2023】Nix と home-manager で dotfiles を管理する話

この記事は、 NTT Communications Advent Calendar 2023 9日目の記事です。

みなさんは dotfiles をどのように管理されているでしょうか? Bash や Zsh といったスクリプトによってインストールを管理したり、 git でホームディレクトリを管理する、 ChefAnsible のような構成管理ツールを用いて管理する方法があると思います。 自分もシェルスクリプトによる管理をおこなったり、 Ansible 等の構成管理ツールの利用や 自前の構成管理ツール をつくって管理していましたが、現在は Nixhome-manager というものを使って管理しています。 今回はこの Nix と home-manager による dotfiles の管理をどのように行えばよいのか、それらによって管理する Pros/Cons にはどのようなものがあるのかについて解説します。

Nix

まずそもそも Nix とはどういったものなのかについて解説します。

Nix とは NixOS という Linux ディストリビューションに搭載された aptyum/dnf のようなパッケージ管理システムです。 Nix はドキュメントにも記載してありますが、 純粋関数型パッケージマネージャー です。

Nix is a purely functional package manager.

Introduction - Nix Reference Manual

purely functional なパッケージマネージャーとはどういったものなのかというとビルドされたパッケージは副作用のないビルド方法を記載した関数によってビルドされ、そのビルドされたものは変更されることがないというものです。 Haskell の値をパッケージマネージャーに見立ててもらうとわかりやすいと思いますが、 Haskell においては値は副作用のない関数によって計算され、その値はその後に変更されることがありません。 これをパッケージ管理で実現したものが Nix になります。

ビルド方法を記載する関数が purely functional であるため、再度ビルドしても同じ生成物が作成されるようになっています。 このため、一度ビルドができてしまえば常に同じ環境を実現できるようになっています。

Nix Language

Nix では Nix Language という言語でパッケージのビルド方法等を記載します。

Nix Language は ドキュメント によると

  • ドメイン特化
  • 宣言的
  • 純粋
  • 関数型
  • 遅延性
  • 動的型付け

という特徴を持つ言語です。

Nix Language は基本的は文字列型や数値型、真理値型等が存在します。 その他にも絶対パスや相対パスも表現できます(先頭が # である行はコメント行です)。

# integer
1
# floating
3.14
# string
"single line string"
''
  multi line string
''
# string interpolation
"toString ${toString 3}"
# boolean
true
# null
null
# absolute path
/etc
# relative path
./foo.json

その他にもリストや集合といった複合型もあります。

# list
[ 1 "123" ]
# set
{ x = 1; y = 2; }

また重要なコンポーネントである関数は次のように記述します。

# f(x) = x + 1
x: x + 1
# f(x, y) = x + y
x: y: x + y
# function call: f(100) = 100 + 1
(x: x + 1) 100

他にも値を束縛するための let ~ in ~if ~ then ~ else ~といった制御構文や関数の引数におけるパターンマッチ等が存在します。 より詳細に知りたい方は Nix Reference ManualNix Language セクションを読んでいただければと思います。

home-manager

そんな Nix を利用してユーザー環境を管理できるようにした仕組みが home-manager です。 home-manager を利用するとホームディレクトリーに dotfiles を設置したり、必要なパッケージを事前にインストールしたりといったことが可能になります。

ユーザー環境の管理自体は簡単で、次のコマンドを実施すると構成を管理する ~/.config/home-manager/home.nix が生成されます。

nix-shell --run sh '<home-manager>' -A install

~/.config/home-manager/home.nix には次のような内容を記載します。

{ config, pkgs, ... }:
{
  home.username = "<ユーザー名>";
  home.homeDirectory = "<home.username ユーザーのホームディレクトリーのパス>";
  # ここは ~/.config/home-manager/home.nix を生成したときにつくコメントを参考にして設定する。
  # デフォルトだとコマンド実行時にバージョンが記載されている
  home.stateVersion = "<home-manager のバージョン>";
  home.packages = [
    # 使用したいパッケージをここに記載する。
    # 以下は vim と kubectl をインストールしている例
    pkgs.vim
    pkgs.kubectl
  ];
  home.file = {
    # ~/.ssh/config の内容をここに記載している。
    # ここに `<ファイルのパス>.text = "<ファイルの内容>"` のように記載しておくと `<ファイルの内容>` を持つ
    # ファイルが `<ファイルのパス>` で指定したパスに作成される。
    # ただし、実体は作成されるファイルはシンボリックリンクになっており、実際は nix によって管理される
    # readonly なファイルになる点に注意。
    ".ssh/config".text = ''
      Host github
        HostName github.com
        User git
    '';
  };
}

home-manager の制御は home-manager コマンドを通して行います。 基本的には switch サブコマンドを実行すれば環境が用意されます。

$ kubectl version
kubectl: command not found
# 環境を準備する
$ home-manager switch
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.9", GitCommit:"c1de2d70269039fe55efb98e737d9a29f9155246", GitTreeState:"clean", BuildDate:"2022-07-13T14:26:51Z", GoVersion:"go1.17.11", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"23", GitVersion:"v1.23.9", GitCommit:"c1de2d70269039fe55efb98e737d9a29f9155246", GitTreeState:"clean", BuildDate:"2022-07-13T14:19:57Z", GoVersion:"go1.17.11", Compiler:"gc", Platform:"linux/amd64"}
# ~/.ssh/config をみてみる
$ cat ~/.ssh/config
Host github
  HostName github.com
  User git

home-manager で switch サブコマンドによって生成されるファイルはシンボリックリンクになっています。 実態は Nix が管理しているファイルになっています。

$ ls ~/.ssh/config
lrwxr-xr-x   1 user  usergroup    84 Dec 10 02:50 config -> /nix/store/pr31jgjnwnpmaf58w35jyrajilfzcail-home-manager-files/.ssh/config

~/.config/home-manager/home.nixhome.file に設定した内容を書き換えて swtich サブコマンドを実行するとこの内容が書き変わります。

{ ... }:
{
  home.file = {
    ".ssh/config".text = ''
      Host gitlab
        HostName gitlab.com
        User git
    '';
  };
}
# dotfiles を再生成
$ home-manager switch
trace: warning: optionsDocBook is deprecated since 23.11 and will be removed in 24.05
trace: warning: optionsDocBook is deprecated since 23.11 and will be removed in 24.05
trace: warning: optionsDocBook is deprecated since 23.11 and will be removed in 24.05
/nix/store/7871wampdlaqva7mpa616gkmjn4c38qj-home-manager-generation
Starting Home Manager activation
Activating checkFilesChanged
Activating checkLaunchAgents
Activating checkLinkTargets
Activating writeBoundary
Activating linkGeneration
Cleaning up orphan links from /home/user
No change so reusing latest profile generation 139
Creating home file links in /home/user
Activating batCache
No themes were found in '/home/user/.config/bat/themes', using the default set
No syntaxes were found in '/home/user/.config/bat/syntaxes', using the default set.
Writing theme set to /home/user/.cache/bat/themes.bin ... okay
Writing syntax set to /home/user/.cache/bat/syntaxes.bin ... okay
Writing metadata to folder /home/user/.cache/bat ... okay
Activating copyFonts
Activating installPackages
replacing old 'home-manager-path'
installing 'home-manager-path'
Activating onFilesChange
Activating setupLaunchAgents

There are 75 unread and relevant news items.
Read them by running the command "home-manager news".
# ~/.ssh/config を見てみる
$ cat ~/.ssh/config
Host gitlab
  HostName gitlab.com
  User git

そのため、 Nix の環境さえ用意できれば dotfiles を IaC で管理できます。 書き換えたければ ~/.config/home-manager/home.nix を書き換え、 home-manager switch を実行すれば環境がそのまま用意されます。 その他にも ~/.config/home-manager/home.nix にある home.packages に必要なパッケージを記載すればパッケージのインストールもしてもらえます。 もしインストールされたものを削除したい場合は nix-gabage-collect コマンドを実行すると不必要な環境が Nix から綺麗さっぱり削除されます。

# インストールされたコマンドは Nix の環境にインストールされ、 ~/.nix-profile/bin に
# シンボリックリンクがはられます。
# インストールされたパッケージや依存物は ~/.config/home-manager/home.nix の home.packages を書き換えただけだと
# Nix の環境にあるキャッシュは削除されません。
# このコマンドは home-manager の機能というよりは Nix が提供する Nix 環境の GC を実施するコマンドです
nix-gabage-collect

また、 Nix の導入が済んでしまえば一時的にパッケージを利用する場合は nix-shell コマンドを利用すると一時的にパッケージをインストールして利用できます。

# Node.js と pnpm を一時的にインストールした環境に入る
$ nix-shell -p nodejs nodePckages.pnpm
these 6 derivations will be built:
  /nix/store/0i23yycgl4g3ysh919zrhqw6s7mv0clq-reconstructpackagelock.js.drv
  /nix/store/10sbwpqks6vpixp3najqz2zr6bfbz2av-linkbins.js.drv
  /nix/store/cay26jcn3vgnhsimhrpbqjmv39w5syg7-addintegrityfields.js.drv
  /nix/store/dxwm67zm4j9rlprgy7qj7j10iywbharh-install-package.drv
  /nix/store/vgc54qkgm1h9haaw95gkpahzss8hb1n3-pinpointDependencies.js.drv
  /nix/store/win93b0d7agghd066d888bjbh5brrri0-pnpm-8.10.2.drv
these 5 paths will be fetched (46.54 MiB download, 408.80 MiB unpacked):
  /nix/store/1ipdb6jghbj1zbnxwydghq8gkgf6v3ca-cctools-llvm-11.1.0-973.0.1-dev
  /nix/store/gf6d8v8qj8rbpnyydyrv2m0vjcfw3bh6-cctools-port-973.0.1-dev
  /nix/store/8sgv1kbxwx641j6v4sv63zh5p01w473k-node-sources
  /nix/store/x551k64la7wmg4xj07yxfdd60wq2rd4y-pnpm-8.10.2.tgz
  /nix/store/4ag0qy6w79b67xslwgi26ax3i91a19zc-tarWrapper
copying path '/nix/store/8sgv1kbxwx641j6v4sv63zh5p01w473k-node-sources' from 'https://cache.nixos.org'...
copying path '/nix/store/x551k64la7wmg4xj07yxfdd60wq2rd4y-pnpm-8.10.2.tgz' from 'https://cache.nixos.org'...
copying path '/nix/store/4ag0qy6w79b67xslwgi26ax3i91a19zc-tarWrapper' from 'https://cache.nixos.org'...
building '/nix/store/cay26jcn3vgnhsimhrpbqjmv39w5syg7-addintegrityfields.js.drv'...
building '/nix/store/dxwm67zm4j9rlprgy7qj7j10iywbharh-install-package.drv'...
building '/nix/store/10sbwpqks6vpixp3najqz2zr6bfbz2av-linkbins.js.drv'...
building '/nix/store/vgc54qkgm1h9haaw95gkpahzss8hb1n3-pinpointDependencies.js.drv'...
building '/nix/store/0i23yycgl4g3ysh919zrhqw6s7mv0clq-reconstructpackagelock.js.drv'...
copying path '/nix/store/gf6d8v8qj8rbpnyydyrv2m0vjcfw3bh6-cctools-port-973.0.1-dev' from 'https://cache.nixos.org'...
copying path '/nix/store/1ipdb6jghbj1zbnxwydghq8gkgf6v3ca-cctools-llvm-11.1.0-973.0.1-dev' from 'https://cache.nixos.org'...
building '/nix/store/win93b0d7agghd066d888bjbh5brrri0-pnpm-8.10.2.drv'...
unpacking sources
patching sources
updateAutotoolsGnuConfigScriptsPhase
configuring
no configure script, doing nothing
building
installing
unpacking source archive /nix/store/x551k64la7wmg4xj07yxfdd60wq2rd4y-pnpm-8.10.2.tgz
pinpointing versions of dependencies...
patching script interpreter paths in .
./pnpm/bin/pnpx.cjs: interpreter directive changed from "#!/usr/bin/env node" to "/nix/store/fwgfw6i5q1hv49bgfl96bmzv72l98khy-nodejs-18.18.2/bin/node"
./pnpm/bin/pnpm.cjs: interpreter directive changed from "#!/usr/bin/env node" to "/nix/store/fwgfw6i5q1hv49bgfl96bmzv72l98khy-nodejs-18.18.2/bin/node"
./pnpm/dist/node_modules/node-gyp/bin/node-gyp.js: interpreter directive changed from "#!/usr/bin/env node" to "/nix/store/fwgfw6i5q1hv49bgfl96bmzv72l98khy-nodejs-18.18.2/bin/node"
./pnpm/dist/node-gyp-bin/node-gyp: interpreter directive changed from "#!/usr/bin/env sh" to "/nix/store/zzpm4317hn2y29rm46krsasaww9wxb1k-bash-5.2-p15/bin/sh"
No package-lock.json file found, reconstructing...
npm WARN config production Use `--omit=dev` instead.
rebuilt dependencies successfully
npm WARN config production Use `--omit=dev` instead.

up to date, audited 1 package in 183ms

found 0 vulnerabilities
linking bin 'pnpm'
linking bin 'pnpx'
post-installation fixup
checking for references to /private/tmp/nix-build-pnpm-8.10.2.drv-0/ in /nix/store/kyprrxixg263c82lzy9gmfpj97kkl32p-pnpm-8.10.2...
patching script interpreter paths in /nix/store/kyprrxixg263c82lzy9gmfpj97kkl32p-pnpm-8.10.2
rewriting symlink /nix/store/kyprrxixg263c82lzy9gmfpj97kkl32p-pnpm-8.10.2/bin to be relative to /nix/store/kyprrxixg263c82lzy9gmfpj97kkl32p-pnpm-8.10.2

[nix-shell:~]$ pnpm --version
8.10.2
[nix-shell:~]$ node --version
v18.18.2

また、 shell.nix というものをディレクトリに用意しておけば、 nix-shell コマンドだけ実行すればそのまま一時的な環境に入ることもできます。

$ ls
shell.nix
$ cat shell.nix
{ pkgs ? import <nixpkgs> {}, ... }:
pkgs.mkShell {
  nativeBuildInputs = [
    pkgs.nodejs
    pkgs.pnpm
  ];
}
$ nix-shell
[nix-shell:~/Test/Directory]$ pnpm --version
8.10.2
[nix-shell:~/Test/Directory]$ node --version
v18.18.2

Nix が提供するパッケージを探す場合は NixOS Search を利用します。 こちらに必要なパッケージ名をサーチボックスに入れて Search ボタンをクリックするとパッケージが提供されているかを検索してくれます。

NixOS Search で nodejs パッケージを探している

NixOS Search における nodejs の検索結果

パッケージを更新する場合は nix-channel--update オプションを利用し、 home-managerswitch コマンドを利用します。

$ nix-channel --update
this derivation will be built:
  /nix/store/ikk0zi83gc4x263imdgdx7d721wh33il-darwin.drv
building '/nix/store/ikk0zi83gc4x263imdgdx7d721wh33il-darwin.drv'...
this derivation will be built:
  /nix/store/csfs0vgc39fwjsz6bx22a9iyx5zx3gwh-home-manager.drv
building '/nix/store/csfs0vgc39fwjsz6bx22a9iyx5zx3gwh-home-manager.drv'...
unpacking channels...
$ home-manager switch
# ここからは長い出力がある

まとめ

ここまでで Nix + home-manager で dotfiles を管理する方法をここまでに記載してきました。 Nix は慣れるまで少し扱いが難しく、また日本語の情報は少ないので扱いにこなれるまで時間はかかります。 しかし、導入が済んでしまえば dotfiles を用意しつつしかも環境を綺麗に保ちながらパッケージの導入ができます。 是非とも今回の記事を活用してよりよい dotfiles 環境を構築してみてください。

もし例が気になる場合は自分が環境をつくってリポジトリに公開している ので、そちらを確認してください。

次回の NTT Communications Advent Calendar 2023 の記事もお楽しみに。