{
  config,
  lib,
  pkgs,
  ...
}:

let
  inherit (lib) mkIf mkMerge readFile;
  inherit (pkgs) writeText;

in
{
  imports = [ ./options.nix ];

  config = mkMerge [
    (mkIf
      (
        config.fediversity.garage.enable
        && config.fediversity.mastodon.s3AccessKeyFile != null
        && config.fediversity.mastodon.s3SecretKeyFile != null
      )
      {
        fediversity.garage = {
          ensureBuckets = {
            mastodon = {
              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 = "";
      };

      ## 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
      ];

      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";
      };
    })
  ];
}