Remove the `docker_image_storage_size_mb` instance setting and the polling
storage monitor entirely. Now that `# docker` jobs are refused under nsjail
(the per-job podman daemon runs outside the sandbox), the asymmetry that
justified a docker-specific disk cap is gone: a normal job can already exhaust
host disk in non-nsjail modes, so a docker-only cap was inconsistent. Docker
jobs now use disk like any other job — bound it at the infra level.
Also scope the rootless slirp4netns network-backend override to the per-job
podman instance via a job-scoped `$HOME` containers.conf instead of a global
`/etc/containers` drop-in, so rootful podman elsewhere in the *-full image is
unaffected (flagged by cubic).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The per-job-podman bind-mount escape can read world-readable host state — including
world-readable /proc (process cmdlines/args via `-v /proc`), other job dirs'
world-readable files, and the dep cache — but NOT 0400 files like /proc/<pid>/environ
(env secrets stay protected on a root worker). Document this in the security notes
(README + compose + code comment) with the corollary: don't pass secrets as
command-line args (windmill uses env). Verified: uid-1000 container via `-v /proc`
reading a root process's environ -> 'Permission denied'; its cmdline -> readable.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Enabling nsjail is an explicit 'fully sandbox jobs' signal, but the per-job podman
daemon runs OUTSIDE the jail and a # docker script can bind-mount worker-visible
paths through it — silently providing it under nsjail would be a surprising hole in
a setup the operator hardened on purpose. So refuse instead: under nsjail, a
# docker job with no explicitly-provided Docker daemon errors with guidance to use
DOCKER_HOST (a network-reachable daemon; a mounted unix socket isn't reachable in
the jail) or a non-nsjail worker group. nsjail is off by default (DISABLE_NSJAIL
defaults true → default workers use unshare/none), so docker-via-podman keeps
working out of the box; this only gates the explicit-nsjail case. Docs updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When the docker worker runs as root (the default for compose/helm workers), start
the per-job podman via `runuser` dropped to a non-root uid so it runs rootless.
This keeps the worker's secrets in /proc/<worker>/environ (DATABASE_URL etc.)
root-owned and therefore unreadable by a `docker run --pid=host` container, and
makes a container escape land unprivileged — without the fragile namespace
confinement (no unshare/mask/pid-ns, which conflicted with podman system service).
A non-root worker can't drop further (podman runs rootless as itself; a --pid=host
container shares its uid), so run the docker worker as root for the /proc protection.
The per-job podman + its containers are spawned in a new process group so teardown
and the storage-cap monitor kill the whole tree (podman is a runuser grandchild).
This does NOT confine the container's filesystem view — a `# docker` script can
still bind-mount worker-visible paths — so docker-capable workers remain a
trusted-tenant capability (documented). Reverses the earlier `user: 1000` advice:
keep the worker root; windmill drops podman itself.
e2e verified (bare-metal, worker as root): stock docker job runs (dropped rootless
podman); a uid-1000 --pid=host container reading the root worker's /proc/environ ->
'Permission denied' (DATABASE_URL/secret protected).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Tag-only routing (no new ScriptLang — the bash executor handles the annotation):
a Bash script with the '# docker' annotation and no explicit tag is auto-tagged
'docker' at script-create (stored on script.tag, before no-op detection) and at
preview push. 'docker' is added to DEFAULT_TAGS so default workers serve it out of
the box; run a worker group with WORKER_TAGS=docker to route docker jobs to
dedicated/bigger workers. Mirrors the routing half of bunnative/nativets.
Soft size cap for the per-job rootless-podman image store via a new instance
setting docker_image_storage_size_mb (default 8GB; 0 = uncapped). A background
monitor polls the graphroot ('podman unshare du', robust to subuid-owned overlay
layers) and, past the cap, logs a clear error and tears the runtime down (kills the
service so an in-flight pull fails, 'system reset' to stop containers + free space).
This is the rootless-compatible enforcement: a uid-1000 worker cannot mount a sized
tmpfs even when privileged, so a kernel hard-cap isn't available; soft (overshoot
up to one ~2s poll). Without this, # docker jobs could fill the worker disk under
nsjail, unlike other languages capped by the nsjail tmpfs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the dedicated windmill_worker_docker group example with guidance on the
default worker: since # docker scripts are tagged "bash" they already run there,
so the only requirements are a *-full image (ships podman) and the /dev/fuse
device — no dedicated group or custom tag. Also note the *-full image's bundled
runtimes (Java, .NET, Ruby, R, Rust, Ansible, Nushell; Oracle/Kerberos in EE).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remove the per-worker-group container_runtime option entirely and decide the docker
runtime automatically: for a `# docker` job, if a Docker daemon is already provided
(DOCKER_HOST set or /var/run/docker.sock mounted) use it (backwards compatible,
unchanged); otherwise start a per-job rootless podman (its own ephemeral daemon,
torn down with the job). podman must be present (the *-full images) — else a clear
error.
Removed: container_runtime from WorkerConfigOpt/WorkerConfig/load_worker_config/
WORKER_CONFIG/monitor, the CE config allowlist entry, and the frontend "Container
runtime" toggle. docker-compose / README: the windmill_worker_docker example no
longer sets CONTAINER_RUNTIME (podman is automatic when no daemon is provided).
Verified e2e: a worker with no CONTAINER_RUNTIME and no DOCKER_HOST auto-runs a
# docker job via per-job podman; the provided-daemon (legacy) path is unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
docker-compose.yml / README: remove the legacy dind sidecar and the
DOCKER_HOST/host-socket opt-in comments (confusing now that podman is the way).
Present a single clean path: a dedicated windmill_worker_docker group with the
rootless podman runtime (full image, user 1000, privileged + /dev/fuse,
CONTAINER_RUNTIME=podman, WORKER_TAGS=docker). `# docker` scripts are tagged by
language ("bash"), so routing is via a custom "docker" tag — documented. The
legacy externally-provided DOCKER_HOST / mounted /var/run/docker.sock still works
in the backend; it's just no longer advertised in the quickstart.
DockerfileFull/FullEe: two fixes required for podman-in-container (found by
testing a containerized worker):
- chmod u+s newuidmap/newgidmap — rootless subuid mapping fails if the package's
file caps are lost in image layers.
- default rootless networking to slirp4netns (containers.conf.d) — the netavark
bridge default fails rootless on hosts without the needed nftables setup.
Verified e2e (podman-in-docker): a containerized worker ran a # docker job via
per-job rootless podman with both fixes + privileged + /dev/fuse; confinement held.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reframe the dind sidecar as legacy in docker-compose.yml and the README, and
point to the recommended path: a dedicated worker group with the rootless podman
container runtime (CONTAINER_RUNTIME=podman / the Container runtime UI option),
which keeps `# docker` scripts unchanged while removing the privileged daemon and
the network-reachable socket. Add a commented windmill_worker_docker example
(full image, user 1000, /dev/fuse) with honest caveats: it runs podman inside the
worker container, so memory monitoring needs cgroup v2 delegation and the
strongest isolation comes from a dedicated host.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The repo-root docker-compose.yml quickstart ran a privileged root Docker
daemon (dind) on tcp://dind:2375 with no TLS on the worker network, and
pointed workers at it via DOCKER_HOST. Because user scripts share the
worker network namespace (no --net isolation by design), any user who can
run a script could reach the daemon and escalate to root on the dind host.
This is a docs/deployment hardening change only — no worker sandbox or
network-isolation behavior is changed:
- Gate the dind sidecar behind the "dind" compose profile so it no longer
starts by default; make DOCKER_HOST and the dind depends_on opt-in.
- Add a prominent SECURITY WARNING comment on the dind service and a
warning callout in the README self-host section: trusted single-tenant
use only, never untrusted/multi-tenant.
- Document how to enable dind TLS + client-cert auth (DOCKER_TLS_CERTDIR,
tcp://dind:2376, cert volumes), including the caveat that TLS does not
protect against a malicious script running on the worker itself.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat: replace host docker socket with dind sidecar for isolation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: comment out dind sidecar by default to avoid wasting resources
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: enable dind by default, comment out insecure host socket mount
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Updates the debugger service to use port 3003 instead of 5679 across
all configuration files, documentation, and code references. This aligns
the debugger with the other windmill-extra services which use ports
3001 (LSP) and 3002 (Multiplayer).
Changes:
- docker-compose.yml: Update port exposure and add DEBUGGER_PORT env
- docker/entrypoint-extra.sh: Change default port from 5679 to 3003
- debugger/dap_debug_service.ts: Update default port in code and docs
- debugger/README.md: Update port documentation
- debugger/test_debug_service.ts: Update test URLs
- docker/test_windmill_extra.ts: Update test configuration
- .github/workflows/publish_extra.yml: Update test container ports
- frontend/src/lib/components/debug/*: Update frontend examples and defaults
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* use own folder for memory
* fixes
* better chat interface
* fix export tab
* move in folder
* dont show flow graph if chat mode
* fix
* fix too long title
* fix user message
* fix
* fix
* remove from server
* cleaner
* cleaning
* cleaning
* cleaning
* main docker file
* fix docker image build test tag
* don't remove tag
* make root user default
* chown tmp folder
* create search and logs folder in order to inherite windmill user permissions
* Dockerfile
* lsp non root
* improving lsp image to get rid of critical vulnerabilities
* formatting
* support /root/.cache mount
* make the cache mount backwards compatible
* Add indexer crate and files
* POC searcher
incomplete schema
only indexes at startup
* POC search component frontend
* Demo of the frontend element
* add Results and Args as text
* minimal functionality
* Make jump to scripts by name
also flows and apps
* Add button on sidebar to open search
* Update lock on indexer after merge
* Make arrow key navigation compatible with scrol
* Show empty result screen and log as a coming feat
* Add summary to script searchable items
* Catch `parts is undefined` error (uFuzzy)
* Index refreshing using tokio interval
* Fix JobLoader workspace being wrongly defined
* Fix click outside
* Add debouncing for completed run search
* Binary mode working + job index tracker
* Warning for no license + fix height scrollbars on content search
* Make it compile without EE files
* remove panic to use errors
* Move global search
* Cleanup UI, no more tab switcher but clear placeholders and actions
* Add tantivy feature flag for windmill-api
* Rework indexer mode
* Mac compatibility for shortcut
* Update test for new run_server
* Prepare sqlx
* Mac compatibility
* Fix openapi yaml
* Fix frontend
* Frontend api fix
* Update docker-compose.yml and caddyfile
With the (by default deactivated) container and reverse proxy to use the
windmill indexer
* fix feature flag for tests
* fix feature falg for running tests
* fix feature flag for running tests
* Make content search use search modal instead
* Add tantivy feature to ee build steps
* Remove old Content search
* change volume location for indexer
* Update dependencies
* Prepare sqlx
* Uncomment line on docker compose
* Add line between input and results
* Update ee repo ref