# NixOS Homelab Mini PC Jan 5, 2025 ![[f31b95a50a6f8e7e7e44eab90d9700c314d8f157a3dad29d809f7788ca93e27a58eb06b65ed80c021afc9a1dbe103d4bfd55b01e55c8b650f944ab930b651905.png|300]] Setting up a GMKtec NucBox G5 with NixOS for a home lab environment. ## Hardware Overview The NucBox G5 features Intel's N97 processor, offering an excellent balance of performance and efficiency for homelab use. ### Core Components - Intel N97 (12th Gen Alder Lake): 4C/4T up to 3.6GHz - 12GB LPDDR5 @ 4800MT/s - 512GB M.2 SATA SSD - Intel UHD Graphics (24 EUs @ 1.2GHz) ### Connectivity - 2x USB 3.2 Gen 2 Type-A - USB-C (power + display) - HDMI 2.0 (4K@60Hz) - Gigabit Ethernet - WiFi 6 (Intel AX201) + BT 5.2 ### Physical Specs - Size: 72 x 72 x 44.5mm - Weight: 168g - VESA mountable ## Performance ### N97 vs N100 The N97 outperforms the N100 with: - 1.2GHz vs 750MHz GPU clock - 12W vs 6W TDP - Better sustained performance ### Power & Thermal - Power: 12V 3A (36W) Type-C - TDP: 8-15W (12W optimal) - Fan: 1800-5000 RPM - Load temps: ~80°C - Noise: Minimal to noticeable, but not disruptive ## Installation ### BIOS Setup ``` Power & Performance: - Power Limit: 15W - GT frequency: 1200MHz - Load Optimized Defaults (F3) Boot: - Secure Boot: Disabled - Boot Mode: UEFI ``` ### NixOS Installation 1. Create bootable USB: ```bash dd if=nix.iso of=/dev/sdX bs=4M status=progress ``` 2. Boot sequence: - Power on - F7 within 3s - Select USB 3. Partition disk: ```bash sudo -s fdisk /dev/sda # Create GPT layout g # Boot partition (500MB) n, 1, {ENTER}, +500M, t, 1 # Swap (4GB) n, 2, {ENTER}, +4096M, t, 19 # Root partition n, 3, {ENTER}, {ENTER} w ``` 4. Format partitions: ```bash mkfs.fat /dev/sda1 mkswap /dev/sda2 && swapon /dev/sda2 mkfs.ext4 /dev/sda3 ``` 5. Mount and generate config: ```bash mount /dev/sda3 /mnt mkdir /mnt/boot mount /dev/sda1 /mnt/boot nixos-generate-config --root /mnt/ ``` 6. Configure wireless networking: ```nix networking = { networkmanager.enable = true; wireless.enable = false; wireless.networks."YOUR_WIFI_NAME" = { psk = "YOUR_WIFI_PASSWORD"; }; interfaces.wlp1s0 = { useDHCP = false; ipv4.addresses = [{ address = "192.168.1.100"; prefixLength = 24; }]; }; defaultGateway = "192.168.1.1"; nameservers = [ "8.8.8.8" "8.8.4.4" ]; }; ``` 7. Install and configure: ```bash nixos-install # Set root password when prompted reboot # After reboot chmod -R 700 /boot nmcli device wifi connect "YOUR_WIFI_NAME" password "YOUR_PASSWORD" ``` 8. Basic system config: ```nix networking.hostName = "hl-ldn-c1-h1"; networking.networkmanager.enable = true; time.timeZone = "Europe/London"; services.openssh = { enable = true; settings = { PasswordAuthentication = true; KbdInteractiveAuthentication = false; PermitRootLogin = "yes"; }; }; systemd.services.NetworkManager = { enable = true; wantedBy = [ "multi-user.target" ]; }; systemd.services.dmesg-persist = { description = "Persist dmesg output"; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "oneshot"; ExecStart = "${pkgs.util-linux}/bin/dmesg -D"; RemainAfterExit = true; }; }; ``` 9. Apply changes: ```bash nixos-rebuild switch ``` **Tips** - Backup BIOS settings before changes - USB boot issues? Reconnect after setting 15W TDP - The N97 plays nice with Linux - expect smooth sailing I've setup a new private repository `name/nix` where I'll keep my various nixOS configurations going forward: ![[c43e67c556348683fa5a89f9c3e4da8644684ca132f3e927cda655e92c8a1a0dc1e5edf628fc9c9c4bdcf86cd44e26204da8272dc4b5f830679badcba952b2d1.png]] ### Stats A quick btop output post-setup: ![[95c6cb1ad95333ceb196d3bd2811f95d0991d45c36cf1790a0ccbb654dbe09d031504b36009d93fe85651c5e60f8a722f27331bd01d0cfa4ee3a45d520942ec0.png]] ## Patching VSCode support (Following [nix-community/nixos-vscode-server](https://github.com/nix-community/nixos-vscode-server)) 1. Install as a tarball: ```nix { imports = [ (fetchTarball "https://github.com/nix-community/nixos-vscode-server/tarball/master") ]; services.vscode-server.enable = true; } ``` 2. Apply changes: ```bash nixos-rebuild switch ``` 3. Enable the service: ```bash systemctl --user enable auto-fix-vscode-server.service ``` 4. Start the service (or reboot): ```bash systemctl --user start auto-fix-vscode-server.service ``` 5. Additional symlink to workaround garbage collection: ```bash ln -sfT /run/current-system/etc/systemd/user/auto-fix-vscode-server.service ~/.config/systemd/user/auto-fix-vscode-server.service ``` 6. Test VSCode Remote Explorer: ![[49705a5eaa9c433f2ee8aa064be44658b2420330a7b905ec6c1df9721a32eadfdc9c5adc6844fbab6736def09c0f810dd718becef6a559175b92b87357a722d4.png]] ## Setup a new user account 1. Configure a new user account: ```nix users.users.ops = { isNormalUser = true; extraGroups = [ "wheel" ]; openssh.authorizedKeys.keys = [ "ssh-rsa ........== char@rack" ]; }; ``` 2. Rebuild configuration: ```bash nixos-rebuild switch ``` 3. Set a password for the new account: ```bash passwd ops ``` 4. Update SSH configuration: ```nix services.openssh = { enable = true; settings = { PasswordAuthentication = false; KbdInteractiveAuthentication = false; PermitRootLogin = "yes"; }; }; ``` 5. Rebuild configuration: ```bash nixos-rebuild switch ``` I'd recommend the VSCode ['save-as-root'](https://marketplace.visualstudio.com/items?itemName=yy0931.save-as-root) extension for saving protected files while SSH'd under your normal user account. ## Docker Setup 1. Add these lines to your `/etc/nixos/configuration.nix`: ```nix virtualisation.docker.enable = true; users.users.<your-username>.extraGroups = [ "docker" ]; ``` 2. Add the Docker Compose package to your system packages: ```nix environment.systemPackages = with pkgs; [ docker-compose ]; ``` 3. After adding these lines, run: ```bash sudo nixos-rebuild switch ``` 4. Confirm docker and docker compose commands work as expected: ```bash [ops@hl-ldn-c1-h1:/]$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES [ops@hl-ldn-c1-h1:/]$ sudo docker-compose Usage: docker compose [OPTIONS] COMMAND Define and run multi-container applications with Docker ``` ## GitHub Access ### Generate SSH Key 1. Create a new ED25519 SSH key: ```bash [ops@hl-ldn-c1-h1:~]$ ssh-keygen -t ed25519 -C "[email protected]" Generating public/private ed25519 key pair. Enter file in which to save the key (/home/ops/.ssh/id_ed25519): Created directory '/home/ops/.ssh'. Enter passphrase for "/home/ops/.ssh/id_ed25519" (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/ops/.ssh/id_ed25519 Your public key has been saved in /home/ops/.ssh/id_ed25519.pub ``` 2. Start the SSH agent and add your key: ```bash [ops@hl-ldn-c1-h1:~]$ eval "$(ssh-agent -s)" Agent pid 14708 [ops@hl-ldn-c1-h1:~]$ ssh-add ~/.ssh/id_ed25519 Enter passphrase for /home/ops/.ssh/id_ed25519: Identity added: /home/ops/.ssh/id_ed25519 ([email protected]) [ops@hl-ldn-c1-h1:~]$ chmod 400 ~/.ssh/id_ed25519 ``` ### Add Key to GitHub 1. Copy your public key: ```bash [ops@hl-ldn-c1-h1:~]$ cat ~/.ssh/id_ed25519.pub ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGgaec5Q3+cOE7UYfutK9BZp11avMn/ibNBeT1nodo56 [email protected] ``` 2. Go to GitHub Settings → SSH Keys → [New SSH Key](https://github.com/settings/ssh/new) 3. Paste your public key ### Clone a repository 1. Clone a private repository: ```bash [ops@hl-ldn-c1-h1:~]$ git clone [email protected]:name/lab.git Cloning into 'lab'... The authenticity of host 'github.com (xx.xx.xx.xx)' can't be established. ED25519 key fingerprint is SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU. This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added 'github.com' (ED25519) to the list of known hosts. remote: Enumerating objects: 6, done. remote: Counting objects: 100% (6/6), done. remote: Compressing objects: 100% (4/4), done. remote: Total 6 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0) Receiving objects: 100% (6/6), done. ``` 2. Confirm it's worked as expected: ```bash [ops@hl-ldn-c1-h1:~]$ ls lab/ README.md ``` 3. Set your Git username and email: ```bash [ops@hl-ldn-c1-h1:~/lab]$ git config --global user.name "char" [ops@hl-ldn-c1-h1:~/lab]$ git config --global user.email "[email protected]" ``` ## Cloudflare Deployment ### Setup Cloudflared 1. Enable the Cloudflared service in your NixOS configuration: ```nix services.cloudflared = { enable = true; }; ``` 2. Rebuild configuration: ```bash nixos-rebuild switch ``` 3. Generate authentication credentials by running: ```bash nix run nixpkgs#cloudflared -- tunnel login ``` This creates a cert.pem file in ~/.cloudflared/. 4. Create a new tunnel with: ```bash nix run nixpkgs#cloudflared -- tunnel create hl-ldn-c1-h1 ``` This generates a credentials file with a UUID format. 5. Add the tunnel and service configuration to your NixOS config: ```nix services.cloudflared = { enable = true; }; systemd.services.cloudflared = { description = "Cloudflare Tunnel"; after = [ "network-online.target" "systemd-resolved.service" ]; wants = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { ExecStart = "${pkgs.cloudflared}/bin/cloudflared tunnel --config /etc/cloudflared/config.yml run"; Restart = "always"; RestartSec = "5s"; User = "ops"; Group = "users"; }; }; environment.etc."cloudflared/config.yml".text = '' tunnel: fd903294-bdff-4ce4-9524-a9ee52610024 credentials-file: /home/ops/.cloudflared/fd903294-bdff-4ce4-9524-a9ee52610024.json ingress: - hostname: "*.char.blog" service: http://localhost:80 - hostname: "char.blog" service: http://localhost:80 - service: http_status:404 ''; ``` 6. After configuration, create a CNAME record in your Cloudflare DNS settings pointing to `<tunnel-id>.cfargotunnel.com`. 7. You can now expose services via a reverse proxy like Nginx Proxy Manager: ![[0fd57f383c82ccd7f877bf518f367ca53abf44b6cfb2faa61699f5d958a947d331a506a9e8dc15bd31edd8d2c37034db0f89caa59d2de3aab14fde263c20cc76.png]] *You will need to set your SSL/TLS encryption settings to be FULL in Cloudflare.* The traffic flow becomes: ```plaintext Internet -> Cloudflare -> Tunnel -> NPM -> Your Services ```