galanthus: Tailscale services declaratively, Jellyfin no container

Tailscale services can now be declared in Nix, which also eliminates my
need for containers completely.

Jellyfin hardware encoding can now also be implemented using the Nix
module.

Hardware support now implemented with nixos-hardware.
This commit is contained in:
Jan Kremer 2026-02-05 11:41:00 +01:00
parent 6addf51d68
commit aaf705b7d6
No known key found for this signature in database
6 changed files with 88 additions and 111 deletions

47
flake.lock generated
View file

@ -10,11 +10,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1762618334,
"narHash": "sha256-wyT7Pl6tMFbFrs8Lk/TlEs81N6L+VSybPfiIgzU8lbQ=",
"lastModified": 1770165109,
"narHash": "sha256-9VnK6Oqai65puVJ4WYtCTvlJeXxMzAp/69HhQuTdl/I=",
"owner": "ryantm",
"repo": "agenix",
"rev": "fcdea223397448d35d9b31f798479227e80183f6",
"rev": "b027ee29d959fda4b60b57566d64c98a202e0feb",
"type": "github"
},
"original": {
@ -31,11 +31,11 @@
]
},
"locked": {
"lastModified": 1770072317,
"narHash": "sha256-hxkLrjOO7pZ5m3ZRP3nCQEccSFDvC2cj7quEldSKhtM=",
"lastModified": 1770165565,
"narHash": "sha256-MplBxmxr8RGSr5lo/bbVcFR52i0b/IagZ1OVDiSzCQA=",
"owner": "9001",
"repo": "copyparty",
"rev": "6694998985e98326ca4ca0a0724cfd4901be2430",
"rev": "16403d8c6c6f768cc69e3366e1c2c648b43b921e",
"type": "github"
},
"original": {
@ -73,11 +73,11 @@
]
},
"locked": {
"lastModified": 1768764703,
"narHash": "sha256-5ulSDyOG1U+1sJhkJHYsUOWEsmtLl97O0NTVMvgIVyc=",
"lastModified": 1770184146,
"narHash": "sha256-DsqnN6LvXmohTRaal7tVZO/AKBuZ02kPBiZKSU4qa/k=",
"owner": "LnL7",
"repo": "nix-darwin",
"rev": "0fc4e7ac670a0ed874abacf73c4b072a6a58064b",
"rev": "0d7874ef7e3ba02d58bebb871e6e29da36fa1b37",
"type": "github"
},
"original": {
@ -129,11 +129,11 @@
]
},
"locked": {
"lastModified": 1769978395,
"narHash": "sha256-gj1yP3spUb1vGtaF5qPhshd2j0cg4xf51pklDsIm19Q=",
"lastModified": 1770263241,
"narHash": "sha256-R1WFtIvp38hS9x63dnijdJw1KyIiy30KGea6e6N7LHs=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "984708c34d3495a518e6ab6b8633469bbca2f77a",
"rev": "04e5203db66417d548ae1ff188a9f591836dfaa7",
"type": "github"
},
"original": {
@ -142,13 +142,29 @@
"type": "github"
}
},
"nixos-hardware": {
"locked": {
"lastModified": 1769302137,
"narHash": "sha256-QEDtctEkOsbx8nlFh4yqPEOtr4tif6KTqWwJ37IM2ds=",
"owner": "NixOS",
"repo": "nixos-hardware",
"rev": "a351494b0e35fd7c0b7a1aae82f0afddf4907aa8",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "master",
"repo": "nixos-hardware",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1770019141,
"narHash": "sha256-VKS4ZLNx4PNrABoB0L8KUpc1fE7CLpQXQs985tGfaCU=",
"lastModified": 1770197578,
"narHash": "sha256-AYqlWrX09+HvGs8zM6ebZ1pwUqjkfpnv8mewYwAo+iM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "cb369ef2efd432b3cdf8622b0ffc0a97a02f3137",
"rev": "00c21e4c93d963c50d4c0c89bfa84ed6e0694df2",
"type": "github"
},
"original": {
@ -164,6 +180,7 @@
"copyparty": "copyparty",
"darwin": "darwin_2",
"home-manager": "home-manager_2",
"nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs"
}
},

View file

