Initial commit

This commit is contained in:
stherm 2026-03-06 08:31:13 +01:00
commit 430194beda
109 changed files with 9066 additions and 0 deletions

View file

@ -0,0 +1,7 @@
{
boot.loader.systemd-boot = {
enable = true;
configurationLimit = 10;
};
boot.loader.efi.canTouchEfiVariables = true;
}

View file

@ -0,0 +1,21 @@
{
inputs,
outputs,
...
}:
{
imports = [
./boot.nix
./hardware.nix
./networking.nix
./packages.nix
./services
./users.nix
outputs.nixosModules.common
outputs.nixosModules.nixvim
];
system.stateVersion = "25.11";
}

View file

@ -0,0 +1,63 @@
#!/usr/bin/env bash
SSD='/dev/disk/by-id/FIXME'
MNT='/mnt'
SWAP_GB=4
# Helper function to wait for devices
wait_for_device() {
local device=$1
echo "Waiting for device: $device ..."
while [[ ! -e $device ]]; do
sleep 1
done
echo "Device $device is ready."
}
# Function to install a package if it's not already installed
install_if_missing() {
local cmd="$1"
local package="$2"
if ! command -v "$cmd" &> /dev/null; then
echo "$cmd not found, installing $package..."
nix-env -iA "nixos.$package"
fi
}
install_if_missing "sgdisk" "gptfdisk"
install_if_missing "partprobe" "parted"
wait_for_device $SSD
echo "Wiping filesystem on $SSD..."
wipefs -a $SSD
echo "Clearing partition table on $SSD..."
sgdisk --zap-all $SSD
echo "Partitioning $SSD..."
sgdisk -n1:1M:+1G -t1:EF00 -c1:BOOT $SSD
sgdisk -n2:0:+"$SWAP_GB"G -t2:8200 -c2:SWAP $SSD
sgdisk -n3:0:0 -t3:8304 -c3:ROOT $SSD
partprobe -s $SSD
udevadm settle
wait_for_device ${SSD}-part1
wait_for_device ${SSD}-part2
wait_for_device ${SSD}-part3
echo "Formatting partitions..."
mkfs.vfat -F 32 -n BOOT "${SSD}-part1"
mkswap -L SWAP "${SSD}-part2"
mkfs.ext4 -L ROOT "${SSD}-part3"
echo "Mounting partitions..."
mount -o X-mount.mkdir "${SSD}-part3" "$MNT"
mkdir -p "$MNT/boot"
mount -t vfat -o fmask=0077,dmask=0077,iocharset=iso8859-1 "${SSD}-part1" "$MNT/boot"
echo "Enabling swap..."
swapon "${SSD}-part2"
echo "Partitioning and setup complete:"
lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL

View file

@ -0,0 +1,48 @@
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [
"ahci"
"nvme"
"sd_mod"
"sdhci_pci"
"sr_mod"
"usb_storage"
"virtio_pci"
"virtio_scsi"
"xhci_pci"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-label/ROOT";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-label/BOOT";
fsType = "vfat";
options = [
"fmask=0022"
"dmask=0022"
];
};
swapDevices = [ { device = "/dev/disk/by-label/SWAP"; } ];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

View file

@ -0,0 +1,4 @@
{
networking.hostName = "cryodev-main";
networking.domain = "cryodev.xyz";
}

View file

@ -0,0 +1,5 @@
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [ ];
}

View file

@ -0,0 +1,13 @@
{
imports = [
./forgejo.nix
./headplane.nix
./headscale.nix
./mailserver.nix
./netdata.nix
./nginx.nix
./openssh.nix
./sops.nix
./tailscale.nix
];
}

View file

@ -0,0 +1,51 @@
{
config,
pkgs,
outputs,
constants,
...
}:
{
imports = [
outputs.nixosModules.forgejo
outputs.nixosModules.forgejo-runner
];
services.forgejo = {
enable = true;
settings = {
server = {
DOMAIN = constants.services.forgejo.fqdn;
ROOT_URL = "https://${constants.services.forgejo.fqdn}/";
HTTP_PORT = constants.services.forgejo.port;
};
service = {
DISABLE_REGISTRATION = true;
};
mailer = {
ENABLED = true;
FROM = "forgejo@${constants.domain}";
SMTP_ADDR = constants.services.mail.fqdn;
SMTP_PORT = constants.services.mail.port;
USER = "forgejo@${constants.domain}";
};
};
sops = true; # Enable sops integration for secrets
};
services.forgejo-runner = {
enable = true;
url = "https://${constants.services.forgejo.fqdn}";
# Token needs to be set up via sops/secrets
sops = true;
};
services.nginx.virtualHosts."${constants.services.forgejo.fqdn}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString constants.services.forgejo.port}";
};
};
}

