Loading nixos/doc/manual/redirects.json +15 −0 Original line number Diff line number Diff line Loading @@ -1544,6 +1544,21 @@ "module-services-emacs-man-pages": [ "index.html#module-services-emacs-man-pages" ], "module-services-ente": [ "index.html#module-services-ente" ], "module-services-ente-quickstart": [ "index.html#module-services-ente-quickstart" ], "module-services-ente-registering-users": [ "index.html#module-services-ente-registering-users" ], "module-services-ente-increasing-storage-limit": [ "index.html#module-services-ente-increasing-storage-limit" ], "module-services-ente-ios-background-sync": [ "index.html#module-services-ente-ios-background-sync" ], "module-services-livebook": [ "index.html#module-services-livebook" ], Loading nixos/modules/services/web-apps/ente.md +12 −54 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 Loading @@ -157,7 +115,7 @@ available. While adding new plans is possible in theory, it requires some manual database operations which isn't worthwhile. Instead, use `ente-cli` with your admin user to modify the storage limit. ## iOS background sync ## iOS background sync {#module-services-ente-ios-background-sync} On iOS, background sync is achived via a silent notification sent by the server every 30 minutes that allows the phone to sync for about 30 seconds, enough for Loading nixos/modules/services/web-apps/ente.nix +4 −1 Original line number Diff line number Diff line Loading @@ -359,5 +359,8 @@ in }) ]; meta.maintainers = with lib.maintainers; [ oddlama ]; meta = { doc = ./ente.md; maintainers = with lib.maintainers; [ oddlama ]; }; } 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 pkgs/by-name/en/ente-web/package.nix +48 −46 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ nodejs, rustPlatform, rustc, sd, wasm-bindgen-cli_0_2_108, wasm-pack, yarnConfigHook, Loading @@ -21,6 +22,7 @@ # can set this parameter to override these occurrences with your own url. Must include the schema. # Example: https://my-ente.example.com enteMainUrl ? null, nixosTests, }: stdenv.mkDerivation (finalAttrs: { Loading Loading @@ -81,16 +83,13 @@ stdenv.mkDerivation (finalAttrs: { packages/wasm/package.json \ --replace-fail "wasm-pack " ${lib.escapeShellArg "${wasm-pack}/bin/wasm-pack "} '' # Replace hardcoded ente.io urls if desired # Replace hardcoded links pointing to the public ente instance so that # users of a self-hosted instance are not accidentally redirected there + lib.optionalString (enteMainUrl != null) '' substituteInPlace \ apps/payments/src/services/billing.ts \ apps/photos/src/pages/shared-albums.tsx \ --replace-fail "https://ente.io" ${lib.escapeShellArg enteMainUrl} substituteInPlace \ apps/accounts/src/pages/index.tsx \ --replace-fail "https://web.ente.io" ${lib.escapeShellArg enteMainUrl} for pattern in "https://web.ente.io" "https://ente.com" "https://ente.io"; do mapfile -d "" -t files < <(grep -rlFZ -- "$pattern" apps/) ${lib.getExe sd} -F -- "$pattern" ${lib.escapeShellArg enteMainUrl} "''${files[@]}" done ''; yarnBuildScript = "build:${enteApp}"; Loading @@ -106,7 +105,9 @@ stdenv.mkDerivation (finalAttrs: { runHook postInstall ''; passthru.updateScript = writeScript "update-ente-web" '' passthru = { tests = { inherit (nixosTests) ente; }; updateScript = writeScript "update-ente-web" '' #!/usr/bin/env nix-shell #!nix-shell -i bash -p coreutils nix-update gnugrep gnused curl Loading Loading @@ -157,6 +158,7 @@ stdenv.mkDerivation (finalAttrs: { echo "Successfully updated wasm-bindgen-cli to $wasm_bindgen_attr" ''; }; meta = { description = "Ente application web frontends"; Loading Loading
nixos/doc/manual/redirects.json +15 −0 Original line number Diff line number Diff line Loading @@ -1544,6 +1544,21 @@ "module-services-emacs-man-pages": [ "index.html#module-services-emacs-man-pages" ], "module-services-ente": [ "index.html#module-services-ente" ], "module-services-ente-quickstart": [ "index.html#module-services-ente-quickstart" ], "module-services-ente-registering-users": [ "index.html#module-services-ente-registering-users" ], "module-services-ente-increasing-storage-limit": [ "index.html#module-services-ente-increasing-storage-limit" ], "module-services-ente-ios-background-sync": [ "index.html#module-services-ente-ios-background-sync" ], "module-services-livebook": [ "index.html#module-services-livebook" ], Loading
nixos/modules/services/web-apps/ente.md +12 −54 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 Loading @@ -157,7 +115,7 @@ available. While adding new plans is possible in theory, it requires some manual database operations which isn't worthwhile. Instead, use `ente-cli` with your admin user to modify the storage limit. ## iOS background sync ## iOS background sync {#module-services-ente-ios-background-sync} On iOS, background sync is achived via a silent notification sent by the server every 30 minutes that allows the phone to sync for about 30 seconds, enough for Loading
nixos/modules/services/web-apps/ente.nix +4 −1 Original line number Diff line number Diff line Loading @@ -359,5 +359,8 @@ in }) ]; meta.maintainers = with lib.maintainers; [ oddlama ]; meta = { doc = ./ente.md; maintainers = with lib.maintainers; [ oddlama ]; }; }
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
pkgs/by-name/en/ente-web/package.nix +48 −46 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ nodejs, rustPlatform, rustc, sd, wasm-bindgen-cli_0_2_108, wasm-pack, yarnConfigHook, Loading @@ -21,6 +22,7 @@ # can set this parameter to override these occurrences with your own url. Must include the schema. # Example: https://my-ente.example.com enteMainUrl ? null, nixosTests, }: stdenv.mkDerivation (finalAttrs: { Loading Loading @@ -81,16 +83,13 @@ stdenv.mkDerivation (finalAttrs: { packages/wasm/package.json \ --replace-fail "wasm-pack " ${lib.escapeShellArg "${wasm-pack}/bin/wasm-pack "} '' # Replace hardcoded ente.io urls if desired # Replace hardcoded links pointing to the public ente instance so that # users of a self-hosted instance are not accidentally redirected there + lib.optionalString (enteMainUrl != null) '' substituteInPlace \ apps/payments/src/services/billing.ts \ apps/photos/src/pages/shared-albums.tsx \ --replace-fail "https://ente.io" ${lib.escapeShellArg enteMainUrl} substituteInPlace \ apps/accounts/src/pages/index.tsx \ --replace-fail "https://web.ente.io" ${lib.escapeShellArg enteMainUrl} for pattern in "https://web.ente.io" "https://ente.com" "https://ente.io"; do mapfile -d "" -t files < <(grep -rlFZ -- "$pattern" apps/) ${lib.getExe sd} -F -- "$pattern" ${lib.escapeShellArg enteMainUrl} "''${files[@]}" done ''; yarnBuildScript = "build:${enteApp}"; Loading @@ -106,7 +105,9 @@ stdenv.mkDerivation (finalAttrs: { runHook postInstall ''; passthru.updateScript = writeScript "update-ente-web" '' passthru = { tests = { inherit (nixosTests) ente; }; updateScript = writeScript "update-ente-web" '' #!/usr/bin/env nix-shell #!nix-shell -i bash -p coreutils nix-update gnugrep gnused curl Loading Loading @@ -157,6 +158,7 @@ stdenv.mkDerivation (finalAttrs: { echo "Successfully updated wasm-bindgen-cli to $wasm_bindgen_attr" ''; }; meta = { description = "Ente application web frontends"; Loading