me like nix
0

Configure Feed

Select the types of activity you want to include in your feed.

1{ pkgs, lib, ... }: 2 3let 4 # Patch Invidious addon to prepend instance URL to relative stream/dash URLs 5 patchedInvidious = pkgs.kodiPackages.invidious.overrideAttrs (old: { 6 postPatch = (old.postPatch or "") + '' 7 substituteInPlace resources/lib/invidious_plugin.py \ 8 --replace-fail \ 9 'url = video_info["dashUrl"]' \ 10 'url = video_info["dashUrl"]; url = self.api_client.instance_url + url if url.startswith("/") else url' \ 11 --replace-fail \ 12 'url = video_info["formatStreams"][-1]["url"]' \ 13 'url = video_info["formatStreams"][-1]["url"]; url = self.api_client.instance_url + url if url.startswith("/") else url' 14 ''; 15 }); 16 17 myKodi = pkgs.kodi-gbm.withPackages (kodiPkgs: with kodiPkgs; [ 18 jellyfin 19 patchedInvidious 20 ]); 21 22 kodiAdvancedSettings = pkgs.writeText "advancedsettings.xml" '' 23 <advancedsettings version="1.0"> 24 <videoplayer> 25 <useprimedecoder>true</useprimedecoder> 26 <useprimedecoderforhw>true</useprimedecoderforhw> 27 </videoplayer> 28 </advancedsettings> 29 ''; 30in 31{ 32 imports = [ ../pi-common/wifi.nix ]; 33 34 networking.hostName = "kodi-pi"; 35 36 # Use the new generational bootloader (matches nixos-raspberrypi installer) 37 boot.loader.raspberry-pi.bootloader = "kernel"; 38 39 # Force 4K30 output when EDID read fails (TV may not be ready at boot) 40 boot.kernelParams = [ "video=HDMI-A-1:3840x2160@30D" ]; 41 42 # Filesystems (matching nixos-raspberrypi installer layout) 43 fileSystems."/" = { 44 device = "/dev/disk/by-label/NIXOS_SD"; 45 fsType = "ext4"; 46 options = [ "noatime" ]; 47 }; 48 fileSystems."/boot/firmware" = { 49 device = "/dev/disk/by-label/FIRMWARE"; 50 fsType = "vfat"; 51 options = [ "noatime" "noauto" "x-systemd.automount" "x-systemd.idle-timeout=1min" ]; 52 }; 53 54 # Graphics 55 hardware.graphics.enable = true; 56 57 # Pi firmware config.txt settings for Kodi 58 hardware.raspberry-pi.config.all.options = { 59 gpu_mem = { enable = true; value = 256; }; 60 hdmi_force_hotplug = { enable = true; value = true; }; 61 }; 62 63 # Audio: ALSA only for HDMI passthrough 64 services.pipewire.enable = false; 65 services.pulseaudio.enable = false; 66 67 # Kodi via GBM (direct DRM, no compositor needed) 68 systemd.services.kodi = { 69 description = "Kodi media center"; 70 wantedBy = [ "multi-user.target" ]; 71 after = [ "network-online.target" "sound.target" "systemd-user-sessions.service" ]; 72 wants = [ "network-online.target" ]; 73 serviceConfig = { 74 Type = "simple"; 75 User = "kodi"; 76 ExecStartPre = pkgs.writeShellScript "kodi-setup" '' 77 mkdir -p /home/kodi/.kodi/userdata 78 cp -f ${kodiAdvancedSettings} /home/kodi/.kodi/userdata/advancedsettings.xml 79 80 # Patch Jellyfin addon settings (Pi 5 has HW HEVC decoder, no need to transcode) 81 JFSETTINGS=/home/kodi/.kodi/userdata/addon_data/plugin.video.jellyfin/settings.xml 82 if [ -f "$JFSETTINGS" ]; then 83 ${pkgs.gnused}/bin/sed -i \ 84 -e 's|"transcode_h265">true|"transcode_h265">false|' \ 85 -e 's|"transcodeHi10P">true|"transcodeHi10P">false|' \ 86 -e 's|"kodiCompanion">false|"kodiCompanion">true|' \ 87 "$JFSETTINGS" 88 fi 89 90 # Configure Invidious addon to use a specific instance (auto-detect is unreliable) 91 INVSETTINGS=/home/kodi/.kodi/userdata/addon_data/plugin.video.invidious/settings.xml 92 if [ -f "$INVSETTINGS" ]; then 93 ${pkgs.gnused}/bin/sed -i \ 94 -e 's|"auto_instance">true|"auto_instance">false|' \ 95 -e 's|"instance_url"[^<]*<|"instance_url">http://mira:3001<|' \ 96 -e 's|"disable_dash"[^>]*>[^<]*<|"disable_dash">false<|' \ 97 "$INVSETTINGS" 98 else 99 mkdir -p /home/kodi/.kodi/userdata/addon_data/plugin.video.invidious 100 cat > "$INVSETTINGS" <<'INVEOF' 101<settings version="2"> 102 <setting id="auto_instance">false</setting> 103 <setting id="instance_url">http://mira:3001</setting> 104 <setting id="disable_dash">false</setting> 105</settings> 106INVEOF 107 fi 108 109 ''; 110 ExecStart = "${myKodi}/bin/kodi-standalone"; 111 Restart = "always"; 112 TimeoutStopSec = "15s"; 113 TimeoutStopFailureMode = "kill"; 114 }; 115 }; 116 117 # Kodi user 118 users.users.kodi = { 119 isNormalUser = true; 120 extraGroups = [ "video" "audio" "input" "render" ]; 121 }; 122 123 # Admin user 124 users.users.sean = { 125 isNormalUser = true; 126 extraGroups = [ "wheel" ]; 127 openssh.authorizedKeys.keys = [ 128 "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDCIqgZ7kedxo+mOW7YG73Vp3zel3h180y3GKvHtRsXfGlpIIvRDy7pgCBQ4AGXYD4y78URQmFohYSAPqCPOPaWcU2un3XG9KvCzEsHmsbskPonitUmCiKvrKkb6oW4jCBtd7AEtBn+AiajAQFtPZ7NN2Df3AmTypvR6Irg7R+nxnfc9NTIHmGvxSDyWcbb4pguL20sctUSqGL6xGh8q/bqhdOThSimM+z9bEUNxK/5rPhwkNniMrp4pJcUrUiAh5/4DiRFG6KT+oeg+/myoz/Z1sPvAs7u/8JDQI4RshRD8Hu0oTkRBN6Hxj478q2SXbeBUZlD6IdjP3RhGpmSecoDdtWqKbpuV3eVRtQtba3KL86GBeV/bugaOdJ1Aud+1SOFJreAAuvxzMMKT+cdQZk6oOPP148DA/No+mDm/2S43lcdCXh79wA6YRAmKQ8jmZxTCtPutrvuZK1rguvvUlEoG/vhdNHh7eDa4Td07V6bjCRPUl8qk/e4M0E3pwsTlZc=" 129 "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIOIgEteUEW06dnBHe2z8vNLwz2iMKe8bba6JgMmOUpcBAAAABHNzaDo= sean@framework16" 130 ]; 131 }; 132 133 # SSH 134 services.openssh = { 135 enable = true; 136 settings = { 137 PasswordAuthentication = false; 138 PermitRootLogin = "no"; 139 }; 140 }; 141 142 # Accept unsigned store paths from local builds 143 nix.settings.require-sigs = false; 144 145 # Binary caches 146 nix.settings.substituters = [ 147 "https://nixos-raspberrypi.cachix.org" 148 "https://seanaye.cachix.org" 149 ]; 150 nix.settings.trusted-public-keys = [ 151 "nixos-raspberrypi.cachix.org-1:4iMO9LXa8BqhU+Rpg6LQKiGa2lsNh/j2oiYLNOQ5sPI=" 152 "seanaye.cachix.org-1:0Qf3cZ1SwnTwqaiNGltYySksjGHnemzRPiodThnvibA=" 153 ]; 154 155 # Networking 156 networking.useDHCP = true; 157 security.sudo.wheelNeedsPassword = false; 158 159 # Firewall 160 networking.firewall.allowedTCPPorts = [ 161 22 # SSH 162 8080 # Kodi web remote 163 ]; 164 165 environment.systemPackages = [ myKodi ]; 166 167 system.stateVersion = "24.11"; 168}