From 3a881979f9a59d4f150a58ceadc0d00dffe77297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=E2=80=9CNiols=E2=80=9D=20Jeannerod?= <nicolas.jeannerod@moduscreate.com> Date: Thu, 13 Feb 2025 11:38:45 +0100 Subject: [PATCH 01/16] Move old services README to a HACKING file --- services/{README.md => HACKING.md} | 3 +++ 1 file changed, 3 insertions(+) rename services/{README.md => HACKING.md} (97%) diff --git a/services/README.md b/services/HACKING.md similarity index 97% rename from services/README.md rename to services/HACKING.md index 1aa2901..14cc752 100644 --- a/services/README.md +++ b/services/HACKING.md @@ -1,3 +1,6 @@ +NOTE[Niols]: This file looks like a README file but is in fact development notes +from a previous engineer of the project. Needs an overhaul. + # Fediverse VMs This repo is, for now, an attempt to familiarize myself with NixOS options for Fediverse applications, and build up a configuration layer that will set most of the relevant options for you (in a semi-opinionated way) given some high-level configuration. The goal is something in the same vein as [nixos-mailserver](https://gitlab.com/simple-nixos-mailserver/nixos-mailserver) but for fediversity. From 237c56791f84a80a967a56c6da89089a3800a72e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=E2=80=9CNiols=E2=80=9D=20Jeannerod?= <nicolas.jeannerod@moduscreate.com> Date: Fri, 14 Feb 2025 15:03:07 +0100 Subject: [PATCH 02/16] Basic services README --- services/README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 services/README.md diff --git a/services/README.md b/services/README.md new file mode 100644 index 0000000..1a73652 --- /dev/null +++ b/services/README.md @@ -0,0 +1,31 @@ +# Services + +This directory contains the definition of a NixOS module allowing to easily set +up the Fediverse services that our project cares about. Those services are +already packaged in nixpkgs, which arguably already provides this. Here is +therefore the important distinction: + +- The goal of nixpkgs is to be generic, bring all the building blocks and let + you do whatever it is you want with them. You get to choose all the options, + if to use a reverse proxy, which one, if to use an S3 backend, which one, + which database, etc. + +- This module aims at being straightforward to use by being opinionated. It only + supports the use case of the Fediversity project and strives to hide as much + of the nitty-gritty details as possible. + +For those that know it, we could say that the current module is an analogous of +[simple-nixos-mailserver] for Fediverse services. + +[simple-nixos-mailserver]: https://gitlab.com/simple-nixos-mailserver/nixos-mailserver + +## Content of this directory + +- [fediversity][./fediversity] contains the definition of the services. Look in + particular at its `default.nix` that contains the definition of the options. + +- [vm][./vm] contains options specific to making the service run in local QEMU + VMs. These modules will for instance override the defaults to disable SSL, and + they will add virtualisation options to forward ports, for instance. + +- [tests][./tests] contain full NixOS tests of the services. From ff03d12dc10295fa0d30da283478ada77f18f18f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=E2=80=9CNiols=E2=80=9D=20Jeannerod?= <nicolas.jeannerod@moduscreate.com> Date: Fri, 14 Feb 2025 16:13:43 +0100 Subject: [PATCH 03/16] Move Garage configuration to own directory --- services/fediversity/default.nix | 2 +- services/fediversity/{garage.nix => garage/default.nix} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename services/fediversity/{garage.nix => garage/default.nix} (100%) diff --git a/services/fediversity/default.nix b/services/fediversity/default.nix index 6fe796a..0747e2d 100644 --- a/services/fediversity/default.nix +++ b/services/fediversity/default.nix @@ -8,7 +8,7 @@ let in { imports = [ - ./garage.nix + ./garage ./mastodon.nix ./pixelfed.nix ./peertube.nix diff --git a/services/fediversity/garage.nix b/services/fediversity/garage/default.nix similarity index 100% rename from services/fediversity/garage.nix rename to services/fediversity/garage/default.nix From b68a821b7725b7e68a3de4863aa695f06d733b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=E2=80=9CNiols=E2=80=9D=20Jeannerod?= <nicolas.jeannerod@moduscreate.com> Date: Fri, 14 Feb 2025 16:17:07 +0100 Subject: [PATCH 04/16] Searate Garage config and options --- services/fediversity/garage/default.nix | 82 +------------------------ services/fediversity/garage/options.nix | 80 ++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 80 deletions(-) create mode 100644 services/fediversity/garage/options.nix diff --git a/services/fediversity/garage/default.nix b/services/fediversity/garage/default.nix index f43fe11..f9015cf 100644 --- a/services/fediversity/garage/default.nix +++ b/services/fediversity/garage/default.nix @@ -17,13 +17,7 @@ in let inherit (builtins) toString; - inherit (lib) - types - mkOption - mkEnableOption - optionalString - concatStringsSep - ; + inherit (lib) optionalString concatStringsSep; inherit (lib.strings) escapeShellArg; inherit (lib.attrsets) filterAttrs mapAttrs'; cfg = config.services.garage; @@ -100,79 +94,7 @@ let in { - # add in options to ensure creation of buckets and keys - options = { - services.garage = { - ensureBuckets = mkOption { - type = types.attrsOf ( - types.submodule { - options = { - website = mkOption { - type = types.bool; - default = false; - }; - # I think setting corsRules should allow another website to show images from your bucket - corsRules = { - enable = mkEnableOption "CORS Rules"; - allowedHeaders = mkOption { - type = types.listOf types.str; - default = [ ]; - }; - allowedMethods = mkOption { - type = types.listOf types.str; - default = [ ]; - }; - allowedOrigins = mkOption { - type = types.listOf types.str; - default = [ ]; - }; - }; - aliases = mkOption { - type = types.listOf types.str; - default = [ ]; - }; - }; - } - ); - default = { }; - }; - ensureKeys = mkOption { - type = types.attrsOf ( - types.submodule { - # TODO: these should be managed as secrets, not in the nix store - options = { - id = mkOption { type = types.str; }; - secret = mkOption { type = types.str; }; - # TODO: assert at least one of these is true - # NOTE: this currently needs to be done at the top level module - ensureAccess = mkOption { - type = types.attrsOf ( - types.submodule { - options = { - read = mkOption { - type = types.bool; - default = false; - }; - write = mkOption { - type = types.bool; - default = false; - }; - owner = mkOption { - type = types.bool; - default = false; - }; - }; - } - ); - default = [ ]; - }; - }; - } - ); - default = { }; - }; - }; - }; + imports = [ ./options.nix ]; config = lib.mkIf config.fediversity.enable { environment.systemPackages = [ diff --git a/services/fediversity/garage/options.nix b/services/fediversity/garage/options.nix new file mode 100644 index 0000000..69d9c4b --- /dev/null +++ b/services/fediversity/garage/options.nix @@ -0,0 +1,80 @@ +{ lib, ... }: + +let + inherit (lib) types mkOption mkEnableOption; +in + +{ + options = { + services.garage = { + ensureBuckets = mkOption { + type = types.attrsOf ( + types.submodule { + options = { + website = mkOption { + type = types.bool; + default = false; + }; + # I think setting corsRules should allow another website to show images from your bucket + corsRules = { + enable = mkEnableOption "CORS Rules"; + allowedHeaders = mkOption { + type = types.listOf types.str; + default = [ ]; + }; + allowedMethods = mkOption { + type = types.listOf types.str; + default = [ ]; + }; + allowedOrigins = mkOption { + type = types.listOf types.str; + default = [ ]; + }; + }; + aliases = mkOption { + type = types.listOf types.str; + default = [ ]; + }; + }; + } + ); + default = { }; + }; + ensureKeys = mkOption { + type = types.attrsOf ( + types.submodule { + # TODO: these should be managed as secrets, not in the nix store + options = { + id = mkOption { type = types.str; }; + secret = mkOption { type = types.str; }; + # TODO: assert at least one of these is true + # NOTE: this currently needs to be done at the top level module + ensureAccess = mkOption { + type = types.attrsOf ( + types.submodule { + options = { + read = mkOption { + type = types.bool; + default = false; + }; + write = mkOption { + type = types.bool; + default = false; + }; + owner = mkOption { + type = types.bool; + default = false; + }; + }; + } + ); + default = [ ]; + }; + }; + } + ); + default = { }; + }; + }; + }; +} From d9188427ede5a85c8bdd395bfcfb0e8c49a6762f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=E2=80=9CNiols=E2=80=9D=20Jeannerod?= <nicolas.jeannerod@moduscreate.com> Date: Fri, 14 Feb 2025 16:25:52 +0100 Subject: [PATCH 05/16] `services.garage` -> `fediversity.garage` for the options that are ours; we want to avoid clashes if possible --- services/fediversity/garage/default.nix | 7 +- services/fediversity/garage/options.nix | 125 ++++++++++++------------ services/fediversity/mastodon.nix | 2 +- services/fediversity/peertube.nix | 2 +- services/fediversity/pixelfed.nix | 2 +- services/tests/mastodon.nix | 4 +- services/tests/peertube.nix | 4 +- services/tests/pixelfed-garage.nix | 5 +- services/vm/garage-vm.nix | 16 ++- 9 files changed, 81 insertions(+), 86 deletions(-) diff --git a/services/fediversity/garage/default.nix b/services/fediversity/garage/default.nix index f9015cf..f1638df 100644 --- a/services/fediversity/garage/default.nix +++ b/services/fediversity/garage/default.nix @@ -7,7 +7,6 @@ let }; in -# TODO: expand to a multi-machine setup { config, lib, @@ -66,7 +65,7 @@ let garage bucket deny --read --write --owner ${bucketArg} --key tmp ''} ''; - ensureBucketsScript = concatMapAttrs ensureBucketScriptFn cfg.ensureBuckets; + ensureBucketsScript = concatMapAttrs ensureBucketScriptFn config.fediversity.garage.ensureBuckets; ensureAccessScriptFn = key: bucket: { @@ -90,7 +89,7 @@ let garage key import --yes -n ${escapeShellArg key} ${escapeShellArg id} ${escapeShellArg secret} || : ${concatMapAttrs (ensureAccessScriptFn key) ensureAccess} ''; - ensureKeysScript = concatMapAttrs ensureKeyScriptFn cfg.ensureKeys; + ensureKeysScript = concatMapAttrs ensureKeyScriptFn config.fediversity.garage.ensureKeys; in { @@ -149,7 +148,7 @@ in mapAttrs' (bucket: _: { name = fedicfg.web.domainForBucket bucket; inherit value; - }) (filterAttrs (_: { website, ... }: website) cfg.ensureBuckets); + }) (filterAttrs (_: { website, ... }: website) config.fediversity.garage.ensureBuckets); systemd.services.ensure-garage = { after = [ "garage.service" ]; diff --git a/services/fediversity/garage/options.nix b/services/fediversity/garage/options.nix index 69d9c4b..56fec59 100644 --- a/services/fediversity/garage/options.nix +++ b/services/fediversity/garage/options.nix @@ -5,76 +5,75 @@ let in { - options = { - services.garage = { - ensureBuckets = mkOption { - type = types.attrsOf ( - types.submodule { - options = { - website = mkOption { - type = types.bool; - default = false; + options.fediversity.garage = { + ensureBuckets = mkOption { + type = types.attrsOf ( + types.submodule { + options = { + website = mkOption { + type = types.bool; + default = false; + }; + # I think setting corsRules should allow another website to show images from your bucket + corsRules = { + enable = mkEnableOption "CORS Rules"; + allowedHeaders = mkOption { + type = types.listOf types.str; + default = [ ]; }; - # I think setting corsRules should allow another website to show images from your bucket - corsRules = { - enable = mkEnableOption "CORS Rules"; - allowedHeaders = mkOption { - type = types.listOf types.str; - default = [ ]; - }; - allowedMethods = mkOption { - type = types.listOf types.str; - default = [ ]; - }; - allowedOrigins = mkOption { - type = types.listOf types.str; - default = [ ]; - }; + allowedMethods = mkOption { + type = types.listOf types.str; + default = [ ]; }; - aliases = mkOption { + allowedOrigins = mkOption { type = types.listOf types.str; default = [ ]; }; }; - } - ); - default = { }; - }; - ensureKeys = mkOption { - type = types.attrsOf ( - types.submodule { - # TODO: these should be managed as secrets, not in the nix store - options = { - id = mkOption { type = types.str; }; - secret = mkOption { type = types.str; }; - # TODO: assert at least one of these is true - # NOTE: this currently needs to be done at the top level module - ensureAccess = mkOption { - type = types.attrsOf ( - types.submodule { - options = { - read = mkOption { - type = types.bool; - default = false; - }; - write = mkOption { - type = types.bool; - default = false; - }; - owner = mkOption { - type = types.bool; - default = false; - }; - }; - } - ); - default = [ ]; - }; + aliases = mkOption { + type = types.listOf types.str; + default = [ ]; }; - } - ); - default = { }; - }; + }; + } + ); + default = { }; + }; + + ensureKeys = mkOption { + type = types.attrsOf ( + types.submodule { + # TODO: these should be managed as secrets, not in the nix store + options = { + id = mkOption { type = types.str; }; + secret = mkOption { type = types.str; }; + # TODO: assert at least one of these is true + # NOTE: this currently needs to be done at the top level module + ensureAccess = mkOption { + type = types.attrsOf ( + types.submodule { + options = { + read = mkOption { + type = types.bool; + default = false; + }; + write = mkOption { + type = types.bool; + default = false; + }; + owner = mkOption { + type = types.bool; + default = false; + }; + }; + } + ); + default = [ ]; + }; + }; + } + ); + default = { }; }; }; } diff --git a/services/fediversity/mastodon.nix b/services/fediversity/mastodon.nix index 2ed4b3e..7486559 100644 --- a/services/fediversity/mastodon.nix +++ b/services/fediversity/mastodon.nix @@ -9,7 +9,7 @@ in lib.mkIf (config.fediversity.enable && config.fediversity.mastodon.enable) { #### garage setup - services.garage = { + fediversity.garage = { ensureBuckets = { mastodon = { website = true; diff --git a/services/fediversity/peertube.nix b/services/fediversity/peertube.nix index bb2b618..ae973c1 100644 --- a/services/fediversity/peertube.nix +++ b/services/fediversity/peertube.nix @@ -17,7 +17,7 @@ lib.mkIf (config.fediversity.enable && config.fediversity.peertube.enable) { 1936 ]; - services.garage = { + fediversity.garage = { ensureBuckets = { peertube-videos = { website = true; diff --git a/services/fediversity/pixelfed.nix b/services/fediversity/pixelfed.nix index 279445e..6c2a3eb 100644 --- a/services/fediversity/pixelfed.nix +++ b/services/fediversity/pixelfed.nix @@ -13,7 +13,7 @@ in }: lib.mkIf (config.fediversity.enable && config.fediversity.pixelfed.enable) { - services.garage = { + fediversity.garage = { ensureBuckets = { pixelfed = { website = true; diff --git a/services/tests/mastodon.nix b/services/tests/mastodon.nix index ef6a667..80ede0c 100644 --- a/services/tests/mastodon.nix +++ b/services/tests/mastodon.nix @@ -69,8 +69,8 @@ pkgs.nixosTest { expect ]; environment.variables = { - AWS_ACCESS_KEY_ID = config.services.garage.ensureKeys.mastodon.id; - AWS_SECRET_ACCESS_KEY = config.services.garage.ensureKeys.mastodon.secret; + AWS_ACCESS_KEY_ID = config.fediversity.garage.ensureKeys.mastodon.id; + AWS_SECRET_ACCESS_KEY = config.fediversity.garage.ensureKeys.mastodon.secret; }; }; }; diff --git a/services/tests/peertube.nix b/services/tests/peertube.nix index 6a5161b..c10e01a 100644 --- a/services/tests/peertube.nix +++ b/services/tests/peertube.nix @@ -197,8 +197,8 @@ pkgs.nixosTest { systemd.services.postgresql.serviceConfig.TimeoutSec = lib.mkForce 3600; environment.variables = { - AWS_ACCESS_KEY_ID = config.services.garage.ensureKeys.peertube.id; - AWS_SECRET_ACCESS_KEY = config.services.garage.ensureKeys.peertube.secret; + AWS_ACCESS_KEY_ID = config.fediversity.garage.ensureKeys.peertube.id; + AWS_SECRET_ACCESS_KEY = config.fediversity.garage.ensureKeys.peertube.secret; PT_INITIAL_ROOT_PASSWORD = "testtest"; }; }; diff --git a/services/tests/pixelfed-garage.nix b/services/tests/pixelfed-garage.nix index 56c5d11..346ffe4 100644 --- a/services/tests/pixelfed-garage.nix +++ b/services/tests/pixelfed-garage.nix @@ -1,4 +1,5 @@ { pkgs, self }: + let lib = pkgs.lib; @@ -160,8 +161,8 @@ pkgs.nixosTest { ]; environment.variables = { POST_MEDIA = ./fediversity.png; - AWS_ACCESS_KEY_ID = config.services.garage.ensureKeys.pixelfed.id; - AWS_SECRET_ACCESS_KEY = config.services.garage.ensureKeys.pixelfed.secret; + AWS_ACCESS_KEY_ID = config.fediversity.garage.ensureKeys.pixelfed.id; + AWS_SECRET_ACCESS_KEY = config.fediversity.garage.ensureKeys.pixelfed.secret; ## without this we get frivolous errors in the logs MC_REGION = "garage"; }; diff --git a/services/vm/garage-vm.nix b/services/vm/garage-vm.nix index aca295e..b115b51 100644 --- a/services/vm/garage-vm.nix +++ b/services/vm/garage-vm.nix @@ -8,10 +8,6 @@ let inherit (lib) mkVMOverride mapAttrs' filterAttrs; - cfg = config.services.garage; - - fedicfg = config.fediversity.internal.garage; - in { imports = [ (modulesPath + "/virtualisation/qemu-vm.nix") ]; @@ -24,21 +20,21 @@ in }; in mapAttrs' (bucket: _: { - name = fedicfg.web.domainForBucket bucket; + name = config.fediversity.internal.garage.web.domainForBucket bucket; inherit value; - }) (filterAttrs (_: { website, ... }: website) cfg.ensureBuckets); + }) (filterAttrs (_: { website, ... }: website) config.fediversity.garage.ensureBuckets); virtualisation.diskSize = 2048; virtualisation.forwardPorts = [ { from = "host"; - host.port = fedicfg.rpc.port; - guest.port = fedicfg.rpc.port; + host.port = config.fediversity.internal.garage.rpc.port; + guest.port = config.fediversity.internal.garage.rpc.port; } { from = "host"; - host.port = fedicfg.web.internalPort; - guest.port = fedicfg.web.internalPort; + host.port = config.fediversity.internal.garage.web.internalPort; + guest.port = config.fediversity.internal.garage.web.internalPort; } ]; } From f4babe38a8db9a7b33fefdec8f92bd81bfe15502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=E2=80=9CNiols=E2=80=9D=20Jeannerod?= <nicolas.jeannerod@moduscreate.com> Date: Fri, 14 Feb 2025 18:32:08 +0100 Subject: [PATCH 06/16] Consolidate Garage options - `fediversity.internal.garage` -> `fediversity.garage` - all in the same place --- services/fediversity/default.nix | 46 +------------------------ services/fediversity/garage/default.nix | 32 +++++++++-------- services/fediversity/garage/options.nix | 43 ++++++++++++++++++++++- services/fediversity/mastodon.nix | 4 +-- services/fediversity/peertube.nix | 8 ++--- services/fediversity/pixelfed.nix | 6 ++-- services/tests/mastodon.nix | 4 +-- services/tests/peertube.nix | 2 +- services/tests/pixelfed-garage.nix | 4 +-- services/vm/garage-vm.nix | 10 +++--- 10 files changed, 80 insertions(+), 79 deletions(-) diff --git a/services/fediversity/default.nix b/services/fediversity/default.nix index 0747e2d..d643c8d 100644 --- a/services/fediversity/default.nix +++ b/services/fediversity/default.nix @@ -1,7 +1,6 @@ { lib, config, ... }: let - inherit (builtins) toString; inherit (lib) mkOption mkEnableOption mkForce; inherit (lib.types) types; @@ -55,49 +54,6 @@ in default = { }; type = types.submodule { options = { - garage = { - api = { - domain = mkOption { - type = types.str; - default = "s3.garage.${config.fediversity.domain}"; - }; - port = mkOption { - type = types.int; - default = 3900; - }; - url = mkOption { - type = types.str; - default = "http://${config.fediversity.internal.garage.api.domain}:${toString config.fediversity.internal.garage.api.port}"; - }; - }; - - rpc = { - port = mkOption { - type = types.int; - default = 3901; - }; - }; - - web = { - rootDomain = mkOption { - type = types.str; - default = "web.garage.${config.fediversity.domain}"; - }; - internalPort = mkOption { - type = types.int; - default = 3902; - }; - domainForBucket = mkOption { - type = types.functionTo types.str; - default = bucket: "${bucket}.${config.fediversity.internal.garage.web.rootDomain}"; - }; - urlForBucket = mkOption { - type = types.functionTo types.str; - default = bucket: "http://${config.fediversity.internal.garage.web.domainForBucket bucket}"; - }; - }; - }; - ## REVIEW: Do we want to recreate options under ## `fediversity.internal` or would we rather use the options from ## the respective services? See Taeer's comment: @@ -132,6 +88,6 @@ in ## NOTE: For a one-machine deployment, this removes the need to provide an ## `s3.garage.<domain>` domain. However, this will quickly stop working once ## we go to multi-machines deployment. - fediversity.internal.garage.api.domain = mkForce "s3.garage.localhost"; + fediversity.garage.api.domain = mkForce "s3.garage.localhost"; }; } diff --git a/services/fediversity/garage/default.nix b/services/fediversity/garage/default.nix index f1638df..5191016 100644 --- a/services/fediversity/garage/default.nix +++ b/services/fediversity/garage/default.nix @@ -19,9 +19,10 @@ let inherit (lib) optionalString concatStringsSep; inherit (lib.strings) escapeShellArg; inherit (lib.attrsets) filterAttrs mapAttrs'; - cfg = config.services.garage; - fedicfg = config.fediversity.internal.garage; concatMapAttrs = scriptFn: attrset: concatStringsSep "\n" (lib.mapAttrsToList scriptFn attrset); + + cfg = config.services.garage; + ensureBucketScriptFn = bucket: { @@ -61,11 +62,13 @@ let ${optionalString corsRules.enable '' garage bucket allow --read --write --owner ${bucketArg} --key tmp # TODO: endpoin-url should not be hard-coded - aws --region ${cfg.settings.s3_api.s3_region} --endpoint-url ${fedicfg.api.url} s3api put-bucket-cors --bucket ${bucketArg} --cors-configuration ${corsRulesJSON} + aws --region ${cfg.settings.s3_api.s3_region} --endpoint-url ${config.fediversity.garage.api.url} s3api put-bucket-cors --bucket ${bucketArg} --cors-configuration ${corsRulesJSON} garage bucket deny --read --write --owner ${bucketArg} --key tmp ''} ''; + ensureBucketsScript = concatMapAttrs ensureBucketScriptFn config.fediversity.garage.ensureBuckets; + ensureAccessScriptFn = key: bucket: { @@ -89,9 +92,10 @@ let garage key import --yes -n ${escapeShellArg key} ${escapeShellArg id} ${escapeShellArg secret} || : ${concatMapAttrs (ensureAccessScriptFn key) ensureAccess} ''; - ensureKeysScript = concatMapAttrs ensureKeyScriptFn config.fediversity.garage.ensureKeys; -in + ensureKeysScript = concatMapAttrs ensureKeyScriptFn config.fediversity.garage.ensureKeys; + +in { imports = [ ./options.nix ]; @@ -101,7 +105,7 @@ in pkgs.awscli ]; - networking.firewall.allowedTCPPorts = [ fedicfg.rpc.port ]; + networking.firewall.allowedTCPPorts = [ config.fediversity.garage.rpc.port ]; services.garage = { enable = true; package = pkgs.garage_0_9; @@ -110,15 +114,15 @@ in # TODO: use a secret file rpc_secret = "d576c4478cc7d0d94cfc127138cbb82018b0155c037d1c827dfb6c36be5f6625"; # TODO: why does this have to be set? is there not a sensible default? - rpc_bind_addr = "[::]:${toString fedicfg.rpc.port}"; - rpc_public_addr = "[::1]:${toString fedicfg.rpc.port}"; - s3_api.api_bind_addr = "[::]:${toString fedicfg.api.port}"; - s3_web.bind_addr = "[::]:${toString fedicfg.web.internalPort}"; - s3_web.root_domain = ".${fedicfg.web.rootDomain}"; + rpc_bind_addr = "[::]:${toString config.fediversity.garage.rpc.port}"; + rpc_public_addr = "[::1]:${toString config.fediversity.garage.rpc.port}"; + s3_api.api_bind_addr = "[::]:${toString config.fediversity.garage.api.port}"; + s3_web.bind_addr = "[::]:${toString config.fediversity.garage.web.internalPort}"; + s3_web.root_domain = ".${config.fediversity.garage.web.rootDomain}"; index = "index.html"; s3_api.s3_region = "garage"; - s3_api.root_domain = ".${fedicfg.api.domain}"; + s3_api.root_domain = ".${config.fediversity.garage.api.domain}"; }; }; @@ -146,7 +150,7 @@ in }; in mapAttrs' (bucket: _: { - name = fedicfg.web.domainForBucket bucket; + name = config.fediversity.garage.web.domainForBucket bucket; inherit value; }) (filterAttrs (_: { website, ... }: website) config.fediversity.garage.ensureBuckets); @@ -166,7 +170,7 @@ in # Give Garage time to start up by waiting until somethings speaks HTTP # behind Garage's API URL. - until ${pkgs.curl}/bin/curl -sio /dev/null ${fedicfg.api.url}; do sleep 1; done + until ${pkgs.curl}/bin/curl -sio /dev/null ${config.fediversity.garage.api.url}; do sleep 1; done # XXX: this is very sensitive to being a single instance # (doing the bare minimum to get garage up and running) diff --git a/services/fediversity/garage/options.nix b/services/fediversity/garage/options.nix index 56fec59..ad3d555 100644 --- a/services/fediversity/garage/options.nix +++ b/services/fediversity/garage/options.nix @@ -1,4 +1,4 @@ -{ lib, ... }: +{ config, lib, ... }: let inherit (lib) types mkOption mkEnableOption; @@ -75,5 +75,46 @@ in ); default = { }; }; + + api = { + domain = mkOption { + type = types.str; + default = "s3.garage.${config.fediversity.domain}"; + }; + port = mkOption { + type = types.int; + default = 3900; + }; + url = mkOption { + type = types.str; + default = "http://${config.fediversity.garage.api.domain}:${toString config.fediversity.garage.api.port}"; + }; + }; + + rpc = { + port = mkOption { + type = types.int; + default = 3901; + }; + }; + + web = { + rootDomain = mkOption { + type = types.str; + default = "web.garage.${config.fediversity.domain}"; + }; + internalPort = mkOption { + type = types.int; + default = 3902; + }; + domainForBucket = mkOption { + type = types.functionTo types.str; + default = bucket: "${bucket}.${config.fediversity.garage.web.rootDomain}"; + }; + urlForBucket = mkOption { + type = types.functionTo types.str; + default = bucket: "http://${config.fediversity.garage.web.domainForBucket bucket}"; + }; + }; }; } diff --git a/services/fediversity/mastodon.nix b/services/fediversity/mastodon.nix index 7486559..1d0e8c6 100644 --- a/services/fediversity/mastodon.nix +++ b/services/fediversity/mastodon.nix @@ -38,7 +38,7 @@ lib.mkIf (config.fediversity.enable && config.fediversity.mastodon.enable) { extraConfig = rec { S3_ENABLED = "true"; # TODO: this shouldn't be hard-coded, it should come from the garage configuration - S3_ENDPOINT = config.fediversity.internal.garage.api.url; + S3_ENDPOINT = config.fediversity.garage.api.url; S3_REGION = "garage"; S3_BUCKET = "mastodon"; # use <S3_BUCKET>.<S3_ENDPOINT> @@ -46,7 +46,7 @@ lib.mkIf (config.fediversity.enable && config.fediversity.mastodon.enable) { AWS_ACCESS_KEY_ID = snakeoil_key.id; AWS_SECRET_ACCESS_KEY = snakeoil_key.secret; S3_PROTOCOL = "http"; - S3_ALIAS_HOST = "${S3_BUCKET}.${config.fediversity.internal.garage.web.rootDomain}"; + S3_ALIAS_HOST = "${S3_BUCKET}.${config.fediversity.garage.web.rootDomain}"; # SEE: the last section in https://docs.joinmastodon.org/admin/optional/object-storage/ # TODO: can we set up ACLs with garage? S3_PERMISSION = ""; diff --git a/services/fediversity/peertube.nix b/services/fediversity/peertube.nix index ae973c1..6105a7d 100644 --- a/services/fediversity/peertube.nix +++ b/services/fediversity/peertube.nix @@ -72,7 +72,7 @@ lib.mkIf (config.fediversity.enable && config.fediversity.peertube.enable) { settings = { object_storage = { enabled = true; - endpoint = config.fediversity.internal.garage.api.url; + endpoint = config.fediversity.garage.api.url; region = "garage"; upload_acl.public = null; # Garage does not support ACL upload_acl.private = null; # Garage does not support ACL @@ -84,17 +84,17 @@ lib.mkIf (config.fediversity.enable && config.fediversity.peertube.enable) { web_videos = rec { bucket_name = "peertube-videos"; prefix = ""; - base_url = config.fediversity.internal.garage.web.urlForBucket bucket_name; + base_url = config.fediversity.garage.web.urlForBucket bucket_name; }; videos = rec { bucket_name = "peertube-videos"; prefix = ""; - base_url = config.fediversity.internal.garage.web.urlForBucket bucket_name; + base_url = config.fediversity.garage.web.urlForBucket bucket_name; }; streaming_playlists = rec { bucket_name = "peertube-playlists"; prefix = ""; - base_url = config.fediversity.internal.garage.web.urlForBucket bucket_name; + base_url = config.fediversity.garage.web.urlForBucket bucket_name; }; }; }; diff --git a/services/fediversity/pixelfed.nix b/services/fediversity/pixelfed.nix index 6c2a3eb..0b1be36 100644 --- a/services/fediversity/pixelfed.nix +++ b/services/fediversity/pixelfed.nix @@ -57,7 +57,7 @@ lib.mkIf (config.fediversity.enable && config.fediversity.pixelfed.enable) { nginx = { forceSSL = true; enableACME = true; - # locations."/public/".proxyPass = "${config.fediversity.internal.garage.web.urlForBucket "pixelfed"}/public/"; + # locations."/public/".proxyPass = "${config.fediversity.garage.web.urlForBucket "pixelfed"}/public/"; }; }; @@ -73,9 +73,9 @@ lib.mkIf (config.fediversity.enable && config.fediversity.pixelfed.enable) { AWS_ACCESS_KEY_ID = snakeoil_key.id; AWS_SECRET_ACCESS_KEY = snakeoil_key.secret; AWS_DEFAULT_REGION = "garage"; - AWS_URL = config.fediversity.internal.garage.web.urlForBucket "pixelfed"; + AWS_URL = config.fediversity.garage.web.urlForBucket "pixelfed"; AWS_BUCKET = "pixelfed"; - AWS_ENDPOINT = config.fediversity.internal.garage.api.url; + AWS_ENDPOINT = config.fediversity.garage.api.url; AWS_USE_PATH_STYLE_ENDPOINT = false; }; diff --git a/services/tests/mastodon.nix b/services/tests/mastodon.nix index 80ede0c..61629aa 100644 --- a/services/tests/mastodon.nix +++ b/services/tests/mastodon.nix @@ -118,7 +118,7 @@ pkgs.nixosTest { server.succeed("toot post --media ${testImage}") with subtest("Access garage"): - server.succeed("mc alias set garage ${nodes.server.fediversity.internal.garage.api.url} --api s3v4 --path off $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY") + server.succeed("mc alias set garage ${nodes.server.fediversity.garage.api.url} --api s3v4 --path off $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY") server.succeed("mc ls garage/mastodon") with subtest("Access image in garage"): @@ -144,7 +144,7 @@ pkgs.nixosTest { raise Exception("mastodon did not send a content security policy header") csp = csp_match.group(1) # the connect-src content security policy should include the garage server - ## TODO: use `nodes.server.fediversity.internal.garage.api.url` same as above, but beware of escaping the regex. Be careful with port 80 though. + ## TODO: use `nodes.server.fediversity.garage.api.url` same as above, but beware of escaping the regex. Be careful with port 80 though. garage_csp = re.match(".*; img-src[^;]*web\.garage\.localhost.*", csp) if garage_csp is None: raise Exception("Mastodon's Content-Security-Policy does not include Garage.") diff --git a/services/tests/peertube.nix b/services/tests/peertube.nix index c10e01a..23b002f 100644 --- a/services/tests/peertube.nix +++ b/services/tests/peertube.nix @@ -220,7 +220,7 @@ pkgs.nixosTest { server.succeed(f"post-video-in-browser {root_password}") with subtest("Find video in garage"): - server.succeed("mc alias set garage ${nodes.server.fediversity.internal.garage.api.url} --api s3v4 --path off $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY") + server.succeed("mc alias set garage ${nodes.server.fediversity.garage.api.url} --api s3v4 --path off $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY") video = server.succeed("mc find garage --regex '\\.mp4'").rstrip() if video == "": raise Exception("Could not find any .mp4 video stored in Garage") diff --git a/services/tests/pixelfed-garage.nix b/services/tests/pixelfed-garage.nix index 346ffe4..fb658a3 100644 --- a/services/tests/pixelfed-garage.nix +++ b/services/tests/pixelfed-garage.nix @@ -201,7 +201,7 @@ pkgs.nixosTest { raise Exception("cannot detect the uploaded image on pixelfed page.") with subtest("access garage"): - server.succeed("mc alias set garage ${nodes.server.fediversity.internal.garage.api.url} --api s3v4 --path off $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY") + server.succeed("mc alias set garage ${nodes.server.fediversity.garage.api.url} --api s3v4 --path off $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY") server.succeed("mc ls garage/pixelfed") with subtest("access image in garage"): @@ -217,7 +217,7 @@ pkgs.nixosTest { with subtest("Check that image comes from garage"): src = server.succeed("su - selenium -c 'selenium-script-get-src ${email} ${password}'") - if not src.startswith("${nodes.server.fediversity.internal.garage.web.urlForBucket "pixelfed"}"): + if not src.startswith("${nodes.server.fediversity.garage.web.urlForBucket "pixelfed"}"): raise Exception("image does not come from garage") ''; } diff --git a/services/vm/garage-vm.nix b/services/vm/garage-vm.nix index b115b51..174d23c 100644 --- a/services/vm/garage-vm.nix +++ b/services/vm/garage-vm.nix @@ -20,7 +20,7 @@ in }; in mapAttrs' (bucket: _: { - name = config.fediversity.internal.garage.web.domainForBucket bucket; + name = config.fediversity.garage.web.domainForBucket bucket; inherit value; }) (filterAttrs (_: { website, ... }: website) config.fediversity.garage.ensureBuckets); @@ -28,13 +28,13 @@ in virtualisation.forwardPorts = [ { from = "host"; - host.port = config.fediversity.internal.garage.rpc.port; - guest.port = config.fediversity.internal.garage.rpc.port; + host.port = config.fediversity.garage.rpc.port; + guest.port = config.fediversity.garage.rpc.port; } { from = "host"; - host.port = config.fediversity.internal.garage.web.internalPort; - guest.port = config.fediversity.internal.garage.web.internalPort; + host.port = config.fediversity.garage.web.internalPort; + guest.port = config.fediversity.garage.web.internalPort; } ]; } From ca6642c8d466e27e5300929ab09f5d259e3a5f88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=E2=80=9CNiols=E2=80=9D=20Jeannerod?= <nicolas.jeannerod@moduscreate.com> Date: Fri, 14 Feb 2025 18:37:48 +0100 Subject: [PATCH 07/16] Same treatment for Mastodon --- services/fediversity/default.nix | 7 +- services/fediversity/mastodon.nix | 87 ---------------------- services/fediversity/mastodon/default.nix | 91 +++++++++++++++++++++++ services/fediversity/mastodon/options.nix | 18 +++++ 4 files changed, 110 insertions(+), 93 deletions(-) delete mode 100644 services/fediversity/mastodon.nix create mode 100644 services/fediversity/mastodon/default.nix create mode 100644 services/fediversity/mastodon/options.nix diff --git a/services/fediversity/default.nix b/services/fediversity/default.nix index d643c8d..16b0c26 100644 --- a/services/fediversity/default.nix +++ b/services/fediversity/default.nix @@ -8,7 +8,7 @@ in { imports = [ ./garage - ./mastodon.nix + ./mastodon ./pixelfed.nix ./peertube.nix ]; @@ -27,7 +27,6 @@ in ''; }; - mastodon.enable = mkEnableOption "default Fediversity Mastodon configuration"; pixelfed.enable = mkEnableOption "default Fediversity Pixelfed configuration"; peertube.enable = mkEnableOption "default Fediversity PeerTube configuration"; @@ -62,10 +61,6 @@ in type = types.str; default = "pixelfed.${config.fediversity.domain}"; }; - mastodon.domain = mkOption { - type = types.str; - default = "mastodon.${config.fediversity.domain}"; - }; peertube.domain = mkOption { type = types.str; default = "peertube.${config.fediversity.domain}"; diff --git a/services/fediversity/mastodon.nix b/services/fediversity/mastodon.nix deleted file mode 100644 index 1d0e8c6..0000000 --- a/services/fediversity/mastodon.nix +++ /dev/null @@ -1,87 +0,0 @@ -let - snakeoil_key = { - id = "GK3515373e4c851ebaad366558"; - secret = "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34"; - }; -in - -{ config, lib, ... }: - -lib.mkIf (config.fediversity.enable && config.fediversity.mastodon.enable) { - #### garage setup - fediversity.garage = { - ensureBuckets = { - mastodon = { - website = true; - corsRules = { - enable = true; - allowedHeaders = [ "*" ]; - allowedMethods = [ "GET" ]; - allowedOrigins = [ "*" ]; - }; - }; - }; - ensureKeys = { - mastodon = { - inherit (snakeoil_key) id secret; - ensureAccess = { - mastodon = { - read = true; - write = true; - owner = true; - }; - }; - }; - }; - }; - services.mastodon = { - extraConfig = rec { - S3_ENABLED = "true"; - # TODO: this shouldn't be hard-coded, it should come from the garage configuration - S3_ENDPOINT = config.fediversity.garage.api.url; - S3_REGION = "garage"; - S3_BUCKET = "mastodon"; - # use <S3_BUCKET>.<S3_ENDPOINT> - S3_OVERRIDE_PATH_STLE = "true"; - AWS_ACCESS_KEY_ID = snakeoil_key.id; - AWS_SECRET_ACCESS_KEY = snakeoil_key.secret; - S3_PROTOCOL = "http"; - S3_ALIAS_HOST = "${S3_BUCKET}.${config.fediversity.garage.web.rootDomain}"; - # SEE: the last section in https://docs.joinmastodon.org/admin/optional/object-storage/ - # TODO: can we set up ACLs with garage? - S3_PERMISSION = ""; - }; - }; - - #### mastodon setup - - # open up access to the mastodon web interface. 80 is necessary if only for ACME - networking.firewall.allowedTCPPorts = [ - 80 - 443 - ]; - - services.mastodon = { - enable = true; - - localDomain = config.fediversity.internal.mastodon.domain; - configureNginx = true; - - # from the documentation: recommended is the amount of your CPU cores minus - # one. but it also must be a positive integer - streamingProcesses = lib.max 1 (config.fediversity.temp.cores - 1); - - # TODO: configure a mailserver so this works - smtp = { - fromAddress = "noreply@${config.fediversity.internal.mastodon.domain}"; - createLocally = false; - }; - }; - - security.acme = { - acceptTerms = true; - preliminarySelfsigned = true; - # TODO: configure a mailserver so we can set up acme - # defaults.email = "test@example.com"; - }; -} diff --git a/services/fediversity/mastodon/default.nix b/services/fediversity/mastodon/default.nix new file mode 100644 index 0000000..083cf91 --- /dev/null +++ b/services/fediversity/mastodon/default.nix @@ -0,0 +1,91 @@ +let + snakeoil_key = { + id = "GK3515373e4c851ebaad366558"; + secret = "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34"; + }; +in + +{ config, lib, ... }: + +{ + imports = [ ./options.nix ]; + + config = lib.mkIf (config.fediversity.enable && config.fediversity.mastodon.enable) { + #### garage setup + fediversity.garage = { + ensureBuckets = { + mastodon = { + website = true; + corsRules = { + enable = true; + allowedHeaders = [ "*" ]; + allowedMethods = [ "GET" ]; + allowedOrigins = [ "*" ]; + }; + }; + }; + ensureKeys = { + mastodon = { + inherit (snakeoil_key) id secret; + ensureAccess = { + mastodon = { + read = true; + write = true; + owner = true; + }; + }; + }; + }; + }; + services.mastodon = { + extraConfig = rec { + S3_ENABLED = "true"; + # TODO: this shouldn't be hard-coded, it should come from the garage configuration + S3_ENDPOINT = config.fediversity.garage.api.url; + S3_REGION = "garage"; + S3_BUCKET = "mastodon"; + # use <S3_BUCKET>.<S3_ENDPOINT> + S3_OVERRIDE_PATH_STLE = "true"; + AWS_ACCESS_KEY_ID = snakeoil_key.id; + AWS_SECRET_ACCESS_KEY = snakeoil_key.secret; + S3_PROTOCOL = "http"; + S3_ALIAS_HOST = "${S3_BUCKET}.${config.fediversity.garage.web.rootDomain}"; + # SEE: the last section in https://docs.joinmastodon.org/admin/optional/object-storage/ + # TODO: can we set up ACLs with garage? + S3_PERMISSION = ""; + }; + }; + + #### mastodon setup + + # open up access to the mastodon web interface. 80 is necessary if only for ACME + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + + services.mastodon = { + enable = true; + + localDomain = config.fediversity.mastodon.domain; + configureNginx = true; + + # from the documentation: recommended is the amount of your CPU cores minus + # one. but it also must be a positive integer + streamingProcesses = lib.max 1 (config.fediversity.temp.cores - 1); + + # TODO: configure a mailserver so this works + smtp = { + fromAddress = "noreply@${config.fediversity.mastodon.domain}"; + createLocally = false; + }; + }; + + security.acme = { + acceptTerms = true; + preliminarySelfsigned = true; + # TODO: configure a mailserver so we can set up acme + # defaults.email = "test@example.com"; + }; + }; +} diff --git a/services/fediversity/mastodon/options.nix b/services/fediversity/mastodon/options.nix new file mode 100644 index 0000000..882b96e --- /dev/null +++ b/services/fediversity/mastodon/options.nix @@ -0,0 +1,18 @@ +{ config, lib, ... }: + +let + inherit (lib) mkOption mkEnableOption; + inherit (lib.types) types; + +in +{ + options.fediversity.mastodon = { + enable = mkEnableOption "Enable a Mastodon server on the machine"; + + domain = mkOption { + type = types.str; + description = "Internal option — change at your own risk"; + default = "mastodon.${config.fediversity.domain}"; + }; + }; +} From a1cfcf1d71685ec85b1103ba7df0d54624c7784f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=E2=80=9CNiols=E2=80=9D=20Jeannerod?= <nicolas.jeannerod@moduscreate.com> Date: Fri, 14 Feb 2025 18:44:35 +0100 Subject: [PATCH 08/16] Same treatment for Peertube --- deployment/flake-part.nix | 11 +- services/fediversity/default.nix | 12 +-- services/fediversity/peertube.nix | 119 --------------------- services/fediversity/peertube/default.nix | 123 ++++++++++++++++++++++ services/fediversity/peertube/options.nix | 28 +++++ services/vm/peertube-vm.nix | 11 +- 6 files changed, 164 insertions(+), 140 deletions(-) delete mode 100644 services/fediversity/peertube.nix create mode 100644 services/fediversity/peertube/default.nix create mode 100644 services/fediversity/peertube/options.nix diff --git a/deployment/flake-part.nix b/deployment/flake-part.nix index 7905286..a0e42ae 100644 --- a/deployment/flake-part.nix +++ b/deployment/flake-part.nix @@ -100,11 +100,12 @@ in fediversity = { enable = true; domain = "fedi103.abundos.eu"; - peertube.enable = true; - - temp.peertubeSecretsFile = pkgs.writeText "secret" '' - 574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24 - ''; + peertube = { + enable = true; + secretsFile = pkgs.writeText "secret" '' + 574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24 + ''; + }; }; } ); diff --git a/services/fediversity/default.nix b/services/fediversity/default.nix index 16b0c26..a8c9f69 100644 --- a/services/fediversity/default.nix +++ b/services/fediversity/default.nix @@ -10,7 +10,7 @@ in ./garage ./mastodon ./pixelfed.nix - ./peertube.nix + ./peertube ]; options = { @@ -28,7 +28,6 @@ in }; pixelfed.enable = mkEnableOption "default Fediversity Pixelfed configuration"; - peertube.enable = mkEnableOption "default Fediversity PeerTube configuration"; temp = mkOption { description = "options that are only used while developing; should be removed eventually"; @@ -39,11 +38,6 @@ in description = "number of cores; should be obtained from NixOps4"; type = types.int; }; - - peertubeSecretsFile = mkOption { - description = "should it be provided by NixOps4? or maybe we should just ask for a main secret from which to derive all the others?"; - type = types.path; - }; }; }; }; @@ -61,10 +55,6 @@ in type = types.str; default = "pixelfed.${config.fediversity.domain}"; }; - peertube.domain = mkOption { - type = types.str; - default = "peertube.${config.fediversity.domain}"; - }; }; }; }; diff --git a/services/fediversity/peertube.nix b/services/fediversity/peertube.nix deleted file mode 100644 index 6105a7d..0000000 --- a/services/fediversity/peertube.nix +++ /dev/null @@ -1,119 +0,0 @@ -let - snakeoil_key = { - id = "GK1f9feea9960f6f95ff404c9b"; - secret = "7295c4201966a02c2c3d25b5cea4a5ff782966a2415e3a196f91924631191395"; - }; -in - -{ config, lib, ... }: - -lib.mkIf (config.fediversity.enable && config.fediversity.peertube.enable) { - networking.firewall.allowedTCPPorts = [ - 80 - 443 - - ## For Live streaming and Live streaming when RTMPS is enabled. - 1935 - 1936 - ]; - - fediversity.garage = { - ensureBuckets = { - peertube-videos = { - website = true; - # TODO: these are too broad, after getting everything works narrow it down to the domain we actually want - corsRules = { - enable = true; - allowedHeaders = [ "*" ]; - allowedMethods = [ "GET" ]; - allowedOrigins = [ "*" ]; - }; - }; - # TODO: these are too broad, after getting everything works narrow it down to the domain we actually want - peertube-playlists = { - website = true; - corsRules = { - enable = true; - allowedHeaders = [ "*" ]; - allowedMethods = [ "GET" ]; - allowedOrigins = [ "*" ]; - }; - }; - }; - ensureKeys = { - peertube = { - inherit (snakeoil_key) id secret; - ensureAccess = { - peertube-videos = { - read = true; - write = true; - owner = true; - }; - peertube-playlists = { - read = true; - write = true; - owner = true; - }; - }; - }; - }; - }; - - services.peertube = { - enable = true; - localDomain = config.fediversity.internal.peertube.domain; - - # TODO: in most of nixpkgs, these are true by default. upstream that unless there's a good reason not to. - redis.createLocally = true; - database.createLocally = true; - - secrets.secretsFile = config.fediversity.temp.peertubeSecretsFile; - - settings = { - object_storage = { - enabled = true; - endpoint = config.fediversity.garage.api.url; - region = "garage"; - upload_acl.public = null; # Garage does not support ACL - upload_acl.private = null; # Garage does not support ACL - - # not supported by garage - # SEE: https://garagehq.deuxfleurs.fr/documentation/connect/apps/#peertube - proxy.proxyify_private_files = false; - - web_videos = rec { - bucket_name = "peertube-videos"; - prefix = ""; - base_url = config.fediversity.garage.web.urlForBucket bucket_name; - }; - videos = rec { - bucket_name = "peertube-videos"; - prefix = ""; - base_url = config.fediversity.garage.web.urlForBucket bucket_name; - }; - streaming_playlists = rec { - bucket_name = "peertube-playlists"; - prefix = ""; - base_url = config.fediversity.garage.web.urlForBucket bucket_name; - }; - }; - }; - serviceEnvironmentFile = "/etc/peertube-env"; - }; - environment.etc.peertube-env.text = '' - AWS_ACCESS_KEY_ID=${snakeoil_key.id} - AWS_SECRET_ACCESS_KEY=${snakeoil_key.secret} - ''; - - ## Proxying through Nginx - - services.peertube = { - configureNginx = true; - listenWeb = 443; - enableWebHttps = true; - }; - services.nginx.virtualHosts.${config.services.peertube.localDomain} = { - forceSSL = true; - enableACME = true; - }; -} diff --git a/services/fediversity/peertube/default.nix b/services/fediversity/peertube/default.nix new file mode 100644 index 0000000..e649c56 --- /dev/null +++ b/services/fediversity/peertube/default.nix @@ -0,0 +1,123 @@ +let + snakeoil_key = { + id = "GK1f9feea9960f6f95ff404c9b"; + secret = "7295c4201966a02c2c3d25b5cea4a5ff782966a2415e3a196f91924631191395"; + }; +in + +{ config, lib, ... }: + +{ + imports = [ ./options.nix ]; + + config = lib.mkIf (config.fediversity.enable && config.fediversity.peertube.enable) { + networking.firewall.allowedTCPPorts = [ + 80 + 443 + + ## For Live streaming and Live streaming when RTMPS is enabled. + 1935 + 1936 + ]; + + fediversity.garage = { + ensureBuckets = { + peertube-videos = { + website = true; + # TODO: these are too broad, after getting everything works narrow it down to the domain we actually want + corsRules = { + enable = true; + allowedHeaders = [ "*" ]; + allowedMethods = [ "GET" ]; + allowedOrigins = [ "*" ]; + }; + }; + # TODO: these are too broad, after getting everything works narrow it down to the domain we actually want + peertube-playlists = { + website = true; + corsRules = { + enable = true; + allowedHeaders = [ "*" ]; + allowedMethods = [ "GET" ]; + allowedOrigins = [ "*" ]; + }; + }; + }; + ensureKeys = { + peertube = { + inherit (snakeoil_key) id secret; + ensureAccess = { + peertube-videos = { + read = true; + write = true; + owner = true; + }; + peertube-playlists = { + read = true; + write = true; + owner = true; + }; + }; + }; + }; + }; + + services.peertube = { + enable = true; + localDomain = config.fediversity.peertube.domain; + + # TODO: in most of nixpkgs, these are true by default. upstream that unless there's a good reason not to. + redis.createLocally = true; + database.createLocally = true; + + secrets.secretsFile = config.fediversity.peertube.secretsFile; + + settings = { + object_storage = { + enabled = true; + endpoint = config.fediversity.garage.api.url; + region = "garage"; + upload_acl.public = null; # Garage does not support ACL + upload_acl.private = null; # Garage does not support ACL + + # not supported by garage + # SEE: https://garagehq.deuxfleurs.fr/documentation/connect/apps/#peertube + proxy.proxyify_private_files = false; + + web_videos = rec { + bucket_name = "peertube-videos"; + prefix = ""; + base_url = config.fediversity.garage.web.urlForBucket bucket_name; + }; + videos = rec { + bucket_name = "peertube-videos"; + prefix = ""; + base_url = config.fediversity.garage.web.urlForBucket bucket_name; + }; + streaming_playlists = rec { + bucket_name = "peertube-playlists"; + prefix = ""; + base_url = config.fediversity.garage.web.urlForBucket bucket_name; + }; + }; + }; + serviceEnvironmentFile = "/etc/peertube-env"; + }; + environment.etc.peertube-env.text = '' + AWS_ACCESS_KEY_ID=${snakeoil_key.id} + AWS_SECRET_ACCESS_KEY=${snakeoil_key.secret} + ''; + + ## Proxying through Nginx + + services.peertube = { + configureNginx = true; + listenWeb = 443; + enableWebHttps = true; + }; + services.nginx.virtualHosts.${config.services.peertube.localDomain} = { + forceSSL = true; + enableACME = true; + }; + }; +} diff --git a/services/fediversity/peertube/options.nix b/services/fediversity/peertube/options.nix new file mode 100644 index 0000000..feedcad --- /dev/null +++ b/services/fediversity/peertube/options.nix @@ -0,0 +1,28 @@ +{ config, lib, ... }: + +let + inherit (lib) mkOption mkEnableOption; + inherit (lib.types) types; + +in +{ + options.fediversity.peertube = { + enable = mkEnableOption "Enable a PeerTube server on the machine"; + + domain = mkOption { + type = types.str; + description = "Internal option — change at your own risk"; + default = "peertube.${config.fediversity.domain}"; + }; + + secretsFile = mkOption { + type = types.path; + description = '' + Internal option — change at your own risk + + FIXME: should it be provided by NixOps4? + or maybe we should just ask for a main secret from which to derive all the others? + ''; + }; + }; +} diff --git a/services/vm/peertube-vm.nix b/services/vm/peertube-vm.nix index 0e2c992..758d64b 100644 --- a/services/vm/peertube-vm.nix +++ b/services/vm/peertube-vm.nix @@ -10,11 +10,12 @@ fediversity = { enable = true; domain = "localhost"; - peertube.enable = true; - - temp.peertubeSecretsFile = pkgs.writeText "secret" '' - 574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24 - ''; + peertube = { + enable = true; + secretsFile = pkgs.writeText "secret" '' + 574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24 + ''; + }; }; services.peertube = { From 1965e83e5d2b7ee8362ad81ddeff07ff4a7527cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=E2=80=9CNiols=E2=80=9D=20Jeannerod?= <nicolas.jeannerod@moduscreate.com> Date: Fri, 14 Feb 2025 18:51:38 +0100 Subject: [PATCH 09/16] Same treatment for Pixelfed --- services/fediversity/default.nix | 21 +--- services/fediversity/pixelfed.nix | 92 ------------------ services/fediversity/pixelfed/default.nix | 96 +++++++++++++++++++ .../group-permissions.patch} | 0 services/fediversity/pixelfed/options.nix | 18 ++++ 5 files changed, 115 insertions(+), 112 deletions(-) delete mode 100644 services/fediversity/pixelfed.nix create mode 100644 services/fediversity/pixelfed/default.nix rename services/fediversity/{pixelfed-group-permissions.patch => pixelfed/group-permissions.patch} (100%) create mode 100644 services/fediversity/pixelfed/options.nix diff --git a/services/fediversity/default.nix b/services/fediversity/default.nix index a8c9f69..5147c8f 100644 --- a/services/fediversity/default.nix +++ b/services/fediversity/default.nix @@ -9,7 +9,7 @@ in imports = [ ./garage ./mastodon - ./pixelfed.nix + ./pixelfed ./peertube ]; @@ -27,8 +27,6 @@ in ''; }; - pixelfed.enable = mkEnableOption "default Fediversity Pixelfed configuration"; - temp = mkOption { description = "options that are only used while developing; should be removed eventually"; default = { }; @@ -41,23 +39,6 @@ in }; }; }; - - internal = mkOption { - description = "options that are only meant to be used internally; change at your own risk"; - default = { }; - type = types.submodule { - options = { - ## REVIEW: Do we want to recreate options under - ## `fediversity.internal` or would we rather use the options from - ## the respective services? See Taeer's comment: - ## https://git.fediversity.eu/taeer/simple-nixos-fediverse/pulls/22#issuecomment-124 - pixelfed.domain = mkOption { - type = types.str; - default = "pixelfed.${config.fediversity.domain}"; - }; - }; - }; - }; }; }; diff --git a/services/fediversity/pixelfed.nix b/services/fediversity/pixelfed.nix deleted file mode 100644 index 0b1be36..0000000 --- a/services/fediversity/pixelfed.nix +++ /dev/null @@ -1,92 +0,0 @@ -let - snakeoil_key = { - id = "GKb5615457d44214411e673b7b"; - secret = "5be6799a88ca9b9d813d1a806b64f15efa49482dbe15339ddfaf7f19cf434987"; - }; -in - -{ - config, - lib, - pkgs, - ... -}: - -lib.mkIf (config.fediversity.enable && config.fediversity.pixelfed.enable) { - fediversity.garage = { - ensureBuckets = { - pixelfed = { - website = true; - # TODO: these are too broad, after getting everything works narrow it down to the domain we actually want - corsRules = { - enable = true; - allowedHeaders = [ "*" ]; - allowedMethods = [ "GET" ]; - allowedOrigins = [ "*" ]; - }; - }; - }; - ensureKeys = { - pixelfed = { - inherit (snakeoil_key) id secret; - ensureAccess = { - pixelfed = { - read = true; - write = true; - owner = true; - }; - }; - }; - }; - }; - - services.pixelfed = { - enable = true; - domain = config.fediversity.internal.pixelfed.domain; - - # TODO: secrets management!!! - secretFile = pkgs.writeText "secrets.env" '' - APP_KEY=adKK9EcY8Hcj3PLU7rzG9rJ6KKTOtYfA - ''; - - ## Taeer feels like this way of configuring Nginx is odd; there should - ## instead be a `services.pixefed.nginx.enable` option and the actual Nginx - ## configuration should be in `services.nginx`. See eg. `pretix`. - ## - ## TODO: If that indeed makes sense, upstream. - nginx = { - forceSSL = true; - enableACME = true; - # locations."/public/".proxyPass = "${config.fediversity.garage.web.urlForBucket "pixelfed"}/public/"; - }; - }; - - services.pixelfed.settings = { - ## NOTE: This depends on the targets, eg. universities might want control - ## over who has an account. We probably want a universal - ## `fediversity.openRegistration` option. - OPEN_REGISTRATION = true; - - # DANGEROUSLY_SET_FILESYSTEM_DRIVER = "s3"; - FILESYSTEM_CLOUD = "s3"; - PF_ENABLE_CLOUD = true; - AWS_ACCESS_KEY_ID = snakeoil_key.id; - AWS_SECRET_ACCESS_KEY = snakeoil_key.secret; - AWS_DEFAULT_REGION = "garage"; - AWS_URL = config.fediversity.garage.web.urlForBucket "pixelfed"; - AWS_BUCKET = "pixelfed"; - AWS_ENDPOINT = config.fediversity.garage.api.url; - AWS_USE_PATH_STYLE_ENDPOINT = false; - }; - - ## Only ever run `pixelfed-data-setup` after `ensure-garage` has done its job. - ## Otherwise, everything crashed dramatically. - systemd.services.pixelfed-data-setup = { - after = [ "ensure-garage.service" ]; - }; - - networking.firewall.allowedTCPPorts = [ - 80 - 443 - ]; -} diff --git a/services/fediversity/pixelfed/default.nix b/services/fediversity/pixelfed/default.nix new file mode 100644 index 0000000..4ce2887 --- /dev/null +++ b/services/fediversity/pixelfed/default.nix @@ -0,0 +1,96 @@ +let + snakeoil_key = { + id = "GKb5615457d44214411e673b7b"; + secret = "5be6799a88ca9b9d813d1a806b64f15efa49482dbe15339ddfaf7f19cf434987"; + }; +in + +{ + config, + lib, + pkgs, + ... +}: + +{ + imports = [ ./options.nix ]; + + config = lib.mkIf (config.fediversity.enable && config.fediversity.pixelfed.enable) { + fediversity.garage = { + ensureBuckets = { + pixelfed = { + website = true; + # TODO: these are too broad, after getting everything works narrow it down to the domain we actually want + corsRules = { + enable = true; + allowedHeaders = [ "*" ]; + allowedMethods = [ "GET" ]; + allowedOrigins = [ "*" ]; + }; + }; + }; + ensureKeys = { + pixelfed = { + inherit (snakeoil_key) id secret; + ensureAccess = { + pixelfed = { + read = true; + write = true; + owner = true; + }; + }; + }; + }; + }; + + services.pixelfed = { + enable = true; + domain = config.fediversity.pixelfed.domain; + + # TODO: secrets management!!! + secretFile = pkgs.writeText "secrets.env" '' + APP_KEY=adKK9EcY8Hcj3PLU7rzG9rJ6KKTOtYfA + ''; + + ## Taeer feels like this way of configuring Nginx is odd; there should + ## instead be a `services.pixefed.nginx.enable` option and the actual Nginx + ## configuration should be in `services.nginx`. See eg. `pretix`. + ## + ## TODO: If that indeed makes sense, upstream. + nginx = { + forceSSL = true; + enableACME = true; + # locations."/public/".proxyPass = "${config.fediversity.garage.web.urlForBucket "pixelfed"}/public/"; + }; + }; + + services.pixelfed.settings = { + ## NOTE: This depends on the targets, eg. universities might want control + ## over who has an account. We probably want a universal + ## `fediversity.openRegistration` option. + OPEN_REGISTRATION = true; + + # DANGEROUSLY_SET_FILESYSTEM_DRIVER = "s3"; + FILESYSTEM_CLOUD = "s3"; + PF_ENABLE_CLOUD = true; + AWS_ACCESS_KEY_ID = snakeoil_key.id; + AWS_SECRET_ACCESS_KEY = snakeoil_key.secret; + AWS_DEFAULT_REGION = "garage"; + AWS_URL = config.fediversity.garage.web.urlForBucket "pixelfed"; + AWS_BUCKET = "pixelfed"; + AWS_ENDPOINT = config.fediversity.garage.api.url; + AWS_USE_PATH_STYLE_ENDPOINT = false; + }; + + ## Only ever run `pixelfed-data-setup` after `ensure-garage` has done its job. + ## Otherwise, everything crashed dramatically. + systemd.services.pixelfed-data-setup = { + after = [ "ensure-garage.service" ]; + }; + + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + }; +} diff --git a/services/fediversity/pixelfed-group-permissions.patch b/services/fediversity/pixelfed/group-permissions.patch similarity index 100% rename from services/fediversity/pixelfed-group-permissions.patch rename to services/fediversity/pixelfed/group-permissions.patch diff --git a/services/fediversity/pixelfed/options.nix b/services/fediversity/pixelfed/options.nix new file mode 100644 index 0000000..1a36ea2 --- /dev/null +++ b/services/fediversity/pixelfed/options.nix @@ -0,0 +1,18 @@ +{ config, lib, ... }: + +let + inherit (lib) mkOption mkEnableOption; + inherit (lib.types) types; + +in +{ + options.fediversity.pixelfed = { + enable = mkEnableOption "Enable a Pixelfed server on the machine"; + + domain = mkOption { + type = types.str; + description = "Internal option — change at your own risk"; + default = "pixelfed.${config.fediversity.domain}"; + }; + }; +} From b547912794b09a47c0d3ce1ad71f084ee68bab0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=E2=80=9CNiols=E2=80=9D=20Jeannerod?= <nicolas.jeannerod@moduscreate.com> Date: Fri, 14 Feb 2025 19:01:54 +0100 Subject: [PATCH 10/16] Make access and secret keys parameters --- deployment/flake-part.nix | 24 ++++++++++++++++++----- services/fediversity/garage/default.nix | 6 +++--- services/fediversity/garage/options.nix | 4 ++-- services/fediversity/mastodon/default.nix | 15 +++++--------- services/fediversity/mastodon/options.nix | 17 ++++++++++++++++ services/fediversity/peertube/default.nix | 14 ++++--------- services/fediversity/peertube/options.nix | 17 ++++++++++++++++ services/fediversity/pixelfed/default.nix | 21 +++++++++----------- services/fediversity/pixelfed/options.nix | 17 ++++++++++++++++ 9 files changed, 93 insertions(+), 42 deletions(-) diff --git a/deployment/flake-part.nix b/deployment/flake-part.nix index a0e42ae..d215a22 100644 --- a/deployment/flake-part.nix +++ b/deployment/flake-part.nix @@ -80,7 +80,13 @@ in fediversity = { enable = true; domain = "fedi101.abundos.eu"; - pixelfed.enable = true; + pixelfed = { + enable = true; + + ## NOTE: Only ever used for testing anyway. + s3AccessKey = "GKb5615457d44214411e673b7b"; + s3SecretKey = "5be6799a88ca9b9d813d1a806b64f15efa49482dbe15339ddfaf7f19cf434987"; + }; }; }; @@ -88,7 +94,13 @@ in fediversity = { enable = true; domain = "fedi102.abundos.eu"; - mastodon.enable = true; + mastodon = { + enable = true; + + ## NOTE: Only ever used for testing anyway. + s3AccessKey = "GK3515373e4c851ebaad366558"; + s3SecretKey = "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34"; + }; temp.cores = 1; # FIXME: should come from NixOps4 eventually }; @@ -102,9 +114,11 @@ in domain = "fedi103.abundos.eu"; peertube = { enable = true; - secretsFile = pkgs.writeText "secret" '' - 574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24 - ''; + + ## NOTE: Only ever used for testing anyway. + secretsFile = pkgs.writeText "secret" "574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24"; + s3AccessKey = "GK1f9feea9960f6f95ff404c9b"; + s3SecretKey = "7295c4201966a02c2c3d25b5cea4a5ff782966a2415e3a196f91924631191395"; }; }; } diff --git a/services/fediversity/garage/default.nix b/services/fediversity/garage/default.nix index 5191016..da0a7e4 100644 --- a/services/fediversity/garage/default.nix +++ b/services/fediversity/garage/default.nix @@ -83,13 +83,13 @@ let ensureKeyScriptFn = key: { - id, - secret, + s3AccessKey, + s3SecretKey, ensureAccess, }: '' ## FIXME: Check whether the key exist and skip this step if that is the case. Get rid of this `|| :` - garage key import --yes -n ${escapeShellArg key} ${escapeShellArg id} ${escapeShellArg secret} || : + garage key import --yes -n ${escapeShellArg key} ${escapeShellArg s3AccessKey} ${escapeShellArg s3SecretKey} || : ${concatMapAttrs (ensureAccessScriptFn key) ensureAccess} ''; diff --git a/services/fediversity/garage/options.nix b/services/fediversity/garage/options.nix index ad3d555..c93534e 100644 --- a/services/fediversity/garage/options.nix +++ b/services/fediversity/garage/options.nix @@ -45,8 +45,8 @@ in types.submodule { # TODO: these should be managed as secrets, not in the nix store options = { - id = mkOption { type = types.str; }; - secret = mkOption { type = types.str; }; + s3AccessKey = mkOption { type = types.str; }; + s3SecretKey = mkOption { type = types.str; }; # TODO: assert at least one of these is true # NOTE: this currently needs to be done at the top level module ensureAccess = mkOption { diff --git a/services/fediversity/mastodon/default.nix b/services/fediversity/mastodon/default.nix index 083cf91..cd1846a 100644 --- a/services/fediversity/mastodon/default.nix +++ b/services/fediversity/mastodon/default.nix @@ -1,10 +1,3 @@ -let - snakeoil_key = { - id = "GK3515373e4c851ebaad366558"; - secret = "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34"; - }; -in - { config, lib, ... }: { @@ -24,9 +17,10 @@ in }; }; }; + ensureKeys = { mastodon = { - inherit (snakeoil_key) id secret; + inherit (config.fediversity.mastodon) s3AccessKey s3SecretKey; ensureAccess = { mastodon = { read = true; @@ -37,6 +31,7 @@ in }; }; }; + services.mastodon = { extraConfig = rec { S3_ENABLED = "true"; @@ -46,8 +41,8 @@ in S3_BUCKET = "mastodon"; # use <S3_BUCKET>.<S3_ENDPOINT> S3_OVERRIDE_PATH_STLE = "true"; - AWS_ACCESS_KEY_ID = snakeoil_key.id; - AWS_SECRET_ACCESS_KEY = snakeoil_key.secret; + AWS_ACCESS_KEY_ID = config.fediversity.mastodon.s3AccessKey; + AWS_SECRET_ACCESS_KEY = config.fediversity.mastodon.s3SecretKey; S3_PROTOCOL = "http"; S3_ALIAS_HOST = "${S3_BUCKET}.${config.fediversity.garage.web.rootDomain}"; # SEE: the last section in https://docs.joinmastodon.org/admin/optional/object-storage/ diff --git a/services/fediversity/mastodon/options.nix b/services/fediversity/mastodon/options.nix index 882b96e..16b148d 100644 --- a/services/fediversity/mastodon/options.nix +++ b/services/fediversity/mastodon/options.nix @@ -9,6 +9,23 @@ in options.fediversity.mastodon = { enable = mkEnableOption "Enable a Mastodon server on the machine"; + s3AccessKey = mkOption { + type = types.str; + description = '' + S3 access key + + In AWS CLI, this would be AWS_ACCESS_KEY_ID. + ''; + }; + + s3SecretKey = mkOption { + description = '' + S3 secret key + + In AWS CLI, this would be AWS_SECRET_ACCESS_KEY. + ''; + }; + domain = mkOption { type = types.str; description = "Internal option — change at your own risk"; diff --git a/services/fediversity/peertube/default.nix b/services/fediversity/peertube/default.nix index e649c56..cf7c620 100644 --- a/services/fediversity/peertube/default.nix +++ b/services/fediversity/peertube/default.nix @@ -1,10 +1,3 @@ -let - snakeoil_key = { - id = "GK1f9feea9960f6f95ff404c9b"; - secret = "7295c4201966a02c2c3d25b5cea4a5ff782966a2415e3a196f91924631191395"; - }; -in - { config, lib, ... }: { @@ -43,9 +36,10 @@ in }; }; }; + ensureKeys = { peertube = { - inherit (snakeoil_key) id secret; + inherit (config.fediversity.peertube) s3AccessKey s3SecretKey; ensureAccess = { peertube-videos = { read = true; @@ -104,8 +98,8 @@ in serviceEnvironmentFile = "/etc/peertube-env"; }; environment.etc.peertube-env.text = '' - AWS_ACCESS_KEY_ID=${snakeoil_key.id} - AWS_SECRET_ACCESS_KEY=${snakeoil_key.secret} + AWS_ACCESS_KEY_ID=${config.fediversity.peertube.s3AccessKey} + AWS_SECRET_ACCESS_KEY=${config.fediversity.peertube.s3SecretKey} ''; ## Proxying through Nginx diff --git a/services/fediversity/peertube/options.nix b/services/fediversity/peertube/options.nix index feedcad..b486437 100644 --- a/services/fediversity/peertube/options.nix +++ b/services/fediversity/peertube/options.nix @@ -9,6 +9,23 @@ in options.fediversity.peertube = { enable = mkEnableOption "Enable a PeerTube server on the machine"; + s3AccessKey = mkOption { + type = types.str; + description = '' + S3 access key + + In AWS CLI, this would be AWS_ACCESS_KEY_ID. + ''; + }; + + s3SecretKey = mkOption { + description = '' + S3 secret key + + In AWS CLI, this would be AWS_SECRET_ACCESS_KEY. + ''; + }; + domain = mkOption { type = types.str; description = "Internal option — change at your own risk"; diff --git a/services/fediversity/pixelfed/default.nix b/services/fediversity/pixelfed/default.nix index 4ce2887..e12a5e1 100644 --- a/services/fediversity/pixelfed/default.nix +++ b/services/fediversity/pixelfed/default.nix @@ -1,10 +1,3 @@ -let - snakeoil_key = { - id = "GKb5615457d44214411e673b7b"; - secret = "5be6799a88ca9b9d813d1a806b64f15efa49482dbe15339ddfaf7f19cf434987"; - }; -in - { config, lib, @@ -12,10 +5,14 @@ in ... }: +let + inherit (lib) mkIf; + +in { imports = [ ./options.nix ]; - config = lib.mkIf (config.fediversity.enable && config.fediversity.pixelfed.enable) { + config = mkIf (config.fediversity.enable && config.fediversity.pixelfed.enable) { fediversity.garage = { ensureBuckets = { pixelfed = { @@ -29,9 +26,10 @@ in }; }; }; + ensureKeys = { pixelfed = { - inherit (snakeoil_key) id secret; + inherit (config.fediversity.pixelfed) s3AccessKey s3SecretKey; ensureAccess = { pixelfed = { read = true; @@ -70,11 +68,10 @@ in ## `fediversity.openRegistration` option. OPEN_REGISTRATION = true; - # DANGEROUSLY_SET_FILESYSTEM_DRIVER = "s3"; FILESYSTEM_CLOUD = "s3"; PF_ENABLE_CLOUD = true; - AWS_ACCESS_KEY_ID = snakeoil_key.id; - AWS_SECRET_ACCESS_KEY = snakeoil_key.secret; + AWS_ACCESS_KEY_ID = config.fediversity.pixelfed.s3AccessKey; + AWS_SECRET_ACCESS_KEY = config.fediversity.pixelfed.s3SecretKey; AWS_DEFAULT_REGION = "garage"; AWS_URL = config.fediversity.garage.web.urlForBucket "pixelfed"; AWS_BUCKET = "pixelfed"; diff --git a/services/fediversity/pixelfed/options.nix b/services/fediversity/pixelfed/options.nix index 1a36ea2..27eff69 100644 --- a/services/fediversity/pixelfed/options.nix +++ b/services/fediversity/pixelfed/options.nix @@ -9,6 +9,23 @@ in options.fediversity.pixelfed = { enable = mkEnableOption "Enable a Pixelfed server on the machine"; + s3AccessKey = mkOption { + type = types.str; + description = '' + S3 access key + + In AWS CLI, this would be AWS_ACCESS_KEY_ID. + ''; + }; + + s3SecretKey = mkOption { + description = '' + S3 secret key + + In AWS CLI, this would be AWS_SECRET_ACCESS_KEY. + ''; + }; + domain = mkOption { type = types.str; description = "Internal option — change at your own risk"; From 8c5bf79ba274d28fc1f737e3c17ee3c7ccc1a2bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=E2=80=9CNiols=E2=80=9D=20Jeannerod?= <nicolas.jeannerod@moduscreate.com> Date: Fri, 14 Feb 2025 19:21:31 +0100 Subject: [PATCH 11/16] Share options that can be shared --- services/fediversity/mastodon/options.nix | 37 ++++------------ services/fediversity/peertube/options.nix | 51 ++++++++--------------- services/fediversity/pixelfed/options.nix | 37 ++++------------ services/fediversity/sharedOptions.nix | 38 +++++++++++++++++ 4 files changed, 71 insertions(+), 92 deletions(-) create mode 100644 services/fediversity/sharedOptions.nix diff --git a/services/fediversity/mastodon/options.nix b/services/fediversity/mastodon/options.nix index 16b148d..841284b 100644 --- a/services/fediversity/mastodon/options.nix +++ b/services/fediversity/mastodon/options.nix @@ -1,35 +1,14 @@ { config, lib, ... }: -let - inherit (lib) mkOption mkEnableOption; - inherit (lib.types) types; - -in { - options.fediversity.mastodon = { - enable = mkEnableOption "Enable a Mastodon server on the machine"; + options.fediversity.mastodon = + (import ../sharedOptions.nix { + inherit config lib; + serviceName = "mastodon"; + serviceDocName = "Mastodon"; + }) + // - s3AccessKey = mkOption { - type = types.str; - description = '' - S3 access key - - In AWS CLI, this would be AWS_ACCESS_KEY_ID. - ''; + { }; - - s3SecretKey = mkOption { - description = '' - S3 secret key - - In AWS CLI, this would be AWS_SECRET_ACCESS_KEY. - ''; - }; - - domain = mkOption { - type = types.str; - description = "Internal option — change at your own risk"; - default = "mastodon.${config.fediversity.domain}"; - }; - }; } diff --git a/services/fediversity/peertube/options.nix b/services/fediversity/peertube/options.nix index b486437..21eaa02 100644 --- a/services/fediversity/peertube/options.nix +++ b/services/fediversity/peertube/options.nix @@ -1,45 +1,28 @@ { config, lib, ... }: let - inherit (lib) mkOption mkEnableOption; + inherit (lib) mkOption; inherit (lib.types) types; in { - options.fediversity.peertube = { - enable = mkEnableOption "Enable a PeerTube server on the machine"; + options.fediversity.peertube = + (import ../sharedOptions.nix { + inherit config lib; + serviceName = "peertube"; + serviceDocName = "PeerTube"; + }) + // - s3AccessKey = mkOption { - type = types.str; - description = '' - S3 access key + { + secretsFile = mkOption { + type = types.path; + description = '' + Internal option — change at your own risk - In AWS CLI, this would be AWS_ACCESS_KEY_ID. - ''; + FIXME: should it be provided by NixOps4? + or maybe we should just ask for a main secret from which to derive all the others? + ''; + }; }; - - s3SecretKey = mkOption { - description = '' - S3 secret key - - In AWS CLI, this would be AWS_SECRET_ACCESS_KEY. - ''; - }; - - domain = mkOption { - type = types.str; - description = "Internal option — change at your own risk"; - default = "peertube.${config.fediversity.domain}"; - }; - - secretsFile = mkOption { - type = types.path; - description = '' - Internal option — change at your own risk - - FIXME: should it be provided by NixOps4? - or maybe we should just ask for a main secret from which to derive all the others? - ''; - }; - }; } diff --git a/services/fediversity/pixelfed/options.nix b/services/fediversity/pixelfed/options.nix index 27eff69..4248c01 100644 --- a/services/fediversity/pixelfed/options.nix +++ b/services/fediversity/pixelfed/options.nix @@ -1,35 +1,14 @@ { config, lib, ... }: -let - inherit (lib) mkOption mkEnableOption; - inherit (lib.types) types; - -in { - options.fediversity.pixelfed = { - enable = mkEnableOption "Enable a Pixelfed server on the machine"; + options.fediversity.pixelfed = + (import ../sharedOptions.nix { + inherit config lib; + serviceName = "pixelfed"; + serviceDocName = "Pixelfed"; + }) + // - s3AccessKey = mkOption { - type = types.str; - description = '' - S3 access key - - In AWS CLI, this would be AWS_ACCESS_KEY_ID. - ''; + { }; - - s3SecretKey = mkOption { - description = '' - S3 secret key - - In AWS CLI, this would be AWS_SECRET_ACCESS_KEY. - ''; - }; - - domain = mkOption { - type = types.str; - description = "Internal option — change at your own risk"; - default = "pixelfed.${config.fediversity.domain}"; - }; - }; } diff --git a/services/fediversity/sharedOptions.nix b/services/fediversity/sharedOptions.nix new file mode 100644 index 0000000..0d6317e --- /dev/null +++ b/services/fediversity/sharedOptions.nix @@ -0,0 +1,38 @@ +{ + config, + lib, + serviceName, + serviceDocName, +}: + +let + inherit (lib) mkOption mkEnableOption; + inherit (lib.types) types; + +in +{ + enable = mkEnableOption "Enable a ${serviceDocName} server on the machine"; + + s3AccessKey = mkOption { + type = types.str; + description = '' + S3 access key for ${serviceDocName}'s bucket/s + + In AWS CLI, this would be AWS_ACCESS_KEY_ID. + ''; + }; + + s3SecretKey = mkOption { + description = '' + S3 secret key for ${serviceDocName}'s bucket/s + + In AWS CLI, this would be AWS_SECRET_ACCESS_KEY. + ''; + }; + + domain = mkOption { + type = types.str; + description = "Internal option — change at your own risk"; + default = "${serviceName}.${config.fediversity.domain}"; + }; +} From 78a85b27ffe8c4765002ed107b30514eb169a782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=E2=80=9CNiols=E2=80=9D=20Jeannerod?= <nicolas.jeannerod@moduscreate.com> Date: Fri, 14 Feb 2025 19:46:12 +0100 Subject: [PATCH 12/16] Put the S3 secrets into files ...but not everywhere, there remains some FIXMEs where ultimately the secrets do get into the store. --- deployment/flake-part.nix | 54 ++++++++++++---------- services/fediversity/garage/default.nix | 6 +-- services/fediversity/garage/options.nix | 7 +-- services/fediversity/mastodon/default.nix | 55 ++++++++++++++--------- services/fediversity/peertube/default.nix | 15 +++++-- services/fediversity/pixelfed/default.nix | 11 ++--- services/fediversity/sharedOptions.nix | 10 +++-- 7 files changed, 96 insertions(+), 62 deletions(-) diff --git a/deployment/flake-part.nix b/deployment/flake-part.nix index d215a22..c903f8a 100644 --- a/deployment/flake-part.nix +++ b/deployment/flake-part.nix @@ -76,35 +76,41 @@ in providers = { inherit (inputs.nixops4.modules.nixops4Provider) local; }; resources = { - fedi101 = makeProcolixVmResource 101 { - fediversity = { - enable = true; - domain = "fedi101.abundos.eu"; - pixelfed = { + fedi101 = makeProcolixVmResource 101 ( + { pkgs, ... }: + { + fediversity = { enable = true; + domain = "fedi101.abundos.eu"; + pixelfed = { + enable = true; - ## NOTE: Only ever used for testing anyway. - s3AccessKey = "GKb5615457d44214411e673b7b"; - s3SecretKey = "5be6799a88ca9b9d813d1a806b64f15efa49482dbe15339ddfaf7f19cf434987"; + ## NOTE: Only ever used for testing anyway. + s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GKb5615457d44214411e673b7b"; + s3SecretKeyFile = pkgs.writeText "s3SecretKey" "5be6799a88ca9b9d813d1a806b64f15efa49482dbe15339ddfaf7f19cf434987"; + }; }; - }; - }; + } + ); - fedi102 = makeProcolixVmResource 102 { - fediversity = { - enable = true; - domain = "fedi102.abundos.eu"; - mastodon = { + fedi102 = makeProcolixVmResource 102 ( + { pkgs, ... }: + { + fediversity = { enable = true; + domain = "fedi102.abundos.eu"; + mastodon = { + enable = true; - ## NOTE: Only ever used for testing anyway. - s3AccessKey = "GK3515373e4c851ebaad366558"; - s3SecretKey = "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34"; + ## NOTE: Only ever used for testing anyway. + s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK3515373e4c851ebaad366558"; + s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34"; + }; + + temp.cores = 1; # FIXME: should come from NixOps4 eventually }; - - temp.cores = 1; # FIXME: should come from NixOps4 eventually - }; - }; + } + ); fedi103 = makeProcolixVmResource 103 ( { pkgs, ... }: @@ -117,8 +123,8 @@ in ## NOTE: Only ever used for testing anyway. secretsFile = pkgs.writeText "secret" "574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24"; - s3AccessKey = "GK1f9feea9960f6f95ff404c9b"; - s3SecretKey = "7295c4201966a02c2c3d25b5cea4a5ff782966a2415e3a196f91924631191395"; + s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK1f9feea9960f6f95ff404c9b"; + s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7295c4201966a02c2c3d25b5cea4a5ff782966a2415e3a196f91924631191395"; }; }; } diff --git a/services/fediversity/garage/default.nix b/services/fediversity/garage/default.nix index da0a7e4..6915cb5 100644 --- a/services/fediversity/garage/default.nix +++ b/services/fediversity/garage/default.nix @@ -83,13 +83,13 @@ let ensureKeyScriptFn = key: { - s3AccessKey, - s3SecretKey, + s3AccessKeyFile, + s3SecretKeyFile, ensureAccess, }: '' ## FIXME: Check whether the key exist and skip this step if that is the case. Get rid of this `|| :` - garage key import --yes -n ${escapeShellArg key} ${escapeShellArg s3AccessKey} ${escapeShellArg s3SecretKey} || : + garage key import --yes -n ${escapeShellArg key} $(cat ${escapeShellArg s3AccessKeyFile}) $(cat ${escapeShellArg s3SecretKeyFile}) || : ${concatMapAttrs (ensureAccessScriptFn key) ensureAccess} ''; diff --git a/services/fediversity/garage/options.nix b/services/fediversity/garage/options.nix index c93534e..baeda2c 100644 --- a/services/fediversity/garage/options.nix +++ b/services/fediversity/garage/options.nix @@ -43,10 +43,11 @@ in ensureKeys = mkOption { type = types.attrsOf ( types.submodule { - # TODO: these should be managed as secrets, not in the nix store options = { - s3AccessKey = mkOption { type = types.str; }; - s3SecretKey = mkOption { type = types.str; }; + s3AccessKeyFile = mkOption { type = types.path; }; + + s3SecretKeyFile = mkOption { type = types.path; }; + # TODO: assert at least one of these is true # NOTE: this currently needs to be done at the top level module ensureAccess = mkOption { diff --git a/services/fediversity/mastodon/default.nix b/services/fediversity/mastodon/default.nix index cd1846a..63e536d 100644 --- a/services/fediversity/mastodon/default.nix +++ b/services/fediversity/mastodon/default.nix @@ -1,5 +1,15 @@ -{ config, lib, ... }: +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib) readFile; + inherit (pkgs) writeText; + +in { imports = [ ./options.nix ]; @@ -20,7 +30,7 @@ ensureKeys = { mastodon = { - inherit (config.fediversity.mastodon) s3AccessKey s3SecretKey; + inherit (config.fediversity.mastodon) s3AccessKeyFile s3SecretKeyFile; ensureAccess = { mastodon = { read = true; @@ -32,26 +42,31 @@ }; }; - services.mastodon = { - extraConfig = rec { - S3_ENABLED = "true"; - # TODO: this shouldn't be hard-coded, it should come from the garage configuration - S3_ENDPOINT = config.fediversity.garage.api.url; - S3_REGION = "garage"; - S3_BUCKET = "mastodon"; - # use <S3_BUCKET>.<S3_ENDPOINT> - S3_OVERRIDE_PATH_STLE = "true"; - AWS_ACCESS_KEY_ID = config.fediversity.mastodon.s3AccessKey; - AWS_SECRET_ACCESS_KEY = config.fediversity.mastodon.s3SecretKey; - S3_PROTOCOL = "http"; - S3_ALIAS_HOST = "${S3_BUCKET}.${config.fediversity.garage.web.rootDomain}"; - # SEE: the last section in https://docs.joinmastodon.org/admin/optional/object-storage/ - # TODO: can we set up ACLs with garage? - S3_PERMISSION = ""; - }; + services.mastodon.extraConfig = rec { + S3_ENABLED = "true"; + # TODO: this shouldn't be hard-coded, it should come from the garage configuration + S3_ENDPOINT = config.fediversity.garage.api.url; + S3_REGION = "garage"; + S3_BUCKET = "mastodon"; + # use <S3_BUCKET>.<S3_ENDPOINT> + S3_OVERRIDE_PATH_STLE = "true"; + S3_PROTOCOL = "http"; + S3_ALIAS_HOST = config.fediversity.garage.web.domainForBucket S3_BUCKET; + # SEE: the last section in https://docs.joinmastodon.org/admin/optional/object-storage/ + # TODO: can we set up ACLs with garage? + S3_PERMISSION = ""; }; - #### mastodon setup + ## FIXME: secrets management; we should have a service that writes the + ## `.env` files based on all the secrets that we need to put there. + services.mastodon.extraEnvFiles = [ + (writeText "s3AccessKey" '' + AWS_ACCESS_KEY_ID=${readFile config.fediversity.mastodon.s3AccessKeyFile} + '') + (writeText "s3SecretKey" '' + AWS_SECRET_ACCESS_KEY=${readFile config.fediversity.mastodon.s3SecretKeyFile} + '') + ]; # open up access to the mastodon web interface. 80 is necessary if only for ACME networking.firewall.allowedTCPPorts = [ diff --git a/services/fediversity/peertube/default.nix b/services/fediversity/peertube/default.nix index cf7c620..3c18486 100644 --- a/services/fediversity/peertube/default.nix +++ b/services/fediversity/peertube/default.nix @@ -1,9 +1,13 @@ { config, lib, ... }: +let + inherit (lib) mkIf readFile; + +in { imports = [ ./options.nix ]; - config = lib.mkIf (config.fediversity.enable && config.fediversity.peertube.enable) { + config = mkIf (config.fediversity.enable && config.fediversity.peertube.enable) { networking.firewall.allowedTCPPorts = [ 80 443 @@ -39,7 +43,7 @@ ensureKeys = { peertube = { - inherit (config.fediversity.peertube) s3AccessKey s3SecretKey; + inherit (config.fediversity.peertube) s3AccessKeyFile s3SecretKeyFile; ensureAccess = { peertube-videos = { read = true; @@ -97,9 +101,12 @@ }; serviceEnvironmentFile = "/etc/peertube-env"; }; + + ## FIXME: secrets management; we should have a service that writes the + ## `.env` files based on all the secrets that we need to put there. environment.etc.peertube-env.text = '' - AWS_ACCESS_KEY_ID=${config.fediversity.peertube.s3AccessKey} - AWS_SECRET_ACCESS_KEY=${config.fediversity.peertube.s3SecretKey} + AWS_ACCESS_KEY_ID=${readFile config.fediversity.peertube.s3AccessKeyFile} + AWS_SECRET_ACCESS_KEY=${readFile config.fediversity.peertube.s3SecretKeyFile} ''; ## Proxying through Nginx diff --git a/services/fediversity/pixelfed/default.nix b/services/fediversity/pixelfed/default.nix index e12a5e1..b845d92 100644 --- a/services/fediversity/pixelfed/default.nix +++ b/services/fediversity/pixelfed/default.nix @@ -6,7 +6,7 @@ }: let - inherit (lib) mkIf; + inherit (lib) mkIf readFile; in { @@ -29,7 +29,7 @@ in ensureKeys = { pixelfed = { - inherit (config.fediversity.pixelfed) s3AccessKey s3SecretKey; + inherit (config.fediversity.pixelfed) s3AccessKeyFile s3SecretKeyFile; ensureAccess = { pixelfed = { read = true; @@ -45,9 +45,12 @@ in enable = true; domain = config.fediversity.pixelfed.domain; - # TODO: secrets management!!! + ## FIXME: secrets management; we should have a service that writes the + ## `.env` file based on all the secrets that we need to put there. secretFile = pkgs.writeText "secrets.env" '' APP_KEY=adKK9EcY8Hcj3PLU7rzG9rJ6KKTOtYfA + AWS_ACCESS_KEY_ID=${readFile config.fediversity.pixelfed.s3AccessKeyFile} + AWS_SECRET_ACCESS_KEY=${readFile config.fediversity.pixelfed.s3SecretKeyFile} ''; ## Taeer feels like this way of configuring Nginx is odd; there should @@ -70,8 +73,6 @@ in FILESYSTEM_CLOUD = "s3"; PF_ENABLE_CLOUD = true; - AWS_ACCESS_KEY_ID = config.fediversity.pixelfed.s3AccessKey; - AWS_SECRET_ACCESS_KEY = config.fediversity.pixelfed.s3SecretKey; AWS_DEFAULT_REGION = "garage"; AWS_URL = config.fediversity.garage.web.urlForBucket "pixelfed"; AWS_BUCKET = "pixelfed"; diff --git a/services/fediversity/sharedOptions.nix b/services/fediversity/sharedOptions.nix index 0d6317e..10ddd5c 100644 --- a/services/fediversity/sharedOptions.nix +++ b/services/fediversity/sharedOptions.nix @@ -1,3 +1,6 @@ +## NOTE: Not a module, but a helper function to create options for Fediversity +## services, as they tend to require the same ones. + { config, lib, @@ -13,8 +16,8 @@ in { enable = mkEnableOption "Enable a ${serviceDocName} server on the machine"; - s3AccessKey = mkOption { - type = types.str; + s3AccessKeyFile = mkOption { + type = types.path; description = '' S3 access key for ${serviceDocName}'s bucket/s @@ -22,7 +25,8 @@ in ''; }; - s3SecretKey = mkOption { + s3SecretKeyFile = mkOption { + type = types.path; description = '' S3 secret key for ${serviceDocName}'s bucket/s From a5d226ed224d0a08520a10935db6f25d046d1129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=E2=80=9CNiols=E2=80=9D=20Jeannerod?= <nicolas.jeannerod@moduscreate.com> Date: Fri, 14 Feb 2025 20:08:01 +0100 Subject: [PATCH 13/16] Get rid of `fediversity.enable` --- deployment/flake-part.nix | 3 --- services/fediversity/default.nix | 9 +-------- services/fediversity/garage/default.nix | 2 +- services/fediversity/mastodon/default.nix | 2 +- services/fediversity/peertube/default.nix | 2 +- services/fediversity/pixelfed/default.nix | 2 +- 6 files changed, 5 insertions(+), 15 deletions(-) diff --git a/deployment/flake-part.nix b/deployment/flake-part.nix index c903f8a..0eeba75 100644 --- a/deployment/flake-part.nix +++ b/deployment/flake-part.nix @@ -80,7 +80,6 @@ in { pkgs, ... }: { fediversity = { - enable = true; domain = "fedi101.abundos.eu"; pixelfed = { enable = true; @@ -97,7 +96,6 @@ in { pkgs, ... }: { fediversity = { - enable = true; domain = "fedi102.abundos.eu"; mastodon = { enable = true; @@ -116,7 +114,6 @@ in { pkgs, ... }: { fediversity = { - enable = true; domain = "fedi103.abundos.eu"; peertube = { enable = true; diff --git a/services/fediversity/default.nix b/services/fediversity/default.nix index 5147c8f..d935499 100644 --- a/services/fediversity/default.nix +++ b/services/fediversity/default.nix @@ -1,7 +1,7 @@ { lib, config, ... }: let - inherit (lib) mkOption mkEnableOption mkForce; + inherit (lib) mkOption; inherit (lib.types) types; in @@ -15,8 +15,6 @@ in options = { fediversity = { - enable = mkEnableOption "the collection of services bundled under Fediversity"; - domain = mkOption { type = types.str; description = '' @@ -50,10 +48,5 @@ in defaults.email = "nicolas.jeannerod+fediversity@moduscreate.com"; # defaults.server = "https://acme-staging-v02.api.letsencrypt.org/directory"; }; - - ## NOTE: For a one-machine deployment, this removes the need to provide an - ## `s3.garage.<domain>` domain. However, this will quickly stop working once - ## we go to multi-machines deployment. - fediversity.garage.api.domain = mkForce "s3.garage.localhost"; }; } diff --git a/services/fediversity/garage/default.nix b/services/fediversity/garage/default.nix index 6915cb5..e3a6012 100644 --- a/services/fediversity/garage/default.nix +++ b/services/fediversity/garage/default.nix @@ -99,7 +99,7 @@ in { imports = [ ./options.nix ]; - config = lib.mkIf config.fediversity.enable { + config = { environment.systemPackages = [ pkgs.minio-client pkgs.awscli diff --git a/services/fediversity/mastodon/default.nix b/services/fediversity/mastodon/default.nix index 63e536d..4fe5ef3 100644 --- a/services/fediversity/mastodon/default.nix +++ b/services/fediversity/mastodon/default.nix @@ -13,7 +13,7 @@ in { imports = [ ./options.nix ]; - config = lib.mkIf (config.fediversity.enable && config.fediversity.mastodon.enable) { + config = lib.mkIf config.fediversity.mastodon.enable { #### garage setup fediversity.garage = { ensureBuckets = { diff --git a/services/fediversity/peertube/default.nix b/services/fediversity/peertube/default.nix index 3c18486..cb46969 100644 --- a/services/fediversity/peertube/default.nix +++ b/services/fediversity/peertube/default.nix @@ -7,7 +7,7 @@ in { imports = [ ./options.nix ]; - config = mkIf (config.fediversity.enable && config.fediversity.peertube.enable) { + config = mkIf config.fediversity.peertube.enable { networking.firewall.allowedTCPPorts = [ 80 443 diff --git a/services/fediversity/pixelfed/default.nix b/services/fediversity/pixelfed/default.nix index b845d92..3198929 100644 --- a/services/fediversity/pixelfed/default.nix +++ b/services/fediversity/pixelfed/default.nix @@ -12,7 +12,7 @@ in { imports = [ ./options.nix ]; - config = mkIf (config.fediversity.enable && config.fediversity.pixelfed.enable) { + config = mkIf config.fediversity.pixelfed.enable { fediversity.garage = { ensureBuckets = { pixelfed = { From 1eeaa04df6d567ebd6964f5c424a2a278494d42a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=E2=80=9CNiols=E2=80=9D=20Jeannerod?= <nicolas.jeannerod@moduscreate.com> Date: Fri, 14 Feb 2025 20:10:55 +0100 Subject: [PATCH 14/16] Introduce `fediversity.garage.enable` --- deployment/flake-part.nix | 3 +++ services/fediversity/garage/default.nix | 4 ++-- services/fediversity/garage/options.nix | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/deployment/flake-part.nix b/deployment/flake-part.nix index 0eeba75..8560e9c 100644 --- a/deployment/flake-part.nix +++ b/deployment/flake-part.nix @@ -88,6 +88,7 @@ in s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GKb5615457d44214411e673b7b"; s3SecretKeyFile = pkgs.writeText "s3SecretKey" "5be6799a88ca9b9d813d1a806b64f15efa49482dbe15339ddfaf7f19cf434987"; }; + garage.enable = true; }; } ); @@ -104,6 +105,7 @@ in s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK3515373e4c851ebaad366558"; s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34"; }; + garage.enable = true; temp.cores = 1; # FIXME: should come from NixOps4 eventually }; @@ -123,6 +125,7 @@ in s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK1f9feea9960f6f95ff404c9b"; s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7295c4201966a02c2c3d25b5cea4a5ff782966a2415e3a196f91924631191395"; }; + garage.enable = true; }; } ); diff --git a/services/fediversity/garage/default.nix b/services/fediversity/garage/default.nix index e3a6012..4d7dc69 100644 --- a/services/fediversity/garage/default.nix +++ b/services/fediversity/garage/default.nix @@ -16,7 +16,7 @@ in let inherit (builtins) toString; - inherit (lib) optionalString concatStringsSep; + inherit (lib) optionalString concatStringsSep mkIf; inherit (lib.strings) escapeShellArg; inherit (lib.attrsets) filterAttrs mapAttrs'; concatMapAttrs = scriptFn: attrset: concatStringsSep "\n" (lib.mapAttrsToList scriptFn attrset); @@ -99,7 +99,7 @@ in { imports = [ ./options.nix ]; - config = { + config = mkIf config.fediversity.garage.enable { environment.systemPackages = [ pkgs.minio-client pkgs.awscli diff --git a/services/fediversity/garage/options.nix b/services/fediversity/garage/options.nix index baeda2c..e528158 100644 --- a/services/fediversity/garage/options.nix +++ b/services/fediversity/garage/options.nix @@ -6,6 +6,8 @@ in { options.fediversity.garage = { + enable = mkEnableOption "Enable a Garage server on the machine"; + ensureBuckets = mkOption { type = types.attrsOf ( types.submodule { From cd83536e2f36e8d9e6f8e0ff6efb66b9adbaf70e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=E2=80=9CNiols=E2=80=9D=20Jeannerod?= <nicolas.jeannerod@moduscreate.com> Date: Sat, 15 Feb 2025 11:19:10 +0100 Subject: [PATCH 15/16] Allow Garage and services to run on different machines --- deployment/flake-part.nix | 61 ++++--- services/fediversity/garage/default.nix | 12 +- services/fediversity/mastodon/default.nix | 157 +++++++++-------- services/fediversity/peertube/default.nix | 205 ++++++++++++---------- services/fediversity/pixelfed/default.nix | 151 ++++++++-------- services/fediversity/sharedOptions.nix | 12 +- services/tests/peertube.nix | 4 +- services/vm/garage-vm.nix | 2 + services/vm/mastodon-vm.nix | 9 +- services/vm/peertube-vm.nix | 7 +- services/vm/pixelfed-vm.nix | 15 +- 11 files changed, 359 insertions(+), 276 deletions(-) diff --git a/deployment/flake-part.nix b/deployment/flake-part.nix index 8560e9c..208aebb 100644 --- a/deployment/flake-part.nix +++ b/deployment/flake-part.nix @@ -71,24 +71,54 @@ in }; }; + ## NOTE: All of these secrets are publicly available in this source file + ## and will end up in the Nix store. We don't care as they are only ever + ## used for testing anyway. + pixelfedS3KeyConfig = + { pkgs, ... }: + { + s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GKb5615457d44214411e673b7b"; + s3SecretKeyFile = pkgs.writeText "s3SecretKey" "5be6799a88ca9b9d813d1a806b64f15efa49482dbe15339ddfaf7f19cf434987"; + }; + mastodonS3KeyConfig = + { pkgs, ... }: + { + s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK3515373e4c851ebaad366558"; + s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34"; + }; + peertubeS3KeyConfig = + { pkgs, ... }: + { + s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK1f9feea9960f6f95ff404c9b"; + s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7295c4201966a02c2c3d25b5cea4a5ff782966a2415e3a196f91924631191395"; + }; + in { providers = { inherit (inputs.nixops4.modules.nixops4Provider) local; }; resources = { + fedi100 = makeProcolixVmResource 100 ( + { pkgs, ... }: + { + fediversity = { + domain = "abundos.eu"; + garage.enable = true; + pixelfed = pixelfedS3KeyConfig { inherit pkgs; }; + mastodon = mastodonS3KeyConfig { inherit pkgs; }; + peertube = peertubeS3KeyConfig { inherit pkgs; }; + }; + } + ); + fedi101 = makeProcolixVmResource 101 ( { pkgs, ... }: { fediversity = { - domain = "fedi101.abundos.eu"; - pixelfed = { + domain = "abundos.eu"; + pixelfed = pixelfedS3KeyConfig { inherit pkgs; } // { enable = true; - - ## NOTE: Only ever used for testing anyway. - s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GKb5615457d44214411e673b7b"; - s3SecretKeyFile = pkgs.writeText "s3SecretKey" "5be6799a88ca9b9d813d1a806b64f15efa49482dbe15339ddfaf7f19cf434987"; }; - garage.enable = true; }; } ); @@ -97,15 +127,10 @@ in { pkgs, ... }: { fediversity = { - domain = "fedi102.abundos.eu"; - mastodon = { + domain = "abundos.eu"; + mastodon = mastodonS3KeyConfig { inherit pkgs; } // { enable = true; - - ## NOTE: Only ever used for testing anyway. - s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK3515373e4c851ebaad366558"; - s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34"; }; - garage.enable = true; temp.cores = 1; # FIXME: should come from NixOps4 eventually }; @@ -116,16 +141,12 @@ in { pkgs, ... }: { fediversity = { - domain = "fedi103.abundos.eu"; - peertube = { + domain = "abundos.eu"; + peertube = peertubeS3KeyConfig { inherit pkgs; } // { enable = true; - ## NOTE: Only ever used for testing anyway. secretsFile = pkgs.writeText "secret" "574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24"; - s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK1f9feea9960f6f95ff404c9b"; - s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7295c4201966a02c2c3d25b5cea4a5ff782966a2415e3a196f91924631191395"; }; - garage.enable = true; }; } ); diff --git a/services/fediversity/garage/default.nix b/services/fediversity/garage/default.nix index 4d7dc69..c8133b7 100644 --- a/services/fediversity/garage/default.nix +++ b/services/fediversity/garage/default.nix @@ -105,7 +105,15 @@ in pkgs.awscli ]; - networking.firewall.allowedTCPPorts = [ config.fediversity.garage.rpc.port ]; + ## REVIEW: Do we want to reverse proxy the RPC and API ports? In fact, + ## shouldn't we just get rid of RPC at all, we're not using it. + networking.firewall.allowedTCPPorts = [ + 80 + 443 + config.fediversity.garage.api.port + config.fediversity.garage.rpc.port + ]; + services.garage = { enable = true; package = pkgs.garage_0_9; @@ -126,6 +134,8 @@ in }; }; + services.nginx.enable = true; + ## Create a proxy from <bucket>.web.garage.<domain> to localhost:3902 for ## each bucket that has `website = true`. services.nginx.virtualHosts = diff --git a/services/fediversity/mastodon/default.nix b/services/fediversity/mastodon/default.nix index 4fe5ef3..8c022ea 100644 --- a/services/fediversity/mastodon/default.nix +++ b/services/fediversity/mastodon/default.nix @@ -6,96 +6,107 @@ }: let - inherit (lib) readFile; + inherit (lib) mkIf mkMerge readFile; inherit (pkgs) writeText; in { imports = [ ./options.nix ]; - config = lib.mkIf config.fediversity.mastodon.enable { - #### garage setup - fediversity.garage = { - ensureBuckets = { - mastodon = { - website = true; - corsRules = { - enable = true; - allowedHeaders = [ "*" ]; - allowedMethods = [ "GET" ]; - allowedOrigins = [ "*" ]; - }; - }; - }; - - ensureKeys = { - mastodon = { - inherit (config.fediversity.mastodon) s3AccessKeyFile s3SecretKeyFile; - ensureAccess = { + config = mkMerge [ + (mkIf + ( + config.fediversity.garage.enable + && config.fediversity.mastodon.s3AccessKeyFile != null + && config.fediversity.mastodon.s3SecretKeyFile != null + ) + { + fediversity.garage = { + ensureBuckets = { mastodon = { - read = true; - write = true; - owner = true; + website = true; + corsRules = { + enable = true; + allowedHeaders = [ "*" ]; + allowedMethods = [ "GET" ]; + allowedOrigins = [ "*" ]; + }; + }; + }; + + ensureKeys = { + mastodon = { + inherit (config.fediversity.mastodon) s3AccessKeyFile s3SecretKeyFile; + ensureAccess = { + mastodon = { + read = true; + write = true; + owner = true; + }; + }; }; }; }; + } + ) + + (mkIf config.fediversity.mastodon.enable { + + services.mastodon.extraConfig = rec { + S3_ENABLED = "true"; + # TODO: this shouldn't be hard-coded, it should come from the garage configuration + S3_ENDPOINT = config.fediversity.garage.api.url; + S3_REGION = "garage"; + S3_BUCKET = "mastodon"; + # use <S3_BUCKET>.<S3_ENDPOINT> + S3_OVERRIDE_PATH_STLE = "true"; + S3_PROTOCOL = "http"; + S3_ALIAS_HOST = config.fediversity.garage.web.domainForBucket S3_BUCKET; + # SEE: the last section in https://docs.joinmastodon.org/admin/optional/object-storage/ + # TODO: can we set up ACLs with garage? + S3_PERMISSION = ""; }; - }; - services.mastodon.extraConfig = rec { - S3_ENABLED = "true"; - # TODO: this shouldn't be hard-coded, it should come from the garage configuration - S3_ENDPOINT = config.fediversity.garage.api.url; - S3_REGION = "garage"; - S3_BUCKET = "mastodon"; - # use <S3_BUCKET>.<S3_ENDPOINT> - S3_OVERRIDE_PATH_STLE = "true"; - S3_PROTOCOL = "http"; - S3_ALIAS_HOST = config.fediversity.garage.web.domainForBucket S3_BUCKET; - # SEE: the last section in https://docs.joinmastodon.org/admin/optional/object-storage/ - # TODO: can we set up ACLs with garage? - S3_PERMISSION = ""; - }; + ## FIXME: secrets management; we should have a service that writes the + ## `.env` files based on all the secrets that we need to put there. + services.mastodon.extraEnvFiles = [ + (writeText "s3AccessKey" '' + AWS_ACCESS_KEY_ID=${readFile config.fediversity.mastodon.s3AccessKeyFile} + '') + (writeText "s3SecretKey" '' + AWS_SECRET_ACCESS_KEY=${readFile config.fediversity.mastodon.s3SecretKeyFile} + '') + ]; - ## FIXME: secrets management; we should have a service that writes the - ## `.env` files based on all the secrets that we need to put there. - services.mastodon.extraEnvFiles = [ - (writeText "s3AccessKey" '' - AWS_ACCESS_KEY_ID=${readFile config.fediversity.mastodon.s3AccessKeyFile} - '') - (writeText "s3SecretKey" '' - AWS_SECRET_ACCESS_KEY=${readFile config.fediversity.mastodon.s3SecretKeyFile} - '') - ]; + # open up access to the mastodon web interface. 80 is necessary if only for ACME + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; - # open up access to the mastodon web interface. 80 is necessary if only for ACME - networking.firewall.allowedTCPPorts = [ - 80 - 443 - ]; + services.mastodon = { + enable = true; - services.mastodon = { - enable = true; + localDomain = config.fediversity.mastodon.domain; + configureNginx = true; - localDomain = config.fediversity.mastodon.domain; - configureNginx = true; + # from the documentation: recommended is the amount of your CPU cores minus + # one. but it also must be a positive integer + streamingProcesses = lib.max 1 (config.fediversity.temp.cores - 1); - # from the documentation: recommended is the amount of your CPU cores minus - # one. but it also must be a positive integer - streamingProcesses = lib.max 1 (config.fediversity.temp.cores - 1); - - # TODO: configure a mailserver so this works - smtp = { - fromAddress = "noreply@${config.fediversity.mastodon.domain}"; - createLocally = false; + # TODO: configure a mailserver so this works + smtp = { + fromAddress = "noreply@${config.fediversity.mastodon.domain}"; + createLocally = false; + }; }; - }; - security.acme = { - acceptTerms = true; - preliminarySelfsigned = true; - # TODO: configure a mailserver so we can set up acme - # defaults.email = "test@example.com"; - }; - }; + security.acme = { + acceptTerms = true; + preliminarySelfsigned = true; + # TODO: configure a mailserver so we can set up acme + # defaults.email = "test@example.com"; + }; + }) + ]; } diff --git a/services/fediversity/peertube/default.nix b/services/fediversity/peertube/default.nix index cb46969..9fa86cf 100644 --- a/services/fediversity/peertube/default.nix +++ b/services/fediversity/peertube/default.nix @@ -1,124 +1,135 @@ { config, lib, ... }: let - inherit (lib) mkIf readFile; + inherit (lib) mkIf mkMerge readFile; in { imports = [ ./options.nix ]; - config = mkIf config.fediversity.peertube.enable { - networking.firewall.allowedTCPPorts = [ - 80 - 443 - - ## For Live streaming and Live streaming when RTMPS is enabled. - 1935 - 1936 - ]; - - fediversity.garage = { - ensureBuckets = { - peertube-videos = { - website = true; - # TODO: these are too broad, after getting everything works narrow it down to the domain we actually want - corsRules = { - enable = true; - allowedHeaders = [ "*" ]; - allowedMethods = [ "GET" ]; - allowedOrigins = [ "*" ]; - }; - }; - # TODO: these are too broad, after getting everything works narrow it down to the domain we actually want - peertube-playlists = { - website = true; - corsRules = { - enable = true; - allowedHeaders = [ "*" ]; - allowedMethods = [ "GET" ]; - allowedOrigins = [ "*" ]; - }; - }; - }; - - ensureKeys = { - peertube = { - inherit (config.fediversity.peertube) s3AccessKeyFile s3SecretKeyFile; - ensureAccess = { + config = mkMerge [ + (mkIf + ( + config.fediversity.garage.enable + && config.fediversity.peertube.s3AccessKeyFile != null + && config.fediversity.peertube.s3SecretKeyFile != null + ) + { + fediversity.garage = { + ensureBuckets = { peertube-videos = { - read = true; - write = true; - owner = true; + website = true; + # TODO: these are too broad, after getting everything works narrow it down to the domain we actually want + corsRules = { + enable = true; + allowedHeaders = [ "*" ]; + allowedMethods = [ "GET" ]; + allowedOrigins = [ "*" ]; + }; }; + # TODO: these are too broad, after getting everything works narrow it down to the domain we actually want peertube-playlists = { - read = true; - write = true; - owner = true; + website = true; + corsRules = { + enable = true; + allowedHeaders = [ "*" ]; + allowedMethods = [ "GET" ]; + allowedOrigins = [ "*" ]; + }; + }; + }; + + ensureKeys = { + peertube = { + inherit (config.fediversity.peertube) s3AccessKeyFile s3SecretKeyFile; + ensureAccess = { + peertube-videos = { + read = true; + write = true; + owner = true; + }; + peertube-playlists = { + read = true; + write = true; + owner = true; + }; + }; }; }; }; - }; - }; + } + ) - services.peertube = { - enable = true; - localDomain = config.fediversity.peertube.domain; + (mkIf config.fediversity.peertube.enable { + networking.firewall.allowedTCPPorts = [ + 80 + 443 - # TODO: in most of nixpkgs, these are true by default. upstream that unless there's a good reason not to. - redis.createLocally = true; - database.createLocally = true; + ## For Live streaming and Live streaming when RTMPS is enabled. + 1935 + 1936 + ]; - secrets.secretsFile = config.fediversity.peertube.secretsFile; + services.peertube = { + enable = true; + localDomain = config.fediversity.peertube.domain; - settings = { - object_storage = { - enabled = true; - endpoint = config.fediversity.garage.api.url; - region = "garage"; - upload_acl.public = null; # Garage does not support ACL - upload_acl.private = null; # Garage does not support ACL + # TODO: in most of nixpkgs, these are true by default. upstream that unless there's a good reason not to. + redis.createLocally = true; + database.createLocally = true; - # not supported by garage - # SEE: https://garagehq.deuxfleurs.fr/documentation/connect/apps/#peertube - proxy.proxyify_private_files = false; + secrets.secretsFile = config.fediversity.peertube.secretsFile; - web_videos = rec { - bucket_name = "peertube-videos"; - prefix = ""; - base_url = config.fediversity.garage.web.urlForBucket bucket_name; - }; - videos = rec { - bucket_name = "peertube-videos"; - prefix = ""; - base_url = config.fediversity.garage.web.urlForBucket bucket_name; - }; - streaming_playlists = rec { - bucket_name = "peertube-playlists"; - prefix = ""; - base_url = config.fediversity.garage.web.urlForBucket bucket_name; + settings = { + object_storage = { + enabled = true; + endpoint = config.fediversity.garage.api.url; + region = "garage"; + upload_acl.public = null; # Garage does not support ACL + upload_acl.private = null; # Garage does not support ACL + + # not supported by garage + # SEE: https://garagehq.deuxfleurs.fr/documentation/connect/apps/#peertube + proxy.proxyify_private_files = false; + + web_videos = rec { + bucket_name = "peertube-videos"; + prefix = ""; + base_url = config.fediversity.garage.web.urlForBucket bucket_name; + }; + videos = rec { + bucket_name = "peertube-videos"; + prefix = ""; + base_url = config.fediversity.garage.web.urlForBucket bucket_name; + }; + streaming_playlists = rec { + bucket_name = "peertube-playlists"; + prefix = ""; + base_url = config.fediversity.garage.web.urlForBucket bucket_name; + }; }; }; + serviceEnvironmentFile = "/etc/peertube-env"; }; - serviceEnvironmentFile = "/etc/peertube-env"; - }; - ## FIXME: secrets management; we should have a service that writes the - ## `.env` files based on all the secrets that we need to put there. - environment.etc.peertube-env.text = '' - AWS_ACCESS_KEY_ID=${readFile config.fediversity.peertube.s3AccessKeyFile} - AWS_SECRET_ACCESS_KEY=${readFile config.fediversity.peertube.s3SecretKeyFile} - ''; + ## FIXME: secrets management; we should have a service that writes the + ## `.env` files based on all the secrets that we need to put there. + environment.etc.peertube-env.text = '' + AWS_ACCESS_KEY_ID=${readFile config.fediversity.peertube.s3AccessKeyFile} + AWS_SECRET_ACCESS_KEY=${readFile config.fediversity.peertube.s3SecretKeyFile} + ''; - ## Proxying through Nginx + ## Proxying through Nginx - services.peertube = { - configureNginx = true; - listenWeb = 443; - enableWebHttps = true; - }; - services.nginx.virtualHosts.${config.services.peertube.localDomain} = { - forceSSL = true; - enableACME = true; - }; - }; + services.peertube = { + configureNginx = true; + listenWeb = 443; + enableWebHttps = true; + }; + services.nginx.virtualHosts.${config.services.peertube.localDomain} = { + forceSSL = true; + enableACME = true; + }; + }) + ]; } diff --git a/services/fediversity/pixelfed/default.nix b/services/fediversity/pixelfed/default.nix index 3198929..2c3c2b7 100644 --- a/services/fediversity/pixelfed/default.nix +++ b/services/fediversity/pixelfed/default.nix @@ -6,89 +6,100 @@ }: let - inherit (lib) mkIf readFile; + inherit (lib) mkIf mkMerge readFile; in { imports = [ ./options.nix ]; - config = mkIf config.fediversity.pixelfed.enable { - fediversity.garage = { - ensureBuckets = { - pixelfed = { - website = true; - # TODO: these are too broad, after getting everything works narrow it down to the domain we actually want - corsRules = { - enable = true; - allowedHeaders = [ "*" ]; - allowedMethods = [ "GET" ]; - allowedOrigins = [ "*" ]; - }; - }; - }; - - ensureKeys = { - pixelfed = { - inherit (config.fediversity.pixelfed) s3AccessKeyFile s3SecretKeyFile; - ensureAccess = { + config = mkMerge [ + (mkIf + ( + config.fediversity.garage.enable + && config.fediversity.pixelfed.s3AccessKeyFile != null + && config.fediversity.pixelfed.s3SecretKeyFile != null + ) + { + fediversity.garage = { + ensureBuckets = { pixelfed = { - read = true; - write = true; - owner = true; + website = true; + # TODO: these are too broad, after getting everything works narrow it down to the domain we actually want + corsRules = { + enable = true; + allowedHeaders = [ "*" ]; + allowedMethods = [ "GET" ]; + allowedOrigins = [ "*" ]; + }; + }; + }; + + ensureKeys = { + pixelfed = { + inherit (config.fediversity.pixelfed) s3AccessKeyFile s3SecretKeyFile; + ensureAccess = { + pixelfed = { + read = true; + write = true; + owner = true; + }; + }; }; }; }; + } + ) + + (mkIf config.fediversity.pixelfed.enable { + services.pixelfed = { + enable = true; + domain = config.fediversity.pixelfed.domain; + + ## FIXME: secrets management; we should have a service that writes the + ## `.env` file based on all the secrets that we need to put there. + secretFile = pkgs.writeText "secrets.env" '' + APP_KEY=adKK9EcY8Hcj3PLU7rzG9rJ6KKTOtYfA + AWS_ACCESS_KEY_ID=${readFile config.fediversity.pixelfed.s3AccessKeyFile} + AWS_SECRET_ACCESS_KEY=${readFile config.fediversity.pixelfed.s3SecretKeyFile} + ''; + + ## Taeer feels like this way of configuring Nginx is odd; there should + ## instead be a `services.pixefed.nginx.enable` option and the actual Nginx + ## configuration should be in `services.nginx`. See eg. `pretix`. + ## + ## TODO: If that indeed makes sense, upstream. + nginx = { + forceSSL = true; + enableACME = true; + # locations."/public/".proxyPass = "${config.fediversity.garage.web.urlForBucket "pixelfed"}/public/"; + }; }; - }; - services.pixelfed = { - enable = true; - domain = config.fediversity.pixelfed.domain; + services.pixelfed.settings = { + ## NOTE: This depends on the targets, eg. universities might want control + ## over who has an account. We probably want a universal + ## `fediversity.openRegistration` option. + OPEN_REGISTRATION = true; - ## FIXME: secrets management; we should have a service that writes the - ## `.env` file based on all the secrets that we need to put there. - secretFile = pkgs.writeText "secrets.env" '' - APP_KEY=adKK9EcY8Hcj3PLU7rzG9rJ6KKTOtYfA - AWS_ACCESS_KEY_ID=${readFile config.fediversity.pixelfed.s3AccessKeyFile} - AWS_SECRET_ACCESS_KEY=${readFile config.fediversity.pixelfed.s3SecretKeyFile} - ''; - - ## Taeer feels like this way of configuring Nginx is odd; there should - ## instead be a `services.pixefed.nginx.enable` option and the actual Nginx - ## configuration should be in `services.nginx`. See eg. `pretix`. - ## - ## TODO: If that indeed makes sense, upstream. - nginx = { - forceSSL = true; - enableACME = true; - # locations."/public/".proxyPass = "${config.fediversity.garage.web.urlForBucket "pixelfed"}/public/"; + FILESYSTEM_CLOUD = "s3"; + PF_ENABLE_CLOUD = true; + AWS_DEFAULT_REGION = "garage"; + AWS_URL = config.fediversity.garage.web.urlForBucket "pixelfed"; + AWS_BUCKET = "pixelfed"; + AWS_ENDPOINT = config.fediversity.garage.api.url; + AWS_USE_PATH_STYLE_ENDPOINT = false; }; - }; - services.pixelfed.settings = { - ## NOTE: This depends on the targets, eg. universities might want control - ## over who has an account. We probably want a universal - ## `fediversity.openRegistration` option. - OPEN_REGISTRATION = true; + ## Only ever run `pixelfed-data-setup` after `ensure-garage` has done its job. + ## Otherwise, everything crashed dramatically. + systemd.services.pixelfed-data-setup = { + after = [ "ensure-garage.service" ]; + }; - FILESYSTEM_CLOUD = "s3"; - PF_ENABLE_CLOUD = true; - AWS_DEFAULT_REGION = "garage"; - AWS_URL = config.fediversity.garage.web.urlForBucket "pixelfed"; - AWS_BUCKET = "pixelfed"; - AWS_ENDPOINT = config.fediversity.garage.api.url; - AWS_USE_PATH_STYLE_ENDPOINT = false; - }; - - ## Only ever run `pixelfed-data-setup` after `ensure-garage` has done its job. - ## Otherwise, everything crashed dramatically. - systemd.services.pixelfed-data-setup = { - after = [ "ensure-garage.service" ]; - }; - - networking.firewall.allowedTCPPorts = [ - 80 - 443 - ]; - }; + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; + }) + ]; } diff --git a/services/fediversity/sharedOptions.nix b/services/fediversity/sharedOptions.nix index 10ddd5c..413e2a7 100644 --- a/services/fediversity/sharedOptions.nix +++ b/services/fediversity/sharedOptions.nix @@ -17,21 +17,25 @@ in enable = mkEnableOption "Enable a ${serviceDocName} server on the machine"; s3AccessKeyFile = mkOption { - type = types.path; + type = types.nullOr types.path; description = '' S3 access key for ${serviceDocName}'s bucket/s - In AWS CLI, this would be AWS_ACCESS_KEY_ID. + In AWS CLI, this would be AWS_ACCESS_KEY_ID. The S3 bucket is only created + when non-`null`. ''; + default = null; }; s3SecretKeyFile = mkOption { - type = types.path; + type = types.nullOr types.path; description = '' S3 secret key for ${serviceDocName}'s bucket/s - In AWS CLI, this would be AWS_SECRET_ACCESS_KEY. + In AWS CLI, this would be AWS_SECRET_ACCESS_KEY. The S3 bucket is only + created when non-`null`. ''; + default = null; }; domain = mkOption { diff --git a/services/tests/peertube.nix b/services/tests/peertube.nix index 23b002f..2671138 100644 --- a/services/tests/peertube.nix +++ b/services/tests/peertube.nix @@ -197,8 +197,8 @@ pkgs.nixosTest { systemd.services.postgresql.serviceConfig.TimeoutSec = lib.mkForce 3600; environment.variables = { - AWS_ACCESS_KEY_ID = config.fediversity.garage.ensureKeys.peertube.id; - AWS_SECRET_ACCESS_KEY = config.fediversity.garage.ensureKeys.peertube.secret; + AWS_ACCESS_KEY_ID = "$(cat ${config.fediversity.peertube.s3AccessKeyFile})"; + AWS_SECRET_ACCESS_KEY = "$(cat ${config.fediversity.peertube.s3SecretKeyFile})"; PT_INITIAL_ROOT_PASSWORD = "testtest"; }; }; diff --git a/services/vm/garage-vm.nix b/services/vm/garage-vm.nix index 174d23c..8cad659 100644 --- a/services/vm/garage-vm.nix +++ b/services/vm/garage-vm.nix @@ -12,6 +12,8 @@ in { imports = [ (modulesPath + "/virtualisation/qemu-vm.nix") ]; + fediversity.garage.enable = true; + services.nginx.virtualHosts = let value = { diff --git a/services/vm/mastodon-vm.nix b/services/vm/mastodon-vm.nix index 5a9daf2..095f822 100644 --- a/services/vm/mastodon-vm.nix +++ b/services/vm/mastodon-vm.nix @@ -1,6 +1,7 @@ { modulesPath, lib, + pkgs, config, ... }: @@ -11,9 +12,13 @@ config = lib.mkMerge [ { fediversity = { - enable = true; domain = "localhost"; - mastodon.enable = true; + mastodon = { + enable = true; + + s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK3515373e4c851ebaad366558"; + s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34"; + }; temp.cores = config.virtualisation.cores; }; diff --git a/services/vm/peertube-vm.nix b/services/vm/peertube-vm.nix index 758d64b..7aedbc3 100644 --- a/services/vm/peertube-vm.nix +++ b/services/vm/peertube-vm.nix @@ -8,13 +8,12 @@ imports = [ (modulesPath + "/virtualisation/qemu-vm.nix") ]; fediversity = { - enable = true; domain = "localhost"; peertube = { enable = true; - secretsFile = pkgs.writeText "secret" '' - 574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24 - ''; + secretsFile = pkgs.writeText "secret" "574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24"; + s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK1f9feea9960f6f95ff404c9b"; + s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7295c4201966a02c2c3d25b5cea4a5ff782966a2415e3a196f91924631191395"; }; }; diff --git a/services/vm/pixelfed-vm.nix b/services/vm/pixelfed-vm.nix index 927d042..8c35aee 100644 --- a/services/vm/pixelfed-vm.nix +++ b/services/vm/pixelfed-vm.nix @@ -1,4 +1,9 @@ -{ lib, modulesPath, ... }: +{ + lib, + pkgs, + modulesPath, + ... +}: let inherit (lib) mkVMOverride; @@ -9,9 +14,13 @@ in imports = [ (modulesPath + "/virtualisation/qemu-vm.nix") ]; fediversity = { - enable = true; domain = "localhost"; - pixelfed.enable = true; + pixelfed = { + enable = true; + + s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GKb5615457d44214411e673b7b"; + s3SecretKeyFile = pkgs.writeText "s3SecretKey" "5be6799a88ca9b9d813d1a806b64f15efa49482dbe15339ddfaf7f19cf434987"; + }; }; services.pixelfed = { From 2ee563f5d9987e76b25dc7a7e08df964e27e8834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=E2=80=9CNiols=E2=80=9D=20Jeannerod?= <nicolas.jeannerod@moduscreate.com> Date: Sat, 15 Feb 2025 11:22:55 +0100 Subject: [PATCH 16/16] Fix Pixelfed --- services/fediversity/pixelfed/default.nix | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/services/fediversity/pixelfed/default.nix b/services/fediversity/pixelfed/default.nix index 2c3c2b7..7df5352 100644 --- a/services/fediversity/pixelfed/default.nix +++ b/services/fediversity/pixelfed/default.nix @@ -51,6 +51,14 @@ in ) (mkIf config.fediversity.pixelfed.enable { + ## NOTE: Pixelfed as packaged in nixpkgs has a permission issue that prevents Nginx + ## from being able to serving the images. We fix it here, but this should be + ## upstreamed. See https://github.com/NixOS/nixpkgs/issues/235147 + services.pixelfed.package = pkgs.pixelfed.overrideAttrs (old: { + patches = (old.patches or [ ]) ++ [ ./group-permissions.patch ]; + }); + users.users.nginx.extraGroups = [ "pixelfed" ]; + services.pixelfed = { enable = true; domain = config.fediversity.pixelfed.domain;