From bec0f66f0d0a657bf10417701d000aa4290a177d Mon Sep 17 00:00:00 2001 From: Patrick Neff Date: Wed, 8 Jan 2025 00:00:32 +0100 Subject: [PATCH] add raspberry stuff --- flake.lock | 206 +++++++++ flake.nix | 17 + lib/genSslCert.nix | 30 ++ modules/home-manager/base/nixpkgs.nix | 4 +- .../mediacenter/kodi/advancedsettings.nix | 74 ---- .../home-manager/mediacenter/kodi/default.nix | 64 --- .../home-manager/mediacenter/kodi/kodi.nix | 417 +++++++----------- .../mediacenter/kodi/passwords.nix | 8 - modules/nixos/base/binary-cache/default.nix | 2 - modules/nixos/base/nixos/default.nix | 29 ++ modules/nixos/base/user/default.nix | 43 +- modules/nixos/home-manager/default.nix | 18 +- modules/nixos/mediacenter/default.nix | 1 + .../nixos/mediacenter/gokosync/default.nix | 4 + .../nixos/mediacenter/jellyfin/default.nix | 46 +- modules/nixos/mediacenter/kodi/default.nix | 43 +- .../kodi/secrets/advancedsettings.xml | 8 +- modules/nixos/raspberry-pi/default.nix | 8 + overlays/jellyfin.nix | 18 + overlays/kodi.nix | 16 +- pkgs/kodi/default.nix | 14 + .../advanced-emulator-launcher/default.nix | 14 + profiles/home-manager/kodi@pi0/home.nix | 11 + profiles/nixos/pi0/configuration.nix | 150 ++++--- profiles/nixos/pi0/hardware-configuration.nix | 71 ++- remote-deploy.sh | 6 +- 26 files changed, 758 insertions(+), 564 deletions(-) create mode 100644 lib/genSslCert.nix delete mode 100644 modules/home-manager/mediacenter/kodi/advancedsettings.nix delete mode 100644 modules/home-manager/mediacenter/kodi/default.nix delete mode 100644 modules/home-manager/mediacenter/kodi/passwords.nix create mode 100644 modules/nixos/mediacenter/gokosync/default.nix create mode 100644 modules/nixos/raspberry-pi/default.nix create mode 100644 overlays/jellyfin.nix create mode 100644 pkgs/kodi/default.nix create mode 100644 pkgs/kodiPackages/advanced-emulator-launcher/default.nix create mode 100644 profiles/home-manager/kodi@pi0/home.nix diff --git a/flake.lock b/flake.lock index 8e38b44..d64428f 100644 --- a/flake.lock +++ b/flake.lock @@ -349,6 +349,32 @@ "type": "github" } }, + "gokosync": { + "inputs": { + "flake-utils": [ + "flake-utils" + ], + "nixpkgs": [ + "nixpkgs" + ], + "systems": [ + "systems" + ] + }, + "locked": { + "lastModified": 1736215102, + "narHash": "sha256-0aMz+9Tk/a5AxUSZLubJpuYfSdgJaCwIK/6CSwuoP2g=", + "ref": "refs/heads/master", + "rev": "ebb45e7fbbb88c16fdb9e8de0d167e6c55510600", + "revCount": 7, + "type": "git", + "url": "ssh://git@git.gaja-group.com/odie/gokosync.git" + }, + "original": { + "type": "git", + "url": "ssh://git@git.gaja-group.com/odie/gokosync.git" + } + }, "guihua": { "flake": false, "locked": { @@ -451,6 +477,40 @@ "type": "github" } }, + "libcamera-src": { + "flake": false, + "locked": { + "lastModified": 1725630279, + "narHash": "sha256-KH30jmHfxXq4j2CL7kv18DYECJRp9ECuWNPnqPZajPA=", + "owner": "raspberrypi", + "repo": "libcamera", + "rev": "69a894c4adad524d3063dd027f5c4774485cf9db", + "type": "github" + }, + "original": { + "owner": "raspberrypi", + "repo": "libcamera", + "rev": "69a894c4adad524d3063dd027f5c4774485cf9db", + "type": "github" + } + }, + "libpisp-src": { + "flake": false, + "locked": { + "lastModified": 1724944683, + "narHash": "sha256-Fo2UJmQHS855YSSKKmGrsQnJzXog1cdpkIOO72yYAM4=", + "owner": "raspberrypi", + "repo": "libpisp", + "rev": "28196ed6edcfeda88d23cc5f213d51aa6fa17bb3", + "type": "github" + }, + "original": { + "owner": "raspberrypi", + "ref": "v1.0.7", + "repo": "libpisp", + "type": "github" + } + }, "luavit-meta": { "flake": false, "locked": { @@ -1110,6 +1170,35 @@ "url": "https://download.gaja-group.com/LuckPerms-Fabric-PlaceholderAPI-Hook.jar" } }, + "raspberry-pi-nix": { + "inputs": { + "libcamera-src": "libcamera-src", + "libpisp-src": "libpisp-src", + "nixpkgs": [ + "nixpkgs" + ], + "rpi-bluez-firmware-src": "rpi-bluez-firmware-src", + "rpi-firmware-nonfree-src": "rpi-firmware-nonfree-src", + "rpi-firmware-src": "rpi-firmware-src", + "rpi-linux-6_10_12-src": "rpi-linux-6_10_12-src", + "rpi-linux-6_6_67-src": "rpi-linux-6_6_67-src", + "rpicam-apps-src": "rpicam-apps-src", + "u-boot-src": "u-boot-src" + }, + "locked": { + "lastModified": 1736181271, + "narHash": "sha256-tCxJzhFxJmRlIKjLREntBYmoQr3db9P6eOE9q6dh/HA=", + "owner": "nix-community", + "repo": "raspberry-pi-nix", + "rev": "6b63ee98284cd68e86bcdb29feeb3009896f1a6b", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "raspberry-pi-nix", + "type": "github" + } + }, "root": { "inputs": { "catppuccin": "catppuccin", @@ -1117,6 +1206,7 @@ "flake-compat": "flake-compat", "flake-parts": "flake-parts", "flake-utils": "flake-utils", + "gokosync": "gokosync", "guihua": "guihua", "home-manager": "home-manager", "lazydev": "lazydev", @@ -1140,11 +1230,114 @@ "nvim-spell-de-latin1-suggestions": "nvim-spell-de-latin1-suggestions", "nvim-spell-de-utf8-dictionary": "nvim-spell-de-utf8-dictionary", "nvim-spell-de-utf8-suggestions": "nvim-spell-de-utf8-suggestions", + "raspberry-pi-nix": "raspberry-pi-nix", "sops-nix": "sops-nix", "systems": "systems_2", "vim-mcfunction": "vim-mcfunction" } }, + "rpi-bluez-firmware-src": { + "flake": false, + "locked": { + "lastModified": 1708969706, + "narHash": "sha256-KakKnOBeWxh0exu44beZ7cbr5ni4RA9vkWYb9sGMb8Q=", + "owner": "RPi-Distro", + "repo": "bluez-firmware", + "rev": "78d6a07730e2d20c035899521ab67726dc028e1c", + "type": "github" + }, + "original": { + "owner": "RPi-Distro", + "ref": "bookworm", + "repo": "bluez-firmware", + "type": "github" + } + }, + "rpi-firmware-nonfree-src": { + "flake": false, + "locked": { + "lastModified": 1723266537, + "narHash": "sha256-T7eTKXqY9cxEMdab8Snda4CEOrEihy5uOhA6Fy+Mhnw=", + "owner": "RPi-Distro", + "repo": "firmware-nonfree", + "rev": "4b356e134e8333d073bd3802d767a825adec3807", + "type": "github" + }, + "original": { + "owner": "RPi-Distro", + "ref": "bookworm", + "repo": "firmware-nonfree", + "type": "github" + } + }, + "rpi-firmware-src": { + "flake": false, + "locked": { + "lastModified": 1727798811, + "narHash": "sha256-eavbshXGYmkYR33y9FLcQMJoAYdYTESVEy0g/RRXnb0=", + "owner": "raspberrypi", + "repo": "firmware", + "rev": "287e6a6c2d3b50eee3e2c5b2eacdd907e5cbe09a", + "type": "github" + }, + "original": { + "owner": "raspberrypi", + "ref": "1.20241001", + "repo": "firmware", + "type": "github" + } + }, + "rpi-linux-6_10_12-src": { + "flake": false, + "locked": { + "lastModified": 1728305462, + "narHash": "sha256-LtvNmGD1D5YYv+C9xxxddAeHw69o3OX/H9M7F663L74=", + "owner": "raspberrypi", + "repo": "linux", + "rev": "26ee50d56618c2d98100b1bc672fd201aed4d00f", + "type": "github" + }, + "original": { + "owner": "raspberrypi", + "ref": "rpi-6.10.y", + "repo": "linux", + "type": "github" + } + }, + "rpi-linux-6_6_67-src": { + "flake": false, + "locked": { + "lastModified": 1734790986, + "narHash": "sha256-q9swM2TmmuzbUuQnbLZk5PseKWD7/SNPwtth6bpGIqE=", + "owner": "raspberrypi", + "repo": "linux", + "rev": "811ff707533bcd67cdcd368bbd46223082009b12", + "type": "github" + }, + "original": { + "owner": "raspberrypi", + "ref": "rpi-6.6.y", + "repo": "linux", + "type": "github" + } + }, + "rpicam-apps-src": { + "flake": false, + "locked": { + "lastModified": 1727515047, + "narHash": "sha256-qCYGrcibOeGztxf+sd44lD6VAOGoUNwRqZDdAmcTa/U=", + "owner": "raspberrypi", + "repo": "rpicam-apps", + "rev": "a8ccf9f3cd9df49875dfb834a2b490d41d226031", + "type": "github" + }, + "original": { + "owner": "raspberrypi", + "ref": "v1.5.2", + "repo": "rpicam-apps", + "type": "github" + } + }, "sops-nix": { "inputs": { "nixpkgs": [ @@ -1258,6 +1451,19 @@ "type": "github" } }, + "u-boot-src": { + "flake": false, + "locked": { + "lastModified": 1719857238, + "narHash": "sha256-mJ2TBy0Y5ZtcGFgtU5RKr0UDUp5FWzojbFb+o/ebRJU=", + "type": "tarball", + "url": "https://ftp.denx.de/pub/u-boot/u-boot-2024.07.tar.bz2" + }, + "original": { + "type": "tarball", + "url": "https://ftp.denx.de/pub/u-boot/u-boot-2024.07.tar.bz2" + } + }, "vanillatweaks": { "flake": false, "locked": { diff --git a/flake.nix b/flake.nix index db71828..64bce5e 100644 --- a/flake.nix +++ b/flake.nix @@ -46,6 +46,7 @@ server = import ./modules/nixos/server; games = import ./modules/nixos/games; sops = import ./modules/nixos/sops; + raspberry-pi = import ./modules/nixos/raspberry-pi; }; nixosConfigurations = flakeLib.mkNixosConfiguration @@ -169,6 +170,13 @@ flake-compat.follows = "flake-compat"; }; }; + raspberry-pi-nix = { + url = "github:nix-community/raspberry-pi-nix"; + inputs = { + nixpkgs.follows = "nixpkgs"; + }; + }; + nixgl = { url = "github:nix-community/nixGL"; inputs.nixpkgs.follows = "nixpkgs"; @@ -282,6 +290,15 @@ }; }; + gokosync = { + url = "git+ssh://git@git.gaja-group.com/odie/gokosync.git"; + inputs = { + nixpkgs.follows = "nixpkgs"; + flake-utils.follows = "flake-utils"; + systems.follows = "systems"; + }; + }; + # Misc csleeptimer = { url = "git+ssh://gitea@git.niederkassel.neff-steindesign.de/odie/csleeptimer.git"; diff --git a/lib/genSslCert.nix b/lib/genSslCert.nix new file mode 100644 index 0000000..89350cc --- /dev/null +++ b/lib/genSslCert.nix @@ -0,0 +1,30 @@ +{ name, dataDir, user, domain, wantedBy ? [], Before ? [] }: { pkgs, ... }: +{ + systemd.services."create-${name}-cert" = { + description = "Create a certificate for ${domain}"; + + script = '' + ${pkgs.openssl}/bin/openssl req -x509 -newkey rsa:4096 -keyout ${domain}.key -out ${domain}.crt -nodes -subj '/CN=${domain}' + ${pkgs.openssl}/bin/openssl pkcs12 -export -out ${domain}.pfx -inkey ${domain}.key -in ${domain}.crt -passout pass: + cat ${domain}.crt ${domain}.key > ${domain}.pem + chmod 644 ${domain}.crt + chmod 640 ${domain}.pfx + chmod 640 ${domain}.key + chmod 640 ${domain}.pem + ''; + + wantedBy = [ "multi-user.target" ] ++ wantedBy; + + unitConfig = { + Before = [ "multi-user.target" ] ++ Before; + ConditionPathExists = "!${dataDir}/${domain}.pfx"; + }; + + serviceConfig = { + User = user; + Type = "oneshot"; + WorkingDirectory = dataDir; + RemainAfterExit = true; + }; + }; +} diff --git a/modules/home-manager/base/nixpkgs.nix b/modules/home-manager/base/nixpkgs.nix index e95ec3c..d793f95 100644 --- a/modules/home-manager/base/nixpkgs.nix +++ b/modules/home-manager/base/nixpkgs.nix @@ -1,3 +1,5 @@ { - nixpkgs.config.allowUnfree = true; + nixpkgs = { + config.allowUnfree = true; + }; } diff --git a/modules/home-manager/mediacenter/kodi/advancedsettings.nix b/modules/home-manager/mediacenter/kodi/advancedsettings.nix deleted file mode 100644 index 6acd324..0000000 --- a/modules/home-manager/mediacenter/kodi/advancedsettings.nix +++ /dev/null @@ -1,74 +0,0 @@ -{ - vars, - mysql, - media, - ... -}: let - inherit (vars) timeZone hostName domain; - datadirs = "smb://${media.host}/kodi/userdata"; -in { - addons = { - unknownsources = "true"; - }; - services = { - devicename = "${hostName}.${domain}"; - webserver = "true"; - webserverauthentication = "false"; - webserverusername = "kodi"; - webserverpassword = "kodi"; - webserverport = "8000"; - webserverssl = "false"; - zeroconf = "true"; - wsdiscovery = "true"; - upnp = "true"; - upnpserver = "true"; - airplay = "true"; - airplayvideosupport = "true"; - }; - locale = { - language = "resource.language.de_de"; - country = "Deutschland"; - timezone = timeZone; - }; - lookandfeed = { - enablerssfeeds = "false"; - }; - videodatabase = { - inherit (mysql) user pass host; - type = "mysql"; - port = builtins.toString mysql.port; - }; - musicdatabase = { - inherit (mysql) user pass host; - type = "mysql"; - port = builtins.toString mysql.port; - }; - videolibrary = { - importwatchedstate = "true"; - importresumepoint = "true"; - }; - pathsubstitution = { - substitute = [ - { - from = "special://profile/playlists/"; - to = "${datadirs}/playlists/"; - } - { - from = "special://profile/sources.xml"; - to = "${datadirs}/sources.xml"; - } - { - from = "special://profile/mediasources.xml"; - to = "${datadirs}/mediasources.xml"; - } - { - from = "special://profile/RssFeeds.xml"; - to = "${datadirs}/RssFeeds.xml"; - } - { - from = "special://profile/favourites.xml"; - to = "${datadirs}/favourites.xml"; - } - ]; - }; -} diff --git a/modules/home-manager/mediacenter/kodi/default.nix b/modules/home-manager/mediacenter/kodi/default.nix deleted file mode 100644 index 982c0ab..0000000 --- a/modules/home-manager/mediacenter/kodi/default.nix +++ /dev/null @@ -1,64 +0,0 @@ -{ - vars, - pkgs, - config, - lib, - ... -}: let - cfg = config.mediacenter.kodi; - inherit (lib) types; -in - with lib; { - options.mediacenter.kodi = { - # enable = mkEnableOption "kodi"; - media = { - host = mkOption { - type = types.str; - default = "media"; - }; - user = mkOption { - type = types.str; - default = "kodi"; - }; - pass = mkOption { - type = types.str; - default = "kodi"; - }; - }; - mysql = { - host = mkOption { - type = types.str; - default = "localhost"; - }; - port = mkOption { - type = types.int; - default = 3306; - }; - user = mkOption { - type = types.str; - default = "kodi"; - }; - pass = mkOption { - type = types.str; - default = "kodi"; - }; - }; - }; - imports = [./kodi.nix]; # import overridden kodi module - config = mkIf cfg.enable { - #programs.kodi = { - mediacenter.kodi = { - # enable = true; - package = pkgs.kodi-standalone; - settings = import ./advancedsettings.nix {inherit vars; inherit (cfg) mysql media;}; - }; - home.file = { - "kodi-passwords.xml" = { - target = ".kodi/userdata/passwords.xml"; - text = import ./passwords.nix { - inherit (cfg) media; - }; - }; - }; - }; - } diff --git a/modules/home-manager/mediacenter/kodi/kodi.nix b/modules/home-manager/mediacenter/kodi/kodi.nix index a8c3140..db48f49 100644 --- a/modules/home-manager/mediacenter/kodi/kodi.nix +++ b/modules/home-manager/mediacenter/kodi/kodi.nix @@ -1,262 +1,171 @@ +{ pkgs, ... }: { - config, - lib, - pkgs, - ... -}: -with lib; let - stylesheetCommonHeader = '' - - - - - ''; - - stylesheetCommonFooter = ""; - - stylesheetNestedTags = '' - - - - - - - - - - - - - - - - - - - - 1 - - - - - ''; - - stylesheetTagsAsSettingWithId = '' - - - - - - - - - ''; - - stylesheetAdvancedSettingsRootTag = '' - - Generated by Home Manager. - - - - - ''; - - stylesheetSourcesRootTag = '' - - Generated by Home Manager. - - - - - ''; - - stylesheetAddonSettingsRootTag = '' - - Generated by Home Manager. - - - - - ''; - - attrsetToXml = attrs: name: stylesheet: - pkgs.runCommand name { - # Package splicing for libxslt does not work correctly leading to errors - # when cross-compiling. Use the version from buildPackages explicitly to - # fix this. - nativeBuildInputs = [pkgs.buildPackages.libxslt.bin]; - xml = builtins.toXML attrs; - passAsFile = ["xml"]; - } '' - xsltproc ${stylesheet} - < "$xmlPath" > "$out" - ''; - - attrsetToAdvancedSettingsXml = attrs: name: let - stylesheet = builtins.toFile "stylesheet.xsl" '' - ${stylesheetCommonHeader} - ${stylesheetAdvancedSettingsRootTag} - ${stylesheetNestedTags} - ${stylesheetCommonFooter} - ''; - in - attrsetToXml attrs name stylesheet; - - attrsetToSourcesXml = attrs: name: let - stylesheet = builtins.toFile "stylesheet.xsl" '' - ${stylesheetCommonHeader} - ${stylesheetSourcesRootTag} - ${stylesheetNestedTags} - ${stylesheetCommonFooter} - ''; - in - attrsetToXml attrs name stylesheet; - - attrsetToAddonSettingsXml = attrs: name: let - stylesheet = builtins.toFile "stylesheet.xsl" '' - ${stylesheetCommonHeader} - ${stylesheetAddonSettingsRootTag} - ${stylesheetTagsAsSettingWithId} - ${stylesheetCommonFooter} - ''; - in - attrsetToXml attrs name stylesheet; -in { - meta.maintainers = [hm.maintainers.dwagenk]; - - options.mediacenter.kodi = { - enable = mkEnableOption "Kodi"; - - package = mkOption { - type = types.package; - default = pkgs.kodi; - defaultText = literalExpression "pkgs.kodi"; - example = - literalExpression - "pkgs.kodi.withPackages (exts: [ exts.pvr-iptvsimple ])"; - description = '' - The `kodi` package to use. - Can be used to specify extensions. + home.file = { + aelProfiles = { + text = '' + + + + 1659964681.6420453 + + + 6bc2506af9af35bc7326d70b7356af51 + retroarch + + + + + + Unknown + root_category + ${pkgs.retroarch}/bin/retroarch + + + + + False + False + True + True + + Audit OFF + + + All ROMs + Flat mode + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1659942644.8321931 + 0.0 + s_icon + s_fanart + s_banner + s_poster + s_clearlogo + s_controller + + + + + + + + + s_boxfront + s_fanart + s_banner + s_flyer + s_clearlogo + + + + + + + + + + + + + + + + ''; + target = + ".kodi/userdata/addon_data/plugin.program.advanced.emulator.launcher/categories.xml"; }; - - datadir = mkOption { - type = types.path; - default = "${config.home.homeDirectory}/.kodi"; - defaultText = - literalExpression ''"''${config.home.homeDirectory}/.kodi"''; - example = literalExpression ''"''${config.xdg.dataHome}/kodi"''; - description = "Directory to store configuration and metadata."; - }; - - settings = mkOption { - type = with types; let - valueType = - oneOf [str (attrsOf valueType) (listOf valueType)] - // { - description = "attribute sets or lists of strings"; - }; - in - nullOr valueType; - default = null; - example = literalExpression '' - { videolibrary.showemptytvshows = "true"; } + germanIptv = { + text = '' + + IPTV Deutsch + true + 1 + + https://iptv-org.github.io/iptv/languages/deu.m3u + true + 1 + false + 0 + 60 + 4 + + false + special://userdata/addon_data/pvr.iptvsimple/providers/providerMappings.xml + 0 + 1 + + + + + + special://userdata/addon_data/pvr.iptvsimple/channelGroups/customTVGroups-example.xml + false + 0 + 1 + + + + + + special://userdata/addon_data/pvr.iptvsimple/channelGroups/customRadioGroups-example.xml + false + 1 + + http://10.0.20.10:3000/guide.xml + true + 0 + false + true + false + 0 + special://userdata/addon_data/pvr.iptvsimple/genres/genreTextMappings/genres.xml + + 1 + + + false + 1 + true + true + true + false + 0 + false + true + false + true + true + true + false + false + + 5 + 0 + 0 + 0 + false + 5 + 15 + false + false + 127.0.0.1 + 4022 + true + false + + + + ''; - description = '' - Configuration to write to the `advancedsettings.xml` - file in kodis userdata directory. Settings specified here will be - immutable from inside kodi and be hidden from the GUI settings dialog. + target = ".kodi/userdata/addon_data/pvr.iptvsimple/instance-settings-2.xml"; - See as - reference for how settings need to be specified. - - The innermost attributes must be of type str. - ''; - }; - - sources = mkOption { - type = with types; let - valueType = - oneOf [str (attrsOf valueType) (listOf valueType)] - // { - description = "attribute sets or lists of strings"; - }; - in - nullOr valueType; - default = null; - example = literalExpression '' - { - video = { - default = "movies"; - source = [ - { name = "videos"; path = "/path/to/videos"; allowsharing = "true"; } - { name = "movies"; path = "/path/to/movies"; allowsharing = "true"; } - ]; - }; - } - ''; - description = '' - Contents to populate the file `sources.xml` in kodis - userdata directory. - - See as - reference for how sources need to be specified. - - Kodi will still show the dialogs to modify sources in the GUI and they - appear to be mutable. This however is not the case and the sources will - stay as specified via Home Manager. - - The innermost attributes must be of type str. - ''; - }; - - addonSettings = mkOption { - type = with types; nullOr (attrsOf (attrsOf str)); - default = null; - example = literalExpression '' - { "service.xbmc.versioncheck".versioncheck_enable = "false"; } - ''; - description = '' - Attribute set with the plugin namespace as toplevel key and the plugins - settings as lower level key/value pairs. - - Kodi will still show the settings of plugins configured via this - mechanism in the GUI and they appear to be mutable. This however is - not the case and the settings will stay as specified via Home Manager. - ''; }; }; - - config = let - cfg = config.mediacenter.kodi; - in - mkIf cfg.enable (mkMerge [ - { - assertions = [ - (lib.hm.assertions.assertPlatform "programs.kodi" pkgs - lib.platforms.linux) - ]; - - home.packages = [cfg.package]; - home.sessionVariables = {KODI_DATA = cfg.datadir;}; - } - - (mkIf (cfg.settings != null) { - home.file."${cfg.datadir}/userdata/advancedsettings.xml".source = - attrsetToAdvancedSettingsXml cfg.settings "kodi-advancedsettings.xml"; - }) - - (mkIf (cfg.sources != null) { - home.file."${cfg.datadir}/userdata/sources.xml".source = - attrsetToSourcesXml cfg.sources "kodi-sources.xml"; - }) - - (mkIf (cfg.addonSettings != null) { - home.file = mapAttrs' (k: v: - attrsets.nameValuePair - "${cfg.datadir}/userdata/addon_data/${k}/settings.xml" { - source = attrsetToAddonSettingsXml v "kodi-addon-${k}-settings.xml"; - }) - cfg.addonSettings; - }) - ]); } diff --git a/modules/home-manager/mediacenter/kodi/passwords.nix b/modules/home-manager/mediacenter/kodi/passwords.nix deleted file mode 100644 index 7d1d322..0000000 --- a/modules/home-manager/mediacenter/kodi/passwords.nix +++ /dev/null @@ -1,8 +0,0 @@ -{media,...}: '' - - - smb://${media.host} - smb://${media.user}:${media.pass}@${media.host} - - -'' diff --git a/modules/nixos/base/binary-cache/default.nix b/modules/nixos/base/binary-cache/default.nix index 798ae8d..f0c52d0 100644 --- a/modules/nixos/base/binary-cache/default.nix +++ b/modules/nixos/base/binary-cache/default.nix @@ -3,11 +3,9 @@ nix = { settings = { substituters = [ - "http://nixcache.odie.home.arpa" "https://nix-community.cachix.org" ]; trusted-public-keys = [ - "nixcache.odie.home.arpa:2j5qAVmtBUSZMPWlIRS8Gn0Il9tbotJ9c2y43N0RLKU=" "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" ]; }; diff --git a/modules/nixos/base/nixos/default.nix b/modules/nixos/base/nixos/default.nix index 8a5f9cf..8985742 100644 --- a/modules/nixos/base/nixos/default.nix +++ b/modules/nixos/base/nixos/default.nix @@ -18,5 +18,34 @@ dates = "weekly"; options = "--delete-older-than 30d"; }; + buildMachines = [ + { + hostName = "nix-cache.gaja-group.intranet"; + #system = "x86_64-linux"; + protocol = "ssh-ng"; + # if the builder supports building for multiple architectures, + # replace the previous line by, e.g., + systems = [ "x86_64-linux" "aarch64-linux" ]; + maxJobs = 4; + speedFactor = 1; + supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ]; + mandatoryFeatures = [ ]; + } + ]; + distributedBuilds = true; + # optional, useful when the builder has a faster internet connection than yours + extraOptions = '' + builders-use-substitutes = true + ''; + settings = { + substituters = [ + "https://nix-community.cachix.org" + "http://nix-cache.gaja-group.intranet:5000" + ]; + trusted-public-keys = [ + "nix-cache.gaja-group.intranet:EcUsafvI9NUrnab3DA71s2PGjAYMgct0FOvCwdYuStw=" + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + ]; + }; }; } diff --git a/modules/nixos/base/user/default.nix b/modules/nixos/base/user/default.nix index 4602102..b604592 100644 --- a/modules/nixos/base/user/default.nix +++ b/modules/nixos/base/user/default.nix @@ -1,13 +1,13 @@ -{ - config, - lib, - pkgs, - vars, - ... -}: let - inherit (vars) username name sshKeys extraGroups; +{ config +, lib +, pkgs +, vars +, ... +}: +let + inherit (vars) username name sshKeys; - baseGroups = [ + extraGroups = vars.extraGroups ++ [ "users" "wheel" "audio" @@ -16,37 +16,32 @@ "power" "adm" "plugdev" + ] ++ lib.optionals config.hardware.raspberry-pi.enable [ + "i2c" + "spi" ]; - rpiGroups = - if config.hardware.raspberry-pi.enable - then [ - "i2c" - "spi" - ] - else []; - allExtraGroups = baseGroups ++ rpiGroups ++ extraGroups; - basePackages = with pkgs; [home-manager]; + basePackages = with pkgs; [ home-manager ]; wslPackages = - if config.wsl.enable + if ((builtins.hasAttr "wsl" config) && config.wsl.enable) then with pkgs; [ wslu wsl-open ] - else []; + else [ ]; packages = basePackages ++ wslPackages; -in { +in +{ options = { hardware.raspberry-pi.enable = lib.mkEnableOption "raspberry pi features"; }; config = { users = { - groups.${username} = {}; + groups.${username} = { }; users = { ${username} = { - inherit packages ; - extraGroups = allExtraGroups; + inherit packages extraGroups; name = username; uid = 1000; isNormalUser = true; diff --git a/modules/nixos/home-manager/default.nix b/modules/nixos/home-manager/default.nix index 721e661..48687be 100644 --- a/modules/nixos/home-manager/default.nix +++ b/modules/nixos/home-manager/default.nix @@ -1,13 +1,14 @@ -{ - flakeLib, - inputs, - outputs, - vars, - ... -}: let +{ flakeLib +, inputs +, outputs +, vars +, ... +}: +let inherit (vars) username hostName; profile = "${username}@${hostName}"; -in { +in +{ imports = [ inputs.home-manager.nixosModules.home-manager ]; @@ -24,5 +25,6 @@ in { ../../../profiles/home-manager/${profile}/home.nix ]; }; + backupFileExtension = "backup"; }; } diff --git a/modules/nixos/mediacenter/default.nix b/modules/nixos/mediacenter/default.nix index a4647d9..a32df78 100644 --- a/modules/nixos/mediacenter/default.nix +++ b/modules/nixos/mediacenter/default.nix @@ -3,5 +3,6 @@ _: imports = [ ./kodi ./jellyfin + ./gokosync ]; } diff --git a/modules/nixos/mediacenter/gokosync/default.nix b/modules/nixos/mediacenter/gokosync/default.nix new file mode 100644 index 0000000..f1abf00 --- /dev/null +++ b/modules/nixos/mediacenter/gokosync/default.nix @@ -0,0 +1,4 @@ +{ inputs, ... }: { + nixpkgs.overlays = [ inputs.gokosync.overlays.default ]; + imports = [ inputs.gokosync.nixosModules.default ]; +} diff --git a/modules/nixos/mediacenter/jellyfin/default.nix b/modules/nixos/mediacenter/jellyfin/default.nix index b563577..41b038d 100644 --- a/modules/nixos/mediacenter/jellyfin/default.nix +++ b/modules/nixos/mediacenter/jellyfin/default.nix @@ -1,7 +1,47 @@ +{ pkgs, lib, config, ... }: +with lib; +let + cfg = config.services.jellyfin; + extraGroups = [ + "users" + "audio" + "video" + "disk" + "power" + "plugdev" + ] ++ lib.optionals config.hardware.raspberry-pi.enable [ + "i2c" + "spi" + ]; +in { - services.jellyfin = { - enable = true; - openFirewall = true; + imports = [ + (import ../../../../lib/genSslCert.nix { + name = "jellyfin"; + inherit (cfg) dataDir user; + domain = "pi0.odie.home.arpa"; + wantedBy = [ "jellyfin.service" ]; + Before = [ "jellyfin.service" ]; + }) + ]; + options = { + services.jellyfin.domain = mkOption { + type = types.str; + default = "localhost"; + }; + }; + config = { + services.jellyfin = { + enable = true; + openFirewall = true; + }; + users.users.jellyfin = { + inherit extraGroups; + }; + networking.firewall = { + allowedUDPPorts = [ 1900 ]; + allowedTCPPorts = [ 8920 ]; + }; }; } diff --git a/modules/nixos/mediacenter/kodi/default.nix b/modules/nixos/mediacenter/kodi/default.nix index b721ffa..475d1ab 100644 --- a/modules/nixos/mediacenter/kodi/default.nix +++ b/modules/nixos/mediacenter/kodi/default.nix @@ -1,38 +1,29 @@ -{ pkgs, ... }: +{ pkgs, lib, config, ... }: let user = "kodi"; - kodi-standalone = pkgs.kodi-wayland.withPackages - (kodiPkgs: with pkgs.kodiPackages; [ - youtube - pvr-iptvsimple - keymap - inputstream-adaptive - inputstream-ffmpegdirect - requests-cache - inputstreamhelper - advanced-emulator-launcher - jellyfin - ]); + extraGroups = [ + "users" + "audio" + "video" + "disk" + "power" + "plugdev" + ] ++ lib.optionals config.hardware.raspberry-pi.enable [ + "i2c" + "spi" + ]; in { services.cage = { inherit user; enable = true; - program = "${kodi-standalone}/bin/kodi-standalone"; + program = "${pkgs.kodi-standalone}/bin/kodi-standalone"; }; users.users.kodi = { + inherit extraGroups; name = user; isNormalUser = true; - extraGroups = [ - "audio" - "video" - "disk" - "plugdev" - "i2c" - "spi" - "power" - ]; }; sops.secrets = { @@ -65,12 +56,14 @@ in environment.systemPackages = with pkgs; [ #kodi-standalone alsa-utils - (retroarch.override { + /* + (retroarch.override { cores = with libretro; [ snes9x pcsx-rearmed nestopia ]; - }) + }) + */ ]; } diff --git a/modules/nixos/mediacenter/kodi/secrets/advancedsettings.xml b/modules/nixos/mediacenter/kodi/secrets/advancedsettings.xml index 3e9e752..23e6f53 100644 --- a/modules/nixos/mediacenter/kodi/secrets/advancedsettings.xml +++ b/modules/nixos/mediacenter/kodi/secrets/advancedsettings.xml @@ -1,5 +1,5 @@ { - "data": "ENC[AES256_GCM,data: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,iv:nFT/yFOmF81VwjM5ab5dJQYrlkDeb9Ov9dzTkMxcUqY=,tag:t2UzVTh0cbuFOZm/RWyu9A==,type:str]", + "data": "ENC[AES256_GCM,data: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,iv:OFKpx7VTY03kM9Dgf/LFkhweMwJabQ/Rf6IVdIWOAVI=,tag:WMQvgxLCmIbrDCuEyyyUOQ==,type:str]", "sops": { "kms": null, "gcp_kms": null, @@ -15,10 +15,10 @@ "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0cGZFU3FrZTVsNFE2ZGVn\nKzRabVo4Y2tLWEZrbW1aY1oydkZWbWFxV1FFClE5dkR2N1RFaWRvYlNwaUh0VGNx\nakVnbW84T3pGc1lGNzlLNmRMdHNzN2sKLS0tIEhZbENEUTdLQ0laL1B5Tmd3UW5h\nTWtlZFp2bXFHQ0tYK1pSV2xPSHhJeGMKV2WF/21OkoIUBSViIzX5pXZX+8OIwkuP\nb/4owrDej1otYCczA7upnO8d7r9HgdzV0PohZ9ghY+L7xMDtE2Pb0A==\n-----END AGE ENCRYPTED FILE-----\n" } ], - "lastmodified": "2025-01-05T05:36:06Z", - "mac": "ENC[AES256_GCM,data:Xm8OaOdmS+XIP1vIA1XUAzM0rvoSXtVmVa3TnyCL5d0hHtJ0WHgCadiEmdngNWaizZ/HyqUipMOR5dRbZSa2KErqvtMXABT5NeoTGQOf11Ug7E+cShfMkEedFXNJ45/qntgpqcd8JqfVHHtcbSb7ccnUapMOFRygtudDb/lHADA=,iv:bVEgaFam+OC5+iGOTA4tH8vU1RRcmuc5tAT03snYgXg=,tag:VMTJjmfH7Qf1/xyQWJFEhA==,type:str]", + "lastmodified": "2025-01-06T09:21:00Z", + "mac": "ENC[AES256_GCM,data:fQZoXecKTIqGjah5sxkylLRE4xgj7wKKBUR4Vk5lf2PvSFyxlC1WUinjPl8ltqm/NTiHY+XeL0mkD0ODlo8LN/QOjz++coWeNHyx5Y8+pSjb6hC/RA3GVfmSeMi6oTJryMbJeZ0fpurXBT3CFlCX2iYdfFOymJcfi92mNYupENQ=,iv:431aHv9TrhPPa7PAEAcgZcyLkM4YMWw+QM8mYr1T4mo=,tag:OUbGZDEfxU9rEGD33L70Jg==,type:str]", "pgp": null, "unencrypted_suffix": "_unencrypted", - "version": "3.9.0" + "version": "3.9.1" } } \ No newline at end of file diff --git a/modules/nixos/raspberry-pi/default.nix b/modules/nixos/raspberry-pi/default.nix new file mode 100644 index 0000000..611a367 --- /dev/null +++ b/modules/nixos/raspberry-pi/default.nix @@ -0,0 +1,8 @@ +{inputs, ...}: { + imports = [ + inputs.raspberry-pi-nix.nixosModules.raspberry-pi + ]; + nixpkgs.overlays = [ + inputs.raspberry-pi-nix.overlays.core + ]; +} diff --git a/overlays/jellyfin.nix b/overlays/jellyfin.nix new file mode 100644 index 0000000..5a34f6d --- /dev/null +++ b/overlays/jellyfin.nix @@ -0,0 +1,18 @@ +{ + jellyfin-web = final: prev: + { + jellyfin-web = prev.jellyfin-web.overrideAttrs (finalAttrs: previousAttrs: { + installPhase = '' + runHook preInstall + + # this is the important line + sed -i "s###" dist/index.html + + mkdir -p $out/share + cp -a dist $out/share/jellyfin-web + + runHook postInstall + ''; + }); + }; +} diff --git a/overlays/kodi.nix b/overlays/kodi.nix index 6c9efe4..1dee6e3 100644 --- a/overlays/kodi.nix +++ b/overlays/kodi.nix @@ -1,14 +1,6 @@ _: final: prev: { - kodi-standalone = - final.kodi-wayland.withPackages - (kodiPkgs: - with kodiPkgs; [ - youtube - pvr-iptvsimple - keymap - inputstream-adaptive - inputstream-ffmpegdirect - requests-cache - inputstreamhelper - ]); + kodiPackages = prev.kodiPackages // { + advanced-emulator-launcher = final.callPackage ../pkgs/kodiPackages/advanced-emulator-launcher {}; + }; + kodi-standalone = final.callPackage ../pkgs/kodi {}; } diff --git a/pkgs/kodi/default.nix b/pkgs/kodi/default.nix new file mode 100644 index 0000000..667fec8 --- /dev/null +++ b/pkgs/kodi/default.nix @@ -0,0 +1,14 @@ +{ callPackage, kodi-wayland, ... }: +kodi-wayland.withPackages + (kodiPkgs: with kodiPkgs; [ + youtube + pvr-iptvsimple + keymap + inputstream-adaptive + inputstream-ffmpegdirect + requests-cache + inputstreamhelper + (callPackage ../../pkgs/kodiPackages/advanced-emulator-launcher { }) + jellyfin + jellycon + ]) diff --git a/pkgs/kodiPackages/advanced-emulator-launcher/default.nix b/pkgs/kodiPackages/advanced-emulator-launcher/default.nix new file mode 100644 index 0000000..92dd5c5 --- /dev/null +++ b/pkgs/kodiPackages/advanced-emulator-launcher/default.nix @@ -0,0 +1,14 @@ +{ pkgs, fetchFromGitHub, ... }: + +pkgs.kodiPackages.buildKodiAddon { + pname = "advanced-emulator-launcher"; + namespace = "plugin.program.advanced.emulator.launcher"; + version = "0.10.1"; + + src = fetchFromGitHub { + owner = "Wintermute0110"; + repo = "plugin.program.AEL.dev"; + rev = "20b082d58518883384735efbd5e9123e7c6d17d8"; + hash = "sha256-+9bZ2m8qSLp+ZyhQnvZUEhYXiDQZUBuG3eJwAyLJg5k="; + }; +} diff --git a/profiles/home-manager/kodi@pi0/home.nix b/profiles/home-manager/kodi@pi0/home.nix new file mode 100644 index 0000000..d057252 --- /dev/null +++ b/profiles/home-manager/kodi@pi0/home.nix @@ -0,0 +1,11 @@ +{ outputs +, ... +}: +{ + imports = [ + outputs.homeManagerModules.base + outputs.homeManagerModules.shell + ]; + + home.stateVersion = "24.11"; +} diff --git a/profiles/nixos/pi0/configuration.nix b/profiles/nixos/pi0/configuration.nix index bc70bf0..8765416 100644 --- a/profiles/nixos/pi0/configuration.nix +++ b/profiles/nixos/pi0/configuration.nix @@ -1,61 +1,45 @@ -/* - { - outputs, - flakeLib, - vars, - ... - }: { - imports = [ - outputs.nixosModules.base - outputs.nixosModules.home-manager - ./hardware-configuration.nix - ]; - - networking = { - inherit (vars) hostName domain; - }; - - home-manager.users = flakeLib.mkNixosHomeConfiguration {inherit vars;}; - } -*/ - { inputs , pkgs , outputs , vars +, config +, lib , ... -}: { +}: +let + haproxy = rec { + dataDir = "/var/lib/haproxy"; + certDir = "${dataDir}/crt"; + domains = [ + "pi0.odie.home.arpa" + "jellyfin.odie.home.arpa" + "gokosync.odie.home.arpa" + ]; + }; +in +{ imports = [ inputs.nixos-hardware.nixosModules.raspberry-pi-4 outputs.nixosModules.base outputs.nixosModules.home-manager outputs.nixosModules.mediacenter - ]; + outputs.nixosModules.sops + outputs.nixosModules.raspberry-pi + ./hardware-configuration.nix + ] ++ map (name: (import ../../../lib/genSslCert.nix { + inherit name; + inherit (config.services.haproxy) user; + dataDir = haproxy.certDir; + domain = name; + wantedBy = [ "haproxy.service" ]; + Before = [ "haproxy.service" ]; + })) haproxy.domains; networking = { inherit (vars) hostName domain; }; - boot = { - kernelPackages = pkgs.linuxPackages_rpi4; - kernelParams = [ "snd_bcm2835.enable_headphones=1" "snd_bcm2835.enable_hdmi=1" ]; - initrd.availableKernelModules = [ - # Allows early (earlier) modesetting for the Raspberry Pi - "vc4" - "bcm2835_dma" - "i2c_bcm2835" - "xhci_pci" - "usbhid" - "usb_storage" - ]; - }; - fileSystems = { - "/" = { - device = "/dev/disk/by-label/NIXOS_SD"; - fsType = "ext4"; - options = [ "noatime" ]; - }; "/media/net/hel_Public" = { device = "hel.odie.home.arpa:/nfs/Public"; fsType = "nfs"; @@ -70,28 +54,9 @@ }; }; - swapDevices = [{ - device = "/var/lib/swapfile"; - size = 4 * 1024; - }]; - - hardware = { - raspberry-pi."4" = { - apply-overlays-dtmerge.enable = true; - fkms-3d.enable = true; - }; - enableRedistributableFirmware = true; - }; - home-manager = { - extraSpecialArgs = { - inherit inputs outputs; - }; - useGlobalPkgs = true; - useUserPackages = true; users = { - kodi = import ../../home-manager/kodi/pi0; - odie = import ../../home-manager/odie/pi0; + kodi = let profile = "kodi@pi0"; in import ../../home-manager/${profile}/home.nix; }; }; @@ -107,19 +72,62 @@ programs.zsh.enable = true; - services.udev.extraRules = '' - # allow access to raspi cec device for video group (and optionally register it as a systemd device, used below) - KERNEL=="vchiq", GROUP="video", MODE="0660", TAG+="systemd", ENV{SYSTEMD_ALIAS}="/dev/vchiq" - ''; + networking.firewall.allowedTCPPorts = [ 80 443 ]; - system = { - stateVersion = "23.05"; + services = { + gokosync.enable = true; + haproxy = { + enable = true; + config = + let + certs = lib.strings.concatMapStrings (d: "crt ${haproxy.certDir}/${d}.pem ") haproxy.domains; + in + '' + global + maxconn 256 + + defaults + mode http + timeout connect 5000ms + timeout client 50000ms + timeout server 50000ms + + frontend http + bind *:80 + bind *:443 ssl ${certs} default-crt ${haproxy.certDir}/pi0.odie.home.arpa.pem + + redirect scheme https code 301 if !{ ssl_fc } + + use_backend be_jellyfin if { ssl_fc_sni jellyfin.odie.home.arpa } + use_backend be_gokosync if { ssl_fc_sni gokosync.odie.home.arpa } + + default_backend be_null + + backend be_null + http-request return status 204 + + backend be_jellyfin + option httpchk + option forwardfor + http-check send meth GET uri /health + http-check expect string Healthy + server server1 127.0.0.1:8920 maxconn 32 ssl verify none + server server2 127.0.0.1:8096 maxconn 32 + + backend be_gokosync + server server1 ${config.services.gokosync.addr}:${builtins.toString config.services.gokosync.port} maxconn 32 + ''; + }; + udev.extraRules = '' + # allow access to raspi cec device for video group (and optionally register it as a systemd device, used below) + KERNEL=="vchiq", GROUP="video", MODE="0660", TAG+="systemd", ENV{SYSTEMD_ALIAS}="/dev/vchiq" + ''; }; + systemd.tmpfiles.rules = [ + "d ${haproxy.certDir} 0770 ${config.users.users.haproxy.name} ${config.users.groups.haproxy.name} -" + ]; nixpkgs = { - hostPlatform.system = "aarch64-linux"; - # Fix missing modules - # https://github.com/NixOS/nixpkgs/issues/154163 overlays = [ (final: prev: { makeModulesClosure = x: prev.makeModulesClosure (x // { allowMissing = true; }); diff --git a/profiles/nixos/pi0/hardware-configuration.nix b/profiles/nixos/pi0/hardware-configuration.nix index 30a0f17..4efa7c8 100644 --- a/profiles/nixos/pi0/hardware-configuration.nix +++ b/profiles/nixos/pi0/hardware-configuration.nix @@ -1,10 +1,14 @@ { lib, pkgs, ... }: { boot = { - loader.grub.enable = false; - loader.generic-extlinux-compatible.enable = true; - kernelPackages = pkgs.linuxPackages_rpi4; - kernelParams = [ "snd_bcm2835.enable_headphones=1" "snd_bcm2835.enable_hdmi=1" ]; - initrd.availableKernelModules = lib.mkDefault [ + loader = { + grub.enable = false; + systemd-boot.enable = false; + generic-extlinux-compatible.enable = false; + }; + /* + kernelPackages = pkgs.linuxPackages_rpi4; + kernelParams = [ "snd_bcm2835.enable_headphones=1" "snd_bcm2835.enable_hdmi=1" "gpu_mem=128" ]; + initrd.availableKernelModules = lib.mkDefault [ "vc4" "bcm2835_dma" "i2c_bcm2835" @@ -12,7 +16,8 @@ "xhci_pci" "usbhid" "usb_storage" - ]; + ]; + */ }; swapDevices = [{ @@ -28,15 +33,59 @@ }; }; + raspberry-pi-nix.board = "bcm2711"; + hardware = { raspberry-pi = { enable = true; - cec.enable = true; - "4" = { - apply-overlays-dtmerge.enable = true; - fkms-3d.enable = true; + config = { + pi4 = { + options = { + arm_boost = { + enable = true; + value = true; + }; + gpu_mem = { + enable = true; + value = "256"; + }; + }; + dt-overlays = { + vc4-kms-v3d = { + enable = true; + params = { cma-256 = { enable = true; }; }; + }; + }; + }; + all = { + options = { + arm_64bit = { + enable = true; + value = true; + }; + }; + base-dt-params = { + BOOT_UART = { + value = 1; + enable = true; + }; + uart_2ndstage = { + value = 1; + enable = true; + }; + }; + dt-overlays = { + disable-bt = { + enable = true; + params = { }; + }; + vc4-kms-v3d = { + enable = true; + params = { }; + }; + }; + }; }; - enableRedistributableFirmware = true; }; }; system.stateVersion = "23.11"; diff --git a/remote-deploy.sh b/remote-deploy.sh index 80d04a6..faa5cad 100755 --- a/remote-deploy.sh +++ b/remote-deploy.sh @@ -5,6 +5,6 @@ set -e HOSTNAME=$1 nix build -L ".#nixosConfigurations.${HOSTNAME}.config.system.build.toplevel" -#nix copy --no-check-sigs --to "ssh-ng://root@${HOSTNAME}" "./result" -#ssh "root@${HOSTNAME}" nix-env -p /nix/var/nix/profiles/system --set "$(readlink ./result)" -#ssh "root@${HOSTNAME}" /nix/var/nix/profiles/system/bin/switch-to-configuration switch +nix copy --no-check-sigs --to "ssh-ng://root@${HOSTNAME}" "./result" +ssh "root@${HOSTNAME}" nix-env -p /nix/var/nix/profiles/system --set "$(readlink ./result)" +ssh "root@${HOSTNAME}" /nix/var/nix/profiles/system/bin/switch-to-configuration switch