From beac17fe6e2dd86c29a73583ba4b703ff1b0ea5a Mon Sep 17 00:00:00 2001 From: Tomi Turtiainen <10324676+tomi@users.noreply.github.com> Date: Tue, 27 Jan 2026 00:26:48 +0200 Subject: [PATCH] Add more documentation how to secure task runners (#4146) Co-authored-by: Kartik Balasubramanian <22399046+HumanistSerif@users.noreply.github.com> --- docs/hosting/configuration/task-runners.md | 8 ++++++-- docs/hosting/securing/hardening-task-runners.md | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/docs/hosting/configuration/task-runners.md b/docs/hosting/configuration/task-runners.md index b1bec1c06..2bc9c3da5 100644 --- a/docs/hosting/configuration/task-runners.md +++ b/docs/hosting/configuration/task-runners.md @@ -10,6 +10,10 @@ Task runners are a generic mechanism to execute tasks in a secure and performant This document describes how task runners work and how you can configure them. +/// warning | Internal mode not recommended for production +Using internal mode in production environments can pose a security risk. For production deployments, use [external mode](#external-mode) to ensure proper isolation between n8n and task runner processes. Refer to [Hardening task runners](/hosting/securing/hardening-task-runners.md) for additional security measures. +/// + ## How it works The task runner feature consists of these components: one or more task runners, a task broker, and a task requester. @@ -36,7 +40,7 @@ In external mode, a [launcher application](https://github.com/n8n-io/task-runner ![Task runner deployed as a side-car container](/_images/hosting/configuration/task-runner-external-mode.png) -When using [Queue mode](/hosting/scaling/queue-mode.md), each worker needs to have its own sidecar container for task runners. +When using [Queue mode](/hosting/scaling/queue-mode.md), each worker needs to have its own sidecar container for task runners. In addition, if you haven't enabled offloading manual executions to workers (if you aren't setting `OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true` in your configuration), then your main instance will run manual executions and needs its own sidecar container for task runners as well. Please note that running n8n with offloading disabled isn't recommended for production. @@ -117,7 +121,7 @@ The default launcher configuration file is locked down, but you can edit this fi path/to/n8n-task-runners.json:/etc/n8n-task-runners.json ``` -## Adding extra dependencies +## Adding extra dependencies ### 1. Extend the `n8nio/runners` image diff --git a/docs/hosting/securing/hardening-task-runners.md b/docs/hosting/securing/hardening-task-runners.md index 784b3465f..4465fc72c 100644 --- a/docs/hosting/securing/hardening-task-runners.md +++ b/docs/hosting/securing/hardening-task-runners.md @@ -11,3 +11,19 @@ contentType: howto ## Run task runners as sidecars in external mode To increase the isolation between the core n8n process and code in the Code node, run task runners in [external mode](/hosting/configuration/task-runners.md#setting-up-external-mode). External task runners launch as separate containers, providing a fully isolated environment to execute the JavaScript defined in the Code node. + +## Use the distroless image + +For a reduced attack surface, use the distroless Docker image variant. Distroless images contain only the application and its runtime dependencies, excluding package managers, shells, and other utilities that aren't needed at runtime. + +To use the distroless image, append the `-distroless` suffix to the Docker tag. For example: `2.4.6-distroless`. + +## Run as the nobody user + +For improved security, configure task runners to run as the unprivileged `nobody` user with user and group ID 65532. This prevents the container process from running with root privileges and limits potential damage from security vulnerabilities. + +## Configure read-only root filesystem + +Configure a [read-only root filesystem](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) to prevent any modifications to the container's filesystem at runtime. This helps protect against malicious code that might attempt to modify system files. + +Task runners still require some temporary storage for operation. To accommodate this, mount a minimal `emptyDir` volume to `/tmp`. If your workflows require more temporary space, increase the size of the volume accordingly.