156 lines
6.3 KiB
Nix
156 lines
6.3 KiB
Nix
{
|
|
description = "Homey - self-hosted home server NixOS configuration";
|
|
|
|
# Binary cache for pre-built Raspberry Pi kernel + firmware packages.
|
|
# nixos-raspberrypi builds against its own pinned nixpkgs and publishes
|
|
# to this cache — using it avoids compiling linuxPackages_rpi4 from source.
|
|
nixConfig = {
|
|
extra-substituters = [
|
|
"https://nixos-raspberrypi.cachix.org"
|
|
];
|
|
extra-trusted-public-keys = [
|
|
"nixos-raspberrypi.cachix.org-1:4iMO9LXa8BqhU+Rpg6LQKiGa2lsNh/j2oiYLNOQ5sPI="
|
|
];
|
|
};
|
|
|
|
inputs = {
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
|
|
|
|
# sops-nix for secret management
|
|
sops-nix = {
|
|
url = "github:Mic92/sops-nix";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
};
|
|
|
|
# Raspberry Pi hardware support — provides vendor kernel, firmware,
|
|
# bootloader management, and a binary cache for pre-built aarch64 packages.
|
|
# Intentionally NOT following our nixpkgs: the cache is built against the
|
|
# flake's own pinned nixpkgs, so following would invalidate all cache hits.
|
|
nixos-raspberrypi.url = "github:nvmd/nixos-raspberrypi/main";
|
|
};
|
|
|
|
outputs = { self, nixpkgs, sops-nix, nixos-raspberrypi, ... }@inputs:
|
|
let
|
|
# Shared specialArgs passed to every host
|
|
commonArgs = {
|
|
inherit inputs nixos-raspberrypi;
|
|
# Top-level site config — override per-host if needed
|
|
homeyConfig = {
|
|
domain = "home.zakobar.com"; # base domain for all services
|
|
organization = "Zakobar Home Server";
|
|
timezone = "Asia/Jerusalem";
|
|
# External HD mount point — set in hardware.nix per host
|
|
# dataDir is intentionally NOT set here; each host sets it
|
|
};
|
|
};
|
|
|
|
# nixos-raspberrypi.lib.nixosSystem is a drop-in replacement for
|
|
# nixpkgs.lib.nixosSystem that:
|
|
# - injects vendor kernel/firmware overlays
|
|
# - wires up the trusted cache substituters
|
|
# - passes nixos-raspberrypi into specialArgs automatically
|
|
# It uses the flake's own pinned nixpkgs by default (currently 25.11).
|
|
mkHost = { hostPath, extraModules ? [] }:
|
|
nixos-raspberrypi.lib.nixosSystem {
|
|
specialArgs = commonArgs;
|
|
modules = [
|
|
sops-nix.nixosModules.sops
|
|
# RPi 4 base: vendor kernel (linuxPackages_rpi4), firmware,
|
|
# bootloader (u-boot), initrd modules, config.txt management
|
|
nixos-raspberrypi.nixosModules.raspberry-pi-4.base
|
|
# SD image target — provides system.build.sdImage
|
|
({ modulesPath, ... }: {
|
|
imports = [ "${modulesPath}/installer/sd-card/sd-image-aarch64.nix" ];
|
|
})
|
|
hostPath
|
|
./modules/common.nix
|
|
./modules/storage.nix
|
|
./modules/caddy.nix
|
|
./modules/cloudflared.nix
|
|
./modules/backup.nix
|
|
./modules/services/openldap.nix
|
|
./modules/services/authelia.nix
|
|
./modules/services/gitea.nix
|
|
./modules/services/nextcloud.nix
|
|
./modules/services/phpldapadmin.nix
|
|
./modules/services/jellyfin.nix
|
|
./modules/services/transmission.nix
|
|
] ++ extraModules;
|
|
};
|
|
|
|
in {
|
|
nixosConfigurations = {
|
|
|
|
# Bootstrap image — flash this first.
|
|
# Minimal: SSH key, WiFi, static IP. No sops, no services.
|
|
# Purpose: boot the Pi, generate the age key, then deploy pi-main.
|
|
pi-main-bootstrap = nixos-raspberrypi.lib.nixosSystem {
|
|
specialArgs = commonArgs;
|
|
modules = [
|
|
nixos-raspberrypi.nixosModules.raspberry-pi-4.base
|
|
({ modulesPath, ... }: {
|
|
imports = [ "${modulesPath}/installer/sd-card/sd-image-aarch64.nix" ];
|
|
})
|
|
./hosts/pi-main/hardware.nix
|
|
({ pkgs, lib, ... }: {
|
|
networking.hostName = "pi-main";
|
|
time.timeZone = commonArgs.homeyConfig.timezone;
|
|
i18n.defaultLocale = "en_US.UTF-8";
|
|
system.stateVersion = "25.05";
|
|
|
|
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
|
nixpkgs.config.allowUnfree = true;
|
|
|
|
# WiFi — PSK inline (bootstrap only, not in Nix store long-term)
|
|
networking.wireless = {
|
|
enable = true;
|
|
networks."Zakobar".psk = "0502711157";
|
|
};
|
|
networking.interfaces.wlan0.ipv4.addresses = [{
|
|
address = "192.168.1.100";
|
|
prefixLength = 24;
|
|
}];
|
|
networking.useDHCP = false;
|
|
networking.interfaces.wlan0.useDHCP = false;
|
|
networking.defaultGateway = "192.168.1.1";
|
|
networking.nameservers = [ "1.1.1.1" "8.8.8.8" ];
|
|
networking.firewall.allowedTCPPorts = [ 22 ];
|
|
|
|
# SSH — key only, no passwords, no root
|
|
services.openssh = {
|
|
enable = true;
|
|
settings = {
|
|
PasswordAuthentication = false;
|
|
PermitRootLogin = "no";
|
|
};
|
|
};
|
|
|
|
users.mutableUsers = false;
|
|
users.users.admin = {
|
|
isNormalUser = true;
|
|
extraGroups = [ "wheel" ];
|
|
openssh.authorizedKeys.keys = [
|
|
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDBFZRqiTsOCAJPMqUyMeLd2MbyjdGoyqDVq5/Inhb6EOaM1NUGG4b6FPmYgFLyJIm5LC9BOo6M7npiaiOs/zMqp+hoGLNQUNwm5/G0uy1bjkEfKdUTdGnJ2+M9rkxrR1c+KXrjkiqECqTbnPE4mJbGyVxBW2MwMeP5w8c0DB5KO528PetvHMPPQuEdXyZzDI4kKtVpMlJoPIrIGlNFX0G/wrgXcM4zU1snOTuYGqZnWW++4kBsgIlRKpf/bLJyUMTp30eLVr0fQ6OMBtj1tzUUBaaowU6VGYQQDU/rIh/NpkA2cEVPXZegM4OohkAqrJBFPIAg90WD9Z/SyQlz0Jn8PpAloP0Cuq2vVRr+QLEwxqGiFq91YQ2VtwksMHwJGVrXRCNegpxTZQijWMEd+o0FD2cEd7Ftw6v2L6g12GJ3QGX/q0d/u0GongLLa9fPXl4VoAu7AL+cUcbX/SS7RCG8kYAR3DwOazVbK0NWEdwvWdoSU4lZ3j2at1xqMGjHjyLiTeUqZBjm+Sl5MJWIYNg+8hnONljvggg4SzDFDAkgVLZtOCaZibsMA1ucGR7VRCM09uoaEI4/ZS5pCBtYcp8X67Bv67Og8s2NFf5sUfYBPPKpdBSs+dEPycNVff6JlmzfNiyzLawacGKIDWYSgkOl43N/5ehtpsL3HMZ+5SVNIw=="
|
|
];
|
|
};
|
|
security.sudo.wheelNeedsPassword = false;
|
|
|
|
environment.systemPackages = [ pkgs.age pkgs.vim ];
|
|
})
|
|
];
|
|
};
|
|
|
|
# Primary Raspberry Pi 4
|
|
pi-main = mkHost {
|
|
hostPath = ./hosts/pi-main/default.nix;
|
|
};
|
|
|
|
# Future second machine (placeholder — uncomment and configure when ready)
|
|
# pi-secondary = mkHost {
|
|
# hostPath = ./hosts/pi-secondary/default.nix;
|
|
# };
|
|
|
|
};
|
|
};
|
|
}
|