Setting external modules on n8n's Code node
You can use most npm libraries on n8n's Code node.
Introduction
n8n is a powerful workflow automation tool. By default, it comes with many built-in nodes and functions. However, sometimes you may want to use external npm packages to extend its functionality. In this post, I'll show you how to do that in a few simple steps.
Why use external modules?
- Access libraries that are not included by default
- Simplify complex logic with well-tested libraries
- Reuse the same codes you already use in your Node.js projects
Step 1: Fork n8n-docker-caddy & setting overrides
However n8n can support external modules, I don't recommend modifying the files directly in your instance, so fork the n8n-docker-caddy and manage your settings in your repository.
- Fork Repository
- Setting up custom domain
- Add npm install in Dockerfile
- Setting up environment variables in docker compose config)
I created a Github repository that's already set up for customization. My forked repository
cat overrides/Caddyfile.local# Replace <domain>.<suffix>n8n.<domain>.<suffix> {reverse_proxy n8n:5678 {flush_interval -1}}
cat overrides/Dockerfile.n8n-customARG N8N_TAG=1.111.0FROM docker.n8n.io/n8nio/n8n:${N8N_TAG}USER root# install libraries you wantRUN npm explore -g n8n -- npm i --omit=dev yahoo-finance2 && npm cache clean --forceUSER node
cat overrides/docker-compose.override.ymlservices:n8n:build:context: ./overridesdockerfile: Dockerfile.n8n-customargs:N8N_TAG: ${N8N_TAG:-1.111.0}environment:# Setting up here- N8N_ENABLE_EXTERNAL_MODULES=true- NODE_FUNCTION_ALLOW_EXTERNAL=yahoo-finance2caddy:volumes:- ./overrides/Caddyfile.local:/etc/caddy/Caddyfile:ro
Step 2: Setting in several files your instance
git clone https://github.com/<your-org>/n8n-docker-caddy.gitcd n8n-docker-caddysudo docker volume create caddy_datasudo docker volume create n8n_datavim .envvim overrides/Caddyfile.localsudo docker compose up -d
Step 3: Testing on n8n
Once the module is installed, you can import and use it inside a Code node. Here's an example that fetches the current stock chart with yahoo-finance2
.
const yf = require("yahoo-finance2").default;const ticker = query.ticker;if (!ticker) {throw new Error("ticker is required");}const period = query.period || "1y";const interval = query.interval || "1d";const columns = query.columns || [];const limit = Number(query.limit ?? 0);function computePeriod1(periodStr) {const now = Date.now();const ONE_DAY = 24 * 60 * 60 * 1000;const m = {"1mo": 30,"3mo": 90,"6mo": 182,"9mo": 273,"1y": 365,"2y": 730,"5y": 1826,};if (!periodStr || periodStr === "max") return new Date(0);if (periodStr === "ytd") {const d = new Date();return new Date(d.getFullYear(), 0, 1);}if (m[periodStr]) return new Date(now - m[periodStr] * ONE_DAY);const dt = new Date(periodStr);if (!isNaN(dt)) return dt;return new Date(now - 365 * ONE_DAY);}function filterColumns(row, columns) {if (!Array.isArray(columns) || columns.length === 0) return row;const out = {};for (const c of columns) {if (c in row) out[c] = row[c];}return out;}const period1 = computePeriod1(period);const period2 = new Date();const res = await yf.chart(ticker, {period1,period2,interval,});let rows = (res.quotes || []).map((q) => {return { ...q, date: q.date instanceof Date ? q.date.toISOString() : q.date };});if (limit > 0 && rows.length > limit) {rows = rows.slice(-limit);}rows = rows.map((r) => filterColumns(r, columns));return JSON.stringify({ticker,period,interval,rows,});
Updating n8n container
Just pull and up the n8n container.
Switch from the official repo to your fork(origin/upstream setup)
If you already cloned the official repo, switch origin from upstream to your forked repo. You should keep your changes isolated on a dedicated branch (e.g., custom/main
). This keeps upstream clean while giving you full control over dependencies.
# stash your upstream's changegit stashgit remote rename origin upstreamgit remote add origin https://github.com/<your-org>/n8n-docker-caddy.gitgit remote -vgit fetch origin --tagsgit checkout -b custom/main origin/custom/main# Now update your configs
Conclusion
By managing n8n with a forked repository and enabling external modules, you can safety extend your workflows with npm libraries. Start small with one library, and you'll quickly see how much more powerful your automation can become.