let
  snakeoil_key = {
    id = "GK3515373e4c851ebaad366558";
    secret = "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34";
  };
in

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

lib.mkIf (config.fediversity.enable && config.fediversity.mastodon.enable) {
 #### garage setup
  services.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.internal.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_HOSTNAME = config.fediversity.internal.garage.web.rootDomain;
      # by default it tries to use "<S3_HOSTNAME>/<S3_BUCKET>"
      S3_ALIAS_HOST = "${S3_BUCKET}.${S3_HOSTNAME}";
      # 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
  networking.firewall.allowedTCPPorts = [ 443 ];

  services.mastodon = {
    enable = true;

    localDomain = config.fediversity.internal.mastodon.domain;
    configureNginx = true;

    # TODO: configure a mailserver so this works
    smtp = {
      fromAddress = "noreply@${config.fediversity.internal.mastodon.domain}";
      createLocally = false;
    };

    # TODO: this is hardware-dependent. let's figure it out when we have hardware
    # streamingProcesses = 1;
  };

  security.acme = {
    acceptTerms = true;
    preliminarySelfsigned = true;
    # TODO: configure a mailserver so we can set up acme
    # defaults.email = "test@example.com";
  };
}