Loading nixos/modules/services/web-apps/ente.md +11 −53 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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 = { Loading Loading @@ -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} Loading nixos/tests/ente/default.nix +34 −25 Original line number Diff line number Diff line { 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; Loading @@ -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 = Loading Loading @@ -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; Loading Loading @@ -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 = { Loading @@ -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) # 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") # 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") # 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() Loading Loading
nixos/modules/services/web-apps/ente.md +11 −53 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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 = { Loading Loading @@ -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} Loading
nixos/tests/ente/default.nix +34 −25 Original line number Diff line number Diff line { 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; Loading @@ -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 = Loading Loading @@ -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; Loading Loading @@ -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 = { Loading @@ -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) # 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") # 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") # 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() Loading