What you need
According to the docs, that size is a starting point, not a measured minimum. Several browser tasks at once or local models need more. For a rented server, the docs name Hetzner Cloud and DigitalOcean, each with Ubuntu 24.04. Hetzner bills you for a server even when it's powered off, according to the docs, as long as it exists. Small free machines have less memory than the starting size. Which hardware suits local models and what it costs is in Your Own AI Server: Hardware and Cost.
Prebuilt bundle or source
The docs describe two routes. Prebuilt server bundles with an installer sit in the “private Nod releases”; you can only download them with access to the repository. Bundles from automated builds expire after 14 days, according to the docs. The advantage of a bundle: the server doesn't have to compile anything.
The public route is building from source. The server then builds the application and its browser tools itself. Neither route needs a separate database, PostgreSQL runs in the stack. I took the source route, and that's the one I describe here.
Step by step: build Nod from source
1. Get the code
git clone --depth 1 --branch nod-v0.7.6 https://github.com/n8n-io/nod.git
cd nod/deployment/self-host
The docs clone without --branch. I pinned a version because, for updates, the docs advise pinning a release or commit so you know what runs on your server. The current version is listed in the GitHub releases.
2. Generate the configuration
sh setup.sh
The script creates a private .env file with the server token, the Vault key for saved credentials and the database password. According to the docs, it never prints the secrets and leaves an existing .env alone. In my run the file had permissions 600, and the script checked for Docker Engine 25 or newer and OpenSSL first. Keep this file on the server and never show it on screen, for example in a recording.
3. Build and start
docker compose up -d --build --wait
I ran the command with --file compose.yaml --env-file .env, the files it uses anyway. My first build ran from 12:57 to 13:09, so about 12.5 minutes. Most of that time went into downloads: the Rust image, Debian packages including LibreOffice, and npm packages, some of them at under 50 KiB/s. Keep the terminal open until the command finishes. Later starts reuse the built images.
Afterwards, six containers reported “healthy”. The three large images:
4. Open it in the browser
On the same computer, open http://localhost:4310. If the server is somewhere else, open an SSH tunnel first (below). In my test the port was bound to 127.0.0.1 only; the Compose file uses 127.0.0.1 unless you change NOD_BIND_ADDRESS. A request without the token got HTTP 403.
The access form needs the value of NOD_AUTH_TOKEN from .env. Instead of opening the file, on a Mac you can copy it straight to the clipboard without it ever showing on screen:
grep '^NOD_AUTH_TOKEN=' .env | cut -d= -f2- | tr -d '\n' | pbcopy
If the server is somewhere else, pull the token over SSH straight into your Mac's clipboard without it showing on any screen:
ssh <user>@<server-address> "grep '^NOD_AUTH_TOKEN=' nod/deployment/self-host/.env | cut -d= -f2-" | tr -d '\n' | pbcopy
Adjust the path to the folder you cloned Nod into.
5. Finish setup
What follows is the same setup as in the app: optional email, a few questions about you, a model, the choice about conversation traces. According to the docs you don't need a model key to install, but Nod can't work without a model.
What runs on the server
With HTTPS, a seventh container joins: Caddy as a reverse proxy. According to the docs, database, workspace and browser stay private, and model keys and saved credentials stay with the server, outside the workspace and browser containers. Data lives in named Docker volumes. Recreating a container keeps them; deleting the volumes deletes your data.
Access from outside
SSH tunnel without a domain
The simplest way onto a remote server is SSH. On your own computer:
ssh -L 4310:127.0.0.1:4310 <user>@<server-address>
Keep the connection open and visit http://localhost:4310. NOD_PUBLIC_URL stays at its default for this, and you still need the token. For another port, change PORT in .env and use it in the tunnel and the browser address too.
HTTPS with a domain and Caddy
Point a domain such as nod.example.com at your server's public address and allow inbound TCP 80 and 443.
Set this in .env: NOD_PUBLIC_URL=https://nod.example.com
Start with the HTTPS profile:
docker compose --profile https up -d --build --wait
Open your HTTPS address and enter the token.
Caddy obtains and renews the certificate. According to the docs, keep using --profile https for every start, stop and status command from then on. If the certificate fails, check DNS and whether your provider or router blocks ports 80 or 443. If you already run your own reverse proxy, forward to port 4310, preserve the Host header, support WebSockets and streaming, and set NOD_PUBLIC_URL to exactly that HTTPS origin.
Connect the desktop app to the server
On the app's first launch choose Connect to a server, later through Replay onboarding… in the Nod menu. Then enter the server address and the token: the HTTPS address, or http://localhost:4310 while your SSH tunnel is open. The app verifies the server before saving the token in your operating system's secure storage.
From then on the app uses the server's conversations, files, models and accounts. Closing it doesn't stop the server. The app's local assistant stays separate; according to the docs, no data moves across. For ChatGPT sign-in on a remote server, you copy the final browser address into Callback URL; you don't need to open port 1455, according to the docs.
Connect apps on the server
Open Apps and select Connect. For apps through Composio, Nod opens a sign-in page at your NOD_PUBLIC_URL. Choose Continue to sign in, finish authorization in the new window and keep the first page open until the connection completes. If your browser blocks popups, allow them for Nod. The SSH tunnel or HTTPS proxy you use to open Nod also carries this sign-in; you don't need another port, according to the docs. After a server restart or a new address, start the connection again.
Telegram and WhatsApp
Under Channels you connect Telegram or WhatsApp; both share the server's assistant. For a server, the docs say:
- Telegram polling and WhatsApp via QR code connect outbound. They work without a domain and without opening a port on your router.
- Telegram webhooks and Meta's WhatsApp Cloud API need a public HTTPS address.
- For Telegram you create a bot with BotFather. After that, only the Telegram account you pair can message Nod.
- According to the docs, the WhatsApp QR connection uses Baileys, an unofficial WhatsApp client. n8n mentions a small risk of account restrictions and recommends a separate bot number.
- Sign-ins and payments stay in the web or desktop app; they never go through the chat.
On the server, channels stay connected as long as it runs.
Security: what you need to know
One server, one person. According to the docs, there's no registration and no multi-user setup. The token grants full access to the assistant and every connected account. Treat it like the password to your inbox. To replace it, generate a new one on the server with openssl rand -hex 32, replace NOD_AUTH_TOKEN in .env and recreate the server with docker compose up -d --wait server. The command prints the new token in the terminal; never run it while recording or sharing your screen. Never replace NOD_VAULT_KEY for this, or your saved credentials become unreadable.
Docker socket in a helper container. So the server can control workspace and browser, the runtime container gets the host's Docker socket (/var/run/docker.sock). Whoever can use that socket effectively has root on the host. That's why Nod hands it only to the helper container, which according to the docs gives the server a restricted Docker connection. The Compose file for version 0.7.6 therefore keeps this helper small: read-only file system, all Linux capabilities dropped, 128 MB of memory. According to the docs, the workspace itself gets no socket. The docs are clear on this: never expose PostgreSQL, the browser, the workspace or the Docker connection.
NET_ADMIN for the workspace firewall. The workspace-network container gets one capability, NET_ADMIN. According to the docs, it blocks private and reserved IPv4 destinations and external IPv6 traffic, and the workspace only starts once this firewall is ready. Its DNS requests go to 1.1.1.1 and 8.8.8.8. If you change the Compose file, keep this service and its network settings.
Metadata services on cloud servers. On cloud VMs, metadata services can hand cloud credentials to workspace commands. According to the docs, the workspace firewall also blocks cloud metadata services. So keep it on and also restrict metadata access at your provider, on AWS for example through instance metadata options.
Use your provider's firewall. According to the docs, Docker's published ports can bypass ufw rules. So use your provider's firewall as well, open only 80 and 443 for the proxy and restrict SSH to your address. Keep token authentication on in a private network or over a VPN too. How to harden a server in general, with keys instead of passwords, updates and a network filter, is in Securing Your Own Server: Linux and Windows. Which data still goes to the model, n8n and other services despite your own hardware is in Nod Privacy: What the AI Agent by n8n Shares.
Running it long term: backups and updates
The containers restart when Docker starts. Run these commands in the nod/deployment/self-host folder, with --profile https if you use HTTPS:
Never use docker compose down --volumes unless you really want to delete the data.
Backup. Wait for active work to finish and give a new target directory whose parent already exists:
sh backup.sh /absolute/path/nod-backup-2026-11-15
The script stops server, browser and workspace while it copies and then restarts whatever was running before. According to the docs, the backup holds the .env with token, Vault key and database password, a database dump, the server, workspace and browser data, and the commit you built from. So the backup contains secrets: store it encrypted, restrict access and keep a copy off the server. TLS certificates aren't included; Caddy gets new ones.
Restoring only works into a fresh installation, according to the docs: clone Nod into a new folder, check out the commit recorded in the backup and run sh restore.sh /absolute/path/nod-backup-2026-11-15 nod-restored in deployment/self-host, without running setup.sh first. Stop the old server before starting the new one, or schedules run twice. A restore returns data to the backup's point in time; it doesn't undo messages or actions that happened afterwards.
Updating a source install. Read the release notes, make a backup, then:
docker compose stop
git fetch origin --tags
git checkout <release-tag-or-commit>
docker compose up -d --build --wait
Database migrations run when Nod starts. According to the docs, an older version must never point at an already upgraded database. The only way back is the backup from before the update.
Nod on a Mac mini
According to the docs, a Mac mini is simply another server for Nod: the Linux containers run in Docker Desktop's virtual machine, as ARM64 on Apple silicon and AMD64 on Intel. It's the same stack as on a Linux server. You don't need the desktop app's local assistant on the Mac mini. My test ran on a MacBook with Docker Desktop, not on a Mac mini; according to the docs, the setup is the same.
How to prepare the Mac:
- Install Docker Desktop for your processor, Apple silicon or Intel.
- Give Docker 8 GB of memory to start and plan for 50 GB of free disk, with room left for macOS.
- In Docker Desktop, turn on “Start Docker Desktop when you sign in to your computer”. Docker then starts after sign-in, not before it.
- Keep the Mac awake while Nod should run. After a power cut or restart, sign in and check that Docker and Nod are up. According to the docs, a Mac with FileVault turned on never signs in automatically.
- Install Nod as described above, in a folder used only for this installation.
Access while you're out. For public access you use a domain and HTTPS, and your router has to forward ports 80 and 443 to the Mac. Some home internet connections block inbound traffic or share one public address among many customers (carrier-grade NAT), and then this won't work. For private access, open an SSH tunnel to the Mac, directly or over your VPN. According to the docs, a VPN alone isn't enough: it neither exposes the port bound to 127.0.0.1 nor provides the HTTPS Nod requires for a remote address. Telegram and WhatsApp via QR code work without opening your router.
Data. The desktop app and the server stack keep separate data. Before an update or a macOS reinstall, run a backup with backup.sh. According to the docs, copying the repository folder alone doesn't save your assistant. If you also want to run local models on the same Mac mini, Local AI on a Mac shows which memory size fits.
Frequently asked questions
Do I need a Mac mini for Nod?
No. According to the docs, the same stack runs on any Linux server with Docker, AMD64 or ARM64, and on any Mac with Docker Desktop. A Mac mini is one way to run Nod on your own hardware at home.
How much memory and disk does Nod need on a server?
The docs give two CPU cores, 8 GB of memory and 50 GB of disk as a starting size, explicitly not a measured minimum. In my test, the three large images alone took about 4.9 GB together, and free space dropped by about 9 GB at times during the build.
Can I use Nod on the go without a domain?
Yes, through an SSH tunnel to the server. Telegram and WhatsApp via QR code need neither a domain nor an open port. You only need a domain with HTTPS if you want to open Nod in a browser without a tunnel or use webhooks.
Can my team share one Nod server?
Not according to the docs. A server belongs to one person, and the token grants full access to every connected account. “Nod for your team” is on n8n's list for later. Until then, each person needs their own installation; on one computer, the docs say that works with a separate folder and port per installation.
Does Nod keep running when I close my laptop?
With your own server, yes: schedules, Telegram and WhatsApp keep running as long as the server does. With the desktop app on your laptop, no.
Can I keep using the desktop app?
Yes, as a window onto the server through Connect to a server. The app's local assistant stays separate, and conversations and accounts aren't transferred.
What to do next
Build the server where you can see it anyway, and reach it through an SSH tunnel. Add a domain, HTTPS and open ports only when you actually need them. Before Nod gets near real accounts, set up the backup and test it once with a restore. Harden the server like any other, as described in Securing Your Own Server: Linux and Windows. How an own server with Claude Code and Slack for several AI employees is built, with its own session and bot per role, is what I show in Claude Code on a Server: tmux, Remote Control; that's my setup and a very different approach from Nod. How the two ways compare on cost, billing and operation is in Nod vs Claude Code: AI Agents Compared. In my German-language community Claude Practitioners I show how I build AI employees with clear permissions and approvals.