diff --git a/backend/src/main.rs b/backend/src/main.rs index d43b9a69bb..89293c379a 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -51,14 +51,14 @@ use windmill_common::{ JOB_DEFAULT_TIMEOUT_SECS_SETTING, JOB_ISOLATION_SETTING, JWT_SECRET_SETTING, KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING, MAVEN_REPOS_SETTING, MAVEN_SETTINGS_XML_SETTING, MONITOR_LOGS_ON_OBJECT_STORE_SETTING, NO_DEFAULT_MAVEN_SETTING, - NPM_CONFIG_REGISTRY_SETTING, NUGET_CONFIG_SETTING, OAUTH_SETTING, OTEL_SETTING, - OTEL_TRACING_PROXY_SETTING, PIP_INDEX_URL_SETTING, POWERSHELL_REPO_PAT_SETTING, - POWERSHELL_REPO_URL_SETTING, PREVIEW_TAGS_OVERRIDE_SETTING, REQUEST_SIZE_LIMIT_SETTING, - REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING, RESTART_COORDINATION_SETTING, - RETENTION_PERIOD_SECS_SETTING, RUBY_REPOS_SETTING, SAML_METADATA_SETTING, - SCIM_TOKEN_SETTING, SMTP_SETTING, STORE_AUDIT_LOGS_S3_SETTING, TEAMS_SETTING, - TIMEOUT_WAIT_RESULT_SETTING, UV_EXCLUDE_NEWER_SETTING, UV_INDEX_STRATEGY_SETTING, - WORKSPACE_REGISTRIES_SETTING, + NPM_CONFIG_REGISTRY_SETTING, NSJAIL_TMPFS_SIZE_MB_SETTING, NUGET_CONFIG_SETTING, + OAUTH_SETTING, OTEL_SETTING, OTEL_TRACING_PROXY_SETTING, PIP_INDEX_URL_SETTING, + POWERSHELL_REPO_PAT_SETTING, POWERSHELL_REPO_URL_SETTING, PREVIEW_TAGS_OVERRIDE_SETTING, + REQUEST_SIZE_LIMIT_SETTING, REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING, + RESTART_COORDINATION_SETTING, RETENTION_PERIOD_SECS_SETTING, RUBY_REPOS_SETTING, + SAML_METADATA_SETTING, SCIM_TOKEN_SETTING, SMTP_SETTING, STORE_AUDIT_LOGS_S3_SETTING, + TEAMS_SETTING, TIMEOUT_WAIT_RESULT_SETTING, UV_EXCLUDE_NEWER_SETTING, + UV_INDEX_STRATEGY_SETTING, WORKSPACE_REGISTRIES_SETTING, }, scripts::ScriptLang, stats_oss::schedule_stats, @@ -127,9 +127,10 @@ use crate::monitor::{ reload_http_route_workspaced_route_setting, reload_hub_api_secret_setting, reload_hub_base_url_setting, reload_instance_events_webhook_setting, reload_job_default_timeout_setting, reload_job_isolation_setting, reload_jwt_secret_setting, - reload_license_key, reload_npm_config_registry_setting, reload_otel_tracing_proxy_setting, - reload_pip_index_url_setting, reload_retention_period_setting, reload_scim_token_setting, - reload_smtp_config, reload_store_audit_logs_s3_setting, reload_uv_exclude_newer_setting, + reload_license_key, reload_npm_config_registry_setting, reload_nsjail_tmpfs_size_setting, + reload_otel_tracing_proxy_setting, reload_pip_index_url_setting, + reload_retention_period_setting, reload_scim_token_setting, reload_smtp_config, + reload_store_audit_logs_s3_setting, reload_uv_exclude_newer_setting, reload_uv_index_strategy_setting, reload_worker_config, MonitorIteration, }; @@ -1782,6 +1783,7 @@ async fn process_notify_event( STORE_AUDIT_LOGS_S3_SETTING => reload_store_audit_logs_s3_setting(conn).await, JOB_DEFAULT_TIMEOUT_SECS_SETTING => reload_job_default_timeout_setting(conn).await, JOB_ISOLATION_SETTING => reload_job_isolation_setting(conn).await, + NSJAIL_TMPFS_SIZE_MB_SETTING => reload_nsjail_tmpfs_size_setting(conn).await, #[cfg(feature = "parquet")] OBJECT_STORE_CONFIG_SETTING => { if !disable_s3_store { diff --git a/backend/src/monitor.rs b/backend/src/monitor.rs index a8f52b2719..2d883776e0 100644 --- a/backend/src/monitor.rs +++ b/backend/src/monitor.rs @@ -62,12 +62,12 @@ use windmill_common::{ HUB_BASE_URL_SETTING, INSTANCE_PYTHON_VERSION_SETTING, JOB_DEFAULT_TIMEOUT_SECS_SETTING, JOB_ISOLATION_SETTING, JWT_SECRET_SETTING, KEEP_JOB_DIR_SETTING, LICENSE_KEY_SETTING, MONITOR_LOGS_ON_OBJECT_STORE_SETTING, NPMRC_SETTING, NPM_CONFIG_REGISTRY_SETTING, - NUGET_CONFIG_SETTING, OTEL_SETTING, OTEL_TRACING_PROXY_SETTING, PIP_INDEX_URL_SETTING, - POWERSHELL_REPO_PAT_SETTING, POWERSHELL_REPO_URL_SETTING, PREVIEW_TAGS_OVERRIDE_SETTING, - REQUEST_SIZE_LIMIT_SETTING, REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING, - RETENTION_PERIOD_SECS_SETTING, SAML_METADATA_SETTING, SCIM_TOKEN_SETTING, - STORE_AUDIT_LOGS_S3_SETTING, TIMEOUT_WAIT_RESULT_SETTING, UV_EXCLUDE_NEWER_SETTING, - UV_INDEX_STRATEGY_SETTING, + NSJAIL_TMPFS_SIZE_MB_SETTING, NUGET_CONFIG_SETTING, OTEL_SETTING, + OTEL_TRACING_PROXY_SETTING, PIP_INDEX_URL_SETTING, POWERSHELL_REPO_PAT_SETTING, + POWERSHELL_REPO_URL_SETTING, PREVIEW_TAGS_OVERRIDE_SETTING, REQUEST_SIZE_LIMIT_SETTING, + REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING, RETENTION_PERIOD_SECS_SETTING, + SAML_METADATA_SETTING, SCIM_TOKEN_SETTING, STORE_AUDIT_LOGS_S3_SETTING, + TIMEOUT_WAIT_RESULT_SETTING, UV_EXCLUDE_NEWER_SETTING, UV_INDEX_STRATEGY_SETTING, }, indexer::load_indexer_config, jwt::JWT_SECRET, @@ -106,9 +106,10 @@ use windmill_worker::{ OtelTracingProxySettings, SameWorkerSender, WorkspaceRegistryMap, BUNFIG_INSTALL_SCOPES, BUN_INSTALL_MIN_RELEASE_AGE, CARGO_REGISTRIES, INSTANCE_PYTHON_VERSION, JAVA_HOME_DIR, JOB_DEFAULT_TIMEOUT, JOB_ISOLATION, KEEP_JOB_DIR, MAVEN_REPOS, MAVEN_SETTINGS_XML, - NO_DEFAULT_MAVEN, NPMRC, NPM_CONFIG_REGISTRY, NSJAIL_AVAILABLE, NUGET_CONFIG, - OTEL_TRACING_PROXY_SETTINGS, PIP_EXTRA_INDEX_URL, PIP_INDEX_URL, POWERSHELL_REPO_PAT, - POWERSHELL_REPO_URL, UNSHARE_PATH, UV_EXCLUDE_NEWER, UV_INDEX_STRATEGY, WORKSPACE_REGISTRIES, + NO_DEFAULT_MAVEN, NPMRC, NPM_CONFIG_REGISTRY, NSJAIL_AVAILABLE, NSJAIL_TMPFS_SIZE_MB, + NUGET_CONFIG, OTEL_TRACING_PROXY_SETTINGS, PIP_EXTRA_INDEX_URL, PIP_INDEX_URL, + POWERSHELL_REPO_PAT, POWERSHELL_REPO_URL, UNSHARE_PATH, UV_EXCLUDE_NEWER, UV_INDEX_STRATEGY, + WORKSPACE_REGISTRIES, }; #[cfg(feature = "parquet")] @@ -384,6 +385,7 @@ pub async fn initial_load( if worker_mode { reload_job_default_timeout_setting(&conn).await; reload_job_isolation_setting(&conn).await; + reload_nsjail_tmpfs_size_setting(&conn).await; reload_extra_pip_index_url_setting(&conn).await; reload_pip_index_url_setting(&conn).await; reload_uv_index_strategy_setting(&conn).await; @@ -1885,6 +1887,16 @@ pub async fn reload_job_default_timeout_setting(conn: &Connection) { .await; } +pub async fn reload_nsjail_tmpfs_size_setting(conn: &Connection) { + reload_option_setting_with_tracing( + conn, + NSJAIL_TMPFS_SIZE_MB_SETTING, + "NSJAIL_TMPFS_SIZE_MB", + NSJAIL_TMPFS_SIZE_MB.clone(), + ) + .await; +} + pub async fn reload_job_isolation_setting(conn: &Connection) { let value = match load_value_from_global_settings_with_conn(conn, JOB_ISOLATION_SETTING, true).await { diff --git a/backend/windmill-common/src/global_settings.rs b/backend/windmill-common/src/global_settings.rs index ab05a500b7..7306865982 100644 --- a/backend/windmill-common/src/global_settings.rs +++ b/backend/windmill-common/src/global_settings.rs @@ -53,6 +53,7 @@ pub const EXPOSE_DEBUG_METRICS_SETTING: &str = "expose_debug_metrics"; pub const KEEP_JOB_DIR_SETTING: &str = "keep_job_dir"; pub const REQUIRE_PREEXISTING_USER_FOR_OAUTH_SETTING: &str = "require_preexisting_user_for_oauth"; pub const JOB_ISOLATION_SETTING: &str = "job_isolation"; +pub const NSJAIL_TMPFS_SIZE_MB_SETTING: &str = "nsjail_tmpfs_size_mb"; pub const OBJECT_STORE_CONFIG_SETTING: &str = "object_store_cache_config"; pub const HUB_API_SECRET_SETTING: &str = "hub_api_secret"; diff --git a/backend/windmill-common/src/instance_config.rs b/backend/windmill-common/src/instance_config.rs index 3b168761e1..eca3acd456 100644 --- a/backend/windmill-common/src/instance_config.rs +++ b/backend/windmill-common/src/instance_config.rs @@ -221,6 +221,8 @@ pub struct GlobalSettings { #[serde(skip_serializing_if = "Option::is_none")] pub job_default_timeout: Option, #[serde(skip_serializing_if = "Option::is_none")] + pub nsjail_tmpfs_size_mb: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub bun_install_min_release_age: Option, #[serde(skip_serializing_if = "Option::is_none")] pub uv_exclude_newer: Option, diff --git a/backend/windmill-worker/nsjail/download.py.config.proto b/backend/windmill-worker/nsjail/download.py.config.proto index ee5b3cc402..8880a565c7 100644 --- a/backend/windmill-worker/nsjail/download.py.config.proto +++ b/backend/windmill-worker/nsjail/download.py.config.proto @@ -90,7 +90,7 @@ mount { dst: "/tmp" fstype: "tmpfs" rw: true - options: "size=500000000" + options: "size={NSJAIL_TMPFS_SIZE}" } diff --git a/backend/windmill-worker/nsjail/download.ruby.config.proto b/backend/windmill-worker/nsjail/download.ruby.config.proto index 12a6012c59..98422abb87 100644 --- a/backend/windmill-worker/nsjail/download.ruby.config.proto +++ b/backend/windmill-worker/nsjail/download.ruby.config.proto @@ -90,7 +90,7 @@ mount { dst: "/tmp" fstype: "tmpfs" rw: true - options: "size=500000000" + options: "size={NSJAIL_TMPFS_SIZE}" } mount { diff --git a/backend/windmill-worker/nsjail/download.rust.config.proto b/backend/windmill-worker/nsjail/download.rust.config.proto index d86fdedd36..0884034076 100644 --- a/backend/windmill-worker/nsjail/download.rust.config.proto +++ b/backend/windmill-worker/nsjail/download.rust.config.proto @@ -53,7 +53,7 @@ mount { dst: "/tmp" fstype: "tmpfs" rw: true - options: "size=500000000" + options: "size={NSJAIL_TMPFS_SIZE}" } mount { diff --git a/backend/windmill-worker/nsjail/run.ansible.config.proto b/backend/windmill-worker/nsjail/run.ansible.config.proto index cba55d2892..7df486c53a 100644 --- a/backend/windmill-worker/nsjail/run.ansible.config.proto +++ b/backend/windmill-worker/nsjail/run.ansible.config.proto @@ -70,7 +70,7 @@ mount { dst: "/tmp" fstype: "tmpfs" rw: true - options: "size=800000000" + options: "size={NSJAIL_TMPFS_SIZE}" } mount { diff --git a/backend/windmill-worker/nsjail/run.bash.config.proto b/backend/windmill-worker/nsjail/run.bash.config.proto index 430437a3d7..1136c8d298 100644 --- a/backend/windmill-worker/nsjail/run.bash.config.proto +++ b/backend/windmill-worker/nsjail/run.bash.config.proto @@ -72,7 +72,7 @@ mount { dst: "/tmp" fstype: "tmpfs" rw: true - options: "size=800000000" + options: "size={NSJAIL_TMPFS_SIZE}" } mount { diff --git a/backend/windmill-worker/nsjail/run.bun.config.proto b/backend/windmill-worker/nsjail/run.bun.config.proto index ef4f054097..280ef8a7f9 100644 --- a/backend/windmill-worker/nsjail/run.bun.config.proto +++ b/backend/windmill-worker/nsjail/run.bun.config.proto @@ -64,7 +64,7 @@ mount { dst: "/tmp" fstype: "tmpfs" rw: true - options: "size=500000000" + options: "size={NSJAIL_TMPFS_SIZE}" } mount { diff --git a/backend/windmill-worker/nsjail/run.csharp.config.proto b/backend/windmill-worker/nsjail/run.csharp.config.proto index 1a2bb97897..b58d6c330f 100644 --- a/backend/windmill-worker/nsjail/run.csharp.config.proto +++ b/backend/windmill-worker/nsjail/run.csharp.config.proto @@ -61,7 +61,7 @@ mount { dst: "/tmp" fstype: "tmpfs" rw: true - options: "size=500000000" + options: "size={NSJAIL_TMPFS_SIZE}" } diff --git a/backend/windmill-worker/nsjail/run.go.config.proto b/backend/windmill-worker/nsjail/run.go.config.proto index d5b7cef099..4fec8f3b2d 100644 --- a/backend/windmill-worker/nsjail/run.go.config.proto +++ b/backend/windmill-worker/nsjail/run.go.config.proto @@ -54,7 +54,7 @@ mount { dst: "/tmp" fstype: "tmpfs" rw: true - options: "size=500000000" + options: "size={NSJAIL_TMPFS_SIZE}" } diff --git a/backend/windmill-worker/nsjail/run.java.config.proto b/backend/windmill-worker/nsjail/run.java.config.proto index be42e98682..3b0a635b0c 100644 --- a/backend/windmill-worker/nsjail/run.java.config.proto +++ b/backend/windmill-worker/nsjail/run.java.config.proto @@ -55,7 +55,7 @@ mount { dst: "/tmp" fstype: "tmpfs" rw: true - options: "size=500000000" + options: "size={NSJAIL_TMPFS_SIZE}" } diff --git a/backend/windmill-worker/nsjail/run.nu.config.proto b/backend/windmill-worker/nsjail/run.nu.config.proto index c2c663c613..40a5de69a1 100644 --- a/backend/windmill-worker/nsjail/run.nu.config.proto +++ b/backend/windmill-worker/nsjail/run.nu.config.proto @@ -55,7 +55,7 @@ mount { dst: "/tmp" fstype: "tmpfs" rw: true - options: "size=800000000" + options: "size={NSJAIL_TMPFS_SIZE}" } mount { diff --git a/backend/windmill-worker/nsjail/run.php.config.proto b/backend/windmill-worker/nsjail/run.php.config.proto index 959ac56f51..965ac7cd36 100644 --- a/backend/windmill-worker/nsjail/run.php.config.proto +++ b/backend/windmill-worker/nsjail/run.php.config.proto @@ -55,7 +55,7 @@ mount { dst: "/tmp" fstype: "tmpfs" rw: true - options: "size=800000000" + options: "size={NSJAIL_TMPFS_SIZE}" } mount { diff --git a/backend/windmill-worker/nsjail/run.powershell.config.proto b/backend/windmill-worker/nsjail/run.powershell.config.proto index 3c9dc8dc57..bab869c9c8 100644 --- a/backend/windmill-worker/nsjail/run.powershell.config.proto +++ b/backend/windmill-worker/nsjail/run.powershell.config.proto @@ -68,7 +68,7 @@ mount { dst: "/tmp" fstype: "tmpfs" rw: true - options: "size=800000000" + options: "size={NSJAIL_TMPFS_SIZE}" } mount { diff --git a/backend/windmill-worker/nsjail/run.python3.config.proto b/backend/windmill-worker/nsjail/run.python3.config.proto index 3c272e6d2b..dec9d6bae7 100644 --- a/backend/windmill-worker/nsjail/run.python3.config.proto +++ b/backend/windmill-worker/nsjail/run.python3.config.proto @@ -58,7 +58,7 @@ mount { dst: "/tmp" fstype: "tmpfs" rw: true - options: "size=500000000" + options: "size={NSJAIL_TMPFS_SIZE}" } mount { diff --git a/backend/windmill-worker/nsjail/run.r.config.proto b/backend/windmill-worker/nsjail/run.r.config.proto index 828e7528e0..0f5d71bf5a 100644 --- a/backend/windmill-worker/nsjail/run.r.config.proto +++ b/backend/windmill-worker/nsjail/run.r.config.proto @@ -55,7 +55,7 @@ mount { dst: "/tmp" fstype: "tmpfs" rw: true - options: "size=500000000" + options: "size={NSJAIL_TMPFS_SIZE}" } diff --git a/backend/windmill-worker/nsjail/run.ruby.config.proto b/backend/windmill-worker/nsjail/run.ruby.config.proto index 09d62f5a0f..3b9509cea6 100644 --- a/backend/windmill-worker/nsjail/run.ruby.config.proto +++ b/backend/windmill-worker/nsjail/run.ruby.config.proto @@ -55,7 +55,7 @@ mount { dst: "/tmp" fstype: "tmpfs" rw: true - options: "size=500000000" + options: "size={NSJAIL_TMPFS_SIZE}" } diff --git a/backend/windmill-worker/nsjail/run.rust.config.proto b/backend/windmill-worker/nsjail/run.rust.config.proto index 86ef63bd26..06da7be662 100644 --- a/backend/windmill-worker/nsjail/run.rust.config.proto +++ b/backend/windmill-worker/nsjail/run.rust.config.proto @@ -54,7 +54,7 @@ mount { dst: "/tmp" fstype: "tmpfs" rw: true - options: "size=500000000" + options: "size={NSJAIL_TMPFS_SIZE}" } diff --git a/backend/windmill-worker/src/ansible_executor.rs b/backend/windmill-worker/src/ansible_executor.rs index 2608cc6088..f745bc1661 100644 --- a/backend/windmill-worker/src/ansible_executor.rs +++ b/backend/windmill-worker/src/ansible_executor.rs @@ -30,8 +30,8 @@ use crate::{ bash_executor::BIN_BASH, common::{ build_command_with_isolation, check_executor_binary_exists, get_reserved_variables, - read_and_check_result, resolve_nsjail_timeout, start_child_process, transform_json, - OccupancyMetrics, + read_and_check_result, resolve_nsjail_timeout, resolve_nsjail_tmpfs_size_bytes, + start_child_process, transform_json, OccupancyMetrics, }, handle_child::handle_child, is_sandboxing_enabled, @@ -1456,6 +1456,10 @@ mount {{ "{ADDITIONAL_PYTHON_PATHS}", additional_python_paths_folders.as_str(), ) + .replace( + "{NSJAIL_TMPFS_SIZE}", + &resolve_nsjail_tmpfs_size_bytes().await, + ) .replace("{TIMEOUT}", &nsjail_timeout), )?; } else { diff --git a/backend/windmill-worker/src/bash_executor.rs b/backend/windmill-worker/src/bash_executor.rs index 31254cf0cf..47f100bd2d 100644 --- a/backend/windmill-worker/src/bash_executor.rs +++ b/backend/windmill-worker/src/bash_executor.rs @@ -41,8 +41,8 @@ use crate::handle_child::run_future_with_polling_update_job_poller; use crate::{ common::{ build_args_map, build_command_with_isolation, get_reserved_variables, read_file, - read_file_content, resolve_nsjail_timeout, start_child_process, OccupancyMetrics, - DEV_CONF_NSJAIL, + read_file_content, resolve_nsjail_timeout, resolve_nsjail_tmpfs_size_bytes, start_child_process, + OccupancyMetrics, DEV_CONF_NSJAIL, }, get_proxy_envs_for_lang, handle_child::handle_child, @@ -215,6 +215,10 @@ exit $exit_status .replace("{SHARED_MOUNT}", shared_mount) .replace("{TRACING_PROXY_CA_CERT_PATH}", &*TRACING_PROXY_CA_CERT_PATH) .replace("#{DEV}", DEV_CONF_NSJAIL) + .replace( + "{NSJAIL_TMPFS_SIZE}", + &resolve_nsjail_tmpfs_size_bytes().await, + ) .replace("{TIMEOUT}", &nsjail_timeout), )?; let mut cmd_args = vec![ diff --git a/backend/windmill-worker/src/bun_executor.rs b/backend/windmill-worker/src/bun_executor.rs index 7b04d47dce..2346cb413f 100644 --- a/backend/windmill-worker/src/bun_executor.rs +++ b/backend/windmill-worker/src/bun_executor.rs @@ -16,8 +16,8 @@ use crate::{ common::{ build_command_with_isolation, create_args_and_out_file, get_reserved_variables, parse_npm_config, read_file, read_file_content, read_result, resolve_nsjail_timeout, - start_child_process, write_file_binary, MaybeLock, OccupancyMetrics, StreamNotifier, - DEV_CONF_NSJAIL, + resolve_nsjail_tmpfs_size_bytes, start_child_process, write_file_binary, MaybeLock, + OccupancyMetrics, StreamNotifier, DEV_CONF_NSJAIL, }, get_proxy_envs_for_lang, handle_child::handle_child, @@ -2185,6 +2185,10 @@ try {{ ) .replace("{TRACING_PROXY_CA_CERT_PATH}", &*TRACING_PROXY_CA_CERT_PATH) .replace("#{DEV}", DEV_CONF_NSJAIL) + .replace( + "{NSJAIL_TMPFS_SIZE}", + &resolve_nsjail_tmpfs_size_bytes().await, + ) .replace("{TIMEOUT}", &nsjail_timeout), )?; diff --git a/backend/windmill-worker/src/common.rs b/backend/windmill-worker/src/common.rs index 8a3ee06452..95c7063328 100644 --- a/backend/windmill-worker/src/common.rs +++ b/backend/windmill-worker/src/common.rs @@ -47,7 +47,9 @@ use windmill_common::{variables, DB}; use tokio::{io::AsyncWriteExt, time::Instant}; use crate::agent_workers::UPDATE_PING_URL; -use crate::{JOB_DEFAULT_TIMEOUT, MAX_RESULT_SIZE, MAX_TIMEOUT_DURATION, PATH_ENV}; +use crate::{ + JOB_DEFAULT_TIMEOUT, MAX_RESULT_SIZE, MAX_TIMEOUT_DURATION, NSJAIL_TMPFS_SIZE_MB, PATH_ENV, +}; use windmill_common::client::AuthedClient; /// Additional nsjail config for development. Currently used for nix flake. @@ -1006,6 +1008,21 @@ pub async fn resolve_nsjail_timeout( (duration.as_secs() + 15).to_string() } +/// Default size (in bytes) of the `/tmp` tmpfs mount inside nsjail sandboxes, +/// used when the `nsjail_tmpfs_size_mb` instance setting is unset. +pub const DEFAULT_NSJAIL_TMPFS_SIZE_BYTES: u64 = 800_000_000; + +/// Resolve the tmpfs `size=` value (in bytes, formatted for the nsjail proto) +/// for the `/tmp` tmpfs mount. When the `nsjail_tmpfs_size_mb` instance setting +/// is `None`, `Some(0)`, or negative, falls back to +/// [`DEFAULT_NSJAIL_TMPFS_SIZE_BYTES`]. +pub async fn resolve_nsjail_tmpfs_size_bytes() -> String { + match *NSJAIL_TMPFS_SIZE_MB.read().await { + Some(mb) if mb > 0 => ((mb as u64).saturating_mul(1_000_000)).to_string(), + _ => DEFAULT_NSJAIL_TMPFS_SIZE_BYTES.to_string(), + } +} + async fn hash_args( #[allow(unused)] db: &DB, #[allow(unused)] client: &AuthedClient, diff --git a/backend/windmill-worker/src/csharp_executor.rs b/backend/windmill-worker/src/csharp_executor.rs index 3d09f0d053..cfd9a544a1 100644 --- a/backend/windmill-worker/src/csharp_executor.rs +++ b/backend/windmill-worker/src/csharp_executor.rs @@ -27,8 +27,8 @@ use windmill_queue::CanceledBy; use crate::{ common::{ build_command_with_isolation, check_executor_binary_exists, create_args_and_out_file, - get_reserved_variables, read_result, resolve_nsjail_timeout, start_child_process, - DEV_CONF_NSJAIL, + get_reserved_variables, read_result, resolve_nsjail_timeout, resolve_nsjail_tmpfs_size_bytes, + start_child_process, DEV_CONF_NSJAIL, }, get_proxy_envs_for_lang, handle_child::handle_child, @@ -603,6 +603,10 @@ pub async fn handle_csharp_job( .replace("{SHARED_MOUNT}", shared_mount) .replace("{TRACING_PROXY_CA_CERT_PATH}", &*TRACING_PROXY_CA_CERT_PATH) .replace("#{DEV}", DEV_CONF_NSJAIL) + .replace( + "{NSJAIL_TMPFS_SIZE}", + &resolve_nsjail_tmpfs_size_bytes().await, + ) .replace("{TIMEOUT}", &nsjail_timeout), )?; let mut nsjail_cmd = Command::new(NSJAIL_PATH.as_str()); diff --git a/backend/windmill-worker/src/go_executor.rs b/backend/windmill-worker/src/go_executor.rs index b4133a2d0c..ee08aa1b30 100644 --- a/backend/windmill-worker/src/go_executor.rs +++ b/backend/windmill-worker/src/go_executor.rs @@ -22,8 +22,8 @@ use windmill_queue::{append_logs, CanceledBy, MiniPulledJob}; use crate::{ common::{ build_command_with_isolation, capitalize, create_args_and_out_file, get_reserved_variables, - read_result, resolve_nsjail_timeout, start_child_process, OccupancyMetrics, - DEV_CONF_NSJAIL, + read_result, resolve_nsjail_timeout, resolve_nsjail_tmpfs_size_bytes, start_child_process, + OccupancyMetrics, DEV_CONF_NSJAIL, }, handle_child::handle_child, is_sandboxing_enabled, read_ee_registry, DISABLE_NUSER, GOPRIVATE, GOPROXY, GO_BIN_CACHE_DIR, @@ -351,6 +351,10 @@ func Run(req Req) (interface{{}}, error){{ .replace("{SHARED_MOUNT}", shared_mount) .replace("{TRACING_PROXY_CA_CERT_PATH}", &*TRACING_PROXY_CA_CERT_PATH) .replace("#{DEV}", DEV_CONF_NSJAIL) + .replace( + "{NSJAIL_TMPFS_SIZE}", + &resolve_nsjail_tmpfs_size_bytes().await, + ) .replace("{TIMEOUT}", &nsjail_timeout), )?; let mut nsjail_cmd = Command::new(NSJAIL_PATH.as_str()); diff --git a/backend/windmill-worker/src/java_executor.rs b/backend/windmill-worker/src/java_executor.rs index 2eaeec01f4..f927f921c8 100644 --- a/backend/windmill-worker/src/java_executor.rs +++ b/backend/windmill-worker/src/java_executor.rs @@ -23,7 +23,8 @@ use windmill_queue::{append_logs, CanceledBy, MiniPulledJob}; use crate::{ common::{ build_command_with_isolation, create_args_and_out_file, get_reserved_variables, - read_result, resolve_nsjail_timeout, start_child_process, OccupancyMetrics, + read_result, resolve_nsjail_timeout, resolve_nsjail_tmpfs_size_bytes, start_child_process, + OccupancyMetrics, }, handle_child, is_sandboxing_enabled, read_ee_registry_bool_with_workspace_override, read_ee_registry_with_workspace_override, @@ -669,6 +670,10 @@ async fn run<'a>( .replace("{SHARED_MOUNT}", &shared_mount) // .replace("{CACHED_TARGET}", &shared_mount) .replace("{CLONE_NEWUSER}", &(!*DISABLE_NUSER).to_string()) + .replace( + "{NSJAIL_TMPFS_SIZE}", + &resolve_nsjail_tmpfs_size_bytes().await, + ) .replace("{TIMEOUT}", &nsjail_timeout), )?; let mut cmd = Command::new(NSJAIL_PATH.as_str()); diff --git a/backend/windmill-worker/src/nu_executor.rs b/backend/windmill-worker/src/nu_executor.rs index c79f8ba968..d9a55c40c9 100644 --- a/backend/windmill-worker/src/nu_executor.rs +++ b/backend/windmill-worker/src/nu_executor.rs @@ -14,8 +14,8 @@ use windmill_queue::{append_logs, CanceledBy, MiniPulledJob}; use crate::{ common::{ build_command_with_isolation, create_args_and_out_file, get_reserved_variables, - read_result, resolve_nsjail_timeout, start_child_process, OccupancyMetrics, - DEV_CONF_NSJAIL, + read_result, resolve_nsjail_timeout, resolve_nsjail_tmpfs_size_bytes, start_child_process, + OccupancyMetrics, DEV_CONF_NSJAIL, }, get_proxy_envs_for_lang, handle_child, is_sandboxing_enabled, DISABLE_NUSER, NSJAIL_PATH, PATH_ENV, TRACING_PROXY_CA_CERT_PATH, @@ -258,6 +258,10 @@ async fn run<'a>( .replace("{CLONE_NEWUSER}", &(!*DISABLE_NUSER).to_string()) .replace("{TRACING_PROXY_CA_CERT_PATH}", &*TRACING_PROXY_CA_CERT_PATH) .replace("#{DEV}", DEV_CONF_NSJAIL) + .replace( + "{NSJAIL_TMPFS_SIZE}", + &resolve_nsjail_tmpfs_size_bytes().await, + ) .replace("{TIMEOUT}", &nsjail_timeout), )?; let mut nsjail_cmd = Command::new(NSJAIL_PATH.as_str()); diff --git a/backend/windmill-worker/src/php_executor.rs b/backend/windmill-worker/src/php_executor.rs index d3d0fb36fb..e0ba015951 100644 --- a/backend/windmill-worker/src/php_executor.rs +++ b/backend/windmill-worker/src/php_executor.rs @@ -20,8 +20,8 @@ use windmill_queue::{append_logs, CanceledBy}; use crate::{ common::{ build_command_with_isolation, check_executor_binary_exists, create_args_and_out_file, - get_reserved_variables, read_result, resolve_nsjail_timeout, start_child_process, - MaybeLock, OccupancyMetrics, + get_reserved_variables, read_result, resolve_nsjail_timeout, resolve_nsjail_tmpfs_size_bytes, + start_child_process, MaybeLock, OccupancyMetrics, }, handle_child::handle_child, is_sandboxing_enabled, COMPOSER_CACHE_DIR, COMPOSER_PATH, DISABLE_NUSER, NSJAIL_PATH, PHP_PATH, @@ -425,6 +425,10 @@ try {{ .replace("{JOB_DIR}", job_dir) .replace("{CLONE_NEWUSER}", &(!*DISABLE_NUSER).to_string()) .replace("{SHARED_MOUNT}", shared_mount) + .replace( + "{NSJAIL_TMPFS_SIZE}", + &resolve_nsjail_tmpfs_size_bytes().await, + ) .replace("{TIMEOUT}", &nsjail_timeout), )?; diff --git a/backend/windmill-worker/src/pwsh_executor.rs b/backend/windmill-worker/src/pwsh_executor.rs index b5b8444f56..5ec6ff6bcd 100644 --- a/backend/windmill-worker/src/pwsh_executor.rs +++ b/backend/windmill-worker/src/pwsh_executor.rs @@ -26,8 +26,8 @@ lazy_static::lazy_static! { use crate::{ common::{ build_args_map, build_command_with_isolation, get_reserved_variables, read_file, - read_file_content, resolve_nsjail_timeout, start_child_process, MaybeLock, - OccupancyMetrics, + read_file_content, resolve_nsjail_timeout, resolve_nsjail_tmpfs_size_bytes, start_child_process, + MaybeLock, OccupancyMetrics, }, handle_child::handle_child, is_sandboxing_enabled, read_ee_registry_with_workspace_override, DISABLE_NUSER, HOME_ENV, @@ -682,6 +682,10 @@ $env:PSModulePath = \"{};$PSModulePathBackup\"", .replace("{CLONE_NEWUSER}", &(!*DISABLE_NUSER).to_string()) .replace("{SHARED_MOUNT}", shared_mount) .replace("{CACHE_DIR}", &*POWERSHELL_CACHE_DIR) + .replace( + "{NSJAIL_TMPFS_SIZE}", + &resolve_nsjail_tmpfs_size_bytes().await, + ) .replace("{TIMEOUT}", &nsjail_timeout), )?; let cmd_args = vec![ diff --git a/backend/windmill-worker/src/python_executor.rs b/backend/windmill-worker/src/python_executor.rs index 7f9c94d844..2023192075 100644 --- a/backend/windmill-worker/src/python_executor.rs +++ b/backend/windmill-worker/src/python_executor.rs @@ -146,8 +146,8 @@ use windmill_object_store::OBJECT_STORE_SETTINGS; use crate::{ common::{ build_command_with_isolation, create_args_and_out_file, get_reserved_variables, read_file, - read_result, resolve_nsjail_timeout, start_child_process, OccupancyMetrics, StreamNotifier, - DEV_CONF_NSJAIL, + read_result, resolve_nsjail_timeout, resolve_nsjail_tmpfs_size_bytes, start_child_process, + OccupancyMetrics, StreamNotifier, DEV_CONF_NSJAIL, }, get_proxy_envs_for_lang, handle_child::handle_child, @@ -1023,6 +1023,10 @@ mount {{ ) .replace("{TRACING_PROXY_CA_CERT_PATH}", &*TRACING_PROXY_CA_CERT_PATH) .replace("#{DEV}", DEV_CONF_NSJAIL) + .replace( + "{NSJAIL_TMPFS_SIZE}", + &resolve_nsjail_tmpfs_size_bytes().await, + ) .replace("{TIMEOUT}", &nsjail_timeout), )?; } else { @@ -2043,6 +2047,10 @@ async fn spawn_uv_install( .replace("{CLONE_NEWUSER}", &(!*DISABLE_NUSER).to_string()) .replace("{TRACING_PROXY_CA_CERT_PATH}", &*TRACING_PROXY_CA_CERT_PATH) .replace("#{DEV}", DEV_CONF_NSJAIL) + .replace( + "{NSJAIL_TMPFS_SIZE}", + &resolve_nsjail_tmpfs_size_bytes().await, + ) .as_str(), )?; diff --git a/backend/windmill-worker/src/r_executor.rs b/backend/windmill-worker/src/r_executor.rs index 70e188dc46..19959ee22c 100644 --- a/backend/windmill-worker/src/r_executor.rs +++ b/backend/windmill-worker/src/r_executor.rs @@ -20,7 +20,8 @@ use windmill_queue::{append_logs, CanceledBy, MiniPulledJob}; use crate::{ common::{ build_command_with_isolation, create_args_and_out_file, get_reserved_variables, - read_result, start_child_process, OccupancyMetrics, DEV_CONF_NSJAIL, + read_result, resolve_nsjail_tmpfs_size_bytes, start_child_process, OccupancyMetrics, + DEV_CONF_NSJAIL, }, get_proxy_envs_for_lang, handle_child::{self}, @@ -580,6 +581,10 @@ async fn run<'a>( .replace("{R_CACHE_DIR}", &*R_CACHE_DIR) .replace("{TRACING_PROXY_CA_CERT_PATH}", &*TRACING_PROXY_CA_CERT_PATH) .replace("#{DEV}", DEV_CONF_NSJAIL) + .replace( + "{NSJAIL_TMPFS_SIZE}", + &resolve_nsjail_tmpfs_size_bytes().await, + ) .replace("{CLONE_NEWUSER}", &(!*DISABLE_NUSER).to_string()), )?; let mut cmd = Command::new(NSJAIL_PATH.as_str()); diff --git a/backend/windmill-worker/src/ruby_executor.rs b/backend/windmill-worker/src/ruby_executor.rs index aff842eb9f..c82d5ad7df 100644 --- a/backend/windmill-worker/src/ruby_executor.rs +++ b/backend/windmill-worker/src/ruby_executor.rs @@ -23,8 +23,8 @@ use windmill_queue::{append_logs, CanceledBy, MiniPulledJob}; use crate::{ common::{ build_command_with_isolation, create_args_and_out_file, get_reserved_variables, - read_result, resolve_nsjail_timeout, start_child_process, OccupancyMetrics, - DEV_CONF_NSJAIL, + read_result, resolve_nsjail_timeout, resolve_nsjail_tmpfs_size_bytes, start_child_process, + OccupancyMetrics, DEV_CONF_NSJAIL, }, get_proxy_envs_for_lang, handle_child::{self}, @@ -619,6 +619,7 @@ async fn install<'a>( envs.clone(), get_reserved_variables(job, &client.token, conn, parent_runnable_path.clone()).await?, ); + let nsjail_tmpfs_size = resolve_nsjail_tmpfs_size_bytes().await; par_install_language_dependencies_seq( InstallDeps::Flat(deps.clone()), "ruby", @@ -638,6 +639,7 @@ async fn install<'a>( .replace("{TARGET}", &dependency.path) .replace("{CLONE_NEWUSER}", &(!*DISABLE_NUSER).to_string()) .replace("{TRACING_PROXY_CA_CERT_PATH}", &*TRACING_PROXY_CA_CERT_PATH) + .replace("{NSJAIL_TMPFS_SIZE}", &nsjail_tmpfs_size) .replace("#{DEV}", DEV_CONF_NSJAIL), // .replace("{BUILD}", &build_dir), )?; let mut cmd = Command::new(NSJAIL_PATH.as_str()); @@ -810,6 +812,7 @@ mount {{ .replace("{TRACING_PROXY_CA_CERT_PATH}", &*TRACING_PROXY_CA_CERT_PATH) .replace("#{DEV}", DEV_CONF_NSJAIL) .replace("{CLONE_NEWUSER}", &(!*DISABLE_NUSER).to_string()) + .replace("{NSJAIL_TMPFS_SIZE}", &resolve_nsjail_tmpfs_size_bytes().await) .replace("{TIMEOUT}", &nsjail_timeout), )?; let mut cmd = Command::new(NSJAIL_PATH.as_str()); diff --git a/backend/windmill-worker/src/rust_executor.rs b/backend/windmill-worker/src/rust_executor.rs index dc3acd8b1d..0f404569da 100644 --- a/backend/windmill-worker/src/rust_executor.rs +++ b/backend/windmill-worker/src/rust_executor.rs @@ -23,8 +23,8 @@ use windmill_queue::{append_logs, CanceledBy}; use crate::{ common::{ build_command_with_isolation, check_executor_binary_exists, create_args_and_out_file, - get_reserved_variables, read_result, resolve_nsjail_timeout, start_child_process, - OccupancyMetrics, DEV_CONF_NSJAIL, + get_reserved_variables, read_result, resolve_nsjail_timeout, resolve_nsjail_tmpfs_size_bytes, + start_child_process, OccupancyMetrics, DEV_CONF_NSJAIL, }, get_proxy_envs_for_lang, handle_child::handle_child, @@ -480,6 +480,10 @@ pub async fn build_rust_crate( .replace("{RUSTUP_HOME}", RUSTUP_HOME.as_str()) .replace("{TRACING_PROXY_CA_CERT_PATH}", &*TRACING_PROXY_CA_CERT_PATH) .replace("#{DEV}", DEV_CONF_NSJAIL) + .replace( + "{NSJAIL_TMPFS_SIZE}", + &resolve_nsjail_tmpfs_size_bytes().await, + ) .replace("{BUILD}", &build_dir), )?; let mut nsjail_cmd = Command::new(NSJAIL_PATH.as_str()); @@ -701,6 +705,10 @@ pub async fn handle_rust_job( .replace("{TRACING_PROXY_CA_CERT_PATH}", &*TRACING_PROXY_CA_CERT_PATH) .replace("#{DEV}", DEV_CONF_NSJAIL) .replace("{SHARED_MOUNT}", shared_mount) + .replace( + "{NSJAIL_TMPFS_SIZE}", + &resolve_nsjail_tmpfs_size_bytes().await, + ) .replace("{TIMEOUT}", &nsjail_timeout), )?; let mut nsjail_cmd = Command::new(NSJAIL_PATH.as_str()); diff --git a/backend/windmill-worker/src/worker.rs b/backend/windmill-worker/src/worker.rs index 7ff9823072..7798e73c98 100644 --- a/backend/windmill-worker/src/worker.rs +++ b/backend/windmill-worker/src/worker.rs @@ -681,6 +681,13 @@ lazy_static::lazy_static! { pub static ref FLOW_RUNNER_RUNNING: Mutex = Mutex::new(false); } +lazy_static::lazy_static! { + /// Optional override for the size of the `/tmp` tmpfs mount in nsjail sandboxes (in megabytes). + /// When `None` (or non-positive), executors fall back to the unified + /// `DEFAULT_NSJAIL_TMPFS_SIZE_BYTES` (800MB). + pub static ref NSJAIL_TMPFS_SIZE_MB: Arc>> = Arc::new(RwLock::new(None)); +} + pub fn sleep_queue() -> u64 { if NATIVE_MODE_RESOLVED.load(std::sync::atomic::Ordering::Relaxed) { 300 diff --git a/frontend/src/lib/components/instanceSettings.ts b/frontend/src/lib/components/instanceSettings.ts index 5b18700f57..1779f09bf8 100644 --- a/frontend/src/lib/components/instanceSettings.ts +++ b/frontend/src/lib/components/instanceSettings.ts @@ -245,6 +245,15 @@ export const settings: Record = { } ] }, + { + label: 'Nsjail tmpfs size (MB)', + key: 'nsjail_tmpfs_size_mb', + description: + 'Override the size of the /tmp tmpfs mount inside the nsjail sandbox (in MB). When left empty, defaults to 800MB. Only applies when the job isolation mode is set to Nsjail.', + fieldType: 'number', + placeholder: '800', + storage: 'setting' + }, { label: 'Default timeout', key: 'job_default_timeout',