NixOS 체험기 - Python 프로그램 실행하기


요약

Nix 설치를 성공적으로 수행한 이후, 기존에 손으로 돌리던 몇몇 루틴들을 NixOS 내의 systemd 서비스로 옮기고 있다. 이번 글에서는 이전 글에서 번거롭다고 징징댔던 파이썬 프로그램 실행에 대해 다뤄보고자 한다.

Nix에 대한 오해? 진실?

본격적으로 Nix를 써보면서 몇가지 느낀 점들이 있는데, 아래와 같다.

Nix는 OS일 수도, /home일 수도, 프로젝트일 수도 있다

내 입장에선 서버에서 이것저것 하다가 날려먹거나 서버를 옮기거나 해야하는 문제가 있어서 해당 설정을 코드로 관리할 수 있다는 점 때문에 NixOS를 바로 사용하게 된 경우지만, 그 외에도 Nix를 접할 경로는 다양하다.

  1. NixOS - 컴퓨터 한대쯤 OS에서부터 제대로 관리하고 싶다면…
  2. home-manager - OS까지 건드리긴 싫지만 내가 쓰는 홈 디렉토리 정도라면…
  3. nix develop - 내가 작업하는 프로젝트 하나 안에서만 살짝 찍먹해보고 싶다면…

다만 이것들을 섞어서 쓰는건 별로였던 것 같다. 처음에는 멋모르고 그냥 NixOS와 home-manager를 둘 다 설정해서 써 봤는데, 철학상 둘이 좀 중복된다는 느낌이다. 예를 들면 NixOS 설정으로도 시스템/유저 서비스를 만들 수 있기 때문에 home-manager에서 제공하는 동일한 설정은 사실 별로…? (물론 유저 레벨에서 서비스가 돌아가야 하는 경우라면 NixOS보단 home-manager가 더 적합할 수도 있다)

Nix에서 잘할 수 있는걸 다르게 하려고 하면 피곤하다

이를테면 기존 서비스는 Docker에 말아서 컨테이너에 밀어놓고 docker-compose로 관리하고 있었는데, 같은 기능을 Nix에서 하려고 하면 영 번거롭더란 말이다. Docker 이미지 빌드하는 것도 직접 해야하는 것 같았고, docker-compose도 손으로 설정해야 하는데, 생각해보면 Nix에서 이미 서비스 빌드에 관한 여러 기능을 제공하기 때문에 굳이 이걸 다시 docker로 말아넣는게 불필요한 작업이어서 굳이 Nix에서는 손쉬운 방법을 제공하지는 않는 듯 하다는 느낌이었다. 다시 말하자면 그냥 nix에서 설정할 수 있으면 하자는 거지.

Python 코드 서비스로 정의하기

대충 코드로 설명하는게 간편할 것 같다.

{ 
  # ...
  systemd.services.crawl-lck = let
    # 파이썬 의존성들이 포함된 파이썬 실행기
    python = pkgs.python3.withPackages (ps: with ps; [ playwright gspread ]);
    # 내가 실행하고 싶은 프로젝트의 git 저장소를 바로 지정. 프로젝트 버전업 때마다 새로 빌드할 필요가 있다.
    crawl = builtins.fetchGit {
      url = "ssh://git@localhost/srv/git/crawl.git";
      # rev를 지정하지 않으면 저장소가 업데이트되어도 새로 받아오지 않는다.
      rev = "deadbeefsomehash";
    };
  in {
    enable = true;
    # 인터넷이 되야 실행할 수 있는 스크립트인 경우
    after = [ "network.target" ];
    environment = {
      # playwright에서 런타임에 쓰는 브라우저들을 지정해줘야 nix에서 설치해준다.
      PLAYWRIGHT_BROWSERS_PATH = "${pkgs.playwright-driver.browsers}";
      PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS = "true";
    };
    serviceConfig = {
      Type = "oneshot";
      WorkingDirectory = "${crawl}";
      ExecStart = "${python}/bin/python3 ${crawl}/lck_2024.py";
    };
  };
}

한마디로, 원래 pip로 관리하던 파이썬 의존성을 이제는 nix에서 관리하게 되었고 런타임 환경(원래라면 서버에서 playwright install을 한번 실행했으면 됐을 문제지만, nix는 그런 상황을 가정하지 않는다)도 nix에서 알아먹을 수 있게 지정해줘야 한다.

결론

아직은… 설정 하나하나 잡기가 느리긴 한데, 어쨌든 내가 원하던 형태에 가깝게 설정이 되고 있다.