NixOS에서 Clash 계열 첫 구성: flake·home-manager·systemd --user (2026)

NixOS·Mihomo(Clash Meta)·flake·home-manager로 검색해 들어오면 보통 “일반 Linux 튜토리얼이 안 통한다”는 감각으로 시작합니다. Ubuntu·Debian·Arch에선 apt·dnf·pacman이 바이너리를 /usr에 풀어 두지만, Nix는 대부분의 프로그램이 /nix/store/… 아래 불변(immutable) 해시 경로에 놓이고, 시스템은 configuration.nix·home.nix 같은 선언적 구성을 빌드해 반영하는 구조입니다. 이 글은 Debian 12·Arch 글과 겹치지 않게, 구독(Subscription) 가져오기·systemd --user 자동 기동·Nix 패키지 쪽 주의만 한 축으로 묶습니다. 전체 프록시 생태는 Clash 생태계 글을 함께 보는 것이 좋습니다.

① NixOS에서 Clash/미호모(Mihomo)를 다루는 전제: 선언과 스토어

NixOS는 “한 번 설치해둔 경로에 실행 파일이 영원히 그대로”가 아닙니다. 채널이나 flake를 바꾸고 nixos-rebuild switch를 돌리면, 같은 도구도 다른 스토어 경로로 갈아끼우는 식이 일상입니다. Clash 호환 코어는 보통 Clash Meta / Mihomo 이름으로 커뮤니티 Nix 패키지·오버레이·모듈에 올라와 있고, GUI(예: Clash Verge)는 배포·버전·래핑(wrapping)이 저장소마다 달라 “우분투에선 되는데 Nix에선 막힌다”는 질문이 잦습니다. 그래서 첫 목표코어 바이너리를 재현 가능한 방식으로 넣는 것과, 구독·YAML이 들어갈 홈(또는 지정) 디렉터리home-manager로 고정하는 것으로 쪼개는 편이 낫습니다. 이후 systemd 사용자 유닛은 그 고정된 경로ExecStart=에만 맞추면 합니다.

보안·업데이트 측면에서도 “수동으로 curl | bash로 받은 단일 바이너리”는 Nix 철학과 잘 맞지 않을 때가 많습니다. flake·nixpkgs·비공식 오버레이로 추적한 패키지가 같은 머신에서 재빌드·롤백·프로필 전환에 유리하다는 점을 먼저 떠올리면 이후 이슈가 줄어듭니다.

② Flake, inputs, nixos-rebuild: 흐름만 짚기

Flake를 쓰는 구성이면, 저장소 루트 flake.nixinputsnixpkgs·(선택) home-manager를 고정하고, outputs에서 NixOS 시스템과 home-manager 설정을 엮습니다. 채널만 쓰는 전통 방식이면 sudo nix-channel --updatesudo nixos-rebuild switch 흐름이 익숙하겠지만, 공식·커뮤니티 자료는 최근 flake 중심 예제가 늘었습니다. 어느 쪽이든 같은 사실은, “구성 파일을 바꾼 뒤 반드시 rebuild·home-manager switch를 한 번 켜 주어야 반영된다”는 점입니다. 임시로 nix run nixpkgs#mihomo처럼 띄워 보는 것은 괜찮지만, 부팅 후 자동 기동까지 가려면 아래 home 쪽 선언과 짝이 맞아야 합니다.

버전 핀(pin)을 바꾸지 않는 한 /nix/store/…-mihomo-…/bin/mihomo 경로는 예측이 어렵기 때문에, 서비스 유닛에는 가능하면 pkgs.mihomo에 대한 심볼릭이나 래퍼를 두고, 래퍼는 ~/.config/mihomo/ 같은 고정된 설정 디렉터리WorkingDirectory=에 묶는 패턴이 안전합니다. (실제 Nix 식·모듈 이름은 nixpkgs 버전에 따르므로, 배포한 세대에 맞춰 nix search nixpkgs mihomo·매뉴얼을 짧게 확인하세요.)

③ Nix 패키지로 코어(mihomo 등) 쓰기: 검색·이름·대안

커뮤니티 오버레이 없이 nixpkgs에 들어온 Mihomo·clash-meta 계열이 있다면, 시스템 environment.systemPackages에 넣거나 home-managerhome.packages에만 올려도 에서 which mihomo로 확인이 가능합니다. 없는 경우 flake로 비공식 입력을 끌어오거나, 자체 derivation을 한 번 씁니다. 이때 라이선스·소스·빌드를 직접 읽는 습관이 중요합니다. Clash 계열 코어GPL·상용 서비스 링크·국가별 사용 규정을 사용자가 점검하는 전제가 있으며, 이 글은 법률·공급자 선택을 대신 판정하지 않습니다. 기술적으로는 바이너리 하나/nix/store에 넣었을 때, 그 다음 구독(Subscription) URL로 받은 config.yaml·프로필이 어느 경로를 읽는지를 맞추는 데 집중합니다.

