Nix에서 URL로 import하기
원문은 Michael Lynch님이 에 게재했습니다. 이 블로그 구독하기
저는 아직 Nix 초보자인데, 최근까지도 해결하지 못했던 것 중 하나가 configuration.nix 파일의 일부를 소스 컨트롤 하에 두는 방법이었습니다.
목표
Nix 설정 파일들을 모듈화하고 재사용 가능하게 만들고 싶습니다. 시스템이나 flake에 따라 필요한 설정 파일만 가져올 수 있도록요. 모든 Nix 설정 파일을 소스 컨트롤 하에 두고 싶습니다. 그래야 서로 다른 시스템이 각 파일의 서로 다른 버전에 의존할 수 있고, 모든 시스템을 동시에 각 설정 파일의 최신 버전으로 업그레이드할 필요가 없으니까요.
로컬 파일로 재사용 가능한 bash 별칭 만들기
제가 만들고 싶은 재사용 가능한 Nix 설정 중 하나는 bash 별칭입니다. 기존 시스템에서는 .bashrc에 다음과 같은 내용이 있습니다:
alias gc='git commit --message'
alias gs='git status'
alias td='pushd $(mktemp -d)'bash에서와 동일한 효과를 내기 위해, NixOS 시스템에 다음 내용을 담은 파일을 만들 수 있습니다. 저는 shell.nix라고 이름 지었지만 이름은 아무거나 상관없습니다:
{
programs.bash.shellAliases = {
gc = "git commit --message";
gs = "git status";
td = "pushd $(mktemp -d)";
};
}이 파일을 /tmp/shell.nix에 저장한 뒤, imports에 해당 경로를 추가하면 /etc/nixos/configuration.nix로 가져올 수 있습니다:
{
imports = [
"/tmp/shell.nix"
];
}sudo nixos-rebuild switch를 실행하고 셸을 재시작하면 bash 별칭이 활성화된 것을 확인할 수 있습니다:
$ td
/tmp/tmp.awb7PW7aus ~
[/tmp/tmp.awb7PW7aus]$ pwd
/tmp/tmp.awb7PW7ausNix 파일을 URL로 옮기기
위의 방법은 동작하지만, 각 Nix 시스템마다 동일한 파일을 복사해야 합니다.
대신 파일을 공개적으로 접근 가능한 URL에 호스팅하고, 그 URL을 참조하는 표준 configuration.nix 파일을 두고 싶습니다.
원격 URL에서 제 shell.nix 파일을 가져오도록 configuration.nix를 수정하는 방법은 다음과 같습니다:
let
shellAliases = builtins.fetchurl {
url = "https://mtlynch.io/notes/nix-import-from-url/shell.nix";
};
in {
imports = [
shellAliases
];
}다시 한번, 이 변경 사항을 configuration.nix에 저장하고 sudo nixos-rebuild switch를 실행한 뒤 셸을 재시작하면, Nix가 URL에서 제 bash 별칭을 가져옵니다.
fetchGit 사용하기 (선택 사항)
원격 Nix 파일을 가져오는 또 다른 방법은 공개 Git 저장소에 저장한 뒤 fetchGit으로 파일을 가져오는 것입니다.
공개 GitHub 저장소에서 제 shell.nix를 가져오는 configuration.nix 파일 예시는 다음과 같습니다:
let
repo = builtins.fetchGit {
url = "https://github.com/mtlynch/nix-files";
rev = "f98500a995cb5838e40be139a8327867faaff2d5";
};
in {
imports = [
"${repo}/shell.nix"
];
}url은 제 GitHub 저장소의 공개 URL이고, rev는 가져오려는 파일 버전의 Git 커밋 해시입니다.
configuration.nix에 이러한 변경을 적용한 뒤 sudo nixos-rebuild switch를 다시 실행하면, Nix가 제 GitHub 저장소에서 shell.nix 파일을 가져옵니다.
더 고급 셸 설정
제 bash 별칭 대부분은 간단한 한 줄짜리이지만, 몇 개는 더 복잡합니다. 그런 경우에는 bash 함수를 정의한 뒤 해당 함수에 대한 짧은 bash 별칭을 만듭니다.
한 예로 제 gcbm bash 별칭이 있습니다. gcbm some-branch처럼 사용하는데, 다음과 같은 동작을 합니다:
- main 브랜치를 체크아웃합니다.
- 원격 저장소에서 최신 변경 사항을 가져옵니다.
some-branch라는 새 브랜치를 체크아웃합니다.
별칭의 핵심 로직은 git_sync_and_branch라는 bash 함수로 구현합니다. shell.nix에서 이를 구현하는 방법은 다음과 같습니다:
{
programs.bash = {
shellInit = ''
function git_sync_and_branch {
local readonly TARGET_BRANCH="''${1}"
local readonly MAIN_BRANCH='master'
git checkout "''${MAIN_BRANCH}" && \
git pull origin "''${MAIN_BRANCH}" && \
if [[ -n "''${TARGET_BRANCH}" ]]; then
git checkout -b "''${TARGET_BRANCH}"
fi
}
'';
shellAliases = {
gc = "git commit --message";
gcbm = "git_sync_and_branch";
gs = "git status";
td = "pushd $(mktemp -d)";
};
};
}주의: 달러 기호 이스케이프
bash 함수를 Nix로 옮기면서 제가 겪은 함정 중 하나는 ${ 시퀀스를 이스케이프해야 한다는 점입니다. 그렇지 않으면 Nix가 이를 로컬 변수로 보간하려고 시도하는데, 사실 이 변수들은 Nix 변수가 아니라 bash 변수이기 때문입니다.
다음은 제가 처음에 git_sync_and_branch bash 함수의 한 줄을 작성하려 했던 방식입니다:
git checkout "${MAIN_BRANCH}"Nix는 다음과 같은 오류와 함께 실패했습니다:
error: undefined variable 'MAIN_BRANCH'${ 앞에 작은따옴표 두 개('')를 붙여 다음과 같이 ${를 이스케이프해야 합니다:
git checkout "''${MAIN_BRANCH}"왜 Home Manager를 쓰지 않나요?
Nix 설정을 모듈화하는 더 대중적인 방법은 Home Manager를 사용하는 것이라고 생각합니다.
하지만 솔직히 말하면, 저는 아직도 Home Manager의 목적을 잘 모르겠습니다. 프로젝트 README에 따르면:
이 프로젝트는 Nixpkgs에 있는 Nix 라이브러리와 함께 Nix 패키지 관리자를 사용하여 사용자 환경을 관리하기 위한 기본 시스템을 제공합니다. 사용자별(전역이 아닌) 패키지와 dotfile을 선언적으로 설정할 수 있게 해줍니다.
이 설명은 Nix가 이미 하는 일처럼 들리기 때문에 저를 더 혼란스럽게 합니다.
Home Manager를 몇 번 살펴본 적이 있지만, 매번 이 새로운 도구를 배우기 위해 많은 투자를 해야 하는데 그 이점이 명확하지 않게 느껴졌습니다.
언젠가는 Home Manager로 Nix 설정을 관리하는 이점을 깨닫게 될지도 모르지만, 지금으로서는 표준 Nix로 원격 Nix 파일을 관리하는 꽤 직관적인 방법을 찾았습니다.
글을 무작위로 읽기
댓글
로그인하고 댓글 남기기