{ lib, pkgs, config, ... }: let inherit (lib) mkIf mkMerge; sources = import ../../../npins; inherit (import "${sources.nix-templating}/lib.nix" { inherit pkgs; nix_templater = pkgs.callPackage "${sources.nix-templating}/pkgs/nix_templater" { }; }) fileContents template_text ; in { imports = with sources; [ ./options.nix "${vars}/options.nix" "${vars}/backends/on-machine.nix" ]; config = mkMerge [ (mkIf ( config.fediversity.garage.enable && config.fediversity.attic.s3AccessKeyFile != null && config.fediversity.attic.s3SecretKeyFile != null ) { fediversity.garage = { ensureBuckets = { attic = { website = true; # TODO: these are too broad, after getting everything to work narrow it down to the domain we actually want corsRules = { enable = true; allowedHeaders = [ "*" ]; allowedMethods = [ "GET" ]; allowedOrigins = [ "*" ]; }; }; }; ensureKeys = { attic = { inherit (config.fediversity.attic) s3AccessKeyFile s3SecretKeyFile; ensureAccess = { peertube-videos = { read = true; write = true; owner = true; }; peertube-playlists = { read = true; write = true; owner = true; }; }; }; }; }; } ) (mkIf config.fediversity.attic.enable { services.postgresql = { enable = true; authentication = lib.mkForce '' local all all trust ''; ensureDatabases = [ "atticd" ]; ensureUsers = [ { name = "atticd"; ensureDBOwnership = true; } ]; }; # open up access to the mastodon web interface. 80 is necessary if only for ACME networking.firewall.allowedTCPPorts = [ 80 443 8080 ]; vars.generators.attic = { runtimeInputs = [ pkgs.openssl ]; files.token.secret = true; script = '' genrsa -traditional 4096 | base64 -w0 > $out/token ''; }; services.atticd = { enable = true; # one `monolithic` and any number of `api-server` nodes mode = "monolithic"; environmentFile = "${ template_text { name = "attic.env"; outPath = "./attic.env"; text = '' ATTIC_SERVER_TOKEN_RS256_SECRET_BASE64=${fileContents config.vars.generators.attic.files.token.path} AWS_ACCESS_KEY_ID=$(cat ${config.fediversity.peertube.s3AccessKeyFile}) AWS_SECRET_ACCESS_KEY=$(cat ${config.fediversity.peertube.s3SecretKeyFile}) ''; } }/bin/attic.env"; # https://github.com/zhaofengli/attic/blob/main/server/src/config-template.toml settings = { # Socket address to listen on # listen = "[::]:8080"; listen = "0.0.0.0:8080"; # listen = "127.0.0.1:8080"; # Allowed `Host` headers # # This _must_ be configured for production use. If unconfigured or the # list is empty, all `Host` headers are allowed. allowed-hosts = [ ]; # The canonical API endpoint of this server # # This is the endpoint exposed to clients in `cache-config` responses. # # This _must_ be configured for production use. If not configured, the # API endpoint is synthesized from the client's `Host` header which may # be insecure. # # The API endpoint _must_ end with a slash (e.g., `https://domain.tld/attic/` # not `https://domain.tld/attic`). api-endpoint = "https://${config.fediversity.attic.domain}/"; # Whether to soft-delete caches # # If this is enabled, caches are soft-deleted instead of actually # removed from the database. Note that soft-deleted caches cannot # have their names reused as long as the original database records # are there. #soft-delete-caches = false; # Whether to require fully uploading a NAR if it exists in the global cache. # # If set to false, simply knowing the NAR hash is enough for # an uploader to gain access to an existing NAR in the global # cache. #require-proof-of-possession = true; # Database connection database = { # Connection URL # # For production use it's recommended to use PostgreSQL. # url = "postgresql:///atticd:password@127.0.0.1:5432/atticd"; url = "postgresql:///atticd?host=/run/postgresql"; # Whether to enable sending on periodic heartbeat queries # # If enabled, a heartbeat query will be sent every minute #heartbeat = false; }; # File storage configuration storage = { # Storage type # # Can be "local" or "s3". type = "s3"; # ## Local storage # The directory to store all files under # path = "%storage_path%"; # ## S3 Storage (set type to "s3" and uncomment below) # The AWS region region = "garage"; # The name of the bucket bucket = "attic"; # Custom S3 endpoint # # Set this if you are using an S3-compatible object storage (e.g., Minio). endpoint = config.fediversity.garage.api.url; # Credentials # # If unset, the credentials are read from the `AWS_ACCESS_KEY_ID` and # `AWS_SECRET_ACCESS_KEY` environment variables. # storage.credentials = { # access_key_id = ""; # secret_access_key = ""; # }; }; # Data chunking # # Warning: If you change any of the values here, it will be # difficult to reuse existing chunks for newly-uploaded NARs # since the cutpoints will be different. As a result, the # deduplication ratio will suffer for a while after the change. chunking = { # The minimum NAR size to trigger chunking # # If 0, chunking is disabled entirely for newly-uploaded NARs. # If 1, all NARs are chunked. nar-size-threshold = 65536; # chunk files that are 64 KiB or larger # The preferred minimum size of a chunk, in bytes min-size = 16384; # 16 KiB # The preferred average size of a chunk, in bytes avg-size = 65536; # 64 KiB # The preferred maximum size of a chunk, in bytes max-size = 262144; # 256 KiB }; # Compression compression = { # Compression type # # Can be "none", "brotli", "zstd", or "xz" type = "zstd"; # Compression level #level = 8; }; # Garbage collection garbage-collection = { # The frequency to run garbage collection at # # By default it's 12 hours. You can use natural language # to specify the interval, like "1 day". # # If zero, automatic garbage collection is disabled, but # it can still be run manually with `atticd --mode garbage-collector-once`. interval = "12 hours"; # Default retention period # # Zero (default) means time-based garbage-collection is # disabled by default. You can enable it on a per-cache basis. #default-retention-period = "6 months"; }; jwt = { # WARNING: Changing _anything_ in this section will break any existing # tokens. If you need to regenerate them, ensure that you use the the # correct secret and include the `iss` and `aud` claims. # JWT `iss` claim # # Set this to the JWT issuer that you want to validate. # If this is set, all received JWTs will validate that the `iss` claim # matches this value. #token-bound-issuer = "some-issuer"; # JWT `aud` claim # # Set this to the JWT audience(s) that you want to validate. # If this is set, all received JWTs will validate that the `aud` claim # contains at least one of these values. #token-bound-audiences = ["some-audience1", "some-audience2"]; }; # jwt.signing = { # # JWT RS256 secret key # # # # Set this to the base64-encoded private half of an RSA PEM PKCS1 key. # # TODO # # You can also set it via the `ATTIC_SERVER_TOKEN_RS256_SECRET_BASE64` # # environment variable. # token-rs256-secret-base64 = "%token_rs256_secret_base64%"; # # JWT HS256 secret key # # # # Set this to the base64-encoded HMAC secret key. # # You can also set it via the `ATTIC_SERVER_TOKEN_HS256_SECRET_BASE64` # # environment variable. # #token-hs256-secret-base64 = ""; # }; }; }; }) ]; }