first commit

This commit is contained in:
Louis Chih-Ming Lee 2026-01-26 01:16:35 +01:00
commit 2a3ea31491
52 changed files with 2991 additions and 0 deletions

View file

@ -0,0 +1,275 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page, on
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
{
inputs,
config,
lib,
pkgs,
...
}:
{
imports = [
# Include the results of the hardware scan.
./hardware-configuration.nix
#./impermanence.nix { inherit lib; }
./disko.nix
./network.nix
];
nix.settings.experimental-features = [
"nix-command"
"flakes"
];
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot.kernelPackages = pkgs.linuxPackages_latest;
networking.hostName = "T14p"; # Define your hostname.
# Pick only one of the below networking options.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
networking.networkmanager.enable = true; # Easiest to use and most distros use this by default.
services.mullvad-vpn.enable = true;
sops = {
defaultSopsFile = ./../../secrets.yaml;
defaultSopsFormat = "yaml";
age.keyFile = "/home/louis/.config/sops/age/keys.txt";
};
hardware.enableAllFirmware = true;
hardware.graphics = {
enable = true;
extraPackages = with pkgs; [
mesa
];
};
hardware.bluetooth = {
enable = true;
powerOnBoot = true;
#settings = {
# General = {
# Experimental = true;
# FastConnectable = true;
# };
# Policy = {
# AutoEnable = true;
# };
#};
};
# Set your time zone.
time.timeZone = "Europe/Amsterdam";
# Configure network proxy if necessary
# networking.proxy.default = "http://user:password@proxy:port/";
# networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
# Select internationalisation properties.
i18n = {
defaultLocale = "en_US.UTF-8";
extraLocales = [
"zh_TW.UTF-8/UTF-8"
"zh_CN.UTF-8/UTF-8"
"nl_NL.UTF-8/UTF-8"
];
};
i18n.inputMethod = {
type = "fcitx5";
enable = true;
fcitx5.addons = with pkgs; [
fcitx5-gtk
fcitx5-rime
fcitx5-chewing
qt6Packages.fcitx5-chinese-addons
rime-data
librime
];
fcitx5.waylandFrontend = true;
};
environment.variables = {
GTK_IM_MODULE = "fcitx";
QT_IM_MODULE = "fcitx";
XMODIFIERS = "@im=fcitx";
GLFW_IM_MODULE = "fcitx";
SDL_IM_MODULE = "fcitx";
MOZ_ENABLE_WAYLAND = 1;
QT_QPA_PLATFORM = "wayland";
};
# electron blurring in wayland
environment.sessionVariables = {
NIXOS_OZONE_WL = "1";
};
console = {
font = "Lat2-Terminus16";
#keyMap = "us";
useXkbConfig = true; # use xkb.options in tty.
};
# Enable the X11 windowing system.
services.xserver.enable = true;
#services.displayManager.cosmic-greeter.enable = true;
services.displayManager.gdm.enable = true;
services.desktopManager.cosmic.enable = true;
programs.sway = {
enable = true;
wrapperFeatures.gtk = true;
extraPackages = with pkgs; [
adwaita-icon-theme
gnome-themes-extra
];
};
fonts.packages = with pkgs; [
lxgw-fusionkai
noto-fonts
noto-fonts-cjk-sans
noto-fonts-cjk-serif
winePackages.fonts
noto-fonts-color-emoji
nerd-fonts.fira-code
];
services.keyd = {
enable = true;
keyboards = {
default = {
ids = [ "*" ];
settings = {
main = {
capslock = "layer(control)";
control = "capslock";
leftmeta = "layer(alt)";
leftalt = "layer(meta)";
rightalt = "esc";
};
};
};
hhkb = {
ids = [ "04fe:0021:f2a164d2" ];
settings = { };
};
};
};
# Configure keymap in X11
# services.xserver.xkb.layout = "us";
# services.xserver.xkb.options = "eurosign:e,caps:escape";
# Enable CUPS to print documents.
services.printing.enable = true;
# Enable sound.
# services.pulseaudio.enable = true;
# OR
services.pipewire = {
enable = true;
pulse.enable = true;
};
# Enable touchpad support (enabled default in most desktopManager).
services.libinput.enable = true;
# Define a user account. Don't forget to set a password with passwd.
users.users.louis = {
isNormalUser = true;
extraGroups = [
"wheel"
"networkmanager"
"video"
];
shell = pkgs.fish;
ignoreShellProgramCheck = true;
packages = with pkgs; [
keyd
tree
wl-clipboard
mako
killall
];
};
programs.firefox.enable = true;
# List packages installed in system profile.
# You can use https://search.nixos.org/ to find more packages (and options).
environment.systemPackages = with pkgs; [
vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
kdePackages.kdeconnect-kde
usbutils
wget
neovim
acpi
texliveFull
zathura
libreoffice
htop
ranger
teams-for-linux
gcc
gnumake
mullvad-vpn
mullvad
sops
age
ssh-to-age
];
# Some programs need SUID wrappers, can be configured further or are
# started in user sessions.
programs.mtr.enable = true;
programs.gnupg.agent = {
enable = true;
enableSSHSupport = true;
};
nixpkgs.config.allowUnfree = true;
# List services that you want to enable:
# Enable the OpenSSH daemon.
services.openssh.enable = true;
# Open ports in the firewall.
# networking.firewall.allowedTCPPorts = [ ... ];
# networking.firewall.allowedUDPPorts = [ ... ];
# Or disable the firewall altogether.
networking.firewall.enable = false;
# Copy the NixOS configuration file and link it from the resulting system
# (/run/current-system/configuration.nix). This is useful in case you
# accidentally delete configuration.nix.
#system.copySystemConfiguration = true;
# This option defines the first version of NixOS you have installed on this particular machine,
# and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
#
# Most users should NEVER change this value after the initial install, for any reason,
# even if you've upgraded your system to a new NixOS release.
#
# This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
# so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
# to actually do that.
#
# This value being lower than the current NixOS release does NOT mean your system is
# out of date, out of support, or vulnerable.
#
# Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
# and migrated your data accordingly.
#
# For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
system.stateVersion = "25.05"; # Did you read the comment?
}

