diff --git a/hosts/laptop-server/config/bootloader.nix b/hosts/laptop-server/config/bootloader.nix index 0e90e13..daf5a93 100644 --- a/hosts/laptop-server/config/bootloader.nix +++ b/hosts/laptop-server/config/bootloader.nix @@ -1,7 +1,13 @@ { ... }: { - boot.loader = { - systemd-boot.enable = true; - efi.canTouchEfiVariables = true; + boot = { + loader = { + systemd-boot = { + enable = true; + }; + efi.canTouchEfiVariables = true; + }; + + initrd.systemd.enable = true; }; -} \ No newline at end of file +} diff --git a/hosts/laptop-server/config/mounts.nix b/hosts/laptop-server/config/mounts.nix index 734d786..545099a 100644 --- a/hosts/laptop-server/config/mounts.nix +++ b/hosts/laptop-server/config/mounts.nix @@ -3,13 +3,16 @@ fileSystems."/mnt/hdd" = { device = "/dev/mapper/hdd"; fsType = "btrfs"; - options = [ "compression=zstd:3" "autodefrag" "nofail" ]; + options = [ "compress=zstd:3" "autodefrag" "nofail" ]; encrypted = { enable = true; label = "hdd"; blkDev = "/dev/disk/by-uuid/eab5e1d6-6956-46fd-b3ac-5fcf525e1df8"; - keyFile = "/mnt-root/root/hdd.key"; + keyFile = "/sysroot/root/hdd.key"; }; }; -} \ No newline at end of file + + # Loading the uas kernel module early is needed to mount the above drive via USB-SATA adapter + boot.initrd.kernelModules = [ "uas" ]; +} diff --git a/hosts/laptop-server/config/services/caddy/Caddyfile b/hosts/laptop-server/config/services/caddy/Caddyfile new file mode 100644 index 0000000..7e241e1 --- /dev/null +++ b/hosts/laptop-server/config/services/caddy/Caddyfile @@ -0,0 +1,36 @@ +# Global options +{ + acme_dns porkbun { + api_key {env.PORKBUN_API_KEY} + api_secret_key {env.PORKBUN_API_SECRET_KEY} + } + email ty@myriation.xyz + + storage file_system { + root /var/lib/caddy + } +} + +# Handle all routes handled by this server +https://*.m.myriation.xyz { + # Enforce always using HTTPS + header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" + # Give an HTTP cat on any errors + handle_errors { + header Content-Type text/html + respond "Error :(\"cat\"" {http.error.status_code} + } + + # Configure all service matchers + @jellyfin host jellyfin.m.myriation.xyz + + # Handle all services + handle @jellyfin { + reverse_proxy jellyfin.containers:8096 + } + + # Handle all unmatched requests as a 404 + handle { + error "Not Found" 404 + } +} \ No newline at end of file diff --git a/hosts/laptop-server/config/services/caddy/default.nix b/hosts/laptop-server/config/services/caddy/default.nix new file mode 100644 index 0000000..d280979 --- /dev/null +++ b/hosts/laptop-server/config/services/caddy/default.nix @@ -0,0 +1,26 @@ +{ pkgs, secrets, ... }: +{ + # TODO: Containerize once I setup a proper shared bridge network + services.caddy = { + enable = true; + package = pkgs.caddy.withPlugins { + plugins = [ "github.com/caddy-dns/porkbun@v0.2.1" ]; + hash = "sha256-oizWuPXI0M9ngBCt/iEXWt+/33wpKlCs1yBPKnzFhRY="; + }; + # Use a custom config because doing Caddyfile in multiline nix strings + # feels messy (and not syntax highlighted) + configFile = ./Caddyfile; + }; + + # Pass secrets through the systemd service's environment variables + systemd.services.caddy.environment = { + PORKBUN_API_KEY = secrets.programs.caddy.porkbun_api_key; + PORKBUN_API_SECRET_KEY = secrets.programs.caddy.porkbun_secret_key; + }; + + # Allow caddy through the firewall + networking.firewall = { + allowedTCPPorts = [ 80 443 ]; # HTTP/1-2 + allowedUDPPorts = [ 443 ]; # HTTP/3 w/ QUIC + }; +} diff --git a/hosts/laptop-server/config/services/default.nix b/hosts/laptop-server/config/services/default.nix index c3c9c87..f442884 100644 --- a/hosts/laptop-server/config/services/default.nix +++ b/hosts/laptop-server/config/services/default.nix @@ -1,13 +1,9 @@ { ... }: { imports = [ - ./jellyfin.nix + ./networking.nix + # Individual services + ./caddy + ./jellyfin ]; - - networking = { - nat = { - enable = true; - externalInterface = "wlp2s0"; - }; - }; -} \ No newline at end of file +} diff --git a/hosts/laptop-server/config/services/jellyfin.nix b/hosts/laptop-server/config/services/jellyfin/default.nix similarity index 73% rename from hosts/laptop-server/config/services/jellyfin.nix rename to hosts/laptop-server/config/services/jellyfin/default.nix index eabd113..4d13301 100644 --- a/hosts/laptop-server/config/services/jellyfin.nix +++ b/hosts/laptop-server/config/services/jellyfin/default.nix @@ -1,7 +1,7 @@ { ... }: { containers.jellyfin = { - config = { pkgs, ...}: { + config = { pkgs, ... }: { system.stateVersion = "25.05"; services.jellyfin = { @@ -13,9 +13,13 @@ networking.firewall.enable = false; }; autoStart = true; - privateNetwork = true; - hostAddress = "172.30.1.2"; # TODO define in config option - localAddress = "172.30.0.2"; + + bindMounts = { + "/var/lib/jellyfin/libraries" = { + hostPath = "/mnt/hdd/jellyfin"; + isReadOnly = false; + }; + }; }; networking = { @@ -23,4 +27,4 @@ nat.internalInterfaces = [ "ve-jellyfin" ]; networkmanager.unmanaged = [ "interface-name:ve-jellyfin" ]; }; -} \ No newline at end of file +} diff --git a/hosts/laptop-server/config/services/networking.nix b/hosts/laptop-server/config/services/networking.nix new file mode 100644 index 0000000..57dff59 --- /dev/null +++ b/hosts/laptop-server/config/services/networking.nix @@ -0,0 +1,34 @@ +{ lib, ... }: +let + services = { + jellyfin = { + hostByte = 2; + ports = []; + }; + }; +in { + config = lib.mkMerge ([{ + # Config always added + networking = { + nat = { + enable = true; + externalInterface = "wlp2s0"; + }; + }; + }] ++ builtins.map (serviceName: { + # Config added per-service + containers.${serviceName} = { + privateNetwork = true; + # Give it an address of 172.30.0.X on the host-side and 172.30.1.X inside the container + # This appears to be necessary as both having addresses the same seems to cause issues + hostAddress = "172.30.0.${builtins.toString services.${serviceName}.hostByte}"; + localAddress = "172.30.1.${builtins.toString services.${serviceName}.hostByte}"; + }; + + networking = { + firewall.trustedInterfaces = [ "ve-${serviceName}" ]; + nat.internalInterfaces = [ "ve-${serviceName}" ]; + networkmanager.unmanaged = [ "interface-name:ve-${serviceName}" ]; + }; + }) (builtins.attrNames services)); +} diff --git a/hosts/laptop-server/hardware-configuration.nix b/hosts/laptop-server/hardware-configuration.nix index 5285839..3c1c125 100644 --- a/hosts/laptop-server/hardware-configuration.nix +++ b/hosts/laptop-server/hardware-configuration.nix @@ -38,4 +38,4 @@ nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; -} \ No newline at end of file +} diff --git a/secrets.example.nix b/secrets.example.nix index 76edd1d..5f3ab24 100644 --- a/secrets.example.nix +++ b/secrets.example.nix @@ -19,6 +19,12 @@ token = null; }; }; + + caddy = { + # The API key and secret key to use for provisioning HTTPS certificates + porkbun_api_key = null; + porkbun_secret_key = null; + }; }; passwords = {