Nix로 만드는 프로젝트별 개발 환경
원문은 Michael Lynch님이 에 게재했습니다. 이 블로그 구독하기
Nix는 기능 범위가 넓고 학습 곡선이 가파른 제품이다. 단일 패키지 설치부터 OS의 모든 파일과 애플리케이션을 관리하는 것까지 가능하다.
Nix로 할 수 있는 유용한 일 중 하나는, 완전 초보자라도 개발 환경을 관리하는 것이다.
Nix를 이용하면 같은 시스템에서 여러 프로젝트를 각각 독립적인 의존성 뷰를 갖도록 운영할 수 있다. 레거시 프로젝트 하나는 Python 2.7과 Node.js 4.x로 돌리면서, 모던 프로젝트 하나는 Python 3.11과 Node.js 20으로 돌려도 서로 간섭하지 않는다.
Nix 경험이 전혀 없어도 20분 정도 작업이면 Nix로 관리되는 개발 환경을 사용할 수 있다.
참고: 필자는 아직 Nix 초보자라 지금 하고 있는 방식이 최적의 해법인지 확신할 수 없다. 더 경험 많은 Nix 사용자 중에 개선 제안이 있다면 알려 달라. 포스트에 반영하겠다.
왜 Docker로 개발 환경을 관리하지 않는가?
나는 Docker를 좋아하고 배포나 특정 DevOps 작업에 사용하지만, 개발 환경 관리에는 도움이 되지 않았다.
나는 VS Code에서 SSH로 개발을 하는데, Docker를 쓰면 이 과정이 번거로워진다. 우회 방법이 있다는 건 알지만, 그 어떤 방법도 매력적으로 느껴진 적은 없다.
왜 Ansible로 개발 환경을 관리하지 않는가?
지난 6년간 Ansible로 개발 환경을 관리해 왔다. 그럭저럭 잘 동작했다.
내가 가진 모든 소프트웨어 프로젝트마다 전용 가상 머신과, 그 VM에 모든 의존성을 구성하기 위한 Ansible 플레이북을 만든다.
문제는 몇 분 정도 뭔가를 실험하고 싶을 때, VM 하나를 통째로 띄우고 플레이북을 작성한 뒤 Ansible이 서버를 프로비저닝할 때까지 10~20분을 기다리는 과정이 전혀 내키지 않는다는 점이다.
Nix가 훨씬 가볍기 때문에 모든 프로젝트를 Ansible 대신 Nix를 쓰도록 천천히 옮기고 있다. Ansible로 의존성을 업그레이드하면 보통 의존성 하나당 20분 정도 걸리지만, Nix에서는 같은 작업을 2분 정도면 할 수 있다.
간단한 Nix 개발 환경 만들기
Nix 개발 환경이 어떻게 동작하는지 보여주기 위해, 아무것도 설치되지 않은 Debian 11 시스템에서 시작하겠다.
Nix 설치
먼저 Nix를 설치한다. 공식 Nix 인스톨러 대신 서드파티 Determinate Systems 인스톨러를 사용한다. Determinate Systems 쪽이 여기서 보여줄 내용에 유용한 몇 가지 주관적인 설정 결정을 해주기 때문이다.
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install && . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh간단한 Python 2.7 애플리케이션 만들기
Nix 개발 환경이 실제로 동작하는 모습을 보여주기 위해, 2020년에 공식 지원이 종료된 레거시 버전인 Python 2.7에서 실행되는 간단한 애플리케이션을 만들어 보겠다.
시작하기 위해 프로젝트용 새 디렉터리를 만든다.
mkdir example && cd example다음으로, Nix 개발 환경을 정의하는 파일인 Nix flake를 다운로드하거나 복사한다:
{
description = "Demo Nix dev environment";
inputs = {
flake-utils.url = "github:numtide/flake-utils";
# 2.7.18.7 release
python-nixpkgs.url = "github:NixOS/nixpkgs/517501bcf14ae6ec47efd6a17dda0ca8e6d866f9";
};
outputs = {
self,
flake-utils,
python-nixpkgs,
} @ inputs:
flake-utils.lib.eachDefaultSystem (system: let
python-nixpkgs = inputs.python-nixpkgs.legacyPackages.${system};
in {
devShells.default = python-nixpkgs.mkShell {
packages = [
python-nixpkgs.python2
];
shellHook = ''
python --version
'';
};
});
}curl --show-error --fail https://mtlynch.io/notes/nixos-dev-environment/flake.nix > flake.nixNix에 익숙하지 않다면 flake.nix 파일이 혼란스러운 문법 덩어리처럼 보일 수 있지만, 대부분 단순한 보일러플레이트다. 더 자세한 설명은 아래에서 하겠다.
마지막으로 Nix 개발 환경을 띄울 차례다. 처음 명령을 실행할 때는 모든 것을 초기화하는 데 몇 분이 걸리지만, 그 다음부터는 초기화가 몇 초 만에 완료된다는 점을 참고하자.
# We need NIXPKGS_ALLOW_INSECURE and --impure because Python 2.7 is past end of
# life.
$ NIXPKGS_ALLOW_INSECURE=1 nix develop --impure
Python 2.7.18.7성공이다! Python 2.7 환경을 사용할 수 있게 됐다.
이 특정 Nix 환경 밖에는 Python 2.7을 전혀 설치하지 않았다는 점에 유의하자. nix develop을 실행하지 않고 새 터미널을 열면 Python이 설치되지 않았다는 다음 오류 메시지가 표시된다:
$ python --version
-bash: python: command not found다시 Python 2.7 Nix 환경으로 돌아와, Python 3에서는 동작하지 않는, 사악하고 더 이상 쓰이지 않는 print 문법을 사용한 간단한 Python 스크립트를 실행해 보자:
$ echo 'print "hello, world!"' > main.py && python main.py
hello, world!멋지다! 이 환경에서 레거시 Python 2.7 코드를 실행할 수 있다.
버전 문자열 찾기
그렇다면 내 flake.nix 파일은 어떻게 동작할까?
flake.nix 파일의 앞부분에 있는 한 줄이 내가 원하는 Python 패키지의 정확한 버전을 선언한다:
{
# 2.7.18.7 release
python-nixpkgs.url = "github:NixOS/nixpkgs/517501bcf14ae6ec47efd6a17dda0ca8e6d866f9";# 2.7.18.7 release 라인은 내 참고용 주석일 뿐이다. Nix는 이를 무시한다. 실제 핵심 역할을 하는 부분은 python-nixpkgs 라인이다.
NixOS/nixpkgs는 GitHub 리포지토리이고, 517501bcf14ae6ec47efd6a17dda0ca8e6d866f9는 python2 패키지가 Python 2.7.18.7에 해당하던 시점의 리포지토리 버전이다.
그 긴 버전 문자열을 어떻게 알았을까? Nixhub를 사용했다.
Nixhub는 Nix 기반 개발자 도구를 판매하는 회사인 Jetpack이 만든 무료 패키지 검색 서비스다.
Nixhub는 불과 세 달 전에 출시됐는데, 덕분에 Nix에서의 작업이 훨씬 쉬워졌다. 특정 버전의 패키지에 대한 버전 해시를 찾고 싶으면 Nixhub에서 검색해 커밋 ID를 찾으면 된다.
그래서 Python 2.7.18.7의 버전 문자열을 찾기 위해 Nixhub에서 python을 검색한 뒤, 결과 목록을 내려 가장 최신의 Python 2.7.x 버전을 찾았다:

NixHub를 이용하면 사람이 읽기 쉬운 버전 문자열을 nixpkgs 참조와 패키지 이름으로 변환할 수 있다.
솔직히 말해 정확한 패키지 버전을 고정하는 일은 엄청나게 번거롭다. 원하는 버전이 2.7.18.7이라고 그냥 지정하면 되는 수준으로 Nix 툴링이 발전했으면 좋겠지만, 지금은 원하는 버전에 해당하는 git 커밋 해시를 찾아 헤매는 이 우회적인 과정을 거쳐야 한다. 하지만 현재로서는 버전을 고정하는 가장 좋은 방법은 이것이다.
flake.nix 파일 이해하기
앞서 보여준 flake.nix 파일에 대해 더 자세히 설명하겠다고 했다.
Nix flake에 대한 모든 것을 설명하지는 않을 것이다. 나 자신도 깊이 이해하고 있지 않기 때문이다. 자신만의 개발 환경을 만드는 데 필요한 최소한의 내용만 설명하겠다. Nix flake에 대해 더 깊이 알고 싶다면 “Practical Nix Flakes.”를 참고하자.
inputs 섹션은 환경에 포함하고 싶은 서로 다른 Nix 소스의 버전을 넣는 곳이다. GitHub 리포지토리에 대한 특수 문법을 사용하고 있지만, 다른 소스 리포지토리나 URL에서도 가져올 수 있다.
{
inputs = {
flake-utils.url = "github:numtide/flake-utils";
# 2.7.18.7 release
python-nixpkgs.url = "github:NixOS/nixpkgs/517501bcf14ae6ec47efd6a17dda0ca8e6d866f9";
};devshells.default는 Nix 셸을 위한 개발 환경을 정의한다. packages에는 환경에서 사용하고 싶은 모든 패키지 목록이 들어간다.
{
devShells.default = python-nixpkgs.mkShell {
packages = [
python-nixpkgs.python2
];대부분의 패키지는 패키지 이름에 버전이 붙지 않는다. htop이나 vim 같은 패키지는 패키지 이름이 항상 동일하지만, Python처럼 특정 패키지는 동일한 Nixpkgs 버전 안에서도 여러 버전이 제공되므로 Python 3와 혼동을 피하기 위해 python이 아닌 python2로 지정해야 한다.
마지막으로 관련된 부분은 shellHook 섹션이다.
{
shellHook = ''
python --version
'';Nix는 셸로 진입시키기 직전에 shellHook에 있는 명령을 실행한다. 여기에 어떤 셸 명령이든 넣을 수 있다.
나는 내 Nix flake가 올바르게 동작하는지 쉽게 확인할 수 있도록 의존성 버전을 출력하는 명령을 넣어 두는 것을 좋아한다.
Python 3로 업그레이드하기
이제 한 줄짜리 Python 앱을 Python 2.7에서 최신 Python 3로 포팅하는 고된 작업을 할 준비가 됐다고 해보자. 다음 두 조각만 업데이트하면 된다:
{
# 3.12.0 release
python-nixpkgs.url = "github:NixOS/nixpkgs/e2b8feae8470705c3f331901ae057da3095cea10";{
packages = [
python-nixpkgs.python312
];새로운 Python 3 flake는 다음과 같다:
{
description = "Demo Nix dev environment";
inputs = {
flake-utils.url = "github:numtide/flake-utils";
# 3.12.0 release
python-nixpkgs.url = "github:NixOS/nixpkgs/e2b8feae8470705c3f331901ae057da3095cea10";
};
outputs = { self, flake-utils, python-nixpkgs }@inputs :
flake-utils.lib.eachDefaultSystem (system:
let
python-nixpkgs = inputs.python-nixpkgs.legacyPackages.${system};
in
{
devShells.default = python-nixpkgs.mkShell {
packages = [
python-nixpkgs.python312
];
shellHook = ''
python --version
'';
};
});
}Ctrl+D를 누르거나 exit을 입력해 기존 Nix 셸을 종료하고, 다음 명령을 실행해 새로운 Python 3 환경을 초기화한다:
$ nix develop
warning: updating lock file '/home/mike/example/flake.lock':
• Updated input 'python-nixpkgs':
'github:NixOS/nixpkgs/517501bcf14ae6ec47efd6a17dda0ca8e6d866f9' (2023-09-27)
→ 'github:NixOS/nixpkgs/e2b8feae8470705c3f331901ae057da3095cea10' (2023-10-03)
Python 3.12.0편리하게도 최신 Python 버전은 안전하지 않다고 간주되지 않으므로, Python 2.7에 필요했던 NIXPKGS_ALLOW_INSECURE 옵션을 생략할 수 있다.
이제 Python 3 환경에 들어와 있어야 한다. 이를 증명하기 위해 Python 2 스타일의 main.py를 실행해 보고, Python 3가 적절히 경악하며 오류를 내는지 확인해 보자:
$ python main.py
File "/home/mike/example/main.py", line 1
print "hello, world!"
^^^^^^^^^^^^^^^^^^^^^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)?Python 3가 의도대로 동작하는 것 같다. 문법을 Python 3에 맞게 수정하고 다시 시도해 보자:
$ echo 'print("hello, world!")' > main.py && python main.py
hello, world!다시 모든 것이 정상이다. Nix flake의 몇 줄만 바꿔서 환경을 Python 2.7에서 Python 3.12로 업데이트했다!
새 의존성 추가하기
패키지를 업데이트하는 방법을 보여줬으니, 이번에는 새 의존성을 추가하는 경우는 어떨까?
Python 파일을 자동으로 실행하는 새로운 bash 스크립트를 추가해 보겠다.
(cat <<EOF
#!/usr/bin/env bash
set -eux
readonly MAIN_SCRIPT="main.py"
python $MAIN_SCRIPT
EOF
) > run.sh && chmod +x run.sh && ./run.sh다음과 같은 출력이 표시될 것이다:
+ readonly MAIN_SCRIPT=main.py
+ MAIN_SCRIPT=main.py
+ python main.py
hello, world!나는 bash에 약하므로 정적 분석 도구가 내 run.sh 스크립트를 개선해 줄 수 있을 것이다.
shellcheck는 bash 스크립트를 위한 훌륭한 린터이며, 나는 bash 코드를 작성하는 곳이면 어디서나 이를 사용한다. shellcheck를 개발 환경으로 가져와 잠재적인 bash 함정에 대한 조언을 얻고 싶으므로 Nix flake를 업데이트한다:
{
description = "Demo Nix dev environment";
inputs = {
flake-utils.url = "github:numtide/flake-utils";
# 3.12.0 release
python-nixpkgs.url = "github:NixOS/nixpkgs/e2b8feae8470705c3f331901ae057da3095cea10";
# 0.9.0 release
shellcheck-nixpkgs.url = "github:NixOS/nixpkgs/8b5ab8341e33322e5b66fb46ce23d724050f6606";
};
outputs = { self, flake-utils, python-nixpkgs, shellcheck-nixpkgs }@inputs :
flake-utils.lib.eachDefaultSystem (system:
let
python-nixpkgs = inputs.python-nixpkgs.legacyPackages.${system};
shellcheck-nixpkgs = inputs.shellcheck-nixpkgs.legacyPackages.${system};
in
{
devShells.default = python-nixpkgs.mkShell {
packages = [
python-nixpkgs.python312
shellcheck-nixpkgs.shellcheck
];
shellHook = ''
python --version
echo "shellcheck" "$(shellcheck --version | grep '^version:')"
'';
};
});
}다시 Ctrl+D를 누르거나 exit을 입력해 기존 Nix 셸을 종료하고, 다음 명령으로 새 셸을 생성한다:
$ nix develop
warning: updating lock file '/home/mike/example/flake.lock':
• Added input 'shellcheck-nixpkgs':
'github:NixOS/nixpkgs/8b5ab8341e33322e5b66fb46ce23d724050f6606' (2023-09-19)
Python 3.12.0
shellcheck version: 0.9.0모든 것이 잘 보인다. shellcheck가 내가 요청한 버전인 0.9.0을 보고한다.
이제 내 run.sh 스크립트에 대해 shellcheck를 실행할 차례다.
$ shellcheck -o all run.sh
In run.sh line 6:
python $MAIN_SCRIPT
^----------^ SC2248 (style): Prefer double quoting even when variables don't contain special characters.
^----------^ SC2250 (style): Prefer putting braces around variable references even when not strictly required.
Did you mean:
python "${MAIN_SCRIPT}"
For more information:
https://www.shellcheck.net/wiki/SC2248 -- Prefer double quoting even when v...
https://www.shellcheck.net/wiki/SC2250 -- Prefer putting braces around vari...오, 성공이다!
사소해 보일 수 있지만, 이는 내가 과거에 겪었던 큰 문제를 해결해 준다. 나는 모든 프로젝트에서 shellcheck를 git pre-commit 훅으로 실행하는 것을 좋아하지만, 지금까지는 항상 단일한 시스템 전체 버전의 shellcheck에 의존해야 했다. shellcheck에 내 프로젝트 중 하나에 적용하고 싶은 새로운 규칙이 생기면, pre-commit 훅이 모든 프로젝트에서 실패하기 시작할 수도 있다.
Nix를 이용하면 각 프로젝트를 실행하고 싶은 린터 버전에 묶을 수 있다. 즉, 전역에서 단일 버전을 공유하는 대신 프로젝트별로 새로운 린터로 업그레이드할 수 있다.
direnv를 사용해 Nix 개발 셸 자동 로드하기
Nix 개발 셸은 동작하지만, 새 터미널 창을 열 때마다 셸에 진입하기 위해 nix develop을 입력해야 한다는 의미다.
이걸 자동화할 수 있을까? direnv를 사용하면 가능하다.
direnv는 프로젝트 디렉터리로 cd할 때마다 Nix 셸을 자동으로 로드한다. 디렉터리에서 나오면 direnv가 자동으로 셸을 언로드한다.
direnv는 일반 apt 패키지로도 제공되지만, 성가시게도 Debian Bullseye 및 이전 버전에서는 사용 가능한 최신 패키지가 2.25.0이다.
Nix flake를 사용하므로 direnv 2.29.0 이상이 필요해서, 대신 공식 direnv 인스톨러를 사용하겠다:
curl -sfL https://direnv.net/install.sh | sudo bin_path=/usr/local/bin bash && echo 'eval "$(direnv hook bash)"' >> ~/.bashrc && . ~/.bashrcdirenv를 --version 플래그와 함께 실행하면 사용 가능한 최신 버전을 사용 중임을 알 수 있다:
$ direnv --version
2.32.3프로젝트에서 direnv를 활성화하려면 Nix flake가 있는 디렉터리로 이동해 다음 명령을 실행해야 한다:
echo 'use flake .' > .envrc && direnv allow이제 프로젝트 디렉터리로 cd할 때마다 direnv가 자동으로 Nix 환경을 로드하고, 디렉터리를 벗어나면 언로드한다.
직접 소유하지 않은 프로젝트를 위한 개발 셸 만들기
나처럼 개발 셸을 좋아하게 되면 작업하는 모든 프로젝트에서 사용하고 싶어질 것이다.
다른 사람의 리포지토리에서 작업하는데 상대가 Nix를 전혀 도입하고 싶어 하지 않을 때는 어떻게 해야 할까?
이 상황을 처리하는 가장 쉬운 방법은 Nix flake용 전용 디렉터리를 만들고, 그 디렉터리 안의 폴더에 서드파티 리포지토리를 넣는 것이다. 예를 들면 다음과 같다:
.
├── examplerepo/ << The actual git repo
├── flake.lock
└── flake.nix이에 대해서는 “Use a Nix Flake without Adding it to Git”에서 더 자세히 설명한다.
새 의존성을 추가할 때마다 초기화는 더 느려진다
Nix 개발 환경에서 내가 발견한 가장 큰 단점은 환경 로드 시간이 느리다는 점이다. 디렉터리로 cd하는 것은 보통 밀리초 단위로 일어나는 일이지만, Nix 환경을 로드해야 하면 5~10초가 걸릴 수 있다.
더 나쁜 점은 의존성이 많아질수록 로드 시간이 더 느려진다는 것이다. Nix는 각 의존성마다 별도의 nixpkgs 인스턴스를 유지해야 하므로, 사용하고 싶은 개발 도구를 하나 추가할 때마다 디렉터리 로드 시간이라는 대가를 치러야 한다.
안타깝게도 이 문제에 대한 해결책을 찾지 못했다.
CI에서 Nix를 위한 좋은 해결책이 없다
프로젝트를 위해 독립적이고 재현 가능한 개발 환경을 만들기 위해 이 모든 작업을 하고 있으니, 당연히 코드를 지속적 통합(CI)에서 실행할 때도 이 환경을 재사용하고 싶다. 안타깝게도 CI 워크플로에 Nix를 통합하는 실용적인 방법을 찾지 못했다.
CI에서 Nix의 문제는 Nix가 자체 환경을 만드는 데 초기에 많은 작업을 해야 한다는 점이다. 내 로컬 개발 시스템에서는 Nix가 처음으로 환경을 초기화하는 데 60~180초가 걸리며, 보통 패키지 서버에서 수 기가바이트의 데이터를 다운로드한다.
느린 초기화는 로컬 시스템에서는 한 번만 일어나면 되므로 짜증나지만 견딜 만하다. CI에서는 더 큰 문제다. 원래 10초 만에 실행되던 간단한 CI 단계가 이제 Nix를 초기화하는 데 2분에, 내가 실제로 원하는 작업을 하는 데 10초가 걸리는 식으로 부풀어 오르기 때문이다.
Nix 전용 클라우드 캐시인 Cachix를 사용해 봤다. 어느 정도 도움이 됐을지도 모르지만, CI 단계당 초기 로드 시간을 90초 이하로 줄이는 방법은 찾지 못했다.
Nix를 중심으로 특별히 구축된 CI 솔루션(Garnix, Hercules, smithy)도 몇 가지 있지만, 아직 시도해 보지 않았다. 완전히 새로운 CI 시스템을 배워야 하기보다는 이미 잘 알고 있는 CircleCI 환경에서 Nix를 사용하고 싶다.
내가 바라는 기능: Nix가 언어별 의존성을 관리하는 것
Nix가 할 수 있을 것 같지만 아직 방법을 찾지 못한 것 중 하나는 언어별 의존성을 관리하는 일이다.
예를 들어 Nix로 requirements.txt 파일에 pip 의존성 목록이 있는 Python 3 프로젝트를 만든다면, Nix가 “어이, requirements.txt가 바뀌었네! 환경도 맞춰 업데이트할게.”라고 말해주면 좋겠다. Node.js와 package.json 파일도 마찬가지다. 하지만 지금까지는 Nix가 그런 파일을 모니터링하게 만드는 방법을 찾지 못했다.
poetry2nix를 본 적은 있지만, Python 프로젝트에서 Poetry를 사용하지 않아 시도해 보지는 않았다. 하지만 내가 상상하는 기능을 달성하는 방법에 대해 제안이 있는 독자가 있다면 댓글로 알려 달라.
업데이트 (2023-10-28): pyproject.nix가 일반 requirements.txt 파일을 지원한다는 것을 알게 됐다. 그래서 이제 그것을 사용하고 있다.
업데이트 (2025-01-17): pyproject.nix가 너무 혼란스러워서 사용을 중단했다. Nix 메인테이너가 Nix로 특별히 포팅한 PyPI 패키지에서만 동작하는 것 같고, 그 외의 경우에는 혼란스럽게 실패한다.
주의할 점
모든 Nix 모험이 그렇듯, Nix 개발 환경에도 주의할 점이 한둘이 아니다. 지금까지 내가 겪은 것들을 아래에 정리해 두었다.
Nix는 flake.nix가 git에 있어야 한다
Nix flake의 이상한 특징 중 하나는, flake가 git 소스 관리 하에 있는 디렉터리에 있는데 flake.nix 파일을 리포지토리에 git add하지 않았다면 다음과 같은 혼란스러운 오류가 표시된다는 점이다:
error: getting status of '/nix/store/66snibk6a9y3dbam1ww7fj0bdrh0ylw6-source/flake.nix': No such file or directory이런 일이 발생하면 git add flake.nix로 고칠 수 있다. 변경 사항을 커밋할 필요조차 없다. flake를 add하는 것만으로 충분하다.
Go: libc 링크 실패
CGO에 의존하는 내 Go 프로젝트에서 Nix 개발 환경에서 코드를 컴파일하려고 할 때 다음과 같은 오류가 발생했다:
runtime.gcdata: missing Go type information for global symbol .dynsym: size 72
runtime/cgo(.text): relocation target stderr not defined
runtime/cgo(.text): relocation target fwrite not defined
runtime/cgo(.text): relocation target vfprintf not definedGo가 내 바이너리를 libc에 링크하는 데 실패한 것으로 보인다. Zig 사용자에게 영향을 미치는 이 이슈와 유사하다.
Nix 환경의 패키지 목록에 libc와 musl을 추가해 봤지만 효과가 없었다.
링크 문제를 해결하는 유일한 방법은 Go 앱을 -tags=netgo,osusergo로 컴파일하는 것이었다. 왜 그게 통하는지는 전혀 모르겠다.
Nix 환경에서 멀티 플랫폼 Go 바이너리를 빌드하는 완전한 예시는 내 PicoShare flake와 빌드 스크립트를 참고하자.
Golang: version X does not match go tool version Y
일부 시스템에서는 빌드 스크립트를 실행할 때 이런 오류가 나타나기 시작했다:
compile: version "go1.18.4" does not match go tool version "go1.19.6"알고 보니 내 GOROOT 환경 변수가 Nix 환경 외부의 Go 컴파일러 버전을 가리키고 있었다.
빠른 해결책은 다음 명령을 실행하는 것이었다:
unset GOROOT영구적인 해결책은 시스템에서 환경 변수를 설정하는 모든 파일을 검색해 GOROOT을 설정하는 파일을 찾는 것이었다. GOROOT에 값을 할당하는 줄을 삭제한 뒤에는 시스템을 재부팅해야 했다. 새 셸을 시작하는 것만으로는 충분하지 않았다.
오래된 패키지 버전은 동작하지 않는다
특정 패키지의 오래된 버전을 시도해 봤는데, 아예 동작하지 않았다.
예를 들어 python39에 대해 nixpkgs 버전 b4e193a23a1c5d8794794e65cabf1f1135d07fd9를 선택하면 Python뿐만 아니라 shellcheck도 고장 난다:
• Updated input 'python-nixpkgs':
'github:NixOS/nixpkgs/e2b8feae8470705c3f331901ae057da3095cea10' (2023-10-03)
→ 'github:NixOS/nixpkgs/b4e193a23a1c5d8794794e65cabf1f1135d07fd9' (2021-02-19)
environment:2863: python: command not found
environment:2864: shellcheck: command not found내 추측으로는 그 정도로 오래된 nixpkgs 버전은 Nix의 새롭고 아직 공식적으로 지원되지 않는 기능인 Nix flake와의 호환성이 생기기 이전 버전이기 때문이다.
내 Nix 개발 flake 몇 가지
지금까지 내가 만든 Nix 개발 flake 몇 가지는 다음과 같다:
- PicoShare - Go 웹 앱
- mtlynch.io - Node.js 의존성이 있는 Hugo 기반 블로그
- python3_seed -
requirements.txt의존성이 있는 기본 Python 앱
참고 자료
문서화된 예제를 많이 찾지 못해 Nix 개발 환경을 동작시키는 방법을 알아내는 데 어려움을 겪었다.
마침내 Nix 환경을 이해하게 해준 것은 Attila Gulyas의 상세 가이드였다.
글을 무작위로 읽기

댓글
로그인하고 댓글 남기기