feat(nsjail): make tmpfs size configurable via instance setting (#9261)

* feat(nsjail): make tmpfs size configurable via instance setting

Adds a new `nsjail_tmpfs_size_mb` instance setting that overrides the
size of the `/tmp` tmpfs mount inside the nsjail sandbox across all
languages. When unset, the existing per-language defaults (500MB or
800MB) continue to apply, so no behavior change for existing
deployments.

The setting is exposed under Settings → Jobs and is read at job
execution time, so changes take effect on the next job without a
restart.

Fixes WIN-1963

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(nsjail): unify default tmpfs size to 800MB

Previously each executor passed its own per-language default (500MB or
800MB) to resolve_nsjail_tmpfs_size. Unify on a single
DEFAULT_NSJAIL_TMPFS_SIZE_BYTES constant (800MB) so the placeholder
behavior is consistent across languages.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(nsjail): resolve tmpfs size outside ruby download closure

The download.ruby config render runs inside a sync closure passed to
par_install_language_dependencies_seq, so `.await` on
resolve_nsjail_tmpfs_size() was a compile error under the `ruby`
feature. Resolve the size once before the closure and capture the
string instead.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(nsjail): rename resolver to *_bytes and clarify fallback

Addresses CI review feedback:
- Rename `resolve_nsjail_tmpfs_size` to `resolve_nsjail_tmpfs_size_bytes`
  so the returned unit is unambiguous at the call site (cubic P2).
- Fix the `NSJAIL_TMPFS_SIZE_MB` doc comment that still said "per-language
  default" — there is no per-language fallback anymore, all unset
  values resolve to the unified 800MB `DEFAULT_NSJAIL_TMPFS_SIZE_BYTES`
  (codex/pi P2).
- Expand the resolver doc to call out that `Some(0)` and negative values
  also fall back, since the match arm is `Some(mb) if mb > 0`.

No behavior change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ruben Fiszel
2026-05-20 13:24:49 +00:00
committed by GitHub
co-authored by Claude Opus 4.7
parent 271f0cbd08
commit 9111f8908d
36 changed files with 172 additions and 61 deletions
+13 -11
View File
@@ -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 {
+21 -9
View File
@@ -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 {
@@ -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";
@@ -221,6 +221,8 @@ pub struct GlobalSettings {
#[serde(skip_serializing_if = "Option::is_none")]
pub job_default_timeout: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub nsjail_tmpfs_size_mb: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bun_install_min_release_age: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub uv_exclude_newer: Option<i64>,
@@ -90,7 +90,7 @@ mount {
dst: "/tmp"
fstype: "tmpfs"
rw: true
options: "size=500000000"
options: "size={NSJAIL_TMPFS_SIZE}"
}
@@ -90,7 +90,7 @@ mount {
dst: "/tmp"
fstype: "tmpfs"
rw: true
options: "size=500000000"
options: "size={NSJAIL_TMPFS_SIZE}"
}
mount {
@@ -53,7 +53,7 @@ mount {
dst: "/tmp"
fstype: "tmpfs"
rw: true
options: "size=500000000"
options: "size={NSJAIL_TMPFS_SIZE}"
}
mount {
@@ -70,7 +70,7 @@ mount {
dst: "/tmp"
fstype: "tmpfs"
rw: true
options: "size=800000000"
options: "size={NSJAIL_TMPFS_SIZE}"
}
mount {
@@ -72,7 +72,7 @@ mount {
dst: "/tmp"
fstype: "tmpfs"
rw: true
options: "size=800000000"
options: "size={NSJAIL_TMPFS_SIZE}"
}
mount {
@@ -64,7 +64,7 @@ mount {
dst: "/tmp"
fstype: "tmpfs"
rw: true
options: "size=500000000"
options: "size={NSJAIL_TMPFS_SIZE}"
}
mount {
@@ -61,7 +61,7 @@ mount {
dst: "/tmp"
fstype: "tmpfs"
rw: true
options: "size=500000000"
options: "size={NSJAIL_TMPFS_SIZE}"
}
@@ -54,7 +54,7 @@ mount {
dst: "/tmp"
fstype: "tmpfs"
rw: true
options: "size=500000000"
options: "size={NSJAIL_TMPFS_SIZE}"
}
@@ -55,7 +55,7 @@ mount {
dst: "/tmp"
fstype: "tmpfs"
rw: true
options: "size=500000000"
options: "size={NSJAIL_TMPFS_SIZE}"
}
@@ -55,7 +55,7 @@ mount {
dst: "/tmp"
fstype: "tmpfs"
rw: true
options: "size=800000000"
options: "size={NSJAIL_TMPFS_SIZE}"
}
mount {
@@ -55,7 +55,7 @@ mount {
dst: "/tmp"
fstype: "tmpfs"
rw: true
options: "size=800000000"
options: "size={NSJAIL_TMPFS_SIZE}"
}
mount {
@@ -68,7 +68,7 @@ mount {
dst: "/tmp"
fstype: "tmpfs"
rw: true
options: "size=800000000"
options: "size={NSJAIL_TMPFS_SIZE}"
}
mount {
@@ -58,7 +58,7 @@ mount {
dst: "/tmp"
fstype: "tmpfs"
rw: true
options: "size=500000000"
options: "size={NSJAIL_TMPFS_SIZE}"
}
mount {
@@ -55,7 +55,7 @@ mount {
dst: "/tmp"
fstype: "tmpfs"
rw: true
options: "size=500000000"
options: "size={NSJAIL_TMPFS_SIZE}"
}
@@ -55,7 +55,7 @@ mount {
dst: "/tmp"
fstype: "tmpfs"
rw: true
options: "size=500000000"
options: "size={NSJAIL_TMPFS_SIZE}"
}
@@ -54,7 +54,7 @@ mount {
dst: "/tmp"
fstype: "tmpfs"
rw: true
options: "size=500000000"
options: "size={NSJAIL_TMPFS_SIZE}"
}
@@ -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 {
+6 -2
View File
@@ -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![
+6 -2
View File
@@ -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),
)?;
+18 -1
View File
@@ -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,
@@ -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());
+6 -2
View File
@@ -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());
+6 -1
View File
@@ -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());
+6 -2
View File
@@ -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());
+6 -2
View File
@@ -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),
)?;
+6 -2
View File
@@ -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![
+10 -2
View File
@@ -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(),
)?;
+6 -1
View File
@@ -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());
+5 -2
View File
@@ -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());
+10 -2
View File
@@ -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());
+7
View File
@@ -681,6 +681,13 @@ lazy_static::lazy_static! {
pub static ref FLOW_RUNNER_RUNNING: Mutex<bool> = 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<RwLock<Option<i64>>> = Arc::new(RwLock::new(None));
}
pub fn sleep_queue() -> u64 {
if NATIVE_MODE_RESOLVED.load(std::sync::atomic::Ordering::Relaxed) {
300
@@ -245,6 +245,15 @@ export const settings: Record<string, Setting[]> = {
}
]
},
{
label: 'Nsjail tmpfs size (MB)',
key: 'nsjail_tmpfs_size_mb',
description:
'Override the size of the <code>/tmp</code> 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',