View file

@ -0,0 +1,35 @@
{
config,
pkgs,
outputs,
constants,
...
}:
{
imports = [
outputs.nixosModules.headplane
];
services.headplane = {
enable = true;
port = constants.services.headplane.port;
headscale = {
url = "http://127.0.0.1:${toString constants.services.headscale.port}";
public_url = "https://${constants.services.headscale.fqdn}";
};
# Secrets for headplane need to be configured via sops
sops.secrets = {
"headplane/cookie_secret" = { };
"headplane/agent_pre_authkey" = { };
};
};
services.nginx.virtualHosts."${constants.services.headplane.fqdn}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString constants.services.headplane.port}";
};
};
}

View file

@ -0,0 +1,32 @@
{
config,
pkgs,
outputs,
constants,
...
}:
{
imports = [
outputs.nixosModules.headscale
];
services.headscale = {
enable = true;
address = "127.0.0.1";
port = constants.services.headscale.port;
settings = {
server_url = "https://${constants.services.headscale.fqdn}";
dns_config.base_domain = constants.domain;
};
};
services.nginx.virtualHosts."${constants.services.headscale.fqdn}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString constants.services.headscale.port}";
proxyWebsockets = true;
};
};
}

View file

@ -0,0 +1,27 @@
{
config,
pkgs,
outputs,
constants,
...
}:
{
imports = [
outputs.nixosModules.mailserver
];
mailserver = {
enable = true;
fqdn = constants.services.mail.fqdn;
domains = [ constants.domain ];
accounts = {
forgejo = { };
admin = {
aliases = [ "postmaster" ];
};
};
certificateScheme = "acme-nginx";
sops = true;
};
}

View file

@ -0,0 +1,34 @@
{
config,
pkgs,
constants,
...
}:
{
services.netdata = {
enable = true;
package = pkgs.netdata.override {
withCloudUi = true;
};
config = {
global = {
"debug log" = "syslog";
"access log" = "syslog";
"error log" = "syslog";
"bind to" = "127.0.0.1";
};
};
};
services.nginx.virtualHosts."${constants.services.netdata.fqdn}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString constants.services.netdata.port}";
proxyWebsockets = true;
# Basic Auth can be added here if desired, or restrict by IP
# extraConfig = "allow 100.64.0.0/10; deny all;"; # Example for Tailscale only
};
};
}

View file

@ -0,0 +1,22 @@
{
inputs,
outputs,
lib,
config,
pkgs,
...
}:
{
imports = [ outputs.nixosModules.nginx ];
services.nginx = {
enable = true;
forceSSL = true; # Force SSL for all vhosts by default if configured to use this option
openFirewall = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
};
}

View file

@ -0,0 +1,12 @@
{
outputs,
...
}:
{
imports = [
outputs.nixosModules.openssh
];
services.openssh.enable = true;
}

View file

@ -0,0 +1,21 @@
{
config,
pkgs,
outputs,
...
}:
{
imports = [
outputs.nixosModules.sops
];
sops = {
defaultSopsFile = ../secrets.yaml;
# age.keyFile is not set, sops-nix defaults to using /etc/ssh/ssh_host_ed25519_key
secrets = {
"forgejo-runner/token" = { };
"tailscale/auth-key" = { };
};
};
}

View file

@ -0,0 +1,23 @@
{
config,
pkgs,
outputs,
constants,
...
}:
{
imports = [
outputs.nixosModules.tailscale
];
services.tailscale = {
enable = true;
# Connect to our own headscale instance
loginServer = "https://${constants.services.headscale.fqdn}";
# Allow SSH access over Tailscale
enableSSH = true;
# Use MagicDNS names
acceptDNS = true;
};
}

View file

@ -0,0 +1,8 @@
{ inputs, outputs, ... }:
{
imports = [
outputs.nixosModules.normalUsers
../../users/steffen
];
}

View file

@ -0,0 +1,8 @@
{
boot = {
loader = {
grub.enable = false;
generic-extlinux-compatible.enable = true;
};
};
}

View file

@ -0,0 +1,21 @@
{
inputs,
outputs,
...
}:
{
imports = [
./boot.nix
./hardware.nix
./networking.nix
./packages.nix
./services
./users.nix
outputs.nixosModules.common
outputs.nixosModules.nixvim
];
system.stateVersion = "25.11";
}

63
hosts/cryodev-pi/disks.sh Normal file
View file

