diff --git a/nixos/modules/services/web-apps/ente.md b/nixos/modules/services/web-apps/ente.md index 95763301fc3d..cb623db653cd 100644 --- a/nixos/modules/services/web-apps/ente.md +++ b/nixos/modules/services/web-apps/ente.md @@ -6,57 +6,20 @@ end-to-end encrypted platform for photos and videos. ## Quickstart {#module-services-ente-quickstart} To host ente, you need the following things: -- S3 storage server (either external or self-hosted like [minio](https://github.com/minio/minio)) +- An S3-compatible object storage server (either an external provider or a + self-hosted one such as [garage](#module-services-garage)). From your + storage provider you will need: + - the S3 endpoint URL + - a bucket name + - an access key ID and secret access key with read/write access to the bucket - Several subdomains pointing to your server: - accounts.example.com - albums.example.com - api.example.com - cast.example.com - photos.example.com - - s3.example.com -The following example shows how to setup ente with a self-hosted S3 storage via minio. -You can host the minio s3 storage on the same server as ente, but as this isn't -a requirement the example shows the minio and ente setup separately. -We assume that the minio server will be reachable at `https://s3.example.com`. - -```nix -{ - services.minio = { - enable = true; - # ente's config must match this region! - region = "us-east-1"; - # Please use a file, agenix or sops-nix to securely store your root user password! - # MINIO_ROOT_USER=your_root_user - # MINIO_ROOT_PASSWORD=a_randomly_generated_long_password - rootCredentialsFile = "/run/secrets/minio-credentials-full"; - }; - - systemd.services.minio.environment.MINIO_SERVER_URL = "https://s3.example.com"; - - # Proxy for minio - networking.firewall.allowedTCPPorts = [ - 80 - 443 - ]; - services.nginx = { - recommendedProxySettings = true; - virtualHosts."s3.example.com" = { - forceSSL = true; - useACME = true; - locations."/".proxyPass = "http://localhost:9000"; - # determine max file upload size - extraConfig = '' - client_max_body_size 16G; - proxy_buffering off; - proxy_request_buffering off; - ''; - }; - }; -} -``` - -And the configuration for ente: +Once you have an S3 endpoint, bucket and credentials, configure ente as follows: ```nix { @@ -84,11 +47,13 @@ And the configuration for ente: s3 = { use_path_style_urls = true; b2-eu-cen = { + # The S3 endpoint, bucket and credentials from your storage provider endpoint = "https://s3.example.com"; + # Must be us-east-1 as it is required internally by ente region = "us-east-1"; bucket = "ente"; - key._secret = pkgs.writeText "minio_user" "minio_user"; - secret._secret = pkgs.writeText "minio_pw" "minio_pw"; + key._secret = "/run/secrets/s3-access-key-id"; + secret._secret = "/run/secrets/s3-secret-access-key"; }; }; key = { @@ -122,13 +87,6 @@ If you have a mail server or smtp relay, you can optionally configure `services.ente.api.settings.smtp` so ente can send you emails (registration code and possibly other events). This is optional. -After starting the minio server, make sure the bucket exists: - -``` -mc alias set minio https://s3.example.com root_user root_password --api s3v4 -mc mb -p minio/ente -``` - Now ente should be ready to go under `https://photos.example.com`. ## Registering users {#module-services-ente-registering-users} diff --git a/nixos/tests/ente/default.nix b/nixos/tests/ente/default.nix index cdc30bda0fa1..fc9ad93eaacf 100644 --- a/nixos/tests/ente/default.nix +++ b/nixos/tests/ente/default.nix @@ -1,11 +1,7 @@ { lib, pkgs, ... }: let - accessKey = "BKIKJAA5BMMU2RHO6IBB"; - secretKey = "V7f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12"; - rootCredentialsFile = pkgs.writeText "minio-credentials-full" '' - MINIO_ROOT_USER=${accessKey} - MINIO_ROOT_PASSWORD=${secretKey} - ''; + garageAccessKey = "GKaaaaaaaaaaaaaaaaaaaaaaaa"; + garageSecretKey = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; certs = import ./snakeoil-certs.nix; domain = certs.domain; @@ -14,22 +10,29 @@ in name = "ente"; meta.maintainers = [ lib.maintainers.oddlama ]; - nodes.minio = + nodes.garage = { ... }: { - environment.systemPackages = [ pkgs.minio-client ]; - services.minio = { + services.garage = { enable = true; - inherit rootCredentialsFile; + package = pkgs.garage_2; + settings = { + replication_factor = 1; + consistency_mode = "consistent"; + rpc_bind_addr = "[::]:3901"; + rpc_public_addr = "[::1]:3901"; + rpc_secret = "5c1915fa04d0b6739675c61bf5907eb0fe3d9c69850c83820f51b4d25d13868c"; + s3_api = { + s3_region = "us-east-1"; + api_bind_addr = "[::]:3900"; + }; + }; }; - networking.firewall.allowedTCPPorts = [ - 9000 - ]; + networking.firewall.allowedTCPPorts = [ 3900 ]; - systemd.services.minio.environment = { - MINIO_SERVER_URL = "https://s3.${domain}"; - }; + # Garage requires at least 1GiB of free disk space to run. + virtualisation.diskSize = 2 * 1024; }; nodes.ente = @@ -71,7 +74,7 @@ in forceSSL = true; sslCertificate = certs.${domain}.cert; sslCertificateKey = certs.${domain}.key; - locations."/".proxyPass = "http://${nodes.minio.networking.primaryIPAddress}:9000"; + locations."/".proxyPass = "http://${nodes.garage.networking.primaryIPAddress}:3900"; extraConfig = '' client_max_body_size 32M; proxy_buffering off; @@ -103,8 +106,8 @@ in endpoint = "https://s3.${domain}"; region = "us-east-1"; bucket = "ente"; - key._secret = pkgs.writeText "accesskey" accessKey; - secret._secret = pkgs.writeText "secretkey" secretKey; + key._secret = pkgs.writeText "accesskey" garageAccessKey; + secret._secret = pkgs.writeText "secretkey" garageSecretKey; }; }; key = { @@ -118,13 +121,19 @@ in }; testScript = '' - minio.start() - minio.wait_for_unit("minio.service") - minio.wait_for_open_port(9000) + garage.start() + garage.wait_for_unit("garage.service") + garage.wait_for_open_port(3900) - # Create a test bucket on the server - minio.succeed("mc alias set minio http://localhost:9000 ${accessKey} ${secretKey} --api s3v4") - minio.succeed("mc mb -p minio/ente") + # Configure the cluster layout + garage_node_id = garage.succeed("garage status | tail -n1 | awk '{ print $1 }'") + garage.succeed(f"garage layout assign -c 1G -z garage {garage_node_id}") + garage.succeed("garage layout apply --version 1") + + # Import the predefined API key and create the bucket + garage.succeed("garage key import ${garageAccessKey} ${garageSecretKey} --yes") + garage.succeed("garage bucket create ente") + garage.succeed("garage bucket allow --read --write ente --key ${garageAccessKey}") # Start ente ente.start()