diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..f000dbe --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,625 @@ +# 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 "" +```