feat: add server configuration

This commit is contained in:
Nickolaj Jepsen 2025-03-09 20:30:33 +01:00
parent 0d47ab58f5
commit 9665106633
42 changed files with 4282 additions and 99 deletions

View file

@ -0,0 +1,29 @@
{
pkgs,
lib,
...
}: {
boot = {
# Use grub as bootloader as it works better with mdadm
loader.grub.enable = true;
loader.systemd-boot.enable = lib.mkForce false;
# HACK: silence mdadm warning on missing MAILADDR or PROGRAM setting
swraid.mdadmConf = ''
PROGRAM ${pkgs.coreutils}/bin/true
'';
};
# Enable OpenGL
hardware.graphics = {
enable = true;
};
# Load nvidia driver for Xorg and Wayland
services.xserver.videoDrivers = ["nvidia"];
hardware.nvidia = {
open = true;
modesetting.enable = true;
};
}

120
hosts/homelab/disks.nix Normal file
View file

@ -0,0 +1,120 @@
{pkgs, ...}: {
# Data disks
environment.systemPackages = with pkgs; [
mergerfs
];
fileSystems."/mnt/data-disk/1" = {
device = "/dev/disk/by-id/ata-WDC_WD120EFBX-68B0EN0_5PKURKPF-part1";
fsType = "ext4";
};
fileSystems."/mnt/data-disk/2" = {
device = "/dev/disk/by-id/ata-WDC_WD120EFBX-68B0EN0_5PKVMK7F-part1";
fsType = "ext4";
};
fileSystems."/mnt/longhorn" = {
device = "/dev/disk/by-id/ata-TOSHIBA_HDWE160_26N7K5N0F56D-part1";
fsType = "ext4";
};
fileSystems."/mnt/data" = {
fsType = "fuse.mergerfs";
device = "/mnt/data-disk/*";
options = ["cache.files=partial" "dropcacheonclose=true" "category.create=mfs"];
};
# System disks
disko.devices = {
disk = {
system1 = {
type = "disk";
device = "/dev/disk/by-id/ata-WDC_WDS500G2B0A-00SM50_1827AD804249";
content = {
type = "gpt";
partitions = {
boot = {
size = "1M";
type = "EF02"; # for grub MBR
};
ESP = {
size = "500M";
type = "EF00";
content = {
type = "mdraid";
name = "boot";
};
};
mdadm = {
size = "100%";
content = {
type = "mdraid";
name = "system";
};
};
};
};
};
system2 = {
type = "disk";
device = "/dev/disk/by-id/ata-WDC_WDS500G2B0A-00SM50_1908BB805114";
content = {
type = "gpt";
partitions = {
boot = {
size = "1M";
type = "EF02"; # for grub MBR
};
ESP = {
size = "500M";
type = "EF00";
content = {
type = "mdraid";
name = "boot";
};
};
mdadm = {
size = "100%";
content = {
type = "mdraid";
name = "system";
};
};
};
};
};
};
mdadm = {
boot = {
type = "mdadm";
level = 1;
metadata = "1.0";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = ["umask=0077"];
};
};
system = {
type = "mdadm";
level = 1;
content = {
type = "btrfs";
extraArgs = ["-f"];
subvolumes = {
"@" = {
mountpoint = "/";
mountOptions = ["compress=zstd" "noatime"];
};
"@nix" = {
mountpoint = "/nix";
mountOptions = ["compress=zstd" "noatime"];
};
"@home" = {
mountpoint = "/home";
mountOptions = ["compress=zstd" "noatime"];
};
};
};
};
};
};
}

View file

