(실패) Nix를 이용한 재사용 가능한 서버 환경 설정


개요

서버 한대 굴리다 보면 이런저런 설정 관리하고 유지보수하기가 생각만큼 쉽지 않다. 예를 들면 nginx 패키지만 깔아서 끝나는게 아니라, 거기에 Let’s encrypt 인증서 + 갱신 시스템도 설정해야 하고, 그 인증서를 nginx에 적용하는 작업을… 매번 서버 옮길 때마다 해야 한다. 나중엔 그냥 /home, /etc 전체를 통으로 백업해서 저장하지 않으면 어딘가 하나 망가져서 다시 삽질해야 하는 상황이 온다.

대안?

결국 서버 설정파일을 모두 Git 저장소 같은 곳에 관리하고 CI같은걸로 배포를 하고 싶다는 셈이다. 몇가지 후보를 생각해 봤는데, (사실은 Copilot이 맘대로 추천해줌)

  • Ansible
  • Chef
  • Puppet
  • SaltStack
  • Nix
  • Docker

내맘대로 정리하자면, Docker는 그냥 Dockerfile에 전체 서버설정을 때려넣은 새 서버를 띄우는 셈이고,

Ansible, Chef, Puppet, SaltStack은 거기에 조금 템플릿 얹어서 설정을 조금 더 쉽게 해놓은 정도…? (사실 이것들은 깊게 연구하지 않아서 더 말을 얹기 힘들다)

그리고 Nix는 여기서 설정을 위한 전용 언어를 만들어서 설정을 생성해내는… 정도라고 해야 하나?

여튼 이번에 Nix를 하나 붙잡고 어떻게든 해 보기로 해 봤다.

그래서, Nix는 어떤데?

간단히 말해서, nix는 nixpkg라고 패키지 저장소를 제공하고, 여기서 빌드를 최대한 쪼개놓았다. nginx 바이너리를 제공하는 패키지가 있고, nginx.conf 파일을 생성하는 별도의 코드가 있어서 여기다가 파라미터를 주입하면 nginx.conf가 생성되는 거라고 이해했다. 참고자료

일단 뭐가 어찌됐든 간단하게라도 nginx.conf를 생성해보기로 맘먹었는데, 근접하게라도 동작한 방법은 다음과 같다:

{pkgs, ...}:
{
  fileSystems."/" = { device = "/mnt"; fsType = "none"; };
  boot.loader.grub.enable = false;

  security.acme.acceptTerms = true;
  security.acme.defaults.email = "admin@example.com";

  services.nginx.enable = true;

  services.nginx.virtualHosts."survived.today" = {
    addSSL = true;
    enableACME = true;
    root = "/var/www/survived.today";
  };

  environment.systemPackages = [ pkgs.nginx ];

  users.extraUsers.user = {
    isNormalUser = true;
    password = "test";
    createHome = true;
    group = "wheel";
  };
}
$ NIXOS_CONFIG=`pwd`/nginx.nix nixos-rebuild build-vm

요렇게 한 다음에 생성된 vm을 실행하고 /etc/systemd/system/nginx.service 파일을 참조해서 설정 파일을 확인해봤는데…

결론

문제는… 설정파일 곳곳에 /nix/store/… 같은 참조가 잔뜩 있어서 밖으로 복사할 수 없는 구조로 만들어졌더라는 것이다. ㅠㅠ 시스템 자체가 NixOS라는 OS에 집중하고 있기 때문에 서버에서 ubuntu를 쓰는 내 입장에선 그대로 사용할 수 없기 때문에 설정파일만 쏙 빼서 쓰려고 했던 계획 자체가 망해버렸다… OTL

하지만

NixOS를 직접 쓰거나, NixOS의 관련 코드만 뽑아다가 설정 파일을 생성해내도록 하면 어떻게 더 비벼볼 구석이 있지 않을까? 하지만 이쯤 되니 그냥 서버에서 손으로 관리하는 nginx.conf 설정파일이 사실 아직 쪼끄만하고 관리할 만 하다는 느낌…은 아니고 그냥 타협하기로 해버렸다.