Self-Host n8n and Ship a Production AI Ops Agent
Stand up n8n on a VPS with HTTPS, connect Slack and CRM, ship a read-first AI ops agent, then gate writes with human approval.
What you will have live
By the end of this playbook you will have:
- A self-hosted n8n instance on a VPS, reachable only over HTTPS on your own subdomain
- Credentials stored in n8n (not in chat logs), with a durable encryption key backed up offline
- One working AI Ops Agent workflow: Slack (or Telegram) question → agent uses tools → posts a useful ops result (CRM lookup or Slack summary)
- A production harden pass: secrets, HTTPS, backups, permissions, and a human approval gate before any CRM write
Prerequisites
Gather these before you start:
- VPS — Ubuntu 22.04 or 24.04, 2 GB RAM minimum (4 GB comfortable), 20+ GB disk, public IPv4. Hetzner, DigitalOcean, Contabo, Linode all work.
- Domain you control — you will create
n8n.yourdomain.com(A record → VPS IP). - SSH access as a sudo user.
- Docker Engine + Docker Compose plugin on the VPS (install steps below if missing).
- Accounts for the first business outcome: Slack workspace (or Telegram bot) where ops lives; CRM you already use (HubSpot, Pipedrive, or Salesforce) or a Google Sheet stand-in for week one; an LLM API key (OpenAI, Anthropic, or another provider n8n’s LLM nodes support).
- A password manager — you will store: VPS root/user password, n8n owner password,
N8N_ENCRYPTION_KEY, DB password (if you add Postgres later), API keys.
Step 1 — Point DNS at the VPS
- In your DNS provider, create an A record:
- Name:
n8n(or the subdomain you prefer) - Value: your VPS public IPv4
- TTL: 300 (or Auto)
- Wait until
dig +short n8n.yourdomain.comreturns the VPS IP from your laptop. - Open ports 80 and 443 on the VPS firewall (uFW / cloud security group). Do not expose
5678to the world — n8n stays on localhost; Traefik publishes HTTPS.
Step 2 — Install Docker on the VPS
SSH in, then:
sudo apt update && sudo apt install -y ca-certificates curl
# Follow Docker’s current Engine install for Ubuntu, then:
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
docker --version
docker compose version
Optional: add your user to the docker group so you can run compose without sudo every time (usermod -aG docker $USER, then re-login).
Step 3 — Create the official n8n Compose stack (HTTPS)
n8n’s current production-shaped Docker Compose path uses Traefik for TLS and binds n8n to 127.0.0.1:5678. As of late September 2026, docs list stable ~2.40.x — pin or use the documented n8nio/n8n image tag your ops standard allows; prefer stable over beta.
mkdir -p ~/n8n-compose/local-files
cd ~/n8n-compose
Create .env (edit values):
DOMAIN_NAME=yourdomain.com
SUBDOMAIN=n8n
GENERIC_TIMEZONE=Asia/Karachi
SSL_EMAIL=you@yourdomain.com
Create compose.yaml from n8n’s Docker Compose guide — Traefik + n8n services, volumes n8n_data and traefik_data, WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/, N8N_PROTOCOL=https, port bind 127.0.0.1:5678:5678.
Add an encryption key before first start (critical):
# Generate once; store in password manager AND in .env
openssl rand -hex 32
Add to .env:
N8N_ENCRYPTION_KEY=paste_the_hex_here
And under the n8n service environment: in compose:
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
Start:
docker compose up -d
docker compose ps
Open https://n8n.yourdomain.com. Create the owner account (first user = admin). Save that password in your vault.
Step 4 — Lock the owner account and basic settings
In n8n:
- Settings → Users — invite only people who should edit workflows. Prefer SSO later; for day one, strong unique passwords.
- Confirm the instance URL and webhook URL match HTTPS (Settings / environment already set
WEBHOOK_URL). - Enable execution pruning (Settings → Executions) so disk does not fill with old runs — e.g. keep successful executions 7–14 days, errors longer if you triage.
- Do not paste API keys into sticky notes or Slack. Use Credentials objects only.
Step 5 — Connect LLM + Slack (or Telegram)
LLM credential
- Credentials → add your provider (OpenAI / Anthropic / etc.).
- Name it clearly:
prod-openai-ops— nevertest. - Restrict who can use the credential if your plan/RBAC allows.
Slack
- Create a Slack app (or use n8n’s Slack credential OAuth flow).
- Scopes typically needed for ops bots: post messages, read channels you choose, and (if using slash commands/events) event subscriptions pointing at your HTTPS webhook URL.
- Install to the workspace; invite the bot to
#opsor#revops. - Save the Slack credential in n8n.
Telegram alternative: create a bot via BotFather, paste the token into n8n’s Telegram credential, and use a Telegram Trigger.
Step 6 — Ship the first AI Ops Agent (read-only CRM outcome)
Goal: an ops person asks in Slack: “What’s the stage and owner for deal Acme?” The agent looks it up and replies in-thread. No writes yet.
Workflow shape
- Trigger — Slack Trigger (app mention or slash command) or Chat Trigger for a quick smoke test.
- AI Agent node — system message that states:
- You are an internal ops assistant for COMPANY.
- You may read CRM / sheets tools.
- You must not invent deal stages; if lookup fails, say so.
- Keep answers short; cite the record id.
- Chat Model — attach your LLM credential.
- Memory (optional) — Window Buffer Memory for short threads.
- Tools (read-only first):
- HubSpot / Pipedrive / Salesforce Get or Search nodes as Agent tools, or
- Google Sheets tool limited to a “Deals mirror” tab if CRM OAuth is blocked this week.
- Reply — Slack node posts the agent’s final text back to the thread.
Smoke test
- Activate the workflow.
- From Slack, mention the bot with a real deal name that exists.
- Confirm: correct stage/owner, no hallucinated fields.
- In n8n Executions, open the run — every tool call should show real parameters.
Step 7 — Add a safe write path (HITL before CRM updates)
When you are ready for writes (e.g. “Log that Acme asked for a quote”):
- Add a CRM Update / Create note tool.
- In the Agent’s tool connector, add a Human review (HITL) step for that write tool (Slack / Gmail / Teams / n8n Chat — see n8n’s Human-in-the-loop for tools docs).
- Wire: Agent → HITL review → Write tool on the
ai_toolpath. The agent still “sees” the write tool’s name/schema; the review node intercepts execution. - Approval message must show actual parameters (deal id, fields to change) — not a model paraphrase.
- Set
limitWaitTimeexplicitly (e.g. 1–4 hours in seconds). Do not leave unbounded waits in production queues. - Deny path: agent should acknowledge “update not applied” and suggest a human follow-up.
Step 8 — Production harden
Run this checklist before you call the agent “production”:
| Area | Action |
|---|---|
| Secrets | All keys in n8n Credentials; N8N_ENCRYPTION_KEY in vault + .env; no keys in workflow static fields |
| HTTPS | Only https://n8n… works; HTTP redirects; 5678 not public |
| Access | Owner + named editors only; remove unused users |
| Backups | Nightly backup of Docker volume n8n_data (and Postgres if you migrate); test restore on a second folder monthly |
| Updates | Pin image tags; read release notes; stage upgrades on a Friday morning, not month-end close |
| Permissions | CRM credentials use least privilege (read-only integration user until HITL writes are proven) |
| HITL | Every tool with side effects (email send, CRM write, refund, ticket close) goes through Human review |
| Observability | Failed executions → Slack #n8n-alerts; prune old successes |
| Timezone | GENERIC_TIMEZONE matches the ops team (e.g. Asia/Karachi) |
Go-live checklist
- [ ]
https://n8n.yourdomain.comloads with valid cert - [ ] Owner MFA/strong password stored in vault
- [ ]
N8N_ENCRYPTION_KEYbacked up offline - [ ] Slack/Telegram bot responds in the intended channel only
- [ ] Read-only CRM (or Sheet) lookup succeeds on 3 real records
- [ ] Write tool blocked until HITL approve; deny leaves CRM unchanged
- [ ] Backup job ran once and a file exists off-box
- [ ] At least one other human can open Executions and revoke credentials
- [ ] Runbook link pasted in
#ops(this playbook URL + who owns the VPS)
Pitfalls
- Exposing port 5678 — bots and scanners will find it. Always reverse-proxy; bind localhost only.
- Losing the encryption key — credentials become permanent garbage. Backup the key the same day you create it.
- SQLite on a tiny disk with no pruning — disk full → silent outage. Prune executions and monitor disk.
- Webhook URL still http:// — Slack events fail randomly. Force HTTPS + matching
WEBHOOK_URL. - Agent writes without HITL — one bad tool call updates the wrong deal. Gate writes from day one.
- Shared “god mode” CRM token — use a dedicated integration user with minimum scopes.
- Beta image in production — prefer documented stable; schedule upgrades.
FAQ
n8n Cloud
Can I use n8n Cloud instead?
Yes. Skip Steps 1–3; still do credentials discipline, HITL on writes, and the go-live checklist. Self-host when you need data residency, custom networking, or cost control at volume.
Cloudflare
Do I need Cloudflare?
Not required. Traefik + Let’s Encrypt is enough. Cloudflare helps if you want WAF/CDN in front; configure SSL mode so you do not break Traefik’s cert flow.
Model Choice
What model should I use?
Start with a current mid-tier model your budget allows. Optimize later; reliability of tools + HITL matters more than model brand for ops lookups.
Next step
When this agent is live and gated, deepen approvals with Production Approvals: n8n Human-in-the-Loop Tool Gates, or connect a chat brain on top via OpenClaw + n8n over MCP.
Governed Handoff
Need a governed CRM/ERP handoff designed for your stack? See Solutions and Architecture, or contact Octacer.
Ready to Implement This Playbook?
Our team can implement these strategies for you, tailored to your specific business needs.
Schedule Consultation