feat: flake NixOS config for jupiter + VirtualBox test image
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
result
|
||||||
|
result-*
|
||||||
|
.direnv/
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# homelab
|
||||||
|
|
||||||
|
Flake-based NixOS config. Host: `jupiter` (ZimaBlade, NAS + services).
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
flake.nix # inputs + nixosConfigurations.jupiter
|
||||||
|
jupiter/configuration.nix # system, users, ssh, samba, containers, caddy
|
||||||
|
jupiter/hardware-configuration.nix # PLACEHOLDER — regenerate on real machine
|
||||||
|
```
|
||||||
|
|
||||||
|
## First install (on the ZimaBlade)
|
||||||
|
|
||||||
|
1. Boot NixOS minimal ISO, partition + mount disks at `/mnt`.
|
||||||
|
2. Generate hardware config:
|
||||||
|
```
|
||||||
|
sudo nixos-generate-config --root /mnt
|
||||||
|
```
|
||||||
|
Copy `/mnt/etc/nixos/hardware-configuration.nix` into `jupiter/`.
|
||||||
|
3. Add your SSH public key to `users.users.erik.openssh.authorizedKeys.keys`.
|
||||||
|
4. Install:
|
||||||
|
```
|
||||||
|
sudo nixos-install --flake .#jupiter
|
||||||
|
```
|
||||||
|
|
||||||
|
## Rebuild after changes
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo nixos-rebuild switch --flake .#jupiter
|
||||||
|
```
|
||||||
|
|
||||||
|
Remote from laptop:
|
||||||
|
```
|
||||||
|
nixos-rebuild switch --flake .#jupiter \
|
||||||
|
--target-host erik@jupiter --use-remote-sudo
|
||||||
|
```
|
||||||
|
|
||||||
|
## Adding a service
|
||||||
|
|
||||||
|
Copy the `whoami` block in `oci-containers.containers`, swap image/ports/volumes.
|
||||||
|
Native NixOS module exists for many apps (Nextcloud, Jellyfin, Grafana...) —
|
||||||
|
prefer `services.<app>` over a container when available.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Backend is Podman with `dockerCompat` — `docker` CLI works, no daemon.
|
||||||
|
- Set correct `time.timeZone` and Samba `path` for your data mount.
|
||||||
|
- `system.stateVersion` = `26.05`, install-time schema. Do NOT bump on upgrades.
|
||||||
|
```
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
description = "Homelab NixOS configuration";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, ... }@inputs:
|
||||||
|
let
|
||||||
|
system = "x86_64-linux";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
nixosConfigurations = {
|
||||||
|
# Real host — install on the ZimaBlade.
|
||||||
|
jupiter = nixpkgs.lib.nixosSystem {
|
||||||
|
inherit system;
|
||||||
|
specialArgs = { inherit inputs; };
|
||||||
|
modules = [ ./jupiter/configuration.nix ];
|
||||||
|
};
|
||||||
|
|
||||||
|
# VirtualBox test image. Build the OVA with:
|
||||||
|
# nix build .#nixosConfigurations.jupiter-vbox.config.system.build.virtualBoxOVA
|
||||||
|
jupiter-vbox = nixpkgs.lib.nixosSystem {
|
||||||
|
inherit system;
|
||||||
|
specialArgs = { inherit inputs; };
|
||||||
|
modules = [ ./jupiter/vm.nix ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
# Real-host config: hardware + bootloader + shared services.
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./hardware-configuration.nix
|
||||||
|
./services.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
# ---- Boot ----
|
||||||
|
# systemd-boot for UEFI. If ZimaBlade boots legacy/BIOS, switch to grub.
|
||||||
|
boot.loader.systemd-boot.enable = true;
|
||||||
|
boot.loader.efi.canTouchEfiVariables = true;
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# PLACEHOLDER — do not use as-is.
|
||||||
|
#
|
||||||
|
# Generate the real file ON the ZimaBlade after booting the NixOS installer:
|
||||||
|
#
|
||||||
|
# sudo nixos-generate-config --root /mnt
|
||||||
|
#
|
||||||
|
# then copy /mnt/etc/nixos/hardware-configuration.nix over this file.
|
||||||
|
# It contains machine-specific disk UUIDs, filesystems, and kernel modules.
|
||||||
|
#
|
||||||
|
# The block below is a minimal example so `nix flake check` does not fail on a
|
||||||
|
# workstation. REPLACE it entirely with the generated output.
|
||||||
|
{ config, lib, pkgs, modulesPath, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
|
||||||
|
|
||||||
|
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" "sd_mod" ];
|
||||||
|
boot.initrd.kernelModules = [ ];
|
||||||
|
boot.kernelModules = [ ];
|
||||||
|
boot.extraModulePackages = [ ];
|
||||||
|
|
||||||
|
# Example root — replace UUID with real value from generated config.
|
||||||
|
fileSystems."/" = {
|
||||||
|
device = "/dev/disk/by-label/nixos";
|
||||||
|
fsType = "ext4";
|
||||||
|
};
|
||||||
|
|
||||||
|
fileSystems."/boot" = {
|
||||||
|
device = "/dev/disk/by-label/BOOT";
|
||||||
|
fsType = "vfat";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Example NAS data mount. Point at your storage disk/pool.
|
||||||
|
# fileSystems."/mnt/data" = {
|
||||||
|
# device = "/dev/disk/by-label/data";
|
||||||
|
# fsType = "ext4";
|
||||||
|
# };
|
||||||
|
|
||||||
|
swapDevices = [ ];
|
||||||
|
|
||||||
|
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
# Portable system + service config. Contains NO bootloader or filesystem
|
||||||
|
# settings, so it can be reused by both the real host (configuration.nix)
|
||||||
|
# and the VirtualBox test image (see flake.nix).
|
||||||
|
|
||||||
|
{
|
||||||
|
# ---- Networking ----
|
||||||
|
networking.hostName = "jupiter";
|
||||||
|
networking.networkmanager.enable = true;
|
||||||
|
|
||||||
|
networking.firewall = {
|
||||||
|
enable = true;
|
||||||
|
allowedTCPPorts = [
|
||||||
|
22 # ssh
|
||||||
|
445 139 # samba
|
||||||
|
80 443 # reverse proxy (caddy)
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# ---- Locale / time ----
|
||||||
|
time.timeZone = "Europe/Berlin";
|
||||||
|
i18n.defaultLocale = "en_US.UTF-8";
|
||||||
|
|
||||||
|
# ---- Users ----
|
||||||
|
users.users.erik = {
|
||||||
|
isNormalUser = true;
|
||||||
|
description = "erik";
|
||||||
|
extraGroups = [ "wheel" "networkmanager" "docker" ];
|
||||||
|
# Replace with your real public key. Password login for ssh is disabled below.
|
||||||
|
openssh.authorizedKeys.keys = [
|
||||||
|
# "ssh-ed25519 AAAA... erik@laptop"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
security.sudo.wheelNeedsPassword = false;
|
||||||
|
|
||||||
|
# ---- SSH ----
|
||||||
|
services.openssh = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
PasswordAuthentication = false;
|
||||||
|
PermitRootLogin = "no";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# ---- Storage / NAS ----
|
||||||
|
services.samba = {
|
||||||
|
enable = true;
|
||||||
|
openFirewall = true;
|
||||||
|
settings = {
|
||||||
|
global = {
|
||||||
|
"workgroup" = "WORKGROUP";
|
||||||
|
"server string" = "jupiter";
|
||||||
|
"security" = "user";
|
||||||
|
};
|
||||||
|
data = {
|
||||||
|
"path" = "/mnt/data";
|
||||||
|
"browseable" = "yes";
|
||||||
|
"read only" = "no";
|
||||||
|
"guest ok" = "no";
|
||||||
|
"valid users" = "erik";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
services.avahi = {
|
||||||
|
enable = true;
|
||||||
|
nssmdns4 = true;
|
||||||
|
publish = {
|
||||||
|
enable = true;
|
||||||
|
userServices = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# ---- Containers ----
|
||||||
|
virtualisation.podman = {
|
||||||
|
enable = true;
|
||||||
|
dockerCompat = true;
|
||||||
|
defaultNetwork.settings.dns_enabled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtualisation.oci-containers = {
|
||||||
|
backend = "podman";
|
||||||
|
containers = {
|
||||||
|
whoami = {
|
||||||
|
image = "traefik/whoami:latest";
|
||||||
|
ports = [ "8080:80" ];
|
||||||
|
autoStart = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# ---- Reverse proxy ----
|
||||||
|
services.caddy = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# ---- System packages ----
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
vim
|
||||||
|
git
|
||||||
|
htop
|
||||||
|
tmux
|
||||||
|
curl
|
||||||
|
];
|
||||||
|
|
||||||
|
# ---- Nix settings ----
|
||||||
|
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
||||||
|
nix.gc = {
|
||||||
|
automatic = true;
|
||||||
|
dates = "weekly";
|
||||||
|
options = "--delete-older-than 30d";
|
||||||
|
};
|
||||||
|
|
||||||
|
system.stateVersion = "26.05";
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{ config, pkgs, lib, modulesPath, ... }:
|
||||||
|
|
||||||
|
# VirtualBox test image. Reuses services.nix but adds console/SSH login
|
||||||
|
# credentials so you can actually get into the VM. Disk + bootloader are
|
||||||
|
# provided by the virtualbox-image module, so hardware-configuration.nix
|
||||||
|
# is intentionally NOT imported here.
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
(modulesPath + "/virtualisation/virtualbox-image.nix")
|
||||||
|
./services.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
# Allow password login for testing (real host is key-only).
|
||||||
|
services.openssh.settings.PasswordAuthentication = lib.mkForce true;
|
||||||
|
|
||||||
|
# Login: erik / test (change or remove for anything but local testing).
|
||||||
|
users.users.erik.initialPassword = "test";
|
||||||
|
users.users.root.initialPassword = "test";
|
||||||
|
|
||||||
|
# Guest additions for clipboard/resize (optional).
|
||||||
|
virtualisation.virtualbox.guest.enable = true;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user