@ -0,0 +1,8 @@
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8dbebe22375a lscr.io/linuxserver/radarr:latest "/init" 13 hours ago Up 15 minutes 7878/tcp deployment-radarr-1
b445f1a00c58 lscr.io/linuxserver/prowlarr:latest "/init" 13 hours ago Up 15 minutes 9696/tcp deployment-prowlarr-1
8ae82963dbcc lscr.io/linuxserver/sonarr:latest "/init" 37 hours ago Up 15 minutes 8989/tcp deployment-sonarr-1
44e019b912ea ghcr.io/open-webui/open-webui:ollama "bash start.sh" 37 hours ago Up 15 minutes (healthy) 8080/tcp open-webui
65956cc9ab2b lscr.io/linuxserver/sabnzbd:latest "/init" 3 days ago Up 15 minutes 8080/tcp deployment-sabnzbd-1
bdddf0848dc3 lscr.io/linuxserver/bazarr:latest "/init" 4 days ago Up 15 minutes 6767/tcp deployment-bazarr-1
b1492d62fcb0 nextcloud:latest "/entrypoint.sh apac…" 9 days ago Up 15 minutes 80/tcp deployment-nextcloud-1

3596
hosts/homelab/facter.json Normal file

File diff suppressed because it is too large Load diff

27
hosts/homelab/flame.nix Normal file
View file

@ -0,0 +1,27 @@
_: let
dataDir = "/var/lib/flame";
domain = "flame.nickolaj.com";
in {
services.nginx.virtualHosts."${domain}" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:5005";
};
};
virtualisation.oci-containers = {
containers = {
flame = {
autoStart = true;
image = "pawelmalak/flame:2.3.1";
volumes = [
"${dataDir}:/app/data"
];
ports = [
"127.0.0.1:5005:5005"
];
};
};
};
}

View file

@ -0,0 +1,175 @@
{
pkgsUnstable,
pkgs,
config,
...
}: let
mosquittoPort = 1883;
zigbee2mqttPort = 8080;
homeAssistantPort = 8123;
in {
age.secrets = {
"zigbee2mqtt-secret.yaml" = {
rekeyFile = ../../secrets/hosts/homelab/zigbee2mqtt-secret.yaml.age;
owner = "zigbee2mqtt";
group = "zigbee2mqtt";
};
z2m-basic-auth = {
rekeyFile = ../../secrets/hosts/homelab/basic-auth.age;
owner = config.services.nginx.user;
inherit (config.services.nginx) group;
};
mosquitto-zigbee2mqtt.rekeyFile = ../../secrets/hosts/homelab/mosquitto-zigbee2mqtt.age;
mosquitto-sas.rekeyFile = ../../secrets/hosts/homelab/mosquitto-sas.age;
mosquitto-ha.rekeyFile = ../../secrets/hosts/homelab/mosquitto-ha.age;
};
networking.firewall.allowedTCPPorts = [
mosquittoPort
];
services = {
nginx.virtualHosts = {
"zigbee.nickolaj.com" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://localhost:${toString zigbee2mqttPort}";
proxyWebsockets = true;
};
basicAuthFile = "${config.age.secrets.z2m-basic-auth.path}";
};
"ha.nickolaj.com" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://localhost:${toString homeAssistantPort}";
proxyWebsockets = true;
};
};
};
home-assistant = {
enable = true;
package = pkgsUnstable.home-assistant;
customComponents = with pkgsUnstable.home-assistant-custom-components; [
adaptive_lighting
sleep_as_android
(pkgs.buildHomeAssistantComponent rec {
owner = "Sian-Lee-SA";
domain = "switch_manager";
version = "v2.0.4b";
src = pkgs.fetchFromGitHub {
inherit owner;
repo = "Home-Assistant-Switch-Manager";
rev = version;
hash = "sha256-W9xO3JjnRKHk/dlXMA6y5nEJl/KsGzPvJoumGw+nohw=";
};
})
];
extraComponents = [
"default_config"
"met"
"mqtt"
"esphome"
"google"
"spotify"
"unifi"
"upnp"
"homeassistant_hardware"
];
config = {
homeassistant = {
name = "Home";
latitude = "56.2";
longitude = "10.2";
elevation = "0";
unit_system = "metric";
time_zone = "Europe/Copenhagen";
};
frontend = {
themes = "!include_dir_merge_named themes";
};
http = {
server_port = homeAssistantPort;
use_x_forwarded_for = true;
trusted_proxies = [
"127.0.0.1"
"::1"
];
base_url = "https://ha.nickolaj.com";
};
automation = "!include automations.yaml";
script = "!include scripts.yaml";
scene = "!include scenes.yaml";
};
};
mosquitto = {
enable = true;
listeners = [
{
port = mosquittoPort;
users."zigbee2mqtt" = {
acl = ["readwrite #"];
passwordFile = "${config.age.secrets.mosquitto-zigbee2mqtt.path}";
};
users."homeassistant" = {
acl = ["readwrite #"];
passwordFile = "${config.age.secrets.mosquitto-ha.path}";
};
users."sleep_as_android" = {
acl = ["readwrite SleepAsAndroid"];
passwordFile = "${config.age.secrets.mosquitto-sas.path}";
};
}
];
};
zigbee2mqtt = {
enable = true;
settings = {
homeassistant = {
enabled = true;
};
mqtt = {
base_topic = "zigbee2mqtt";
server = "mqtt://localhost:${toString mosquittoPort}";
user = "zigbee2mqtt";
password = "!${config.age.secrets."zigbee2mqtt-secret.yaml".path} password";
};
frontend = {
enabled = true;
port = zigbee2mqttPort;
};
serial = {
port = "/dev/serial/by-id/usb-Silicon_Labs_Sonoff_Zigbee_3.0_USB_Dongle_Plus_0001-if00-port0";
adapter = "zstack";
};
advanced = {
network_key = [
233
138
136
76
51
117
128
127
74
84
33
179
116
61
79
101
];
channel = 25;
log_level = "debug";
};
};
};
};
}

