feat: add max file size env providing customizable limitation

This commit is contained in:
Benebo7 2026-07-30 00:05:07 -03:00
parent e4e5016948
commit 5ef02cdecc
7 changed files with 20 additions and 7 deletions

View file

@ -93,6 +93,10 @@ CERT_EMAIL=
# If a CDN/load balancer sits in front of Caddy, narrow this to that proxy's CIDRs.
# TRUSTED_PROXIES=0.0.0.0/0
# SURFSENSE_MAX_BODY_SIZE=5GB
# Per-file cap for authenticated document uploads (MB). Keep it at or below
# SURFSENSE_MAX_BODY_SIZE above, which limits the whole request at the proxy.
# Passed to both the backend (enforcement) and the frontend (pre-upload check).
# MAX_FILE_SIZE_MB=500
#
# Browser API and Zero URLs are same-origin relative behind bundled Caddy.
# Next.js server-side calls use Docker DNS through SURFSENSE_BACKEND_INTERNAL_URL

View file

@ -127,6 +127,7 @@ services:
- NEXT_FRONTEND_URL=${NEXT_FRONTEND_URL:-http://localhost:3000}
- WHATSAPP_BRIDGE_URL=${WHATSAPP_BRIDGE_URL:-http://whatsapp-bridge:9929}
- SEARXNG_URL=${SEARXNG_URL:-http://searxng:8080}
- MAX_FILE_SIZE_MB=${MAX_FILE_SIZE_MB:-500}
# Daytona Sandbox uncomment and set credentials to enable cloud code execution
# - DAYTONA_SANDBOX_ENABLED=TRUE
# - DAYTONA_API_KEY=${DAYTONA_API_KEY:-}
@ -268,6 +269,7 @@ services:
ETL_SERVICE: ${ETL_SERVICE:-DOCLING}
DEPLOYMENT_MODE: ${DEPLOYMENT_MODE:-self-hosted}
SURFSENSE_BACKEND_INTERNAL_URL: http://backend:8000
MAX_FILE_SIZE_MB: ${MAX_FILE_SIZE_MB:-500}
depends_on:
backend:
condition: service_healthy

View file

@ -148,6 +148,7 @@ services:
BACKEND_URL: ${BACKEND_URL:-${SURFSENSE_PUBLIC_URL:-http://localhost:${LISTEN_HTTP_PORT:-3929}}}
WHATSAPP_BRIDGE_URL: ${WHATSAPP_BRIDGE_URL:-http://whatsapp-bridge:9929}
SEARXNG_URL: ${SEARXNG_URL:-http://searxng:8080}
MAX_FILE_SIZE_MB: ${MAX_FILE_SIZE_MB:-500}
# Daytona Sandbox uncomment and set credentials to enable cloud code execution
# DAYTONA_SANDBOX_ENABLED: "TRUE"
# DAYTONA_API_KEY: ${DAYTONA_API_KEY:-}
@ -295,6 +296,7 @@ services:
ETL_SERVICE: ${ETL_SERVICE:-DOCLING}
DEPLOYMENT_MODE: ${DEPLOYMENT_MODE:-self-hosted}
SURFSENSE_BACKEND_INTERNAL_URL: http://backend:8000
MAX_FILE_SIZE_MB: ${MAX_FILE_SIZE_MB:-500}
labels:
- "com.centurylinklabs.watchtower.enable=true"
depends_on:

View file

@ -56,7 +56,10 @@ logger = logging.getLogger(__name__)
router = APIRouter()
MAX_FILE_SIZE_BYTES = 500 * 1024 * 1024 # 500 MB per file
# Per-file upload cap. Operators raise MAX_FILE_SIZE_MB when self-hosting on
# hardware that can take it; the frontend reads the same value for its
# pre-upload check.
MAX_FILE_SIZE_BYTES = int(os.getenv("MAX_FILE_SIZE_MB", "500")) * 1024 * 1024
@router.post("/documents")

View file

@ -13,6 +13,7 @@ export async function RuntimeConfig({ children }: { children: React.ReactNode })
authType: process.env.AUTH_TYPE ?? BUILD_TIME_AUTH_TYPE,
etlService: process.env.ETL_SERVICE ?? BUILD_TIME_ETL_SERVICE,
deploymentMode: process.env.DEPLOYMENT_MODE ?? BUILD_TIME_DEPLOYMENT_MODE,
maxFileSizeMB: Number(process.env.MAX_FILE_SIZE_MB ?? "500")
};
return <RuntimeConfigProvider value={value}>{children}</RuntimeConfigProvider>;

View file

@ -9,6 +9,7 @@ export interface RuntimeConfigValue {
authType: AuthType;
etlService: string;
deploymentMode: DeploymentMode;
maxFileSizeMB: number;
}
const RuntimeConfigContext = createContext<RuntimeConfigValue | null>(null);

View file

@ -121,8 +121,7 @@ function flattenTree(
const FOLDER_BATCH_SIZE_BYTES = 20 * 1024 * 1024;
const FOLDER_BATCH_MAX_FILES = 10;
const MAX_FILE_SIZE_MB = 500;
const MAX_FILE_SIZE_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024;
const toggleRowClass =
"flex items-center justify-between rounded-lg bg-slate-400/5 dark:bg-white/5 p-3";
@ -133,7 +132,7 @@ export function DocumentUploadTab({
onAccordionStateChange,
}: DocumentUploadTabProps) {
const t = useTranslations("upload_documents");
const { etlService } = useRuntimeConfig();
const { etlService, maxFileSizeMB } = useRuntimeConfig();
const [files, setFiles] = useState<FileWithId[]>([]);
const [uploadProgress, setUploadProgress] = useState(0);
const [accordionValue, setAccordionValue] = useState<string>("");
@ -146,7 +145,8 @@ export function DocumentUploadTab({
const progressIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
const [folderUpload, setFolderUpload] = useState<FolderUploadData | null>(null);
const [isFolderUploading, setIsFolderUploading] = useState(false);
const MAX_FILE_SIZE_BYTES = maxFileSizeMB * 1024 * 1024;
useEffect(() => {
return () => {
if (progressIntervalRef.current) {
@ -175,7 +175,7 @@ export function DocumentUploadTab({
toast.error(t("file_too_large"), {
description: t("file_too_large_desc", {
name: oversized[0].name,
maxMB: MAX_FILE_SIZE_MB,
maxMB: maxFileSizeMB,
}),
});
}
@ -191,7 +191,7 @@ export function DocumentUploadTab({
return [...prev, ...newEntries];
});
},
[t]
[t, MAX_FILE_SIZE_BYTES, maxFileSizeMB]
);
const onDrop = useCallback(