70
hosts/T14p/disko.nix Normal file
View file

@ -0,0 +1,70 @@
{
disko.devices = {
disk = {
main = {
type = "disk";
device = "/dev/nvme1n1";
content = {
type = "gpt";
partitions = {
ESP = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
luks = {
size = "100%";
content = {
type = "luks";
name = "crypted";
# disable settings.keyFile if you want to use interactive password entry
#passwordFile = "/tmp/secret.key"; # Interactive
settings = {
allowDiscards = true;
#keyFile = "/tmp/secret.key";
};
#additionalKeyFiles = [ "/tmp/additionalSecret.key" ];
content = {
type = "btrfs";
extraArgs = [ "-f" ];
subvolumes = {
"@root" = {
mountpoint = "/";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@persist" = {
mountpoint = "/persist";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@nix" = {
mountpoint = "/nix";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@swap" = {
mountpoint = "/.swapvol";
swap.swapfile.size = "20G";
};
};
};
};
};
};
};
};
};
};
}

View file

@ -0,0 +1,26 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
imports =
[ (modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ "xhci_pci" "thunderbolt" "nvme" "usb_storage" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.enp0s31f6.useDHCP = lib.mkDefault true;
# networking.interfaces.wlp0s20f3.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -0,0 +1,56 @@
{ lib, ... }:
let
impermanence = builtins.fetchTarball "https://github.com/nix-community/impermanence/archive/master.tar.gz";
in
{
boot.initrd.postResumeCommands = lib.mkAfter ''
mkdir /btrfs_tmp
mount /dev/mapper/crypted /btrfs_tmp
if [[ -e /btrfs_tmp/@root ]]; then
mkdir -p /btrfs_tmp/@old_roots
timestamp=$(date --date="@$(stat -c %Y /btrfs_tmp/root)" "+%Y-%m-%-d_%H:%M:%S")
mv /btrfs_tmp/@root "/btrfs_tmp/@old_roots/$timestamp"
fi
delete_subvolume_recursively() {
IFS=$'\n'
for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do
delete_subvolume_recursively "/btrfs_tmp/$i"
done
btrfs subvolume delete "$1"
}
for i in $(find /btrfs_tmp/@old_roots/ -maxdepth 1 -mtime +10); do
delete_subvolume_recursively "$i"
done
btrfs subvolume create /btrfs_tmp/@root
umount /btrfs_tmp
'';
imports = [ "${impermanence}/nixos.nix" ];
environment.persistence."/persist" = {
enable = true;
hideMounts = true;
directories = [
"/var/log"
"/var/lib/bluetooth"
"/var/lib/nixox"
"/var/lib/systemd/coredump"
"/etc/NetworkManager/system-connections"
];
files = [
"/etc/machine-id"
];
users.louis = {
directories = [
"Documents"
"Downloads"
];
};
};
fileSystems."/persist".neededForBoot = true;
}

34
hosts/T14p/leiden.crt Normal file
View file

@ -0,0 +1,34 @@
-----BEGIN CERTIFICATE-----
MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw
MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV
BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy
dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B
3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY
tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/
Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2
VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT
79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6
c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT
Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l
c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee
UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE
Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G
A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF
Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO
VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3
ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs
8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR
iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze
Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ
XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/
qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB
VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB
L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG
jjxDah2nGN59PRbxYvnKkKj9
-----END CERTIFICATE-----

83
hosts/T14p/network.nix Normal file
View file

@ -0,0 +1,83 @@
{
pkgs,
lib,
config,
...
}:
let
wifi = ssid: alias: priority: {
sops.secrets."wifi_${alias}" = { };
sops.templates."wifi_${alias}.nmconnection" = {
path = "/etc/NetworkManager/system-connections/wifi_${ssid}.nmconnection";
owner = "root";
group = "root";
mode = "0600";
content = ''
[connection]
id=${ssid}
type=wifi
autoconnect=true
autoconnect-priority=${toString priority}
[wifi]
ssid=${ssid}
mode=infrastructure
[wifi-security]
key-mgmt=wpa-psk
psk=${config.sops.placeholder."wifi_${alias}"}
[ipv4]
method=auto
[ipv6]
addr-gen-mode=default
method=auto
'';
};
};
in
lib.mkMerge [
(wifi "Ziggo966936B" "home" 100)
{
sops.secrets.wifi_leiden_identity = { };
sops.secrets.wifi_leiden_password = { };
sops.templates."wifi_eduroam.nmconnection" = {
path = "/etc/NetworkManager/system-connections/eduroam.nmconnection";
owner = "root";
group = "root";
mode = "0600";
content = ''
[connection]
id=eduroam
type=wifi
[wifi]
ssid=eduroam
mode=infrastructure
[wifi-security]
key-mgmt=wpa-eap
[802-1x]
eap=peap
identity=${config.sops.placeholder.wifi_leiden_identity}
password=${config.sops.placeholder.wifi_leiden_password}
anonymous-identity=anonymous@leidenuniv.nl
phase2-auth=mschapv2
ca-cert=${./leiden.crt}
'';
};
}
{
# Run nmcli reload after every switch
system.activationScripts.nm-reload = {
text = ''
${pkgs.networkmanager}/bin/nmcli connection reload || true
'';
deps = [ ];
};
}
]

View file

@ -0,0 +1,64 @@
{
pkgs,
lib,
domain,
isProd,
inputs,
config,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
(modulesPath + "/profiles/qemu-guest.nix")
./disko-config.nix
./secret.nix
./media.nix
./nginx.nix
./immich.nix
./forego.nix
# ./vm.nix
];
system.stateVersion = "25.11";
environment.systemPackages = with pkgs; [
vim
cifs-utils
btrfs-progs
forgejo
];
nix.settings.experimental-features = [
"nix-command"
"flakes"
];
boot.loader.grub = {
# enable = true;
efiSupport = true;
efiInstallAsRemovable = true;
};
services.openssh.enable = true;
users.users.root.openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDBUxBUar3CyZCZTet3s8s28Pu1d0viuDe6YoMQBVdFB louis@T14p"
];
networking.hostName = "webserver";
networking.firewall.allowedTCPPorts = [
80
443
22
];
security.acme = lib.mkIf isProd {
acceptTerms = true;
defaults.email = "admin@${domain}";
};
}

