From b40ea721bda1b702dfcfc9514ce326361048f3fc Mon Sep 17 00:00:00 2001 From: Leendert de Borst Date: Fri, 24 Apr 2026 15:48:31 +0200 Subject: [PATCH] Make server max accepted upload size configurable (#1786) --- .env.example | 5 +++++ apps/server/AliasVault.Api/Program.cs | 15 +++++++++++++++ .../AliasVault.Api/Properties/launchSettings.json | 6 ++++-- apps/server/entrypoint.sh | 5 +++++ apps/server/nginx-443.conf | 3 ++- apps/server/nginx-80-443.conf | 3 ++- install.sh | 6 ++++++ 7 files changed, 39 insertions(+), 4 deletions(-) diff --git a/.env.example b/.env.example index 1f6c2216a..5834faa3d 100644 --- a/.env.example +++ b/.env.example @@ -106,3 +106,8 @@ IP_LOGGING_ENABLED=true # Set the support email address which is shown to users in the main web app. # Keep this blank if you don't want to show a support email. SUPPORT_EMAIL= + +# Maximum upload size in megabytes for client-to-server requests (vault sync, +# API uploads, etc.). Increase if you run into "413 Request Entity Too Large" +# errors when syncing large vaults. Defaults to 100MB. +MAX_UPLOAD_SIZE_MB=100 diff --git a/apps/server/AliasVault.Api/Program.cs b/apps/server/AliasVault.Api/Program.cs index 6da98ce12..0024b0b21 100644 --- a/apps/server/AliasVault.Api/Program.cs +++ b/apps/server/AliasVault.Api/Program.cs @@ -23,6 +23,7 @@ using AliasVault.Shared.Server.Services; using AliasVault.Shared.Server.Utilities; using Asp.Versioning; using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; @@ -57,6 +58,20 @@ config.HiddenPrivateEmailDomains = hiddenPrivateEmailDomains?.ToList() ?? new Li var ipLoggingEnabled = Environment.GetEnvironmentVariable("IP_LOGGING_ENABLED") ?? "false"; config.IpLoggingEnabled = bool.Parse(ipLoggingEnabled); +// Configure maximum upload size (applies to vault syncs and any other client uploads). +var maxUploadSizeMb = int.TryParse(Environment.GetEnvironmentVariable("MAX_UPLOAD_SIZE_MB"), out var parsedMb) && parsedMb > 0 ? parsedMb : 100; +var maxUploadSizeBytes = (long)maxUploadSizeMb * 1024 * 1024; + +builder.WebHost.ConfigureKestrel(options => +{ + options.Limits.MaxRequestBodySize = maxUploadSizeBytes; +}); + +builder.Services.Configure(options => +{ + options.MultipartBodyLengthLimit = maxUploadSizeBytes; +}); + builder.Services.AddSingleton(config); builder.Services.AddSingleton(sp => sp.GetRequiredService()); diff --git a/apps/server/AliasVault.Api/Properties/launchSettings.json b/apps/server/AliasVault.Api/Properties/launchSettings.json index 0fe4f8535..b638e8ba2 100644 --- a/apps/server/AliasVault.Api/Properties/launchSettings.json +++ b/apps/server/AliasVault.Api/Properties/launchSettings.json @@ -11,7 +11,8 @@ "PUBLIC_REGISTRATION_ENABLED": "true", "PRIVATE_EMAIL_DOMAINS": "example.tld,example2.tld,disabled.tld", "HIDDEN_PRIVATE_EMAIL_DOMAINS": "disabled.tld", - "IP_LOGGING_ENABLED": "true" + "IP_LOGGING_ENABLED": "true", + "MAX_UPLOAD_SIZE_MB": "1" }, "dotnetRunMessages": true, "applicationUrl": "http://0.0.0.0:5092" @@ -27,7 +28,8 @@ "PUBLIC_REGISTRATION_ENABLED": "true", "PRIVATE_EMAIL_DOMAINS": "example.tld,example2.tld,disabled.tld", "HIDDEN_PRIVATE_EMAIL_DOMAINS": "disabled.tld", - "IP_LOGGING_ENABLED": "true" + "IP_LOGGING_ENABLED": "true", + "MAX_UPLOAD_SIZE_MB": "100" }, "dotnetRunMessages": true, "applicationUrl": "https://0.0.0.0:7223" diff --git a/apps/server/entrypoint.sh b/apps/server/entrypoint.sh index 7a0c885bb..34c54806e 100644 --- a/apps/server/entrypoint.sh +++ b/apps/server/entrypoint.sh @@ -14,6 +14,11 @@ else cp /etc/nginx/nginx-443.conf /etc/nginx/nginx.conf fi +# Substitute MAX_UPLOAD_SIZE placeholder in the active nginx config. +# Default to 100MB when unset (suitable for all-in-one images without explicit config). +MAX_UPLOAD_SIZE_MB_VALUE="${MAX_UPLOAD_SIZE_MB:-100}" +sed -i "s|__MAX_UPLOAD_SIZE__|${MAX_UPLOAD_SIZE_MB_VALUE}|g" /etc/nginx/nginx.conf + # Function to check if certificate needs regeneration needs_cert_regeneration() { # If cert doesn't exist, need to generate diff --git a/apps/server/nginx-443.conf b/apps/server/nginx-443.conf index 69af1f4aa..eb9189af3 100644 --- a/apps/server/nginx-443.conf +++ b/apps/server/nginx-443.conf @@ -6,7 +6,8 @@ events { } http { - client_max_body_size 25M; + # Placeholder replaced at container startup by entrypoint.sh based on MAX_UPLOAD_SIZE_MB (default 100). + client_max_body_size __MAX_UPLOAD_SIZE__M; upstream client { server client:3000 max_fails=1 fail_timeout=5s; diff --git a/apps/server/nginx-80-443.conf b/apps/server/nginx-80-443.conf index 23dad877d..c5023fc8e 100644 --- a/apps/server/nginx-80-443.conf +++ b/apps/server/nginx-80-443.conf @@ -6,7 +6,8 @@ events { } http { - client_max_body_size 25M; + # Placeholder replaced at container startup by entrypoint.sh based on MAX_UPLOAD_SIZE_MB (default 100). + client_max_body_size __MAX_UPLOAD_SIZE__M; upstream client { server client:3000 max_fails=1 fail_timeout=5s; diff --git a/install.sh b/install.sh index 1dd3a9866..41f5bd782 100755 --- a/install.sh +++ b/install.sh @@ -3368,6 +3368,12 @@ check_and_populate_env() { if ! grep -q "^SMTP_ADVERTISED_HOSTNAME=" "$ENV_FILE" 2>/dev/null; then update_env_var "SMTP_ADVERTISED_HOSTNAME" "" fi + + # MAX_UPLOAD_SIZE_MB + if ! grep -q "^MAX_UPLOAD_SIZE_MB=" "$ENV_FILE" 2>/dev/null; then + update_env_var "MAX_UPLOAD_SIZE_MB" "100" + printf " Set MAX_UPLOAD_SIZE_MB\n" + fi } main "$@"