@ -0,0 +1,63 @@
#!/usr/bin/env bash
SSD='/dev/disk/by-id/FIXME'
MNT='/mnt'
SWAP_GB=4
# Helper function to wait for devices
wait_for_device() {
local device=$1
echo "Waiting for device: $device ..."
while [[ ! -e $device ]]; do
sleep 1
done
echo "Device $device is ready."
}
# Function to install a package if it's not already installed
install_if_missing() {
local cmd="$1"
local package="$2"
if ! command -v "$cmd" &> /dev/null; then
echo "$cmd not found, installing $package..."
nix-env -iA "nixos.$package"
fi
}
install_if_missing "sgdisk" "gptfdisk"
install_if_missing "partprobe" "parted"
wait_for_device $SSD
echo "Wiping filesystem on $SSD..."
wipefs -a $SSD
echo "Clearing partition table on $SSD..."
sgdisk --zap-all $SSD
echo "Partitioning $SSD..."
sgdisk -n1:1M:+1G -t1:EF00 -c1:BOOT $SSD
sgdisk -n2:0:+"$SWAP_GB"G -t2:8200 -c2:SWAP $SSD
sgdisk -n3:0:0 -t3:8304 -c3:ROOT $SSD
partprobe -s $SSD
udevadm settle
wait_for_device ${SSD}-part1
wait_for_device ${SSD}-part2
wait_for_device ${SSD}-part3
echo "Formatting partitions..."
mkfs.vfat -F 32 -n BOOT "${SSD}-part1"
mkswap -L SWAP "${SSD}-part2"
mkfs.ext4 -L ROOT "${SSD}-part3"
echo "Mounting partitions..."
mount -o X-mount.mkdir "${SSD}-part3" "$MNT"
mkdir -p "$MNT/boot"
mount -t vfat -o fmask=0077,dmask=0077,iocharset=iso8859-1 "${SSD}-part1" "$MNT/boot"
echo "Enabling swap..."
swapon "${SSD}-part2"
echo "Partitioning and setup complete:"
lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL

View file

@ -0,0 +1,23 @@
{ pkgs, lib, ... }:
{
boot = {
kernelPackages = pkgs.linuxKernel.packages.linux_rpi4;
initrd.availableKernelModules = [
"xhci_pci"
"usbhid"
"usb_storage"
];
};
fileSystems = {
"/" = {
device = "/dev/disk/by-label/NIXOS_SD";
fsType = "ext4";
options = [ "noatime" ];
};
};
nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux";
hardware.enableRedistributableFirmware = true;
}

View file

@ -0,0 +1,4 @@
{
networking.hostName = "cryodev-pi";
networking.domain = "cryodev.xyz";
}

View file

@ -0,0 +1,5 @@
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [ ];
}

View file

@ -0,0 +1,24 @@
{
config,
pkgs,
outputs,
constants,
...
}:
{
imports = [
outputs.nixosModules.comin
];
services.comin = {
enable = true;
remotes = [
{
name = "origin";
url = "https://${constants.services.forgejo.fqdn}/steffen/cryodev-server.git";
branches.main.name = "main";
}
];
};
}

View file

@ -0,0 +1,9 @@
{
imports = [
./nginx.nix
./openssh.nix
./tailscale.nix
./netdata.nix
./comin.nix
];
}

View file

@ -0,0 +1,31 @@
{
config,
pkgs,
outputs,
constants,
...
}:
{
services.netdata = {
enable = true;
config = {
stream = {
enabled = "yes";
destination = "${constants.hosts.cryodev-main.ip}:${toString constants.services.netdata.port}";
"api key" = config.sops.placeholder."netdata/stream/child-uuid";
};
};
};
# Make sure sops is enabled/imported for this host to handle the secret
imports = [ outputs.nixosModules.sops ];
sops = {
defaultSopsFile = ../secrets.yaml;
secrets."netdata/stream/child-uuid" = {
owner = "netdata";
group = "netdata";
};
};
}

View file

@ -0,0 +1,14 @@
{
outputs,
...
}:
{
imports = [ outputs.nixosModules.nginx ];
services.nginx = {
enable = true;
forceSSL = true;
openFirewall = true;
};
}

View file

@ -0,0 +1,12 @@
{
outputs,
...
}:
{
imports = [
outputs.nixosModules.openssh
];
services.openssh.enable = true;
}

View file

@ -0,0 +1,28 @@
{
config,
pkgs,
outputs,
constants,
...
}:
{
imports = [
outputs.nixosModules.tailscale
];
services.tailscale = {
enable = true;
# Connect to our own headscale instance
loginServer = "https://${constants.services.headscale.fqdn}";
# Allow SSH access over Tailscale
enableSSH = true;
# Use MagicDNS names
acceptDNS = true;
# Auth key for automated enrollment
authKeyFile = config.sops.secrets."tailscale/auth-key".path;
};
sops.secrets."tailscale/auth-key" = { };
}

View file

@ -0,0 +1,9 @@
{ inputs, outputs, ... }:
{
imports = [
outputs.nixosModules.normalUsers
../../users/steffen
../../users/cryotherm
];
}