View file

@ -0,0 +1,86 @@
{ lib, ... }:
let
disk-id = "scsi-0QEMU_QEMU_HARDDISK_110162268";
data-id = "scsi-0HC_Volume_104473479";
in
{
disko.devices = {
# --- DISK 1: MAIN OS (38GB) ---
disk.main = {
# You were right! This IS the correct ID for the 38GB drive.
device = "/dev/disk/by-id/${disk-id}";
type = "disk";
content = {
type = "gpt";
partitions = {
boot = {
size = "1M";
type = "EF02";
priority = 1;
};
ESP = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
root = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
};
};
};
};
};
disk.volume = {
# This is the ID for your volume (from your ls output)
device = "/dev/disk/by-id/${disk-id}";
type = "disk";
content = {
type = "gpt";
partitions = {
data = {
size = "100%";
content = {
type = "btrfs";
extraArgs = [ "-f" ];
mountpoint = "/mnt/data";
subvolumes = {
"@postgresql" = {
mountpoint = "/mnt/data/postgresql";
mountOptions = [
"nodatacow"
"noatime"
];
};
"@forgejo" = {
mountpoint = "/mnt/data/forgejo";
mountOptions = [
"compress=zstd"
"noatime"
];
};
"@immich" = {
mountpoint = "/mnt/data/immich";
mountOptions = [
"compress=zstd"
"noatime"
];
};
};
};
};
};
};
};
};
}

