diff --git a/services/fediversity/default.nix b/services/fediversity/default.nix index 0747e2d9..d643c8df 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. 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 f1638dfd..51910164 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 56fec596..ad3d5551 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 7486559a..1d0e8c63 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 . @@ -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 ae973c15..6105a7d3 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 6c2a3ebb..0b1be364 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 80ede0c5..61629aa7 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 c10e01a8..23b002f2 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 346ffe4b..fb658a3c 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 b115b51e..174d23c0 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; } ]; }