# NixOS Homelab Install Guide 이 문서는 `yggdrasil`, `midgard`를 NixOS installer USB에서 부팅한 뒤 이 repo를 source of truth로 사용해 최초 설치하는 절차를 설명한다. 기본 원칙: - 최초 설치는 NixOS installer USB 환경에 `root`로 SSH 접속해서 진행한다. - 설치 후 운영은 `poby` 사용자와 SSH key로 접속한다. - 대상 머신에서 설정 파일을 직접 고치지 않는다. - 대상 머신은 디스크 ID와 하드웨어 정보를 조회하는 용도로만 사용한다. - 실제 설정 변경은 항상 이 Git repo에서 한다. - `disko`는 대상 디스크를 재파티션/포맷한다. 디스크 선택을 반드시 확인한다. ## 현재 repo 상태 이 repo는 두 호스트를 가진 flake로 구성된다. ```text yggdrasil midgard ``` 공통 설정은 `modules/`에 있고, 호스트별 설정은 `hosts//`에 있다. 설치 전에 반드시 채워야 하는 파일: ```text hosts/yggdrasil/disko.nix hosts/yggdrasil/hardware-configuration.nix hosts/yggdrasil/default.nix hosts/midgard/disko.nix hosts/midgard/hardware-configuration.nix hosts/midgard/default.nix ``` 현재 `hosts//default.nix`의 imports는 의도적으로 주석 처리되어 있다. ```nix # imports = [ # ./hardware-configuration.nix # ./disko.nix # ]; ``` 각 호스트의 disk by-id와 hardware configuration을 채운 뒤에만 이 imports를 활성화한다. ## 설치 전 준비 워크스테이션에서 확인한다. ```bash cd /Users/kmeatai/Developer/homelab git status -sb ``` 작업트리가 깨끗한 상태에서 시작하는 것을 권장한다. 필요한 것: - Nix가 설치된 워크스테이션 - 이 repo - NixOS installer USB - 대상 머신의 유선 또는 안정적인 무선 네트워크 - `poby`로 접속할 SSH private key - 대상 머신의 기존 데이터 백업 주의: - 이 절차는 대상 머신 디스크를 지운다. - yggdrasil을 먼저 설치하고 검증한 뒤 midgard를 설치한다. - 동시에 두 머신을 진행하지 않는다. ## 1. 대상 머신을 installer USB로 부팅 먼저 `yggdrasil`부터 진행한다. 대상 머신에 NixOS installer USB를 꽂고 부팅한다. installer shell이 뜨면 대상 머신 콘솔에서 root 비밀번호를 임시로 설정한다. ```bash sudo passwd root ``` 이 비밀번호는 installer live environment에서만 쓰는 임시 비밀번호다. 설치 후 재부팅하면 최종 NixOS 설정이 적용되고 root SSH login은 비활성화된다. SSH 서버를 시작한다. ```bash sudo systemctl start sshd ``` 대상 머신의 IP 주소를 확인한다. ```bash ip addr ``` LAN IP를 기록한다. ```text ``` ## 2. 워크스테이션에서 installer에 SSH 접속 확인 워크스테이션에서 접속한다. ```bash ssh root@ ``` 접속되면 installer 환경 안에 들어온 것이다. 프롬프트가 헷갈리면 다음 명령으로 현재 머신을 확인한다. ```bash hostname cat /etc/os-release ``` 확인 후 SSH 세션은 열어둬도 되고, 필요한 명령만 실행한 뒤 나와도 된다. ```bash exit ``` ## 3. disk by-id 확인 대상 머신 installer shell에서 실행한다. ```bash lsblk -o NAME,SIZE,MODEL,SERIAL,TYPE ls -l /dev/disk/by-id/ ``` 또는 워크스테이션에서 SSH로 직접 실행해도 된다. ```bash ssh root@ 'lsblk -o NAME,SIZE,MODEL,SERIAL,TYPE; ls -l /dev/disk/by-id/' ``` 목표는 설치할 내부 디스크의 안정적인 by-id 경로를 찾는 것이다. 예시: ```text /dev/disk/by-id/ata-Samsung_SSD_860_EVO_250GB_S3Z... /dev/disk/by-id/nvme-Samsung_SSD_970_EVO_... ``` 사용하지 말아야 할 값: ```text /dev/sda /dev/nvme0n1 ``` 이 이름들은 부팅 순서나 USB 장치에 따라 바뀔 수 있다. 주의: - USB installer 자체를 대상 디스크로 고르면 안 된다. - 크기, 모델명, serial을 보고 내부 디스크인지 확인한다. - 확신이 없으면 여기서 멈추고 다시 확인한다. ## 4. disko.nix의 placeholder 교체 워크스테이션의 repo에서 `hosts/yggdrasil/disko.nix`를 연다. 현재는 이런 placeholder가 있다. ```nix device = "/dev/disk/by-id/REPLACE_WITH_YGGDRASIL_DISK_ID"; ``` installer에서 확인한 실제 by-id 경로로 교체한다. 예시: ```nix device = "/dev/disk/by-id/ata-Samsung_SSD_860_EVO_250GB_S3Z..."; ``` 이 파일은 다음 레이아웃을 만든다. ```text GPT partition table 512M EFI System Partition -> /boot, vfat remaining disk -> /, ext4 ``` 이 단계는 아직 설치를 실행하지 않는다. 파일만 수정한다. ## 5. hardware-configuration.nix 생성 대상 머신 installer shell에서 실행한다. ```bash nixos-generate-config --show-hardware-config ``` 출력 전체를 복사해서 워크스테이션 repo의 파일에 붙여 넣는다. ```text hosts/yggdrasil/hardware-configuration.nix ``` 기존 placeholder 전체를 생성된 내용으로 교체한다. 워크스테이션에서 바로 파일로 저장하려면 다음처럼 해도 된다. ```bash ssh root@ \ 'nixos-generate-config --show-hardware-config' \ > hosts/yggdrasil/hardware-configuration.nix ``` 주의: - `hardware-configuration.nix`는 대상 머신에서 생성한 값을 사용한다. - yggdrasil에서 생성한 파일을 midgard에 재사용하지 않는다. - disko가 `/`와 `/boot` 파일시스템을 선언하므로 생성된 hardware config를 그대로 믿지 말고 검토한다. `hardware-configuration.nix`에는 보통 이런 내용이 남으면 된다. ```nix imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; boot.initrd.availableKernelModules = [ ... ]; boot.initrd.kernelModules = [ ... ]; boot.kernelModules = [ ... ]; boot.extraModulePackages = [ ... ]; nixpkgs.hostPlatform = "x86_64-linux"; hardware.cpu.intel.updateMicrocode = ...; hardware.cpu.amd.updateMicrocode = ...; ``` 다음 항목은 `disko.nix`와 중복되거나 installer/live 환경의 값일 수 있으므로 특히 확인한다. ```nix fileSystems."/" fileSystems."/boot" swapDevices ``` 이 repo에서는 `/`와 `/boot`는 `disko.nix`가 담당한다. swap은 `modules/swap.nix`의 zram swap이 담당한다. 따라서 hardware config에 위 항목이 들어 있다면 왜 필요한지 확실할 때만 남긴다. ## 6. host default.nix imports 활성화 워크스테이션 repo에서 `hosts/yggdrasil/default.nix`를 연다. 주석 처리된 imports를 활성화한다. 변경 전: ```nix # imports = [ # ./hardware-configuration.nix # ./disko.nix # ]; ``` 변경 후: ```nix imports = [ ./hardware-configuration.nix ./disko.nix ]; ``` 이제 `yggdrasil` flake config가 실제 하드웨어 설정과 디스크 레이아웃을 포함한다. ## 7. 설치 전 로컬 검토 워크스테이션에서 변경 사항을 확인한다. ```bash git diff -- hosts/yggdrasil ``` 특히 다음을 확인한다. ```text hosts/yggdrasil/disko.nix device가 실제 내부 디스크 by-id인지 hosts/yggdrasil/hardware-configuration.nix yggdrasil installer에서 생성한 내용인지 hosts/yggdrasil/default.nix imports가 활성화되었는지 ``` Nix 문법만 가볍게 확인할 수 있다. ```bash nix-instantiate --parse hosts/yggdrasil/default.nix >/dev/null nix-instantiate --parse hosts/yggdrasil/disko.nix >/dev/null nix-instantiate --parse hosts/yggdrasil/hardware-configuration.nix >/dev/null ``` `flake.lock`이 아직 없다면 이후 flake 평가 또는 설치 과정에서 생성될 수 있다. 생성되면 설치 성공 후 함께 커밋한다. ## 8. nixos-anywhere 실행 워크스테이션에서 실행한다. ```bash nix run github:nix-community/nixos-anywhere -- \ --flake .#yggdrasil \ root@ ``` 워크스테이션의 Nix에서 flakes가 꺼져 있다는 에러가 나면 같은 명령에 experimental features를 명시한다. ```bash nix --extra-experimental-features "nix-command flakes" \ run github:nix-community/nixos-anywhere -- \ --flake .#yggdrasil \ root@ ``` 이 명령은 대상 머신에 SSH로 접속해서 다음을 수행한다. ```text disko 기반 파티션/포맷 NixOS system closure 복사/설치 bootloader 설치 초기 NixOS 설정 적용 ``` 중요: - 이 단계에서 대상 디스크의 기존 데이터는 삭제된다. - 실행 전 disk by-id를 다시 확인한다. - 설치 중 에러가 나면 출력 내용을 저장하고 다음 단계로 진행하지 않는다. ## 9. 설치 후 재부팅과 SSH 확인 설치가 끝나면 대상 머신을 재부팅한다. USB installer를 제거하고 내부 디스크로 부팅한다. 부팅 후 워크스테이션에서 SSH 접속을 확인한다. LAN IP 또는 hostname이 잡혀 있으면: ```bash ssh poby@yggdrasil ``` IP로 먼저 확인해도 된다. ```bash ssh poby@ ``` root SSH 접속은 실패해야 정상이다. ```bash ssh root@yggdrasil ``` password SSH login도 실패해야 정상이다. 접속 후 기본 상태를 확인한다. ```bash hostname sudo systemctl status sshd sudo systemctl status tailscaled zramctl free -h df -h ``` ## 10. Tailscale 로그인 설치 후 `poby`로 접속한 상태에서 Tailscale을 tailnet에 붙인다. ```bash sudo tailscale up ``` 브라우저 인증 URL이 나오면 인증한다. 인증 후 상태를 확인한다. ```bash tailscale status tailscale ip ``` 이후에는 Tailscale IP 또는 MagicDNS 이름으로 SSH 접속할 수 있다. ```bash ssh poby@yggdrasil ``` ## 11. 첫 remote rebuild 테스트 워크스테이션에서 실행한다. 워크스테이션이 macOS일 수 있으므로 build도 Linux 대상 머신에서 수행하도록 `--build-host`를 명시한다. `poby`는 `wheel`이고 Nix trusted user에 포함되므로 remote build와 remote switch에 사용할 수 있다. ```bash nix run github:NixOS/nixpkgs/nixos-25.11#nixos-rebuild -- \ test \ --flake .#yggdrasil \ --build-host poby@yggdrasil \ --target-host poby@yggdrasil \ --use-remote-sudo ``` 문제가 없으면 switch를 실행한다. ```bash nix run github:NixOS/nixpkgs/nixos-25.11#nixos-rebuild -- \ switch \ --flake .#yggdrasil \ --build-host poby@yggdrasil \ --target-host poby@yggdrasil \ --use-remote-sudo ``` 이 방식이 설치 이후의 기본 운영 모델이다. ```text repo 수정 nixos-rebuild test 또는 nix run ...#nixos-rebuild -- test nixos-rebuild switch 또는 nix run ...#nixos-rebuild -- switch git commit ``` ## 12. yggdrasil 변경사항 커밋 설치가 성공하면 워크스테이션에서 변경사항을 확인한다. ```bash git status -sb git diff -- hosts/yggdrasil flake.lock ``` 커밋한다. ```bash git add hosts/yggdrasil if [ -f flake.lock ]; then git add flake.lock; fi git commit -m "configure yggdrasil hardware" ``` ## 13. midgard 설치 yggdrasil 설치와 검증이 끝난 뒤 midgard를 같은 방식으로 진행한다. 반복할 파일: ```text hosts/midgard/disko.nix hosts/midgard/hardware-configuration.nix hosts/midgard/default.nix ``` 반복할 명령: ```bash sudo passwd root sudo systemctl start sshd ip addr lsblk -o NAME,SIZE,MODEL,SERIAL,TYPE ls -l /dev/disk/by-id/ nixos-generate-config --show-hardware-config ``` 워크스테이션에서 설치: ```bash nix run github:nix-community/nixos-anywhere -- \ --flake .#midgard \ root@ ``` 설치 후 확인: ```bash ssh poby@midgard sudo tailscale up tailscale status zramctl df -h ``` remote rebuild 테스트: ```bash nix run github:NixOS/nixpkgs/nixos-25.11#nixos-rebuild -- \ test \ --flake .#midgard \ --build-host poby@midgard \ --target-host poby@midgard \ --use-remote-sudo ``` 성공하면: ```bash nix run github:NixOS/nixpkgs/nixos-25.11#nixos-rebuild -- \ switch \ --flake .#midgard \ --build-host poby@midgard \ --target-host poby@midgard \ --use-remote-sudo ``` 커밋: ```bash git add hosts/midgard if [ -f flake.lock ]; then git add flake.lock; fi git commit -m "configure midgard hardware" ``` ## 14. 설치 후 기본 검증 체크리스트 각 호스트에서 확인한다. ```bash hostname whoami groups sudo -n true systemctl is-active sshd systemctl is-active tailscaled tailscale status zramctl free -h df -h bootctl status ``` 기대값: ```text whoami -> poby groups -> wheel, networkmanager 포함 sudo -n true -> 비밀번호 없이 성공 sshd -> active tailscaled -> active zramctl -> zram device 표시 /boot -> vfat EFI partition / -> ext4 root filesystem ``` 워크스테이션에서 확인한다. ```bash ssh poby@yggdrasil ssh poby@midgard ``` root SSH는 실패해야 한다. ```bash ssh root@yggdrasil ssh root@midgard ``` ## 15. 롤백 기본 NixOS 설정 변경 후 문제가 생기면 대상 머신에서 이전 generation으로 되돌릴 수 있다. ```bash sudo nixos-rebuild switch --rollback ``` 부팅 자체가 실패하면 부팅 메뉴에서 이전 generation을 선택한다. ## 16. 다음 단계 두 머신의 base install이 끝난 뒤에만 다음을 진행한다. ```text sops-nix 실제 secrets 구성 backup 구성 monitoring 구성 Podman 구성 Caddy / DNS / apps ``` 서비스는 하나씩 추가하고, 각 단계마다 다음을 반복한다. ```bash nix run github:NixOS/nixpkgs/nixos-25.11#nixos-rebuild -- \ test \ --flake .# \ --build-host poby@ \ --target-host poby@ \ --use-remote-sudo nix run github:NixOS/nixpkgs/nixos-25.11#nixos-rebuild -- \ switch \ --flake .# \ --build-host poby@ \ --target-host poby@ \ --use-remote-sudo git add . git commit -m "" ```