View file

@ -0,0 +1,71 @@
{ lib, config, ... }:
let
volume-id = "scsi-0HC_Volume_104473479";
in
{
systemd.tmpfiles.rules = [
"d /mnt/ 0755 root root -"
"d /mnt/box 0770 root root -"
"d /mnt/box/immich 0770 immich immich -"
"d /mnt/box/immich 0770 immich immich -"
"d /mnt/box/immich/library 0770 immich immich -"
"d /mnt/box/immich/upload 0770 immich immich -"
"d /mnt/box/immich/thumbs 0770 immich immich -"
"d /mnt/box/immich/encoded-video 0770 immich immich -"
"d /mnt/box/immich/profile 0770 immich immich -"
"d /mnt/box/immich/backups 0770 immich immich -"
"d /mnt/volume 0777 root root -"
"d /mnt/volume/postgresql 0700 postgres postgres -"
"d /mnt/volume/forgejo 0750 forgejo forgejo -"
"d /mnt/volume/immich 0750 immich immich -"
];
fileSystems."/mnt/data/postgres" = {
device = "/dev/disk/by-id/${volume-id}";
fsType = "btrfs";
options = [
"subvol=@postgres"
"nodatacow" # <--- Disables Copy-on-Write for performance
"noatime"
];
};
fileSystems."/mnt/data/immich" = {
device = "/dev/disk/by-id/${volume-id}";
fsType = "btrfs";
options = [
"subvol=@immich"
"compress=zstd"
"noatime"
];
};
fileSystems."/mnt/data/forgejo" = {
device = "/dev/disk/by-id/${volume-id}";
fsType = "btrfs";
options = [
"subvol=@forgejo"
"compress=zstd"
"noatime"
];
};
#fileSystems."/mnt/box" = {
# device = "//u536222.your-storagebox.de/backup";
# fsType = "cifs";
# options = [
# "x-systemd.automount"
# "noauto"
# "rw"
# "credentials=${config.sops.secrets.storage_box_credentials.path}"
# "uid=900"
# "gid=100"
# "file_mode=0660"
# "dir_mode=0770"
# ];
#};
}

74
hosts/hetzner/forego.nix Normal file
View file

@ -0,0 +1,74 @@
{
domain,
isProd,
config,
pkgs,
...
}:
{
# 1. Access the Secret
sops.secrets.forgejo_db_password = {
owner = "forgejo";
# Restart forgejo if the password changes
restartUnits = [ "forgejo.service" ];
};
services.forgejo = {
enable = true;
# 2. STORAGE (SSD)
stateDir = "/mnt/data/forgejo";
# 3. DATABASE (Shared Postgres)
database = {
type = "postgres";
name = "forgejo";
user = "forgejo";
createDatabase = false; # We let NixOS manage this below
socket = "/run/postgresql"; # Ultra-fast socket connection
passwordFile = config.sops.secrets.forgejo_db_password.path;
};
# 4. SETTINGS
settings = {
server = {
DOMAIN = "git.${domain}";
ROOT_URL = "https://git.${domain}/";
HTTP_PORT = 3000;
# Run internal SSH on 2222 so it doesn't block your Admin SSH (22)
SSH_PORT = 2222;
START_SSH_SERVER = true;
};
# Disable registration to prevent random internet people from joining
service.DISABLE_REGISTRATION = true;
# Optional: Metrics for Grafana later
metrics.ENABLED = true;
};
};
# 5. POSTGRESQL PROVISIONING
# This automatically creates the DB and User when you deploy
services.postgresql = {
ensureDatabases = [ "forgejo" ];
ensureUsers = [
{
name = "forgejo";
ensureDBOwnership = true;
}
];
};
# 6. REVERSE PROXY
services.nginx.virtualHosts."git.${domain}" = {
forceSSL = isProd;
enableACME = isProd;
locations."/" = {
proxyPass = "http://127.0.0.1:3000";
};
};
# 7. FIREWALL
# Allow Git-over-SSH on the custom port
networking.firewall.allowedTCPPorts = [ 2222 ];
}

79
hosts/hetzner/immich.nix Normal file
View file