그래픽 클라이언트(예: Clash Verge)Nix로 쓰려면, nixpkgs에 있는지, NUR·flake 입력에 있는지를 먼저 찾고, Wayland·libayatana 의존성 같은 데스크톱 조합을 확인합니다. 빌드가 실패하면 순수 코어 + 웹/CLI로 내려가 규칙만 돌리는 전략도 흔합니다. 분류(rules)·DNS 개념을 한 번에 잡고 싶다면 프록시 그룹 가이드TUN 모드 글의 점검 순서를 참고하세요. 둘 다 배포판을 가리지 않습니다.

④ home-manager: 설정 경로, 구독, 재현 가능한 홈

home-manager사용자 범위에서 ~ 아래 점 파일·systemd --user 유닛·환경 변수를 선언합니다. Clash/Mihomo는 보통 ~/.config/mihomo/·~/.config/clash/ 계열에 config.yaml·Country.mmdb·(선택) GeoIP 자료를 둡니다. 구독(Subscription) 가져오기는 (1) 앱/코어에 URL을 직접 넣어 자동 갱신하거나, (2) CI·쉘로 주기적 fetch 후 홈에 복사하는 식인데, Nix에선 (2)를 home.file·외부 시크릿으로 묶는 예도 있습니다. 민감한 구독 URL을 저장소에 커밋하지 않도록, sops-nix·age·--impure 로컬 override 같은 패턴만 “안전에 대한 주의”로 짚어 둡니다. 자세한 URL 이슈는 구독 링크 FAQ를 병행하세요. OS·클라이언트에 공통으로 나오는 질문과 요청 제한·User-Agent 힌트가 정리돼 있습니다.

home-managersystemd.user.services를 선언하면, 아래 ⑤와 같은 unit~/.config/systemd/user/ 쪽에 생성되고, systemctl --user daemon-reload·enable --now로 켤 수 있습니다. “그래픽이 없는 서버에서만 코어를 돌린다”면 default.target만으로도 때로 충분하지만, 데스크톱이면 ⑥처럼 graphical session 이후에 맞추는 편이 낫습니다. 한 번 수동으로 ExecStart에 스토어 절대 경로를 박아 넣고 나면, 다음 nix 업그레이드에서 깨질 수 있음을 꼭 기억하세요. 지속하려면 wrap-run 스크립트home.file에 두고 그 스크립트를 ExecStart=에 적거나, pkgs.writeShellScriptderivation에 싣는 쪽이 유지보수에 유리합니다.

💡 한 줄 요약 고정해야 할 것은 “어느 구독이 어느 config.yaml에 매핑되는가”이고, 변동하는 것은 /nix/store/…/bin/… 본체 경로입니다. 스크립트 한 겹으로 감싸 WorkingDirectory + 설정 파일만 안정시키면, systemd 유닛은 훨씬 덜 꼬입니다.

⑤ systemd --user: Mihomo(Clash) 코어 서비스 예시

아래는 개념스켈레톤입니다. 실제 User=·Group=·CapabilityBoundingSet=·AmbientCapabilities=·RestrictAddressFamilies= 등은 환경(셀프호스트·VPS·랩탑)마다 달리며, TUN·NET_ADMIN이 필요한지 여부는 TUN 문서의 모델과 맞춰야 합니다. 프로덕션 하드닝은 systemd 매뉴얼·NixOS 위키 “hard” 예제를 따로 보세요. 영어/숫자 식은 그대로 두었습니다.

[Unit]
Description=mihomo (user) — Clash/Meta compatible core
After=graphical-session-pre.target
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
# Replace with a stable wrapper in $HOME, not a raw /nix/store/... that changes every upgrade
ExecStart=%h/.local/bin/mihomo-user-wrapper run -d %h/.config/mihomo
WorkingDirectory=%h/.config/mihomo
Restart=on-failure
RestartSec=3

[Install]
WantedBy=default.target

mihomo-user-wrapper는 (예시) PATHpkgs.mihomo·필수 lib를 싣는 용도입니다. 로그journalctl --user -u mihomo.service -e로, “실행 파일 없음”, “설정 없음”, “포트 점유”를 나눕니다. 로그인 없이 항상 떠 있게 하려면 linger(loginctl enable-linger USERNAME)와 정책·보안을 다시 봅니다. 일반 데스크톱 사후 대응엔 linger가 과할 때가 많습니다.