@ -3,6 +3,7 @@
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
darwin = {
url = "github:LnL7/nix-darwin";
inputs.nixpkgs.follows = "nixpkgs";

View file

@ -1,11 +1,14 @@
{
config,
inputs,
lib,
modulesPath,
...
}:
{
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
inputs.nixos-hardware.nixosModules.common-cpu-intel
];
boot = {
initrd.availableKernelModules = [
@ -54,6 +57,9 @@
interfaces.eno1.wakeOnLan.enable = true;
};
environment.sessionVariables = {
LIBVA_DRIVER_NAME = "i965"; # Prefered for Skylake processors
};
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -1,91 +1,40 @@
{ pkgs, ... }:
{
containers.jellyfin = {
autoStart = true;
allowedDevices = [
{
node = "/dev/dri/card0";
modifier = "rw";
}
{
node = "/dev/dri/renderD128";
modifier = "rw";
}
];
bindMounts = {
"/media" = {
hostPath = "/mnt/sdb1/media";
isReadOnly = false;
services = {
jellyfin = {
enable = true; # port = 8096
hardwareAcceleration = {
enable = true;
type = "qsv";
device = "/dev/dri/renderD128";
};
"/dev/dri/card0" = {
hostPath = "/dev/dri/card0";
isReadOnly = false;
};
"/dev/dri/renderD128" = {
hostPath = "/dev/dri/renderD128";
isReadOnly = false;
# forceEncodingConfig = true;
transcoding = {
enableHardwareEncoding = true;
};
};
};
config =
{ pkgs, ... }:
{
services = {
jellyfin = {
enable = true; # port = 8096
};
tailscale = {
enable = true;
useRoutingFeatures = "server";
interfaceName = "userspace-networking";
};
};
environment.systemPackages = with pkgs; [
jellyfin
jellyfin-web
jellyfin-ffmpeg
libva-utils
## Grab EPG data daily
systemd = {
services = {
epg = {
script = "${pkgs.nodejs}/bin/npm run --prefix /media/TV/epg/ grab -- --channels=custom.channels.xml";
path = [
pkgs.bash
pkgs.nodejs
];
## Hardware transcoding
nixpkgs.config.allowUnfree = true;
hardware.graphics = {
enable = true;
extraPackages = with pkgs; [
## Intel Core i5 Skylake
intel-ocl
intel-media-driver
intel-compute-runtime-legacy1
];
serviceConfig = {
Type = "oneshot";
User = "root";
};
## Grab EPG data daily
systemd = {
services = {
epg = {
script = "${pkgs.nodejs}/bin/npm run --prefix /media/TV/epg/ grab -- --channels=custom.channels.xml";
path = [
pkgs.bash
pkgs.nodejs
];
serviceConfig = {
Type = "oneshot";
User = "root";
};
startAt = "daily"; # Creates a timer
};
jellyfin.environment.LIBVA_DRIVER_NAME = "iHD";
};
timers.epg.timerConfig.Persistent = true;
};
environment.sessionVariables = {
LIBVA_DRIVER_NAME = "iHD";
};
system.stateVersion = "24.05";
startAt = "daily"; # Creates a timer
};
jellyfin.environment.LIBVA_DRIVER_NAME = "iHD";
};
timers.epg.timerConfig.Persistent = true;
};
}

View file

@ -9,7 +9,6 @@
global = {
"vfs objects" = "catia fruit streams_xattr";
# "fruit:model" = "MacPro7,1@ECOLOR=226,226,224";
"fruit:model" = "MacSamba";
};
TimeMachine = {

View file

@ -4,29 +4,34 @@
enable = true;
useRoutingFeatures = "both";
extraUpFlags = [ "--ssh" ];
serve = {
enable = true;
services = {
cloud = {
endpoints = {
"tcp:443" = "https://localhost:3923";
};
};
jellyfin = {
endpoints = {
"tcp:443" = "https://localhost:8096";
};
};
};
};
};
networking = {
nftables.enable = true;
firewall = {
enable = true;
# Always allow traffic from your Tailscale network
trustedInterfaces = [ "${config.services.tailscale.interfaceName}" ];
# Allow the Tailscale UDP port through the firewall
allowedUDPPorts = [ config.services.tailscale.port ];
checkReversePath = "loose";
};
};
# 2. Force tailscaled to use nftables (Critical for clean nftables-only systems)
# This avoids the "iptables-compat" translation layer issues.
systemd.services.tailscaled.serviceConfig.Environment = [
"TS_DEBUG_FIREWALL_MODE=nftables"
];
# 3. Optimization: Prevent systemd from waiting for network online
# (Optional but recommended for faster boot with VPNs)
# systemd.network.wait-online.enable = false;
# boot.initrd.systemd.network.wait-online.enable = false;
systemd.network.wait-online.ignoredInterfaces = [ "${config.services.tailscale.interfaceName}" ];
}