From 16da0a275c4abb3527d737ad3887a1a3c236fe94 Mon Sep 17 00:00:00 2001 From: sinavir Date: Thu, 17 Oct 2024 12:08:41 +0200 Subject: [PATCH 1/6] feat(patches): Remove unecessary patches --- patches/01-castopod.patch | 808 ------------------ patches/03-nextcloud.patch | 28 - patches/04-crabfit-karla.patch | 24 - ...05-pmnos-correctness-build-directory.patch | 54 -- patches/default.nix | 128 +-- 5 files changed, 3 insertions(+), 1039 deletions(-) delete mode 100644 patches/01-castopod.patch delete mode 100644 patches/03-nextcloud.patch delete mode 100644 patches/04-crabfit-karla.patch delete mode 100644 patches/05-pmnos-correctness-build-directory.patch diff --git a/patches/01-castopod.patch b/patches/01-castopod.patch deleted file mode 100644 index 2acd493..0000000 --- a/patches/01-castopod.patch +++ /dev/null @@ -1,808 +0,0 @@ -From 3b656cbdf40c6056983e95ac5c87839a68571096 Mon Sep 17 00:00:00 2001 -From: Alexander Tomokhov -Date: Tue, 3 Oct 2023 22:20:59 +0400 -Subject: [PATCH 1/8] castopod: 1.6.4 -> 1.6.5 - ---- - pkgs/applications/audio/castopod/default.nix | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/pkgs/applications/audio/castopod/default.nix b/pkgs/applications/audio/castopod/default.nix -index 9d9f83e2ecce40..83c70f9b36646d 100644 ---- a/pkgs/applications/audio/castopod/default.nix -+++ b/pkgs/applications/audio/castopod/default.nix -@@ -7,11 +7,11 @@ - }: - stdenv.mkDerivation { - pname = "castopod"; -- version = "1.6.4"; -+ version = "1.6.5"; - - src = fetchurl { -- url = "https://code.castopod.org/adaures/castopod/uploads/ce56d4f149242f12bedd20f9a2b0916d/castopod-1.6.4.tar.gz"; -- sha256 = "080jj91yxbn3xsbs0sywzwa2f5in9bp9qi2zwqcfqpaxlq9ga62v"; -+ url = "https://code.castopod.org/adaures/castopod/uploads/5aaaa6cf2edaed25bd7253449e5f8584/castopod-1.6.5.tar.gz"; -+ sha256 = "04gcq2vmfy5aa2fmsm1qqv1k8g024nikmysdrhy33wj460d529b5"; - }; - - dontBuild = true; - -From 4cd096c27c52ff9948bc7d9ebc05490147ca9675 Mon Sep 17 00:00:00 2001 -From: Alexander Tomokhov -Date: Tue, 3 Oct 2023 22:19:36 +0400 -Subject: [PATCH 2/8] nixos/castopod: fix startup, displaying images, uploads - up to 500 MiB - -- new maxUploadSize option -- new dataDir option (with ReadWritePaths systemd support) -- admin page reports correct free disk space (instead of /nix/store) -- fix example configuration in documentation -- now podcast creation and file upload are tested during NixOS test -- move castopod from audio to web-apps folder -- verbose logging from the browser test ---- - nixos/modules/module-list.nix | 2 +- - .../services/{audio => web-apps}/castopod.md | 11 +- - .../services/{audio => web-apps}/castopod.nix | 60 ++-- - nixos/tests/castopod.nix | 263 +++++++++++++----- - pkgs/applications/audio/castopod/default.nix | 13 +- - 5 files changed, 256 insertions(+), 93 deletions(-) - rename nixos/modules/services/{audio => web-apps}/castopod.md (72%) - rename nixos/modules/services/{audio => web-apps}/castopod.nix (80%) - -diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix -index 627427262da632..97043c965400c5 100644 ---- a/nixos/modules/module-list.nix -+++ b/nixos/modules/module-list.nix -@@ -337,7 +337,6 @@ - ./services/amqp/rabbitmq.nix - ./services/audio/alsa.nix - ./services/audio/botamusique.nix -- ./services/audio/castopod.nix - ./services/audio/gmediarender.nix - ./services/audio/gonic.nix - ./services/audio/goxlr-utility.nix -@@ -1282,6 +1281,7 @@ - ./services/web-apps/bookstack.nix - ./services/web-apps/c2fmzq-server.nix - ./services/web-apps/calibre-web.nix -+ ./services/web-apps/castopod.nix - ./services/web-apps/coder.nix - ./services/web-apps/changedetection-io.nix - ./services/web-apps/chatgpt-retrieval-plugin.nix -diff --git a/nixos/modules/services/audio/castopod.md b/nixos/modules/services/web-apps/castopod.md -similarity index 72% -rename from nixos/modules/services/audio/castopod.md -rename to nixos/modules/services/web-apps/castopod.md -index ee8590737a7c73..f61bf1166a4d24 100644 ---- a/nixos/modules/services/audio/castopod.md -+++ b/nixos/modules/services/web-apps/castopod.md -@@ -4,6 +4,7 @@ Castopod is an open-source hosting platform made for podcasters who want to enga - - ## Quickstart {#module-services-castopod-quickstart} - -+Configure ACME (https://nixos.org/manual/nixos/unstable/#module-security-acme). - Use the following configuration to start a public instance of Castopod on `castopod.example.com` domain: - - ```nix -@@ -11,11 +12,11 @@ networking.firewall.allowedTCPPorts = [ 80 443 ]; - services.castopod = { - enable = true; - database.createLocally = true; -- nginx.virtualHost = { -- serverName = "castopod.example.com"; -- enableACME = true; -- forceSSL = true; -- }; -+ localDomain = "castopod.example.com"; -+}; -+services.nginx.virtualHosts."castopod.example.com" = { -+ enableACME = true; -+ forceSSL = true; - }; - ``` - -diff --git a/nixos/modules/services/audio/castopod.nix b/nixos/modules/services/web-apps/castopod.nix -similarity index 80% -rename from nixos/modules/services/audio/castopod.nix -rename to nixos/modules/services/web-apps/castopod.nix -index b782b548914795..7c99551c83183f 100644 ---- a/nixos/modules/services/audio/castopod.nix -+++ b/nixos/modules/services/web-apps/castopod.nix -@@ -4,7 +4,6 @@ let - fpm = config.services.phpfpm.pools.castopod; - - user = "castopod"; -- stateDirectory = "/var/lib/castopod"; - - # https://docs.castopod.org/getting-started/install.html#requirements - phpPackage = pkgs.php.withExtensions ({ enabled, all }: with all; [ -@@ -29,6 +28,15 @@ in - defaultText = lib.literalMD "pkgs.castopod"; - description = lib.mdDoc "Which Castopod package to use."; - }; -+ dataDir = lib.mkOption { -+ type = lib.types.path; -+ default = "/var/lib/castopod"; -+ description = lib.mdDoc '' -+ The path where castopod stores all data. This path must be in sync -+ with the castopod package (where it is hardcoded during the build in -+ accordance with its own `dataDir` argument). -+ ''; -+ }; - database = { - createLocally = lib.mkOption { - type = lib.types.bool; -@@ -111,6 +119,18 @@ in - Options for Castopod's PHP pool. See the documentation on `php-fpm.conf` for details on configuration directives. - ''; - }; -+ maxUploadSize = lib.mkOption { -+ type = lib.types.int; -+ default = 512; -+ description = lib.mdDoc '' -+ Maximum supported size for a file upload in MiB. Maximum HTTP body -+ size is set to this value for nginx and PHP (because castopod doesn't -+ support chunked uploads yet: -+ https://code.castopod.org/adaures/castopod/-/issues/330). Note, that -+ practical upload size limit is smaller. For example, with 512 MiB -+ setting - around 500 MiB is possible. -+ ''; -+ }; - }; - }; - -@@ -120,13 +140,13 @@ in - sslEnabled = with config.services.nginx.virtualHosts.${cfg.localDomain}; addSSL || forceSSL || onlySSL || enableACME || useACMEHost != null; - baseURL = "http${lib.optionalString sslEnabled "s"}://${cfg.localDomain}"; - in -- lib.mapAttrs (name: lib.mkDefault) { -+ lib.mapAttrs (_name: lib.mkDefault) { - "app.forceGlobalSecureRequests" = sslEnabled; - "app.baseURL" = baseURL; - -- "media.baseURL" = "/"; -+ "media.baseURL" = baseURL; - "media.root" = "media"; -- "media.storage" = stateDirectory; -+ "media.storage" = cfg.dataDir; - - "admin.gateway" = "admin"; - "auth.gateway" = "auth"; -@@ -142,13 +162,13 @@ in - services.phpfpm.pools.castopod = { - inherit user; - group = config.services.nginx.group; -- phpPackage = phpPackage; -+ inherit phpPackage; - phpOptions = '' -- # https://code.castopod.org/adaures/castopod/-/blob/main/docker/production/app/uploads.ini -+ # https://code.castopod.org/adaures/castopod/-/blob/develop/docker/production/common/uploads.template.ini - file_uploads = On - memory_limit = 512M -- upload_max_filesize = 500M -- post_max_size = 512M -+ upload_max_filesize = ${toString cfg.maxUploadSize}M -+ post_max_size = ${toString cfg.maxUploadSize}M - max_execution_time = 300 - max_input_time = 300 - ''; -@@ -165,25 +185,25 @@ in - path = [ pkgs.openssl phpPackage ]; - script = - let -- envFile = "${stateDirectory}/.env"; -+ envFile = "${cfg.dataDir}/.env"; - media = "${cfg.settings."media.storage"}/${cfg.settings."media.root"}"; - in - '' -- mkdir -p ${stateDirectory}/writable/{cache,logs,session,temp,uploads} -+ mkdir -p ${cfg.dataDir}/writable/{cache,logs,session,temp,uploads} - - if [ ! -d ${lib.escapeShellArg media} ]; then - cp --no-preserve=mode,ownership -r ${cfg.package}/share/castopod/public/media ${lib.escapeShellArg media} - fi - -- if [ ! -f ${stateDirectory}/salt ]; then -- openssl rand -base64 33 > ${stateDirectory}/salt -+ if [ ! -f ${cfg.dataDir}/salt ]; then -+ openssl rand -base64 33 > ${cfg.dataDir}/salt - fi - - cat <<'EOF' > ${envFile} - ${lib.generators.toKeyValue { } cfg.settings} - EOF - -- echo "analytics.salt=$(cat ${stateDirectory}/salt)" >> ${envFile} -+ echo "analytics.salt=$(cat ${cfg.dataDir}/salt)" >> ${envFile} - - ${if (cfg.database.passwordFile != null) then '' - echo "database.default.password=$(cat ${lib.escapeShellArg cfg.database.passwordFile})" >> ${envFile} -@@ -192,10 +212,10 @@ in - ''} - - ${lib.optionalString (cfg.environmentFile != null) '' -- cat ${lib.escapeShellArg cfg.environmentFile}) >> ${envFile} -+ cat ${lib.escapeShellArg cfg.environmentFile} >> ${envFile} - ''} - -- php spark castopod:database-update -+ php ${cfg.package}/share/castopod/spark castopod:database-update - ''; - serviceConfig = { - StateDirectory = "castopod"; -@@ -204,6 +224,7 @@ in - RemainAfterExit = true; - User = user; - Group = config.services.nginx.group; -+ ReadWritePaths = cfg.dataDir; - }; - }; - -@@ -212,9 +233,7 @@ in - wantedBy = [ "multi-user.target" ]; - path = [ phpPackage ]; - script = '' -- php public/index.php scheduled-activities -- php public/index.php scheduled-websub-publish -- php public/index.php scheduled-video-clips -+ php ${cfg.package}/share/castopod/spark tasks:run - ''; - serviceConfig = { - StateDirectory = "castopod"; -@@ -222,6 +241,8 @@ in - Type = "oneshot"; - User = user; - Group = config.services.nginx.group; -+ ReadWritePaths = cfg.dataDir; -+ LogLevelMax = "notice"; # otherwise periodic tasks flood the journal - }; - }; - -@@ -251,6 +272,7 @@ in - extraConfig = '' - try_files $uri $uri/ /index.php?$args; - index index.php index.html; -+ client_max_body_size ${toString cfg.maxUploadSize}M; - ''; - - locations."^~ /${cfg.settings."media.root"}/" = { -@@ -278,7 +300,7 @@ in - }; - }; - -- users.users.${user} = lib.mapAttrs (name: lib.mkDefault) { -+ users.users.${user} = lib.mapAttrs (_name: lib.mkDefault) { - description = "Castopod user"; - isSystemUser = true; - group = config.services.nginx.group; -diff --git a/nixos/tests/castopod.nix b/nixos/tests/castopod.nix -index 4435ec617d4e67..2db7aa0bda6507 100644 ---- a/nixos/tests/castopod.nix -+++ b/nixos/tests/castopod.nix -@@ -4,74 +4,211 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: - meta = with lib.maintainers; { - maintainers = [ alexoundos misuzu ]; - }; -+ - nodes.castopod = { nodes, ... }: { -+ # otherwise 500 MiB file upload fails! -+ virtualisation.diskSize = 512 + 3 * 512; -+ - networking.firewall.allowedTCPPorts = [ 80 ]; -- networking.extraHosts = '' -- 127.0.0.1 castopod.example.com -- ''; -+ networking.extraHosts = -+ lib.strings.concatStringsSep "\n" -+ (lib.attrsets.mapAttrsToList -+ (name: _: "127.0.0.1 ${name}") -+ nodes.castopod.services.nginx.virtualHosts); -+ - services.castopod = { - enable = true; - database.createLocally = true; - localDomain = "castopod.example.com"; -+ maxUploadSize = 512; - }; -- environment.systemPackages = -- let -- username = "admin"; -- email = "admin@castood.example.com"; -- password = "v82HmEp5"; -- testRunner = pkgs.writers.writePython3Bin "test-runner" -- { -- libraries = [ pkgs.python3Packages.selenium ]; -- flakeIgnore = [ -- "E501" -- ]; -- } '' -- from selenium.webdriver.common.by import By -- from selenium.webdriver import Firefox -- from selenium.webdriver.firefox.options import Options -- from selenium.webdriver.support.ui import WebDriverWait -- from selenium.webdriver.support import expected_conditions as EC -- -- options = Options() -- options.add_argument('--headless') -- driver = Firefox(options=options) -- try: -- driver.implicitly_wait(20) -- driver.get('http://castopod.example.com/cp-install') -- -- wait = WebDriverWait(driver, 10) -- -- wait.until(EC.title_contains("installer")) -- -- driver.find_element(By.CSS_SELECTOR, '#username').send_keys( -- '${username}' -- ) -- driver.find_element(By.CSS_SELECTOR, '#email').send_keys( -- '${email}' -- ) -- driver.find_element(By.CSS_SELECTOR, '#password').send_keys( -- '${password}' -- ) -- driver.find_element(By.XPATH, "//button[contains(., 'Finish install')]").click() -- -- wait.until(EC.title_contains("Auth")) -- -- driver.find_element(By.CSS_SELECTOR, '#email').send_keys( -- '${email}' -- ) -- driver.find_element(By.CSS_SELECTOR, '#password').send_keys( -- '${password}' -- ) -- driver.find_element(By.XPATH, "//button[contains(., 'Login')]").click() -- -- wait.until(EC.title_contains("Admin dashboard")) -- finally: -- driver.close() -- driver.quit() -- ''; -- in -- [ pkgs.firefox-unwrapped pkgs.geckodriver testRunner ]; - }; -+ -+ nodes.client = { nodes, pkgs, lib, ... }: -+ let -+ domain = nodes.castopod.services.castopod.localDomain; -+ -+ getIP = node: -+ (builtins.head node.networking.interfaces.eth1.ipv4.addresses).address; -+ -+ targetPodcastSize = 500 * 1024 * 1024; -+ lameMp3Bitrate = 348300; -+ lameMp3FileAdjust = -800; -+ targetPodcastDuration = toString -+ ((targetPodcastSize + lameMp3FileAdjust) / (lameMp3Bitrate / 8)); -+ mp3file = with pkgs; -+ runCommand "gen-castopod.mp3" { nativeBuildInputs = [ sox lame ]; } '' -+ sox -n -r 48000 -t wav - synth ${targetPodcastDuration} sine 440 ` -+ `| lame --noreplaygain -cbr -q 9 -b 320 - $out -+ FILESIZE="$(stat -c%s $out)" -+ [ "$FILESIZE" -gt 0 ] -+ [ "$FILESIZE" -le "${toString targetPodcastSize}" ] -+ ''; -+ -+ bannerWidth = 3000; -+ banner = pkgs.runCommand "gen-castopod-cover.jpg" { } '' -+ ${pkgs.imagemagick}/bin/magick ` -+ `-background green -bordercolor white -gravity northwest xc:black ` -+ `-duplicate 99 ` -+ `-seed 1 -resize "%[fx:rand()*72+24]" ` -+ `-seed 0 -rotate "%[fx:rand()*360]" -border 6x6 -splice 16x36 ` -+ `-seed 0 -rotate "%[fx:floor(rand()*4)*90]" -resize "150x50!" ` -+ `+append -crop 10x1@ +repage -roll "+%[fx:(t%2)*72]+0" -append ` -+ `-resize ${toString bannerWidth} -quality 1 $out -+ ''; -+ -+ coverWidth = toString 3000; -+ cover = pkgs.runCommand "gen-castopod-banner.jpg" { } '' -+ ${pkgs.imagemagick}/bin/magick ` -+ `-background white -bordercolor white -gravity northwest xc:black ` -+ `-duplicate 99 ` -+ `-seed 1 -resize "%[fx:rand()*72+24]" ` -+ `-seed 0 -rotate "%[fx:rand()*360]" -border 6x6 -splice 36x36 ` -+ `-seed 0 -rotate "%[fx:floor(rand()*4)*90]" -resize "144x144!" ` -+ `+append -crop 10x1@ +repage -roll "+%[fx:(t%2)*72]+0" -append ` -+ `-resize ${coverWidth} -quality 1 $out -+ ''; -+ in -+ { -+ networking.extraHosts = -+ lib.strings.concatStringsSep "\n" -+ (lib.attrsets.mapAttrsToList -+ (name: _: "${getIP nodes.castopod} ${name}") -+ nodes.castopod.services.nginx.virtualHosts); -+ -+ environment.systemPackages = -+ let -+ username = "admin"; -+ email = "admin@${domain}"; -+ password = "Abcd1234"; -+ podcastTitle = "Some Title"; -+ episodeTitle = "Episode Title"; -+ browser-test = pkgs.writers.writePython3Bin "browser-test" -+ { -+ libraries = [ pkgs.python3Packages.selenium ]; -+ flakeIgnore = [ "E124" "E501" ]; -+ } '' -+ from selenium.webdriver.common.by import By -+ from selenium.webdriver import Firefox -+ from selenium.webdriver.firefox.options import Options -+ from selenium.webdriver.firefox.service import Service -+ from selenium.webdriver.support.ui import WebDriverWait -+ from selenium.webdriver.support import expected_conditions as EC -+ from subprocess import STDOUT -+ import logging -+ -+ selenium_logger = logging.getLogger("selenium") -+ selenium_logger.setLevel(logging.DEBUG) -+ selenium_logger.addHandler(logging.StreamHandler()) -+ -+ options = Options() -+ options.add_argument('--headless') -+ service = Service(log_output=STDOUT) -+ driver = Firefox(options=options, service=service) -+ driver = Firefox(options=options) -+ driver.implicitly_wait(20) -+ -+ # install ########################################################## -+ -+ driver.get('http://${domain}/cp-install') -+ -+ wait = WebDriverWait(driver, 10) -+ -+ wait.until(EC.title_contains("installer")) -+ -+ driver.find_element(By.CSS_SELECTOR, '#username').send_keys( -+ '${username}' -+ ) -+ driver.find_element(By.CSS_SELECTOR, '#email').send_keys( -+ '${email}' -+ ) -+ driver.find_element(By.CSS_SELECTOR, '#password').send_keys( -+ '${password}' -+ ) -+ driver.find_element(By.XPATH, -+ "//button[contains(., 'Finish install')]" -+ ).click() -+ -+ wait.until(EC.title_contains("Auth")) -+ -+ driver.find_element(By.CSS_SELECTOR, '#email').send_keys( -+ '${email}' -+ ) -+ driver.find_element(By.CSS_SELECTOR, '#password').send_keys( -+ '${password}' -+ ) -+ driver.find_element(By.XPATH, -+ "//button[contains(., 'Login')]" -+ ).click() -+ -+ wait.until(EC.title_contains("Admin dashboard")) -+ -+ # create podcast ################################################### -+ -+ driver.get('http://${domain}/admin/podcasts/new') -+ -+ wait.until(EC.title_contains("Create podcast")) -+ -+ driver.find_element(By.CSS_SELECTOR, '#cover').send_keys( -+ '${cover}' -+ ) -+ driver.find_element(By.CSS_SELECTOR, '#banner').send_keys( -+ '${banner}' -+ ) -+ driver.find_element(By.CSS_SELECTOR, '#title').send_keys( -+ '${podcastTitle}' -+ ) -+ driver.find_element(By.CSS_SELECTOR, '#handle').send_keys( -+ 'some_handle' -+ ) -+ driver.find_element(By.CSS_SELECTOR, '#description').send_keys( -+ 'Some description' -+ ) -+ driver.find_element(By.CSS_SELECTOR, '#owner_name').send_keys( -+ 'Owner Name' -+ ) -+ driver.find_element(By.CSS_SELECTOR, '#owner_email').send_keys( -+ 'owner@email.xyz' -+ ) -+ driver.find_element(By.XPATH, -+ "//button[contains(., 'Create podcast')]" -+ ).click() -+ -+ wait.until(EC.title_contains("${podcastTitle}")) -+ -+ driver.find_element(By.XPATH, -+ "//span[contains(., 'Add an episode')]" -+ ).click() -+ -+ wait.until(EC.title_contains("Add an episode")) -+ -+ # upload podcast ################################################### -+ -+ driver.find_element(By.CSS_SELECTOR, '#audio_file').send_keys( -+ '${mp3file}' -+ ) -+ driver.find_element(By.CSS_SELECTOR, '#cover').send_keys( -+ '${cover}' -+ ) -+ driver.find_element(By.CSS_SELECTOR, '#description').send_keys( -+ 'Episode description' -+ ) -+ driver.find_element(By.CSS_SELECTOR, '#title').send_keys( -+ '${episodeTitle}' -+ ) -+ driver.find_element(By.XPATH, -+ "//button[contains(., 'Create episode')]" -+ ).click() -+ -+ wait.until(EC.title_contains("${episodeTitle}")) -+ -+ driver.close() -+ driver.quit() -+ ''; -+ in -+ [ pkgs.firefox-unwrapped pkgs.geckodriver browser-test ]; -+ }; -+ - testScript = '' - start_all() - castopod.wait_for_unit("castopod-setup.service") -@@ -79,9 +216,9 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: - castopod.wait_for_unit("nginx.service") - castopod.wait_for_open_port(80) - castopod.wait_until_succeeds("curl -sS -f http://castopod.example.com") -- castopod.succeed("curl -s http://localhost/cp-install | grep 'Create your Super Admin account' > /dev/null") - -- with subtest("Create superadmin and log in"): -- castopod.succeed("PYTHONUNBUFFERED=1 systemd-cat -t test-runner test-runner") -+ with subtest("Create superadmin, log in, create and upload a podcast"): -+ client.succeed(\ -+ "PYTHONUNBUFFERED=1 systemd-cat -t browser-test browser-test") - ''; - }) -diff --git a/pkgs/applications/audio/castopod/default.nix b/pkgs/applications/audio/castopod/default.nix -index 83c70f9b36646d..badace09587d2b 100644 ---- a/pkgs/applications/audio/castopod/default.nix -+++ b/pkgs/applications/audio/castopod/default.nix -@@ -3,7 +3,7 @@ - , ffmpeg-headless - , lib - , nixosTests --, stateDirectory ? "/var/lib/castopod" -+, dataDir ? "/var/lib/castopod" - }: - stdenv.mkDerivation { - pname = "castopod"; -@@ -20,13 +20,16 @@ stdenv.mkDerivation { - postPatch = '' - # not configurable at runtime unfortunately: - substituteInPlace app/Config/Paths.php \ -- --replace "__DIR__ . '/../../writable'" "'${stateDirectory}/writable'" -+ --replace "__DIR__ . '/../../writable'" "'${dataDir}/writable'" - -- # configuration file must be writable, place it to ${stateDirectory} -+ substituteInPlace modules/Admin/Controllers/DashboardController.php \ -+ --replace "disk_total_space('./')" "disk_total_space('${dataDir}')" -+ -+ # configuration file must be writable, place it to ${dataDir} - substituteInPlace modules/Install/Controllers/InstallController.php \ -- --replace "ROOTPATH" "'${stateDirectory}/'" -+ --replace "ROOTPATH" "'${dataDir}/'" - substituteInPlace public/index.php spark \ -- --replace "DotEnv(ROOTPATH)" "DotEnv('${stateDirectory}')" -+ --replace "DotEnv(ROOTPATH)" "DotEnv('${dataDir}')" - - # ffmpeg is required for Video Clips feature - substituteInPlace modules/MediaClipper/VideoClipper.php \ - -From 45d43fe39fa3167d5cf7ba9a2cb9fcd6fbe2c5c3 Mon Sep 17 00:00:00 2001 -From: Alexander Tomokhov -Date: Mon, 11 Dec 2023 09:00:26 +0400 -Subject: [PATCH 3/8] nixos/castopod: little documentation fix - ---- - nixos/modules/services/web-apps/castopod.nix | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/nixos/modules/services/web-apps/castopod.nix b/nixos/modules/services/web-apps/castopod.nix -index 7c99551c83183f..11cf4b36aeb385 100644 ---- a/nixos/modules/services/web-apps/castopod.nix -+++ b/nixos/modules/services/web-apps/castopod.nix -@@ -126,9 +126,10 @@ in - Maximum supported size for a file upload in MiB. Maximum HTTP body - size is set to this value for nginx and PHP (because castopod doesn't - support chunked uploads yet: -- https://code.castopod.org/adaures/castopod/-/issues/330). Note, that -- practical upload size limit is smaller. For example, with 512 MiB -- setting - around 500 MiB is possible. -+ https://code.castopod.org/adaures/castopod/-/issues/330). -+ -+ Note, that practical upload size limit is smaller. For example, with -+ 512 MiB setting - around 500 MiB is possible. - ''; - }; - }; - -From 4aafd48b7e76748eaf0ff7409b12b455d1db31ec Mon Sep 17 00:00:00 2001 -From: sinavir -Date: Fri, 23 Feb 2024 22:02:10 +0100 -Subject: [PATCH 4/8] castopod: 1.6.5 -> 1.10.3 - ---- - pkgs/applications/audio/castopod/default.nix | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/pkgs/applications/audio/castopod/default.nix b/pkgs/applications/audio/castopod/default.nix -index badace09587d2b..438f1d728f9624 100644 ---- a/pkgs/applications/audio/castopod/default.nix -+++ b/pkgs/applications/audio/castopod/default.nix -@@ -10,8 +10,8 @@ stdenv.mkDerivation { - version = "1.6.5"; - - src = fetchurl { -- url = "https://code.castopod.org/adaures/castopod/uploads/5aaaa6cf2edaed25bd7253449e5f8584/castopod-1.6.5.tar.gz"; -- sha256 = "04gcq2vmfy5aa2fmsm1qqv1k8g024nikmysdrhy33wj460d529b5"; -+ url = "https://code.castopod.org/adaures/castopod/uploads/2bb52d4607a772ac8b397efa3559a3ae/castopod-1.10.3.tar.gz"; -+ sha256 = "0w1yl14v3aajm089vwpq9wkiibv3w312y004ggdbf7xwzsrmjs51"; - }; - - dontBuild = true; - -From 6205595efbdcc2f3440022b4ff7258e2f50a6427 Mon Sep 17 00:00:00 2001 -From: sinavir -Date: Fri, 23 Feb 2024 22:27:24 +0100 -Subject: [PATCH 6/8] nixos/castopod: use LoadCredentials - ---- - nixos/modules/services/web-apps/castopod.nix | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/nixos/modules/services/web-apps/castopod.nix b/nixos/modules/services/web-apps/castopod.nix -index 11cf4b36aeb385..042fb3954d2b73 100644 ---- a/nixos/modules/services/web-apps/castopod.nix -+++ b/nixos/modules/services/web-apps/castopod.nix -@@ -67,6 +67,8 @@ in - description = lib.mdDoc '' - A file containing the password corresponding to - [](#opt-services.castopod.database.user). -+ -+ This file is loaded using systemd LoadCredentials. - ''; - }; - }; -@@ -93,6 +95,8 @@ in - Environment file to inject e.g. secrets into the configuration. - See [](https://code.castopod.org/adaures/castopod/-/blob/main/.env.example) - for available environment variables. -+ -+ This file is loaded using systemd LoadCredentials. - ''; - }; - configureNginx = lib.mkOption { -@@ -207,19 +211,23 @@ in - echo "analytics.salt=$(cat ${cfg.dataDir}/salt)" >> ${envFile} - - ${if (cfg.database.passwordFile != null) then '' -- echo "database.default.password=$(cat ${lib.escapeShellArg cfg.database.passwordFile})" >> ${envFile} -+ echo "database.default.password=$(cat "$CREDENTIALS_DIRECTORY/dbpasswordfile)" >> ${envFile} - '' else '' - echo "database.default.password=" >> ${envFile} - ''} - - ${lib.optionalString (cfg.environmentFile != null) '' -- cat ${lib.escapeShellArg cfg.environmentFile} >> ${envFile} -+ cat "$CREDENTIALS_DIRECTORY/envfile" >> ${envFile} - ''} - - php ${cfg.package}/share/castopod/spark castopod:database-update - ''; - serviceConfig = { - StateDirectory = "castopod"; -+ LoadCredential = lib.optional (cfg.environmentFile != null) -+ "envfile:${cfg.environmentFile}" -+ ++ (lib.optional (cfg.database.passwordFile != null) -+ "dbpasswordfile:${cfg.database.passwordFile}"); - WorkingDirectory = "${cfg.package}/share/castopod"; - Type = "oneshot"; - RemainAfterExit = true; - -From 9b03fc35a30671e5d4146bbcbe6b5536fa9baacc Mon Sep 17 00:00:00 2001 -From: sinavir -Date: Sat, 2 Mar 2024 18:01:54 +0100 -Subject: [PATCH 7/8] nixos/castopod: build mp3 in the test - ---- - nixos/tests/castopod.nix | 31 +++++++++++++++++++++---------- - 1 file changed, 21 insertions(+), 10 deletions(-) - -diff --git a/nixos/tests/castopod.nix b/nixos/tests/castopod.nix -index 2db7aa0bda6507..2bdc6941c23815 100644 ---- a/nixos/tests/castopod.nix -+++ b/nixos/tests/castopod.nix -@@ -37,14 +37,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: - targetPodcastDuration = toString - ((targetPodcastSize + lameMp3FileAdjust) / (lameMp3Bitrate / 8)); - mp3file = with pkgs; -- runCommand "gen-castopod.mp3" { nativeBuildInputs = [ sox lame ]; } '' -- sox -n -r 48000 -t wav - synth ${targetPodcastDuration} sine 440 ` -- `| lame --noreplaygain -cbr -q 9 -b 320 - $out -- FILESIZE="$(stat -c%s $out)" -- [ "$FILESIZE" -gt 0 ] -- [ "$FILESIZE" -le "${toString targetPodcastSize}" ] -- ''; -- -+ runCommand ; - bannerWidth = 3000; - banner = pkgs.runCommand "gen-castopod-cover.jpg" { } '' - ${pkgs.imagemagick}/bin/magick ` -@@ -185,7 +178,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: - # upload podcast ################################################### - - driver.find_element(By.CSS_SELECTOR, '#audio_file').send_keys( -- '${mp3file}' -+ '/tmp/podcast.mp3' - ) - driver.find_element(By.CSS_SELECTOR, '#cover').send_keys( - '${cover}' -@@ -206,7 +199,23 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: - driver.quit() - ''; - in -- [ pkgs.firefox-unwrapped pkgs.geckodriver browser-test ]; -+ [ -+ pkgs.firefox-unwrapped -+ pkgs.geckodriver -+ browser-test -+ (pkgs.writeShellApplication { -+ name = "build-mp3"; -+ runtimeInputs = with pkgs; [ sox lame ]; -+ text = '' -+ out=/tmp/podcast.mp3 -+ sox -n -r 48000 -t wav - synth ${targetPodcastDuration} sine 440 ` -+ `| lame --noreplaygain -cbr -q 9 -b 320 - $out -+ FILESIZE="$(stat -c%s $out)" -+ [ "$FILESIZE" -gt 0 ] -+ [ "$FILESIZE" -le "${toString targetPodcastSize}" ] -+ ''; -+ }) -+ ]; - }; - - testScript = '' -@@ -217,6 +226,8 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: - castopod.wait_for_open_port(80) - castopod.wait_until_succeeds("curl -sS -f http://castopod.example.com") - -+ client.succeed("build-mp3") -+ - with subtest("Create superadmin, log in, create and upload a podcast"): - client.succeed(\ - "PYTHONUNBUFFERED=1 systemd-cat -t browser-test browser-test") - -From 538281e8be427f820371f4005e991e0281872e12 Mon Sep 17 00:00:00 2001 -From: sinavir -Date: Sat, 2 Mar 2024 18:04:35 +0100 -Subject: [PATCH 8/8] nixos/castopod: Increase test timeouts - ---- - nixos/tests/castopod.nix | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/nixos/tests/castopod.nix b/nixos/tests/castopod.nix -index 2bdc6941c23815..2c5c745f7da0df 100644 ---- a/nixos/tests/castopod.nix -+++ b/nixos/tests/castopod.nix -@@ -105,7 +105,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: - - driver.get('http://${domain}/cp-install') - -- wait = WebDriverWait(driver, 10) -+ wait = WebDriverWait(driver, 20) - - wait.until(EC.title_contains("installer")) - diff --git a/patches/03-nextcloud.patch b/patches/03-nextcloud.patch deleted file mode 100644 index 0263c0d..0000000 --- a/patches/03-nextcloud.patch +++ /dev/null @@ -1,28 +0,0 @@ ---- a/nixos/modules/services/web-apps/nextcloud.nix -+++ b/nixos/modules/services/web-apps/nextcloud.nix -@@ -131,6 +131,7 @@ - (mkRemovedOptionModule [ "services" "nextcloud" "disableImagemagick" ] '' - Use services.nextcloud.enableImagemagick instead. - '') -+ (mkRenamedOptionModule [ "services" "nextcloud" "config" "objectstore" "s3" "autocreate" ] [ "services" "nextcloud" "config" "objectstore" "s3" "verify_bucket_exists" ]) - ]; - - options.services.nextcloud = { -@@ -487,7 +487,7 @@ - The name of the S3 bucket. - ''; - }; -- autocreate = mkOption { -+ verify_bucket_exists = mkOption { - type = types.bool; - description = lib.mdDoc '' - Create the objectstore if it does not exist. -@@ -820,7 +820,7 @@ - 'class' => '\\OC\\Files\\ObjectStore\\S3', - 'arguments' => [ - 'bucket' => '${s3.bucket}', -- 'autocreate' => ${boolToString s3.autocreate}, -+ 'verify_bucket_exists' => ${boolToString s3.verify_bucket_exists}, - 'key' => '${s3.key}', - 'secret' => nix_read_secret('${s3.secretFile}'), - ${optionalString (s3.hostname != null) "'hostname' => '${s3.hostname}',"} diff --git a/patches/04-crabfit-karla.patch b/patches/04-crabfit-karla.patch deleted file mode 100644 index 366928a..0000000 --- a/patches/04-crabfit-karla.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/pkgs/by-name/cr/crabfit-frontend/package.nix b/pkgs/by-name/cr/crabfit-frontend/package.nix -index 99d7be0fdeae..9f858e8a9a9e 100644 ---- a/pkgs/by-name/cr/crabfit-frontend/package.nix -+++ b/pkgs/by-name/cr/crabfit-frontend/package.nix -@@ -8,7 +8,7 @@ - nodejs, - yarn, - fixup_yarn_lock, -- google-fonts, -+ karla, - api_url ? "http://127.0.0.1:3000", - frontend_url ? "crab.fit", - }: -@@ -83,9 +83,7 @@ stdenv.mkDerivation (finalAttrs: { - patchShebangs node_modules - - mkdir -p src/app/fonts -- cp "${ -- google-fonts.override { fonts = [ "Karla" ]; } -- }/share/fonts/truetype/Karla[wght].ttf" src/app/fonts/karla.ttf -+ cp "${karla}/share/fonts/truetype/Karla-Regular.ttf" src/app/fonts/karla.ttf - - runHook postConfigure - ''; diff --git a/patches/05-pmnos-correctness-build-directory.patch b/patches/05-pmnos-correctness-build-directory.patch deleted file mode 100644 index 0a57672..0000000 --- a/patches/05-pmnos-correctness-build-directory.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 4d6e57d2d577cc105c9e0cd397408e9e3ce85cd0 Mon Sep 17 00:00:00 2001 -From: Raito Bezarius -Date: Tue, 8 Oct 2024 16:33:14 +0200 -Subject: [PATCH] fix(packaging): correctness of the build top directory - -It was using /build which is an implementation detail and not -guaranteed. - -Signed-off-by: Raito Bezarius ---- - pkgs/pve-container/default.nix | 6 +++--- - pkgs/pve-rs/default.nix | 2 +- - 2 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/pkgs/pve-container/default.nix b/pkgs/pve-container/default.nix -index 445c271..5633c0f 100644 ---- a/pkgs/pve-container/default.nix -+++ b/pkgs/pve-container/default.nix -@@ -30,7 +30,7 @@ perl536.pkgs.toPerlModule ( - postPatch = '' - sed -i Makefile \ - -e "s/pct.1 pct.conf.5 pct.bash-completion pct.zsh-completion //" \ -- -e "s,/usr/share/lxc,/build/lxc," \ -+ -e "s,/usr/share/lxc,$NIX_BUILD_TOP/lxc," \ - -e "/pve-doc-generator/d" \ - -e "/PVE_GENERATING_DOCS/d" \ - -e "/SERVICEDIR/d" \ -@@ -45,8 +45,8 @@ perl536.pkgs.toPerlModule ( - dontPatchShebangs = true; - - postConfigure = '' -- cp -r ${lxc}/share/lxc /build -- chmod -R +w /build/lxc -+ cp -r ${lxc}/share/lxc $NIX_BUILD_TOP/ -+ chmod -R +w $NIX_BUILD_TOP/lxc - ''; - - makeFlags = [ -diff --git a/pkgs/pve-rs/default.nix b/pkgs/pve-rs/default.nix -index c024287..881beab 100644 ---- a/pkgs/pve-rs/default.nix -+++ b/pkgs/pve-rs/default.nix -@@ -57,7 +57,7 @@ perl536.pkgs.toPerlModule ( - ]; - - makeFlags = [ -- "BUILDIR=/build" -+ "BUILDIR=$NIX_BUILD_TOP" - "BUILD_MODE=release" - "DESTDIR=$(out)" - "GITVERSION:=${src.rev}" --- -2.46.0 - diff --git a/patches/default.nix b/patches/default.nix index bec48f0..e0742d1 100644 --- a/patches/default.nix +++ b/patches/default.nix @@ -6,131 +6,9 @@ let in { - "nixos-24.05" = [ - # netbox qrcode plugin - { - _type = "commit"; - sha = "ae4bf4c110378ebacb3989c9533726859cfebbfa"; - hash = "sha256-SgHhW9HCkDQsxT3eG4P9q68c43e3sbDHRY9qs7oSt8o="; - } + "nixos-24.05" = [ netboxAgent ]; - netboxAgent + "nixos-unstable" = [ netboxAgent ]; - { - id = "275165"; - hash = "sha256-9a26V3Pi8yLD3N9+mC1kvJoruxRTp/qOHapnt6VX7pw="; - } - - # karla: init at 2.004 - { - _type = "commit"; - sha = "7c51104112e8ea0e2ac53bf7d535e677f7686a9e"; - hash = "sha256-1TBLzZkvkFhCL8RYVVIUhTyrH3+X1iJIMkyHffmrOWc="; - } - - # Crabfit: don't depend on all google-fonts - { - _type = "static"; - path = ./04-crabfit-karla.patch; - } - ]; - "nixos-23.11" = [ - # netbox module - { - _type = "commit"; - sha = "163fed297ed65a24241f190d8e954ce1877f9020"; - includes = [ "nixos/modules/services/web-apps/netbox.nix" ]; - hash = "sha256-mjeRxtZozgLNzHkCxcTs3xnonNPkmPoaGxawixC9jfo="; - } - - # netbox qrcode plugin - { - _type = "commit"; - sha = "ae4bf4c110378ebacb3989c9533726859cfebbfa"; - hash = "sha256-SgHhW9HCkDQsxT3eG4P9q68c43e3sbDHRY9qs7oSt8o="; - } - - netboxAgent - - # missing jsonargparse deps for netbox-agent - { - # json arg parse dep: typesched-client - _type = "commit"; - sha = "b1770afd23a7a1ebb4e5bccd8d34dfb3a58a4341"; - hash = "sha256-PNUOPgmNFQr+bwG8MQiwlI4+zkDKLL3e1GgHHskX/Dk="; - } - { - # json arg parse dep: reconplogger - _type = "commit"; - sha = "3835e47059eee32eaf5ef0eb03fce90e8c9b8ab4"; - hash = "sha256-owJL1nmYfEXSHekBGgbJrTkl3OpX6dG9oq3mjN4Xgj8="; - } - { - # json arg parse dep: logmatic - _type = "commit"; - sha = "b0de35af031b4282ac99919384f029a18704d819"; - hash = "sha256-0nJzF2WMPNs2/zI65T1j9DQ0kORDKCu3H2PWjd/bXuo="; - } - { - # init at 4.27.2 - _type = "commit"; - sha = "aa724f81163725b54a06623d191de6d4c064c5ea"; - hash = "sha256-ZWOVpVVsmjBCCiMe/j4YKz6YP4m5I8TTbqWNqBaMtKA="; - } - { - # 4.27.2 -> 4.27.3 - id = "284460"; - hash = "sha256-di9F8d5l0QDWt9yNpamHMyMm4AVxnsRko8+/Ruo7G3I="; - } - { - # 4.27.3 -> 4.27.4 - id = "285873"; - hash = "sha256-GRytcYvIsMP2RfHlmOJIH3po2/KmfZ3fDwo3YUyXGEU="; - } - { - # 4.27.4 -> 4.27.5 - id = "288546"; - hash = "sha256-iHXwZQKlaWmbd9kJbm6YyjIc3bPFHGbIghYRCPsSGHo="; - } - { - # 4.27.5 -> 4.27.6 - id = "296359"; - hash = "sha256-BHevlu8eqkoRgxwFMoS9bkT/9+w0Hfp3JXWh6UKovUk="; - } - { - # 4.27.6 -> 4.27.7 - id = "297825"; - hash = "sha256-tu91+T1G/sHfCLfLL4Jk/zLU/QwnHLbpxiYzRBJXFXw="; - } - - # castopod: 1.6.4 -> 1.7.0 + ajout du support de loadcredentials - { - _type = "static"; - path = ./01-castopod.patch; - } - - # nixos/nextcloud: Rename autocreate (a no-op) to verify_bucket_exists - { - _type = "static"; - path = ./03-nextcloud.patch; - } - ]; - - "nixos-unstable" = [ - netboxAgent - - # netbox qrcode plugin - { - _type = "commit"; - sha = "ae4bf4c110378ebacb3989c9533726859cfebbfa"; - hash = "sha256-SgHhW9HCkDQsxT3eG4P9q68c43e3sbDHRY9qs7oSt8o="; - } - ]; - - "proxmox-nixos" = [ - { - _type = "static"; - path = ./05-pmnos-correctness-build-directory.patch; - } - ]; + "proxmox-nixos" = [ ]; } -- 2.47.0 From 3ce077f92cb5259251b914ea04250d7af9a51e8a Mon Sep 17 00:00:00 2001 From: sinavir Date: Thu, 17 Oct 2024 12:56:29 +0200 Subject: [PATCH 2/6] chore(iso): Remove as it is broken Several stuff are broken in the generation of the iso: - Impure (using nixpkgs in user nix_path) - Using a software which is just a wrpper around nixpkgs - Raid stuff is kinda broken (depend on the version of nixpkgs you use, going back to impurity stated above) --- iso/build-iso.sh | 5 -- iso/configuration.nix | 38 --------- iso/dgn-install/README.md | 1 - iso/dgn-install/default.nix | 20 ----- iso/dgn-install/dgn-install.sh | 149 --------------------------------- iso/nixpkgs.nix | 9 -- 6 files changed, 222 deletions(-) delete mode 100755 iso/build-iso.sh delete mode 100644 iso/configuration.nix delete mode 100644 iso/dgn-install/README.md delete mode 100644 iso/dgn-install/default.nix delete mode 100644 iso/dgn-install/dgn-install.sh delete mode 100644 iso/nixpkgs.nix diff --git a/iso/build-iso.sh b/iso/build-iso.sh deleted file mode 100755 index a210aad..0000000 --- a/iso/build-iso.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -NIXPKGS=$(nix-build --no-out-link nixpkgs.nix) - -nixos-generate -c configuration.nix -I NIX_PATH="$NIXPKGS" -f install-iso diff --git a/iso/configuration.nix b/iso/configuration.nix deleted file mode 100644 index e7cabf8..0000000 --- a/iso/configuration.nix +++ /dev/null @@ -1,38 +0,0 @@ -{ lib, pkgs, ... }: - -let - dgn-keys = import ../keys; - - dgn-members = (import ../meta lib).organization.groups.root; -in - -{ - imports = [ ./dgn-install ]; - - boot = { - blacklistedKernelModules = [ "snd_pcsp" ]; - kernelPackages = pkgs.linuxPackages_latest; - tmp.cleanOnBoot = true; - - loader = { - systemd-boot.enable = true; - efi.canTouchEfiVariables = true; - }; - - supportedFilesystems = [ - "exfat" - "zfs" - "bcachefs" - ]; - - swraid.enable = lib.mkForce false; - }; - - console.keyMap = "fr"; - - services = { - openssh.enable = true; - }; - - users.users.root.openssh.authorizedKeys.keys = dgn-keys.getKeys dgn-members; -} diff --git a/iso/dgn-install/README.md b/iso/dgn-install/README.md deleted file mode 100644 index 32f2f2f..0000000 --- a/iso/dgn-install/README.md +++ /dev/null @@ -1 +0,0 @@ -Script pour installer automatiquement NixOS sur les machines de la DGNum diff --git a/iso/dgn-install/default.nix b/iso/dgn-install/default.nix deleted file mode 100644 index 3028540..0000000 --- a/iso/dgn-install/default.nix +++ /dev/null @@ -1,20 +0,0 @@ -{ pkgs, ... }: - -let - installScript = pkgs.writeShellApplication { - name = "dgn-install"; - - runtimeInputs = with pkgs; [ - coreutils - gnused - nixos-install-tools - zfs - ]; - - text = builtins.readFile ./dgn-install.sh; - }; -in - -{ - environment.systemPackages = [ installScript ]; -} diff --git a/iso/dgn-install/dgn-install.sh b/iso/dgn-install/dgn-install.sh deleted file mode 100644 index ae7d179..0000000 --- a/iso/dgn-install/dgn-install.sh +++ /dev/null @@ -1,149 +0,0 @@ -bootDevice= -rootDevice= - -domain="par01.infra.dgnum.eu" -hostname="dgn0x" - -hasZFS= - -while [ "$#" -gt 0 ]; do - i="$1" - shift 1 - case "$i" in - --root) - rootDevice="$1" - shift 1 - ;; - --boot) - bootDevice="$1" - shift 1 - ;; - --swap) - swapDevice="$1" - shift 1 - ;; - --domain) - domain="$1" - shift 1 - ;; - --hostname) - hostname="$1" - shift 1 - ;; - --with-zfs) - hasZFS="1" - ;; - *) - echo "$0: unknown option \`$i'" - exit 1 - ;; - esac -done - -if [ -z "$bootDevice" ]; then - echo "Missing boot partition" - exit 1 -fi - -if [ -z "$rootDevice" ]; then - echo "Missing root partition" - exit 1 -fi - -# Mount the partitions to where they should be -mount "$rootDevice" /mnt -mkdir /mnt/boot - -mount "$bootDevice" /mnt/boot - -if [ -n "$swapDevice" ]; then - swapon "$swapDevice" -fi - -# Generate configration -nixos-generate-config --root /mnt - -NIX="/mnt/etc/nixos/" - -# Setup our own files -mv $NIX/configuration.nix $NIX/base-configuration.nix - -cat < $NIX/dgnum-server.nix -{ ... }: { - services.nscd.enableNsncd = false; - programs.bash.promptInit = '' - # Provide a nice prompt if the terminal supports it. - if [ "\$TERM" != "dumb" ] || [ -n "\$INSIDE_EMACS" ]; then - PROMPT_COLOR="1;31m" - ((UID)) && PROMPT_COLOR="1;32m" - if [ -n "\$INSIDE_EMACS" ] || [ "\$TERM" = "eterm" ] || [ "\$TERM" = "eterm-color" ]; then - # Emacs term mode doesn't support xterm title escape sequence (\e]0;) - PS1="\n\[\033[\$PROMPT_COLOR\][\u@\$(hostname -f):\w]\\\$\[\033[0m\] " - else - PS1="\n\[\033[\$PROMPT_COLOR\][\[\e]0;\u@\H: \w\a\]\u@\$(hostname -f):\w]\\\$\[\033[0m\] " - fi - if test "\$TERM" = "xterm"; then - PS1="\[\033]2;\$(hostname -f):\u:\w\007\]\$PS1" - fi - fi - ''; -} -EOF - -cat < $NIX/configuration.nix -{ pkgs, ... }: { - imports = [ - ./base-configuration.nix - ./dgnum-server.nix - $(if [ -n "$hasZFS" ]; then echo './zfs.nix'; fi) - ]; - - boot.tmp.cleanOnBoot = true; - - console.keyMap = "fr"; - - time.timeZone = "Europe/Paris"; - - environment.systemPackages = with pkgs; [ - vim - wget - kitty.terminfo - ]; - - networking = { - hostName = "$hostname"; - domain = "$domain"; - }; - - # Activate SSH and set the keys - services.openssh = { - enable = true; - - settings.PasswordAuthentication = false; - }; - - users.users.root.openssh.authorizedKeys.keyFiles = [ ./rootKeys ]; -} -EOF - -if [ -n "$hasZFS" ]; then - cat < $NIX/zfs.nix -{ ... }: { - boot = { - supportedFilesystems = [ "zfs" ]; - zfs.forceImportRoot = false; - zfs.extraPools = [ - $(zpool list -Ho name | sed 's/^/"/;s/$/"/') - ]; - }; - - networking.hostId = "$(head -c4 /dev/urandom | od -A none -t x4 | sed 's/ //')"; -} -EOF -fi - -# Copy the keys -cp /etc/ssh/authorized_keys.d/root $NIX/rootKeys - -# Perform the installation -nixos-install diff --git a/iso/nixpkgs.nix b/iso/nixpkgs.nix deleted file mode 100644 index c859113..0000000 --- a/iso/nixpkgs.nix +++ /dev/null @@ -1,9 +0,0 @@ -let - version = (import ../meta/nixpkgs.nix).default; - nixpkgs = (import ../npins)."nixos-${version}"; -in - -(import nixpkgs { }).srcOnly { - name = "nixpkgs-for-iso"; - src = nixpkgs; -} -- 2.47.0 From 2ac0a35c5ea960378e9cf6b164aba3e23766728b Mon Sep 17 00:00:00 2001 From: sinavir Date: Thu, 17 Oct 2024 13:03:15 +0200 Subject: [PATCH 3/6] chore(meta): Revamp and remove DNS for now We don't have a dns server for the lab infra for now. Later we will probably reintroduce the tooling for our dns server. This will be good for people to get into understanding the main infra repository. --- .forgejo/workflows/check-meta.yaml | 8 -- default.nix | 2 - meta/dns.nix | 136 --------------------- meta/network.nix | 183 ----------------------------- meta/nodes.nix | 106 ----------------- meta/options.nix | 48 -------- meta/organization.nix | 49 +------- meta/verify.nix | 13 -- 8 files changed, 6 insertions(+), 539 deletions(-) delete mode 100644 meta/dns.nix diff --git a/.forgejo/workflows/check-meta.yaml b/.forgejo/workflows/check-meta.yaml index 27af558..179d206 100644 --- a/.forgejo/workflows/check-meta.yaml +++ b/.forgejo/workflows/check-meta.yaml @@ -15,11 +15,3 @@ jobs: - name: Check the validity of meta options run: nix-build meta/verify.nix -A meta - - check_dns: - runs-on: nix - steps: - - uses: actions/checkout@v3 - - - name: Check the validity of the DNS configuration - run: nix-build meta/verify.nix -A dns --no-out-link diff --git a/default.nix b/default.nix index 414feb8..0dbf784 100644 --- a/default.nix +++ b/default.nix @@ -74,8 +74,6 @@ in host: { site, ... }: "${host}.${site}.infra.dgnum.eu" ) (import ./meta/nodes.nix); - dns = import ./meta/dns.nix; - mkCacheSettings = import ./machines/storage01/tvix-cache/cache-settings.nix; shells = { diff --git a/meta/dns.nix b/meta/dns.nix deleted file mode 100644 index d6d59a0..0000000 --- a/meta/dns.nix +++ /dev/null @@ -1,136 +0,0 @@ -{ lib, dns, ... }: - -let - inherit (lib) mapAttrs' nameValuePair; - inherit (lib.extra) fuseAttrs mapSingleFuse; - - inherit (dns.lib.combinators) mx spf ttl; - - meta = (import ./.) lib; - - mkCNAME = host: { CNAME = [ host ]; }; - - mkHosted = - server: - { - dual ? [ ], - v4 ? [ ], - v6 ? [ ], - }: - let - base = "${server}.${meta.nodes.${server}.site}.infra"; - mkHost = host: mapSingleFuse (_: mkCNAME host); - in - fuseAttrs [ - (mkHost base dual) - (mkHost "v4.${base}" v4) - (mkHost "v6.${base}" v6) - ]; - - cnames = builtins.mapAttrs (_: to: { CNAME = [ to ]; }) { - "dev" = "dev.pages.codeberg.page."; - "irc" = "public.p.lahfa.xyz."; - "webmail" = "kurisu.dual.lahfa.xyz."; - - # Transition to new site names - "web01.dmi01.infra" = "web01.rat01.infra"; - "web02.dmi01.infra" = "web02.rat01.infra"; - "compute01.par01.infra" = "compute01.pav01.infra"; - "storage01.par01.infra" = "storage01.pav01.infra"; - - # Miscelleanous redirections - "traque" = "traque.katvayor.net."; - - # Temporary redirection for the BDS - # FIXME: finish the django apps module - "gestiobds.dj" = "cof.ens.fr."; - }; - - hosted = fuseAttrs (builtins.attrValues (builtins.mapAttrs mkHosted { })); - - kurisuDKIM = [ - { - selector = "kurisu"; - k = "rsa"; - s = [ "email" ]; - p = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDa5KuK6ry+Ss2VsKL0FsDpoBlc7dcXZyp62fGqFJFJv4/GEivPWiwbr2o5oLKjQVI4kIYjIZsyQJFtI/Xcu4BrtDdBknb5WvCN8V9EvIMh3pfXOBLVx4oqw4BR7wF8Rw1J9xyfgsfK+m2n0M39XlMHH0Nuy6kU48jH9vYpZs17ZQIDAQAB"; - } - ]; -in - -{ - SOA = { - nameServer = "ns01.dgnum.eu."; - adminEmail = "dns.dgnum.eu"; - retry = 3600; - minimum = 300; - }; - - # Primary DNS servers - NS = [ - "ns01.dgnum.eu." # ns-03.hubrecht.ovh - "ns02.dgnum.eu." # kurisu.lahfa.xyz - ]; - - # dgnum.codeberg.pages - # ALIAS = [ "codeberg.page" ]; - A = [ "217.197.91.145" ]; - AAAA = [ "2001:67c:1401:20f0::1" ]; - - MX = map (ttl 3600) [ (mx.mx 10 "kurisu.lahfa.xyz.") ]; - - SRV = [ - { - service = "autodiscover"; - proto = "tcp"; - port = 443; - target = "autoconfig.mail.lahfa.xyz."; - } - ]; - - TXT = [ - "dgnum.codeberg.page" - (spf.strict [ "a:kurisu.lahfa.xyz" ]) - ]; - DMARC = [ { p = "none"; } ]; - DKIM = kurisuDKIM; - - subdomains = - hosted - // cnames - // { - ns01 = { - A = [ "51.178.27.125" ]; - AAAA = [ "2001:41d0:305:2100::542c" ]; - }; - ns02 = { - A = [ "163.172.69.160" ]; - AAAA = [ "2001:bc8:38ee::1" ]; - }; - } - // { - infra = { - MX = map (ttl 3600) [ (mx.mx 10 "kurisu.lahfa.xyz.") ]; - - TXT = [ (spf.strict [ "a:kurisu.lahfa.xyz" ]) ]; - DMARC = [ { p = "none"; } ]; - DKIM = kurisuDKIM; - - subdomains = mapAttrs' ( - host: - { site, ... }: - nameValuePair "${host}.${site}" ( - with meta.network.${host}.addresses; - { - A = ipv4; - AAAA = ipv6; - subdomains = { - v4.A = ipv4; - v6.AAAA = ipv6; - }; - } - ) - ) meta.nodes; - }; - }; -} diff --git a/meta/network.nix b/meta/network.nix index 6216bf2..4d2043a 100644 --- a/meta/network.nix +++ b/meta/network.nix @@ -1,34 +1,4 @@ { - bridge01 = { - hostId = "f57f3ba0"; - - interfaces = { }; - netbirdIp = null; - }; - - compute01 = { - interfaces = { - eno1 = { - ipv4 = [ - { - address = "129.199.146.147"; - prefixLength = 24; - } - { - address = "192.168.1.147"; - prefixLength = 24; - } - ]; - - gateways = [ "129.199.146.254" ]; - enableDefaultDNS = true; - }; - }; - - hostId = "8df60941"; - netbirdIp = "100.80.75.197"; - }; - krz01 = { interfaces = { eno1 = { @@ -51,157 +21,4 @@ hostId = "bd11e8fc"; netbirdIp = "100.80.103.206"; }; - - geo01 = { - interfaces = { - eno1 = { - ipv4 = [ - { - address = "129.199.210.194"; - prefixLength = 24; - } - ]; - - gateways = [ "129.199.210.254" ]; - - dns = [ - "129.199.96.11" - "129.199.72.99" - ]; - }; - }; - - hostId = "b88fee0c"; - netbirdIp = "100.80.8.66"; - }; - - geo02 = { - interfaces = { - eno1 = { - ipv4 = [ - { - address = "129.199.210.69"; - prefixLength = 24; - } - ]; - - gateways = [ "129.199.210.254" ]; - - dns = [ - "129.199.96.11" - "129.199.72.99" - ]; - }; - }; - - hostId = "45d65237"; - netbirdIp = "100.80.233.249"; - }; - - storage01 = { - interfaces = { - eno1 = { - ipv4 = [ - { - address = "129.199.146.148"; - prefixLength = 24; - } - { - address = "192.168.1.148"; - prefixLength = 24; - } - ]; - - gateways = [ "129.199.146.254" ]; - enableDefaultDNS = true; - }; - }; - - hostId = "d4e7c369"; - netbirdIp = "100.80.156.154"; - }; - - vault01 = { - interfaces = { - vlan-uplink-cri = { - ipv4 = [ - { - # see also machines/vault01/networking.nix - address = "129.199.195.129"; - prefixLength = 32; - } - ]; - gateways = [ ]; - enableDefaultDNS = true; - }; - }; - - hostId = "e83b600d"; - netbirdIp = "100.80.255.180"; - }; - - web01 = { - interfaces = { - ens3 = { - ipv4 = [ - { - address = "129.199.129.53"; - prefixLength = 24; - } - ]; - - gateways = [ "129.199.129.1" ]; - enableDefaultDNS = true; - }; - }; - - hostId = "050df79e"; - netbirdIp = "100.80.77.90"; - }; - - web02 = { - interfaces = { - ens3 = { - ipv4 = [ - { - address = "129.199.129.235"; - prefixLength = 24; - } - ]; - - gateways = [ "129.199.129.1" ]; - enableDefaultDNS = true; - }; - }; - - hostId = "b431ca10"; - netbirdIp = null; # web02 is not to be connected on the VPN - }; - - rescue01 = { - interfaces = { - ens18 = { - ipv6 = [ - { - address = "2a01:e0a:de4:a0e1:2d73:2a7e:18db:5728"; - prefixLength = 64; - } - ]; - - ipv4 = [ - { - address = "192.168.0.232"; - prefixLength = 21; - } - ]; - gateways = [ "192.168.0.1" ]; - enableDefaultDNS = true; - }; - }; - - addresses.ipv4 = [ "82.67.34.230" ]; - - hostId = "007f0200"; - netbirdIp = "100.80.97.140"; - }; } diff --git a/meta/nodes.nix b/meta/nodes.nix index 884cf71..c5b6763 100644 --- a/meta/nodes.nix +++ b/meta/nodes.nix @@ -19,66 +19,6 @@ - luj01 -> VM de Luj */ { - bridge01 = { - site = "hyp01"; - - hashedPassword = "$y$j9T$EPJdz70kselouXAVUmAH01$8nYbUBY9NPTMfYigegY0qFSdxJwhqzW8sFacDqEYCP5"; - - stateVersion = "24.05"; - - adminGroups = [ "fai" ]; - - deployment = { - targetHost = "fd26:baf9:d250:8000::ffff"; - sshOptions = [ - "-J" - "root@vault01.hyp01.infra.dgnum.eu" - ]; - }; - }; - - web01 = { - site = "rat01"; - - deployment.tags = [ "web" ]; - - hashedPassword = "$y$j9T$9YqXO93VJE/GP3z8Sh4h51$hrBsEPL2O1eP/wBZTrNT8XV906V4JKbQ0g04IWBcyd2"; - - stateVersion = "23.05"; - vm-cluster = "Hyperviseur NPS"; - - nixpkgs = "24.05"; - }; - - compute01 = { - site = "pav01"; - - hashedPassword = "$y$j9T$2nxZHq84G7fWvWMEaGavE/$0ADnmD9qMpXJJ.rWWH9086EakvZ3wAg0mSxZYugOf3C"; - - stateVersion = "23.05"; - nix-modules = [ "services/stirling-pdf" ]; - nixpkgs = "24.05"; - }; - - geo01 = { - site = "oik01"; - deployment.tags = [ "geo" ]; - - hashedPassword = "$y$j9T$2XmDpJu.QLhV57yYCh5Lf1$LK.X0HKB02Q0Ujvhj5nIofW2IRrIAL/Uxnvl9AXM1L8"; - - stateVersion = "24.05"; - nixpkgs = "24.05"; - }; - - geo02 = { - site = "oik01"; - deployment.tags = [ "geo" ]; - - hashedPassword = "$y$j9T$Q4fbMpSm9beWu4DPNAR9t0$dx/1pH4GPY72LpS5ZiECXAZFDdxwmIywztsX.qo2VVA"; - - stateVersion = "24.05"; - nixpkgs = "24.05"; - }; krz01 = { site = "pav01"; @@ -87,51 +27,5 @@ stateVersion = "24.05"; nixpkgs = "unstable"; - - adminGroups = [ "lab" ]; - }; - - storage01 = { - site = "pav01"; - - hashedPassword = "$y$j9T$tvRu1EJ9MwDSvEm0ogwe70$bKSw6nNteN0L3NOy2Yix7KlIvO/oROQmQ.Ynq002Fg8"; - - stateVersion = "23.11"; - nixpkgs = "24.05"; - - nix-modules = [ "services/forgejo-nix-runners" ]; - }; - - vault01 = { - site = "hyp01"; - deployment.targetHost = "vault01.hyp01.infra.dgnum.eu"; - - hashedPassword = "$y$j9T$5osXVNxCDxu3jIndcyh7G.$UrjiDRpMu3W59tKHLGNdLWllZh.4p8IM4sBS5SrNrN1"; - - stateVersion = "23.11"; - nixpkgs = "24.05"; - - adminGroups = [ "fai" ]; - }; - - web02 = { - site = "rat01"; - - hashedPassword = "$y$j9T$p42UVNy78PykkQOjPwXNJ/$B/zCUOrHXVSFGUY63wnViMiSmU2vCWsiX0y62qqgNQ5"; - - stateVersion = "24.05"; - nixpkgs = "24.05"; - vm-cluster = "Hyperviseur NPS"; - }; - - rescue01 = { - site = "luj01"; - - deployment.targetHost = "v6.rescue01.luj01.infra.dgnum.eu"; - - hashedPassword = "$y$j9T$nqoMMu/axrD0m8AlUFdbs.$UFVmIdPAOHBe2jJv5HJJTcDgINC7LTnSGRQNs9zS1mC"; - - stateVersion = "23.11"; - vm-cluster = "Hyperviseur Luj"; }; } diff --git a/meta/options.nix b/meta/options.nix index e8f4e6a..0344793 100644 --- a/meta/options.nix +++ b/meta/options.nix @@ -70,39 +70,6 @@ in Groups of the DGNum organization. ''; }; - - external = mkOption { - type = attrsOf (listOf str); - description = '' - External services used by the DGNum organization. - ''; - }; - - services = mkOption { - type = attrsOf (submodule { - options = { - admins = mkOption { - type = listOf str; - default = [ ]; - description = '' - List of administrators of the service. - ''; - }; - - adminGroups = mkOption { - type = listOf str; - default = [ ]; - description = '' - List of administrator groups of the service. - ''; - }; - }; - }); - description = '' - Administrator access of the different DGNum services, - it is mainly indicative as most services cannot configure this statically. - ''; - }; }; nodes = mkOption { @@ -360,21 +327,6 @@ in extract "adminGroups" config.nodes )) - # Check that all services admins exist - (membersExists (name: "A member of the service ${name} admins was not found in the members list.") ( - extract "admins" org.services - )) - - # Check that all services adminGroups exist - (groupsExists ( - name: "A member of the service ${name} adminGroups was not found in the groups list." - ) (extract "adminGroups" org.services)) - - # Check that all external services admins exist - (membersExists ( - name: "A member of the external service ${name} admins was not found in the members list." - ) org.external) - # Check that all members have ssh keys (builtins.map (name: { assertion = ((import ../keys)._keys.${name} or [ ]) != [ ]; diff --git a/meta/organization.nix b/meta/organization.nix index cf0c2b5..b8a4016 100644 --- a/meta/organization.nix +++ b/meta/organization.nix @@ -10,6 +10,11 @@ email = "catvayor@dgnum.eu"; }; + cst1 = { + name = "Constantin Gierczak--Galle"; + email = "cst1@dgnum.eu"; + }; + ecoppens = { name = "Elias Coppens"; email = "ecoppens@dgnum.eu"; @@ -48,52 +53,10 @@ "raito" "mdebray" "luj" - ]; - - # members of this group are root on the fai infrastructure - fai = [ "catvayor" "ecoppens" + "cst1" ]; - lab = [ - "catvayor" - "ecoppens" - ]; - - }; - - external = { - dns = [ - "thubrecht" - "raito" - ]; - - email = [ "raito" ]; - - irc = [ "raito" ]; - }; - - services = { - # Démarches Normaliennes - ds-fr.admins = [ - "thubrecht" - "jemagius" - ]; - - # Cloud DGNum - nextcloud.admins = [ - "thubrecht" - "raito" - ]; - - # Netbox DGNum - netbox.adminGroups = [ - "root" - "fai" - ]; - - # Videos DGNum - peertube.admins = [ "thubrecht" ]; }; } diff --git a/meta/verify.nix b/meta/verify.nix index ecf2ed2..51beb99 100644 --- a/meta/verify.nix +++ b/meta/verify.nix @@ -3,8 +3,6 @@ let sources = import ../npins; pkgs = import sources.nixpkgs { }; - - dns = import sources."dns.nix" { inherit pkgs; }; in { @@ -22,15 +20,4 @@ in else pkgs.writers.writeJSON "meta.json" config; - dns = dns.util.writeZone "dgnum.eu" ( - pkgs.lib.recursiveUpdate { SOA.serial = 0; } ( - import ./dns.nix { - inherit dns; - - lib = pkgs.lib // { - extra = import ../lib/nix-lib; - }; - } - ) - ); } -- 2.47.0 From b8f729c290ea084a257b0a25bd6ec6707e1e8ca8 Mon Sep 17 00:00:00 2001 From: sinavir Date: Thu, 17 Oct 2024 13:41:10 +0200 Subject: [PATCH 4/6] chore(proxmox-nixos): Update --- machines/krz01/proxmox/default.nix | 12 +++++------- npins/sources.json | 10 +++++----- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/machines/krz01/proxmox/default.nix b/machines/krz01/proxmox/default.nix index 2f501e1..650163f 100644 --- a/machines/krz01/proxmox/default.nix +++ b/machines/krz01/proxmox/default.nix @@ -1,14 +1,12 @@ -{ sources, lib, ... }: +{ sources, ... }: let proxmox-nixos = import sources.proxmox-nixos; in { imports = [ proxmox-nixos.nixosModules.proxmox-ve ]; - services.proxmox-ve.enable = true; - nixpkgs.overlays = [ proxmox-nixos.overlays.x86_64-linux ]; - networking.firewall = { - trustedInterfaces = [ "wt0" ]; - allowedTCPPorts = lib.mkForce [ 22 ]; + services.proxmox-ve = { + enable = true; + openFirewall = false; }; - + nixpkgs.overlays = [ proxmox-nixos.overlays.x86_64-linux ]; } diff --git a/npins/sources.json b/npins/sources.json index 7d4d2be..070e0fc 100644 --- a/npins/sources.json +++ b/npins/sources.json @@ -179,10 +179,10 @@ "repo": "proxmox-nixos" }, "branch": "main", - "revision": "7869ffc2e0db36f314fb60f1ab0087b760700b00", - "url": "https://github.com/SaumonNet/proxmox-nixos/archive/7869ffc2e0db36f314fb60f1ab0087b760700b00.tar.gz", - "hash": "0cam36s3ar366y41rvihjqghkdjl9a1n1wzym8p2mkar1r9x7haj" + "revision": "950e4cccac0f942076e8558f7f9f4d496cabfb18", + "url": "https://github.com/SaumonNet/proxmox-nixos/archive/950e4cccac0f942076e8558f7f9f4d496cabfb18.tar.gz", + "hash": "0bhqw42ydc0jfkfqw64xsg518a1pbxnvpqw92nna7lm8mzpxm6d4" } - }, + }, "version": 3 -} +} \ No newline at end of file -- 2.47.0 From eae18caa21b3997631b216b2974ed8ebf14e5000 Mon Sep 17 00:00:00 2001 From: sinavir Date: Fri, 18 Oct 2024 10:03:17 +0200 Subject: [PATCH 5/6] chore(shell): Specialize for lab-infra --- default.nix | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/default.nix b/default.nix index 0dbf784..ac4404e 100644 --- a/default.nix +++ b/default.nix @@ -78,13 +78,9 @@ in shells = { default = pkgs.mkShell { - name = "dgnum-infra"; + name = "dgnum-lab-infra"; packages = [ - (pkgs.nixos-generators.overrideAttrs (_: { - version = "1.8.0-unstable"; - src = builtins.storePath sources.nixos-generators; - })) pkgs.npins (pkgs.callPackage ./lib/colmena { inherit (nix-pkgs) colmena; }) -- 2.47.0 From c2e8ca5e33fc794f613ea2f65fbe9029b171fe7d Mon Sep 17 00:00:00 2001 From: Julien Malka Date: Fri, 18 Oct 2024 11:20:33 +0200 Subject: [PATCH 6/6] chore(deps): update nix-pkgs --- npins/sources.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/npins/sources.json b/npins/sources.json index 070e0fc..5ea7635 100644 --- a/npins/sources.json +++ b/npins/sources.json @@ -131,9 +131,9 @@ "url": "https://git.hubrecht.ovh/hubrecht/nix-pkgs" }, "branch": "main", - "revision": "3e731378f3984313ef902c5e5a49e002e6e2c27e", + "revision": "0e80d4dcdd54a75556c0784de55dc139ad4fe797", "url": null, - "hash": "1vy2dj9fyy653w6idvi1r73s0nd2a332a1xkppddjip6rk0i030p" + "hash": "1hlb0cczxq0jrzw4lhmkibnb8skcar0rmny594aqgyikknwzx2qf" }, "nixos-23.11": { "type": "Channel", -- 2.47.0