그래픽 Clash Verge 류를 user unit에 올릴 때는 DISPLAY·WAYLAND_DISPLAY·XDG_RUNTIME_DIR 전달이 이슈인 경우가 있어, Ubuntu Verge + systemd 글의 “그래픽 세션 이후” 힌트를 함께 읽는 편이 낫습니다. 발행판은 다르지만 사용자 서비스의 막힘(환경)은 겹칩니다.

⑥ 권한, TUN, NixOS 모듈: 왜 “그냥 켰는데” 안 뜨나

TUN·Meta 스택은 커널 모듈·/dev/net/tun·capabilities·namespaced 라우팅이 한꺼번에 얽힙니다. 일반 Linux 튜토리얼이 “sudo만 하면 끝”인 반면, NixOS에선 security.wrappers·boot.kernelModules·서드파티 module이 필요한 경우가 있습니다. 클라이언트EPERM을 내면, “앱 권한” 이전에 unit·setcap·group·DynamicUser= 제약을 의심합니다. 한 번 시스템 범위로 돌릴지·사용자로만 둘지에 따라 정책이 갈리므로, 랩톱 단일 유저면 ⑤·그래픽 자동 기동 조합이 흔하고, 헤드리스rootless 컨테이너·root 서비스를 비교합니다.

방화벽·nftables 체인nixos options로 선언한 값과 (만약) clash자체 iptables를 쓰는지 충돌이 없는지 살핍니다. “노드는 살아 있는데 웹만 안 열린다”는 보통 DNS·fake-ip·DoH 순서 문제로 이어집니다. 분류(rules) 규칙입문 튜토리얼의 “모드(규칙/글로벌 등)” 흐름을 맞춰 주세요. 기본 Linux 데스크톱 경험은 Debian 12·Arch와 동일한 “우선 한 축(시스템 프록시 또는 TUN) 정하기”가 유효합니다. 동시을 켜 이중 경로를 만들면, 의심할 목록이 길어집니다.

⑦ 트러블슈팅: 스토어 갱신 이후, 구독, DNS

rebuild 직후 서비스가 죽었다면, ExecStart가 여전히 올바른 래퍼를 가리키는지, pkgs 경로가 빠지지 않았는지 1) 확인합니다. 2) 구독이 갱신돼 노드 풀은 찼는데 지연/선택 그룹이 빈 것처럼 보이는지(프로필 혼동). 3) DNS가 로컬 스텁클라이언트가 충돌하지 않는지. 4) 이중 VPN·다른 프록시 데몬포트가 겹치지 않는지. 5) ~/.config/… 권한너무 열려 자동 백업 스크립트에 걸리지는 않는지(개인 운용 범주). 6) 하드닝·SELinux급NixOS엔 희귀하지만, Flatpak·스냅 샌드박스 뒤의 앱이 호스트 프록시를 못 쓰는지 점검합니다.

문제를 한 번에 여러 갈래로 “동시에” 만지다 보면 원인이 흐려집니다. journalctl 한 줄, 앱 로그 한 줄, ss -tlnp리슨 포트 한 번 — 이렇게 레이어를 나누는 습관이 선언적 OS에서도 동일합니다. 로컬 미러·git 프록시까지 같이 쓰는 하이브리드 환경이면, WSL2·Docker Desktop 글의 “호스트/게스트 DNS” 구분 힌트가 부분적으로 겹칩니다.

⑧ 정리: flake·home·systemd를 한 루프로

NixOS에서 Clash 호환 스택을 쓰려면, 배포판별 패키지 매니저 튜토리얼의 명령을 그대로 옮기기보다, Nix 패키지·/nix/store·rebuild 루프에 맞춰 구독(Subscription) 가져오기systemd --user같은 구성 안에 둡니다. home-manageruser unit을 묶고, flake로 입력·버전을 박제하면, 롤백·재현·공유 측면에서 우분투식 수동 바이너리 복사보다 운이 덜 꼬이는 경우가 많습니다. 반대로, “한방에 GUI까지”를 같은 flake에 억지로 넣다 빌드깨질 때는, 코어만 먼저 안정시키는 편이 낫습니다. 비교·선택이 필요할 때 Clash vs VPN도 참고하세요. 여러 클라이언트 중 어떤 바이너리를 고를지는 다운로드 페이지에서 환경에 맞게 고르는 흐름이 자연스럽습니다. 상용 앱에 가려진 규칙·DNS를 손에 익혀 두면, Nix에 옮겨도 같은 진단 루틴이 그대로 통합니다. → Clash를 무료로 내려받고, NixOS에서도 선언적 구성과 맞는 첫 프록시 루프를 잡아 보세요.