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 :(" {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 = {