Getting n8n running from the GitHub repository takes about five minutes: clone, copy the env file, docker compose up. Keeping it running as something you depend on takes considerably longer, and the gap is Postgres instead of SQLite, TLS, a webhook URL that resolves from outside, backups of an encryption key, and an upgrade path.
The n8n repositories are good and the quickstart works. What a quickstart cannot tell you is which of its defaults are fine forever and which are placeholders for a real deployment. Several of the defaults are the second kind, and one of them — the encryption key — will silently destroy every credential you have stored if you get it wrong.
Table of contents
- What is in the repositories
- Move off SQLite before you rely on it
- The encryption key, which you must not lose
- TLS, the domain, and webhook URLs
- Resources, upgrades, and the ongoing part
- Self-hosted or managed
- How this fits the rest of the stack
- FAQ
What is in the repositories
There are a few distinct things on GitHub and it is worth knowing which is which.
- n8n-io/n8n — the application source. Clone this to contribute or to build from source. Not what you want for running it.
- n8n-io/n8n-hosting — compose and Kubernetes examples for various environments. This is the reference for a deployment.
- n8n-io/self-hosted-ai-starter-kit — a bundle of n8n with a local model runner and a vector store. A good demonstration and considerably more than you need if you only want n8n.
For running it, the official Docker image is the route rather than building from source:
docker volume create n8n_data
docker run -it --rm \
--name n8n \
-p 5678:5678 \
-e GENERIC_TIMEZONE="Europe/London" \
-e TZ="Europe/London" \
-e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true \
-e N8N_RUNNERS_ENABLED=true \
-v n8n_data:/home/node/.n8n \
n8nio/n8n
That gets you a working instance on port 5678 with data in a named volume. It is a fine way to try it. It is not a deployment, for the reasons below.
Pin the image to a version tag rather than using latest. An unattended container that pulls a new major version and applies migrations you did not plan for is a bad way to spend a morning.
Move off SQLite before you rely on it
n8n defaults to SQLite, which is genuinely fine for evaluating it and a poor choice for anything you depend on.
SQLite is a single file with a single writer. Under concurrent workflow executions it locks, the database file grows steadily with execution history, and backing it up correctly while the application is running requires care that a naive file copy does not provide. It also rules out running more than one n8n process, which forecloses both scaling and a queue-mode worker setup.
Switch to Postgres, which n8n supports directly:
services:
n8n:
image: n8nio/n8n:1.60.0
restart: unless-stopped
ports:
- "5678:5678"
environment:
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=n8n
- DB_POSTGRESDB_USER=n8n
- DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
- N8N_HOST=n8n.example.com
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://n8n.example.com/
- GENERIC_TIMEZONE=Europe/London
volumes:
- n8n_data:/home/node/.n8n
depends_on:
- postgres
Do this before you build workflows, because migrating an established SQLite instance to Postgres afterwards is an export and import you would rather not perform on something people are using.
Also set an execution data retention policy. n8n stores the full data of every execution by default, and on a busy instance that grows without limit until the disk fills. EXECUTIONS_DATA_MAX_AGE and EXECUTIONS_DATA_PRUNE control it, and the default is not what you want in production.
The encryption key, which you must not lose
This is the single most important thing in this article.
n8n encrypts every stored credential — API keys, OAuth tokens, database passwords, everything — with a key. If you do not set N8N_ENCRYPTION_KEY, one is generated on first run and written into the data volume.
Lose that key and every credential in your instance becomes permanently unreadable. Not resettable — unreadable. You re-enter every credential in every workflow by hand, which for an instance connecting to twenty services is a very long afternoon and requires you to still have all twenty credentials somewhere.
The ways people lose it are mundane. Recreating the container without the volume. Restoring the database from backup onto a fresh instance with a new generated key. Moving to a new host and copying the database but not the volume.
So: set it explicitly as an environment variable, store it in a password manager or secret store, and back it up separately from the database. A database backup without the encryption key is not a complete backup, and that fact is not obvious until you try to restore.
openssl rand -hex 32
Set it before creating any credentials. Changing it later means the existing ones cannot be decrypted, which is the same problem arriving on your own schedule.
TLS, the domain, and webhook URLs
n8n serves plain HTTP on port 5678. Putting that on the internet directly means credentials and workflow data cross the network unencrypted.
Run a reverse proxy in front with a certificate. Caddy, nginx with certbot, or Traefik all work; Caddy is the least configuration for this specific job.
Then tell n8n what its public address is, which matters more than it appears:
N8N_HOST=n8n.example.com
N8N_PROTOCOL=https
N8N_PORT=443
WEBHOOK_URL=https://n8n.example.com/
WEBHOOK_URL is the one that causes confusion. n8n generates webhook URLs to hand to external services, and without this it generates them from its internal address. You copy a URL beginning with localhost into a payment provider’s dashboard, it never fires, and nothing in the n8n interface indicates why.
If webhooks are central to what you are doing, note that they must be reachable from the internet, which means either a public address or a tunnel. An n8n instance on a home network behind NAT can call out perfectly well and cannot receive a webhook without one.
Enable authentication as well. n8n has user management, and an instance reachable without a login is an instance where anyone can read your stored credentials through the workflow editor.
Resources, upgrades, and the ongoing part
n8n is a Node application and it is not especially light. A single container running modest workflows wants around 1GB of RAM as a floor, and more if workflows process sizeable payloads — a workflow handling a large file holds it in memory.
Queue mode splits execution into separate worker processes coordinated through Redis, which is how you scale beyond one instance. It is more moving parts and it is the answer when a single instance cannot keep up.
Upgrades are the recurring cost. n8n releases frequently, some releases include database migrations, and occasionally a node’s behaviour changes. The routine that avoids surprises: read the release notes, back up the database and the encryption key, pin to the new specific version, restart, verify a few workflows actually ran. Skipping several major versions and jumping is where migration problems concentrate.
Then there is monitoring, which is the part most self-hosted instances lack. A workflow that silently stopped firing is worse than one that visibly failed, because nobody notices until someone asks why the thing it was doing has not happened for three weeks. At minimum, alert on the container being down and on execution failures.
Self-hosted or managed
An honest comparison, since it is the actual decision behind this search.
Self-hosting gives you full control, no per-execution limits, and data that stays on infrastructure you chose. Those are real advantages, particularly where the workflows touch data that has somewhere it is allowed to be.
The cost is everything above: a database to run, a proxy and certificate to maintain, a key to protect, upgrades to apply, monitoring to build, and a server that is yours when it stops at an inconvenient time. The software is free and the operation is not.
n8n is one of the managed tools on RunxBuild, deployed with its own plan, custom domains, environment variables, autoscaling, and logs — and a managed Postgres alongside it on the private network rather than a container you maintain. On the Basic plan at $6 a month with a managed database beside it, the arithmetic against a VPS plus your own time is worth doing rather than assuming.
The right answer depends on whether the operational work is something you want to own. If you enjoy it, or your requirements demand it, self-hosting from the repository is well documented and works. If the workflows matter more than the infrastructure under them, the managed route removes the failure modes described in this article rather than teaching you to handle them.
How this fits the rest of the stack
Running n8n from GitHub is five minutes; running it as something you depend on means Postgres, TLS, an explicit encryption key backed up separately, a correct webhook URL, retention limits, and an upgrade routine. All of that is doable and none of it is what you wanted to be doing. n8n is a managed tool on RunxBuild with its own plan, custom domains, autoscaling, and logs, with managed Postgres available beside it on the private network. The RunxBuild hosting calculator puts the tool and the database in one view so the comparison against a VPS is a real one.
Useful related references:
- n8n vs Make: Where the Complexity Goes
- n8n Use Cases: What It Is Genuinely Good At, and What It Is Not
- n8n Alternatives: The Honest Comparison by What You Are Escaping
- Deploying from GitHub on RunxBuild
FAQ
Is n8n free to self-host?
The software is available to run yourself at no licence cost under its source-available licence, subject to terms that restrict offering it as a competing hosted service. What is not free is the operation: a server, a database, TLS, backups, upgrades, and monitoring. Price your own time into that comparison rather than treating self-hosted as zero.
Should I use SQLite or Postgres with n8n?
Postgres for anything you depend on. SQLite is a single file with one writer, so it locks under concurrent executions, grows with execution history, and rules out running more than one n8n process. Switch before building workflows, because migrating an established instance later is an export and import.
What happens if I lose the n8n encryption key?
Every stored credential becomes permanently unreadable and must be re-entered by hand. The key encrypts all API keys, tokens, and passwords in the instance. Set N8N_ENCRYPTION_KEY explicitly, store it in a password manager, and back it up separately — a database backup without it is not a complete backup.
Why are my n8n webhooks not being triggered?
Most often WEBHOOK_URL is unset, so n8n generated a URL based on its internal address and the one you pasted into the external service points at localhost. Set WEBHOOK_URL, N8N_HOST, and N8N_PROTOCOL to the public address. Also confirm the instance is reachable from the internet at all — an instance behind NAT can call out but cannot receive.
How much memory does n8n need?
Around 1GB as a floor for a single instance running modest workflows, and more if any workflow handles large payloads, since files are held in memory during processing. Beyond one instance, queue mode splits execution into separate workers coordinated through Redis, which is how you scale rather than making one container larger.