Setting up python libraries on the self hosted n8n

Describe the problem/error/question

Hi guys!
Me and my colleagues are having hard time setting up the python libraries which can be used with the code node in our workflows.
We are using Docker on the Ubuntu machine.
The docker-compose.yml, task-runners.json and Dockerfile are already set up by my colleauge who used only HTTP request nodes. He did not use the code node with custom Python/JS libraries.
Locally on my PC, I installed Docker desktop, set up the docker-compose.yml, task-runners.json and Dockerfile and everything worked fine. When I tried to reproduce that on the production I got the errors. I will paste the errors below.
First we tried setting up the pdf-lib JS library, then we tried setting up the pypdf library.
Could you please help us resolve the issue.
How can we set up custom JS/Python libraries?
What are the best practices (regarding the containers setup) if multiple users are going to create workflows in n8n?

What is the error message (if any)?

Error message in terminal: root@n8nsvrp01:~/n8n-docker# sudo docker compose up -d --build task-runners
WARN[0000] Docker Compose is configured to build using Bake, but buildx isn’t installed
[+] Building 0.8s (7/7) FINISHED docker:default
=> [task-runners internal] load build definition from runner.Dockerfile 0.0s
=> => transferring dockerfile: 399B 0.0s
=> [task-runners internal] load metadata for Docker Hub Container Image Library | App Containerization 0.5s
=> [task-runners internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [task-runners 1/4] FROM Docker Hub Container Image Library | App Containerization 0.0s
=> => resolve Docker Hub Container Image Library | App Containerization 0.0s
=> CACHED [task-runners 2/4] WORKDIR /build 0.0s
=> CACHED [task-runners 3/4] RUN npm init -y && npm install pdf-lib 0.0s
=> ERROR [task-runners 4/4] RUN cd /opt/runners/task-runner-python && VIRTUAL_ENV=/opt/runners/task-runner-python/.venv uv pip install --python /opt/runners/task-runner-python/.venv/bin/python pypdf && chown -R runner 0.2s

[task-runners 4/4] RUN cd /opt/runners/task-runner-python && VIRTUAL_ENV=/opt/runners/task-runner-python/.venv uv pip install --python /opt/runners/task-runner-python/.venv/bin/python pypdf && chown -R runner /opt/runners/task-runner-python/.venv:
0.183 /bin/sh: cd: line 0: can’t cd to /opt/runners/task-runner-python: No such file or directory


failed to solve: process “/bin/sh -c cd /opt/runners/task-runner-python && VIRTUAL_ENV=/opt/runners/task-runner-python/.venv uv pip install --python /opt/runners/task-runner-python/.venv/bin/python pypdf && chown -R runner /opt/runners/task-runner-python/.venv” did not complete successfully: exit code: 2

Please share your workflow

Share the output returned by the last node

Cannot find module ‘pako’ Require stack: - /opt/runners/task-runner-javascript/node_modules/@pdf-lib/standard-fonts/lib/utils.js - /opt/runners/task-runner-javascript/node_modules/@pdf-lib/standard-fonts/lib/Font.js - /opt/runners/task-runner-javascript/node_modules/@pdf-lib/standard-fonts/lib/index.js - /opt/runners/task-runner-javascript/node_modules/pdf-lib/cjs/utils/objects.js - /opt/runners/task-runner-javascript/node_modules/pdf-lib/cjs/utils/index.js - /opt/runners/task-runner-javascript/node_modules/pdf-lib/cjs/core/errors.js - /opt/runners/task-runner-javascript/node_modules/pdf-lib/cjs/core/index.js - /opt/runners/task-runner-javascript/node_modules/pdf-lib/cjs/api/objects.js - /opt/runners/task-runner-javascript/node_modules/pdf-lib/cjs/api/operators.js - /opt/runners/task-runner-javascript/node_modules/pdf-lib/cjs/api/colors.js - /opt/runners/task-runner-javascript/node_modules/pdf-lib/cjs/api/operations.js - /opt/runners/task-runner-javascript/node_modules/pdf-lib/cjs/api/form/appearances.js - /opt/runners/task-runner-javascript/node_modules/pdf-lib/cjs/api/form/index.js - /opt/runners/task-runner-javascript/node_modules/pdf-lib/cjs/api/index.js - /opt/runners/task-runner-javascript/node_modules/pdf-lib/cjs/index.js - /opt/runners/task-runner-javascript/dist/js-task-runner/require-resolver.js - /opt/runners/task-runner-javascript/dist/js-task-runner/js-task-runner.js - /opt/runners/task-runner-javascript/dist/start.js

Information on your n8n setup

  • n8n version: 2.17.8.
  • Database (default: SQLite): Postgre:15
  • n8n EXECUTIONS_PROCESS setting (default: own, main):
  • Running n8n via (Docker, npm, n8n cloud, desktop app): Docker
  • Operating system: Ubuntu 26.04

Hey @Todor_n8n, while you wait for a response, here are some things that might help:

Suggested resources

Automatically matched to your question.

Docs:

Forum:

@salmansolutions, @MehranZ, @Miquel_Colomer - you’ve helped with similar issues before, can you take a look?

Automatically suggested by n8n’s community bot. It’s a pilot - please share feedback here.

Thank you so much Lopez for fast and detailed response!
We will try to make the fixes.

Best regards,

Todor

Hey @Todor_n8n ,
this is a classic “almost the right Dockerfile, wrong directory” situation. I’ve hit both of these exact errors.

The Python build is dying because /opt/runners/task-runner-python isn’t in the image you’re building from. That folder only exists on n8nio/runners, and the tag needs to match n8n (2.17.8). If FROM is n8nio/n8n, a Node image, or some JS-only custom image, cd fails immediately. Also skip the WORKDIR /build + npm init -y dance — that creates a brand new project the Code node never looks at.

For JS, the runner already has its own package tree at /opt/runners/task-runner-javascript, and it uses pnpm, not npm. pdf-lib showing up while pako is missing is what you get when npm installs into a different folder (or only copies the top-level package). pako is a nested dep, and the runner’s require resolver is pretty picky about where it looks.

This is the pattern that actually works:
```FROM n8nio/runners:2.17.8

USER root
RUN cd /opt/runners/task-runner-javascript && pnpm add pdf-lib
RUN cd /opt/runners/task-runner-python && uv pip install pypdf
COPY n8n-task-runners.json /etc/n8n-task-runners.json
USER runner```

Then allowlist them in n8n-task-runners.jsonNODE_FUNCTION_ALLOW_EXTERNAL for JS, N8N_RUNNERS_EXTERNAL_ALLOW for Python. Installing the package is not enough; the allowlist is a separate gate. For JS you’ll want pako on that list too, or * while you’re still debugging.

On the “worked on my laptop, exploded on Ubuntu” bit: your log already shows the npm layer as CACHED, and Compose is complaining that Bake/buildx isn’t installed. After you fix the Dockerfile, rebuild with --no-cache, and install docker-buildx-plugin so you’re not fighting the builder on top of everything else.

For a shared instance, I’d keep one custom runners image with a small, agreed-upon set of libs, pin the n8n + runners tags together, and treat adding a package as a rebuild — not something people do inside a running container. Wildcard allowlists are fine while you figure this out; in prod I’d list packages explicitly.

If you can paste the Dockerfile FROM line and the task-runners service from compose, it’s usually obvious in ten seconds why that Python path is missing.

Hi @Todor_n8n Welcome!
n8n denies every Python standard library import by default, so once the image builds, import pypdf still fails on pypdf’s own internal imports of zlib, struct and hashlib. Set the transitive imports flag in the python block of n8n-task-runners.json, which lets an allowlisted package’s own imports skip the allowlist:

{
  "runner-type": "python",
  "env-overrides": {
    "PYTHONPATH": "/opt/runners/task-runner-python",
    "N8N_RUNNERS_EXTERNAL_ALLOW": "pypdf",
    "N8N_RUNNERS_ALLOW_TRANSITIVE_IMPORTS": "true",
    "N8N_RUNNERS_STDLIB_ALLOW": "io,base64"
  }
}

What you import yourself in the Code node is still checked against the allowlist, so N8N_RUNNERS_STDLIB_ALLOW has to list the stdlib modules your own script uses.

Thank you Anatoly for taking your time to answer my questions!
I will take a look and let you know.

Best regards,

Todor

Thank you Anshul for helping me out with the problems our team had!
I will take a look and let you know.

Best regards,

Todor

it’s my pleasure, do you use whatsapp? I am interested in collaborating with you.