@ -0,0 +1,79 @@
{
domain,
lib,
isProd,
config,
pkgs,
...
}:
{
sops.secrets.immich_db_password = { };
sops.secrets.immich_jwt_secret = { };
sops.templates."immich.env".content = ''
DB_PASSWORD=${config.sops.placeholder.immich_db_password}
JWT_SECRET=${config.sops.placeholder.immich_jwt_secret}
'';
#users.users.immich.extraGroups = [ "users" ];
users.users.immich.uid = 900;
users.groups.immich.gid = 900;
services.immich = {
enable = true;
host = "127.0.0.1";
port = 2283;
mediaLocation = "/mnt/media/immich";
secretsFile = config.sops.templates."immich.env".path;
redis.enable = true;
database = {
enable = true;
createDB = true;
user = "immich";
name = "immich";
host = "/run/postgresql";
};
machine-learning.enable = true;
};
systemd.services.immich-server = {
requires = [ "mnt-media.mount" ];
after = [ "mnt-media.mount" ];
serviceConfig = {
DynamicUser = lib.mkForce false;
ReadWritePaths = [ "/mnt/media/immich" ];
BindPaths = [ "/mnt/media/immich" ];
};
};
services.postgresql = {
enable = true;
dataDir = "/mnt/data/postgresql";
ensureDatabases = [ "immich" ];
ensureUsers = [
{
name = "immich";
ensureDBOwnership = true;
}
];
};
services.nginx.virtualHosts."photo.${domain}" = {
forceSSL = isProd;
enableACME = isProd;
locations."/" = {
proxyPass = "http://127.0.0.1:2283";
proxyWebsockets = true;
extraConfig = "client_max_body_size 50G;";
};
};
}

34
hosts/hetzner/media.nix Normal file
View file

@ -0,0 +1,34 @@
{ config, ... }:
{
systemd.tmpfiles.rules = [
# 1. THE PARENT DIRS
# Change 0770 -> 0755 so users like 'postgres' can walk through the door.
"d /mnt/data 0755 root root -"
"d /mnt/media 0755 root root -"
# 2. THE SERVICES (SSD / Data)
# IMPORTANT: These MUST match where your services.postgresql.dataDir points
"d /mnt/data/postgresql 0700 postgres postgres -"
"d /mnt/data/forgejo 0750 forgejo forgejo -"
# 3. THE STORAGE (HDD / Media)
"d /mnt/media/immich 0750 immich immich -"
];
fileSystems."/mnt/media" = {
device = "//u536222.your-storagebox.de/backup";
fsType = "cifs";
options = [
"nofail"
"noperm"
"rw"
"credentials=${config.sops.secrets.storage_box_credentials.path}"
"uid=900"
"gid=900"
"forceuid"
"forcegid"
"file_mode=0660"
"dir_mode=0770"
];
};
}

18
hosts/hetzner/nginx.nix Normal file
View file

@ -0,0 +1,18 @@
{ domain, isProd, ... }:
{
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedTlsSettings = isProd;
virtualHosts."${domain}" = {
forceSSL = isProd;
enableACME = isProd;
locations."/test" = {
return = "200 'Hello! You are accessing: ${domain}/test'";
extraConfig = "default_type text/plain;";
};
};
};
}

10
hosts/hetzner/secret.nix Normal file
View file

@ -0,0 +1,10 @@
{ ... }:
{
sops = {
defaultSopsFile = ./../../secrets.yaml;
defaultSopsFormat = "yaml";
age.keyFile = "/var/lib/sops-nix/key.txt";
};
sops.secrets.storage_box_credentials = { };
}

55
hosts/hetzner/vm.nix Normal file
View file

@ -0,0 +1,55 @@
{ lib, ... }:
{
virtualisation.vmVariant = {
virtualisation = {
memorySize = 4096;
cores = 2;
graphics = false;
sharedDirectories = {
sops-keys = {
source = "/home/louis/.config/sops/age";
target = "/var/lib/sops-nix";
};
};
forwardPorts = [
{
from = "host";
host.port = 8080;
guest.port = 80;
}
];
};
fileSystems."/mnt/volume" = lib.mkForce {
device = "none";
fsType = "tmpfs";
options = [
"size=2G"
"mode=777"
];
};
fileSystems."/mnt/box" = lib.mkForce {
device = "none";
fsType = "tmpfs";
options = [
"size=2G"
"mode=777"
];
};
sops.age.keyFile = lib.mkForce "/var/lib/sops-nix/keys.txt";
users.users.root.password = "root";
services.openssh.settings.PermitRootLogin = "yes";
services.openssh.settings.PasswordAuthentication = true;
documentation.enable = false;
systemd.services.NetworkManager-wait-online.enable = false;
networking.useDHCP = lib.mkDefault true;
services.qemuGuest.enable = true;
networking.enableIPv6 = false;
};
}