13
hosts/homelab/netdata.nix Normal file
View file

@ -0,0 +1,13 @@
{
config,
pkgsUnstable,
...
}: {
age.secrets.netdata-claim-token.rekeyFile = ../../secrets/netdata-claim-token.age;
services.netdata = {
enable = true;
package = pkgsUnstable.netdataCloud;
claimTokenFile = "${config.age.secrets.netdata-claim-token.path}";
};
}

12
hosts/homelab/nginx.nix Normal file
View file

@ -0,0 +1,12 @@
_: {
networking.firewall.allowedTCPPorts = [80 443];
services.nginx = {
enable = true;
recommendedProxySettings = true;
};
security.acme = {
acceptTerms = true;
defaults.email = "nickolaj@fireproof.website";
};
}

18
hosts/homelab/plex.nix Normal file
View file

@ -0,0 +1,18 @@
_: let
domain = "plex.nickolaj.com";
in {
services.nginx.virtualHosts."${domain}" = {
forceSSL = true;
enableACME = true;
http2 = true;
locations."/" = {
proxyWebsockets = true;
proxyPass = "http://localhost:32400/";
};
};
services.plex = {
enable = true;
openFirewall = true;
};
}

19
hosts/homelab/restic.nix Normal file
View file

@ -0,0 +1,19 @@
{
pkgs,
config,
...
}: {
environment.systemPackages = with pkgs; [
restic
];
age.secrets.restic-password.rekeyFile = ../../secrets/hosts/homelab/restic-password.age;
age.secrets.restic-env.rekeyFile = ../../secrets/hosts/homelab/restic-env.age;
services.restic.backups.server = {
repository = "b2:fireproof-backup";
timerConfig = null;
passwordFile = "${config.age.secrets.restic-password.path}";
environmentFile = "${config.age.secrets.restic-env.path}";
};
}

View file

@ -0,0 +1,21 @@
{config, ...}: let
domain = "bitwarden.nickolaj.com";
in {
services.vaultwarden = {
enable = true;
config = {
DOMAIN = "https://${domain}";
SIGNUPS_ALLOWED = false;
ROCKET_ADDRESS = "127.0.0.1";
ROCKET_PORT = 8222;
};
};
services.nginx.virtualHosts."${domain}" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://${toString config.services.vaultwarden.config.ROCKET_ADDRESS}:${toString config.services.vaultwarden.config.ROCKET_PORT}";
};
};
}