Last updated: 5 November 2026. Plan prices are from giganodes.host/vps/india and giganodes.host/vps/india/n8n-vps on that date and exclude 18% GST. Software versions (Ubuntu 24.04, n8n, Ollama, Caddy) were current when written; re-check the images before you deploy.
n8n gives you the automation glue, Ollama gives you a language model that never leaves your server, and a single VPS in India keeps both inside the country at a fixed rupee price. This tutorial walks through the whole build: picking a plan that can honestly hold a quantised 3B, 7B or 8B model next to n8n, installing Docker on Ubuntu 24.04, a Compose file that puts n8n, Ollama, PostgreSQL and Caddy behind HTTPS, wiring the Ollama node, a Telegram-to-LLM-to-Google-Sheets workflow, then backups, firewalling and updates. Nothing here needs a GPU.
TL;DR: Use Cloud VPS S (4 vCore EPYC 7C13, 8 GB RAM, ₹1,800/mo or ₹1,584/mo annual) for n8n plus a 3B quantised model, or a 7B/8B Q4 model with little headroom. Use Cloud VPS M (6 vCore, 16 GB, ₹3,600/mo or ₹3,168/mo annual) if you want a 7B/8B model to run comfortably alongside PostgreSQL and busy workflows. CPU-only inference is slow: expect single-digit tokens per second. Put Ollama on the internal Docker network only, expose n8n through Caddy on 443, lock everything else with UFW, and back up the PostgreSQL dump plus the n8n data volume nightly.
Which VPS Plan Fits n8n Plus Ollama in India?
The honest answer is 8 GB of RAM for a 3B model, 16 GB if you want a 7B or 8B model to run without squeezing n8n and PostgreSQL. Ollama loads the whole quantised model into RAM; a 3B model at 4-bit quantisation is roughly 2 GB on disk and needs a little more than that in memory once context is added, while 7B and 8B models at Q4 are roughly 4.5 to 5 GB on disk and want 6 GB or more in use. n8n itself, PostgreSQL, Caddy and Ubuntu take about 1.5 to 2 GB between them.
These are the AMD EPYC 7C13 plans on giganodes.host/vps/india, which are the same plans listed on the n8n VPS page. Every plan has NVMe storage, a dedicated IPv4, full root access and Cloudflare Magic Transit DDoS protection included. The n8n page starts its recommendations at Cloud VPS S, as does our n8n VPS India guide, and after testing the stack we agree: Cloud Nano (1 vCore, 2 GB) and Cloud XS (2 vCore, 4 GB) can run n8n alone, but not n8n and a useful model together.
| Plan | vCores / RAM / NVMe | Monthly | Annual (per month) | Model size that fits with n8n | Our verdict |
|---|---|---|---|---|---|
| Cloud XS | 2 / 4 GB / 40 GB | ₹1,000/mo | ₹880/mo | 1B class only; not recommended for this stack | n8n only, no Ollama |
| Cloud VPS S | 4 / 8 GB / 60 GB | ₹1,800/mo | ₹1,584/mo | 3B Q4 comfortably; 7B/8B Q4 with little headroom | Minimum we recommend |
| Cloud VPS M | 6 / 16 GB / 120 GB | ₹3,600/mo | ₹3,168/mo | 7B/8B Q4 comfortably; room for two loaded models | Best fit for most teams |
| Cloud VPS L | 12 / 32 GB / 256 GB | ₹7,200/mo | ₹6,336/mo | 13B/14B Q4; several models loaded at once | Only if you need larger models |
| Cloud VPS XL | 20 / 64 GB / 512 GB | ₹14,400/mo | ₹12,672/mo | 30B class Q4 (still CPU-slow) | Compare with a dedicated server first |
Prices exclude 18% GST; a GST invoice is issued on every payment. Annual billing saves 12%.
Two cautions before you buy. First, CPU-only inference is slow. On any of these plans, expect single-digit tokens per second from a 7B/8B model, faster from a 3B. That is fine for a Telegram bot, a summariser or a classifier that runs in the background; it is not fine for a chat UI where a human is waiting. Second, more vCores help throughput but do not change that picture much; RAM capacity is what decides which model you can load at all. If you need more than a few tokens per second, read our Ollama on VPS guide for the trade-offs, and our VPS sizing guide for the general method.
Step 1: Prepare Ubuntu 24.04 and Install Docker
Start from a fresh Ubuntu 24.04 LTS image, create a non-root user, and install Docker from Docker’s own repository so Compose v2 comes with it. Pick Ubuntu 24.04 when ordering in the VirtFusion panel; the VPS is live within about a minute.
ssh root@YOUR_SERVER_IP
apt update && apt upgrade -y
adduser deploy
usermod -aG sudo deploy
rsync --archive --chown=deploy:deploy ~/.ssh /home/deploy
Log back in as deploy and install Docker Engine and the Compose plugin.
sudo apt install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo usermod -aG docker deploy
newgrp docker
docker compose version
Point a DNS A record at the server now, for example n8n.yourdomain.in, so Caddy can issue a certificate the moment it starts. If you proxy through Cloudflare, leave the record on “DNS only” (grey cloud) until the first certificate is issued.
Step 2: Create the Project and Environment File
Keep everything in one directory with a .env file that Compose reads automatically. The encryption key is what n8n uses to encrypt stored credentials; lose it and every saved API key in n8n becomes unreadable, so copy it into your password manager.
mkdir -p ~/n8n-ollama && cd ~/n8n-ollama
openssl rand -hex 32 # use this for N8N_ENCRYPTION_KEY
openssl rand -hex 16 # use this for POSTGRES_PASSWORD
nano .env
# .env
DOMAIN=n8n.yourdomain.in
ACME_EMAIL=you@yourdomain.in
N8N_ENCRYPTION_KEY=paste-64-hex-chars-here
GENERIC_TIMEZONE=Asia/Kolkata
TZ=Asia/Kolkata
POSTGRES_USER=n8n
POSTGRES_PASSWORD=paste-32-hex-chars-here
POSTGRES_DB=n8n
# Ollama tuning for a CPU-only box
OLLAMA_KEEP_ALIVE=30m
OLLAMA_NUM_PARALLEL=1
OLLAMA_MAX_LOADED_MODELS=1
OLLAMA_MAX_LOADED_MODELS=1 and OLLAMA_NUM_PARALLEL=1 matter on an 8 GB plan: they stop Ollama from trying to hold two models or two concurrent generations in memory and tipping the server into swap. On Cloud VPS M you can raise parallelism to 2 if your workflows fire often.
Step 3: The Docker Compose File (n8n + Ollama + PostgreSQL + Caddy)
This Compose file runs four containers on a private network. Only Caddy publishes ports 80 and 443 to the internet. n8n and Ollama talk to each other by container name, and Ollama’s port 11434 is never exposed on the host, which is the single most important security decision in this whole setup.
# docker-compose.yml
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
ollama:
image: ollama/ollama:latest
restart: unless-stopped
environment:
OLLAMA_HOST: 0.0.0.0
OLLAMA_KEEP_ALIVE: ${OLLAMA_KEEP_ALIVE}
OLLAMA_NUM_PARALLEL: ${OLLAMA_NUM_PARALLEL}
OLLAMA_MAX_LOADED_MODELS: ${OLLAMA_MAX_LOADED_MODELS}
volumes:
- ollama_models:/root/.ollama
# No "ports:" block on purpose. Ollama is reachable only from n8n.
n8n:
image: docker.n8n.io/n8nio/n8n:latest
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
N8N_HOST: ${DOMAIN}
N8N_PORT: 5678
N8N_PROTOCOL: https
N8N_EDITOR_BASE_URL: https://${DOMAIN}/
WEBHOOK_URL: https://${DOMAIN}/
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
GENERIC_TIMEZONE: ${GENERIC_TIMEZONE}
TZ: ${TZ}
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: 5432
DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}
DB_POSTGRESDB_USER: ${POSTGRES_USER}
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
N8N_RUNNERS_ENABLED: "true"
EXECUTIONS_DATA_PRUNE: "true"
EXECUTIONS_DATA_MAX_AGE: 168
volumes:
- n8n_data:/home/node/.n8n
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
environment:
DOMAIN: ${DOMAIN}
ACME_EMAIL: ${ACME_EMAIL}
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
volumes:
postgres_data:
ollama_models:
n8n_data:
caddy_data:
caddy_config:
The Caddyfile is three lines. Caddy requests and renews the Let’s Encrypt certificate itself.
# Caddyfile
{
email {$ACME_EMAIL}
}
{$DOMAIN} {
reverse_proxy n8n:5678
}
Bring the stack up and watch the logs until n8n reports it is listening and Caddy reports a certificate.
docker compose up -d
docker compose logs -f caddy n8n
Open https://n8n.yourdomain.in, create the owner account, and you are in. If you would rather use Traefik, the only change is replacing the Caddy service with a Traefik container that has a Let’s Encrypt resolver and adding router labels to the n8n service; the rest of the file is unchanged. We use Caddy here because there is less to get wrong. The n8n self-hosting guide covers the n8n-only version of this stack if you want the simpler starting point.
Step 4: Pull a Model into Ollama
Pull the model from inside the Ollama container; the weights land in the ollama_models volume and survive restarts and updates. Match the model to your plan using the table above.
# Cloud VPS S (8 GB): a 3B model is the safe default
docker compose exec ollama ollama pull llama3.2:3b
# Cloud VPS M (16 GB): 7B/8B at Q4 runs comfortably
docker compose exec ollama ollama pull llama3.1:8b
docker compose exec ollama ollama pull qwen2.5:7b
# Check what is installed and test a prompt
docker compose exec ollama ollama list
docker compose exec ollama ollama run llama3.2:3b "Reply with one word: ready"
The first response after a pull or a restart takes longer because the model has to load into RAM; after that, OLLAMA_KEEP_ALIVE=30m keeps it resident between workflow runs. Watch memory while the model answers: docker stats --no-stream will show you whether you are near the plan’s limit. If you see swap use in free -m, step down a model size or step up a plan. For a DeepSeek-family model instead, our DeepSeek on VPS guide has the sizing notes.
Step 5: Connect the n8n Ollama Node
n8n reaches Ollama over the Docker network at http://ollama:11434, and that address goes into one credential that every Ollama node reuses. In the n8n editor: Credentials, Add credential, search for Ollama, set Base URL to http://ollama:11434, save. The test button should return a green tick; if it fails, the two containers are not on the same Compose network or Ollama has not finished starting.
There are two Ollama nodes in n8n and both are sub-nodes that attach to a parent:
- Ollama Chat Model plugs into a Basic LLM Chain or an AI Agent node. Use this for almost everything.
- Ollama Model is the plain completion variant for the older LLM Chain node.
In the Ollama Chat Model node, pick the model you pulled from the dropdown (it reads the list from Ollama live), set Temperature low (0.2 to 0.4) for classification and extraction tasks, and set a sensible num_ctx in the options if your prompts are long; a 4,096-token context is a reasonable ceiling for an 8 GB plan because context also costs RAM.
Step 6: A Sample Workflow (Telegram to Ollama to Google Sheets)
This workflow turns a Telegram bot into a note-taker: a message arrives, the local model classifies it and writes a one-line summary, the result is appended to a Google Sheet, and the user gets a confirmation. It runs end to end on the VPS with only Telegram and Google as external calls.
- Telegram Trigger (On message). Create a bot with @BotFather, paste the token into a Telegram credential. Because
WEBHOOK_URLis set to your HTTPS domain, n8n registers the webhook with Telegram automatically. - Basic LLM Chain with the Ollama Chat Model attached. Prompt (Define below):
Classify the note into one of: task, idea, expense, other. Then write a one-sentence summary. Reply as JSON with keys "category" and "summary" only. Note: {{ $json.message.text }}. Turn on “Require Specific Output Format” and attach a Structured Output Parser with the schema{"category":"string","summary":"string"}. - Google Sheets (Append row). Connect a Google OAuth2 credential, select the sheet, and map columns:
timestamp={{ $now.toISO() }},from={{ $('Telegram Trigger').item.json.message.from.username }},category={{ $json.output.category }},summary={{ $json.output.summary }},raw={{ $('Telegram Trigger').item.json.message.text }}. - Telegram (Send message). Chat ID
{{ $('Telegram Trigger').item.json.message.chat.id }}, textSaved as {{ $json.output.category }}: {{ $json.output.summary }}.
Activate the workflow and send the bot a message. On Cloud VPS S with a 3B model the reply typically arrives in a few seconds; with an 8B model expect noticeably longer, which is why we keep the human-facing confirmation short and let the model do classification rather than long-form writing. If you would rather trigger from your own app, swap the Telegram Trigger for a Webhook node; the URL will be https://n8n.yourdomain.in/webhook/your-path and the rest of the chain is identical. More patterns like this are in our AI automation VPS guide.
Step 7: Back Up n8n and Ollama
Back up two things: the PostgreSQL database (workflows, executions, users) and the n8n_data volume (the encryption key and settings). The Ollama model volume is large and can always be re-pulled, so skip it. This script dumps both nightly and keeps seven days.
mkdir -p ~/backups && nano ~/backup-n8n.sh
#!/usr/bin/env bash
set -euo pipefail
cd ~/n8n-ollama
STAMP=$(date +%F)
docker compose exec -T postgres pg_dump -U n8n -d n8n | gzip > ~/backups/n8n-db-$STAMP.sql.gz
docker run --rm -v n8n-ollama_n8n_data:/data -v ~/backups:/backup alpine \
tar czf /backup/n8n-data-$STAMP.tar.gz -C /data .
find ~/backups -name "n8n-*" -mtime +7 -delete
chmod +x ~/backup-n8n.sh
(crontab -l 2>/dev/null; echo "30 2 * * * /home/deploy/backup-n8n.sh") | crontab -
Backups on the same disk only protect you from your own mistakes, not from a lost server. Add one line with rclone to copy ~/backups to any S3-compatible bucket or Google Drive, and take a VirtFusion snapshot from the GigaNodes panel before any major upgrade. n8n also lets you export workflows as JSON from the editor; a weekly export into a private git repository is a cheap second copy.
Step 8: Secure the Server with UFW, SSH Keys and Fail2ban
Only three ports should answer from the internet: 22 for SSH, 80 and 443 for Caddy. n8n’s 5678 and Ollama’s 11434 stay inside Docker. Set UFW to deny everything else by default.
sudo apt install -y ufw fail2ban
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
Two things trip people up here. First, Docker manipulates iptables directly and can bypass UFW for any container port you publish with ports:; that is exactly why the Compose file above publishes only Caddy. Never add "11434:11434" to the Ollama service “for testing”. Second, disable password logins once your key works:
sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
sudo systemctl restart ssh
sudo systemctl enable --now fail2ban
Inside n8n, keep user management on (it is the default), use a long owner password, and enable two-factor authentication in Settings. If only you will ever open the editor, add a basic_auth block to the Caddyfile for a second login layer in front of n8n, leaving /webhook/* paths open so Telegram and other services can still reach your triggers. Network-layer DDoS is handled upstream by Cloudflare Magic Transit, included on every GigaNodes plan, so public webhooks stay reachable during an attack. Our Linux VPS hardening checklist covers the remaining items: unattended security updates, auditd and log shipping.
Step 9: Update n8n, Ollama and the Models
Updating is a backup, a pull and a restart; Compose keeps your data volumes untouched. Run the backup script first every time, because n8n database migrations are one-way.
cd ~/n8n-ollama
~/backup-n8n.sh
docker compose pull
docker compose up -d
docker image prune -f
docker compose exec ollama ollama pull llama3.2:3b # refresh the model tag too
Read the n8n release notes before a major version jump; node behaviour sometimes changes and a workflow that passed yesterday can need a small edit. A Compose stack this size needs about five minutes of maintenance a month, which is well below what an execution-capped n8n Cloud plan or a hosted LLM API bill would cost you in attention. For a comparison of this build against paid automation and API options, see our VPS for AI tools roundup.
How We Sized These Recommendations
- Plan data is from giganodes.host/vps/india and giganodes.host/vps/india/n8n-vps, read on 5 November 2026. We did not quote any competitor pricing in this tutorial.
- Model memory guidance comes from the published sizes of Q4-quantised 3B, 7B and 8B models in the Ollama library plus the overhead of context and the other containers. We give ranges, not decimals, and we have not published token-per-second figures because they vary with model, quantisation, prompt length and how busy n8n is at the same moment.
- Security choices follow the principle of publishing one container only. Where a convenience (exposing Ollama’s port) would have made the tutorial shorter, we left it out and said why.
- Where GigaNodes loses: there is no GPU plan, so anyone who needs fast interactive chat with a 7B+ model should look at a GPU host or a hosted API instead and keep only n8n here. The 48-hour money-back guarantee is paid as account credit, not cash.
Frequently Asked Questions
Can I run n8n and Ollama on a 4 GB VPS?
You can run n8n alone on Cloud XS (2 vCore, 4 GB, ₹1,000/mo), and that is a sensible n8n-only choice. Adding Ollama with anything beyond a 1B-class model will push a 4 GB server into swap and stall workflows. For n8n plus a 3B model, start at Cloud VPS S with 8 GB.
How fast is Ollama on a CPU-only VPS in India?
Slow compared with a GPU, and adequate for background automation. Expect single-digit tokens per second from a 7B or 8B quantised model on the EPYC plans, more from a 3B. Classification, extraction, tagging and short summaries work well; long articles or real-time chat with a waiting human do not.
Should Ollama’s port be exposed so I can call it from my laptop?
No. Ollama has no authentication, so a published 11434 port is an open model API for the whole internet, and Docker’s published ports bypass UFW. Keep Ollama on the internal Docker network and call it from n8n. If you need remote access, open an SSH tunnel with ssh -L 11434:localhost:11434 instead.
Do I need PostgreSQL, or is SQLite enough for n8n?
n8n works with its default SQLite database, but PostgreSQL is the better choice on a server that will also be running an LLM. It handles concurrent executions more reliably, keeps the data volume small, and pg_dump makes consistent backups trivial. The Compose file above includes it, and the extra memory cost is small.
Which model should I pull first?
Pull a 3B-class instruct model such as llama3.2:3b first, test your workflow end to end, then try a 7B/8B model only if the 3B’s output quality is not enough and your plan has 16 GB. Smaller models answer faster and leave more RAM for n8n, which matters more than most people expect on a shared box.
Can I run OpenClaw or another agent framework on the same server?
Yes, as another Compose service on the same internal network pointing at http://ollama:11434, but budget RAM for it and move to Cloud VPS M or L. GigaNodes also sells a dedicated OpenClaw VPS configuration, and our Claude Code VPS guide covers running coding agents on the same hardware.
Ready to build it? Deploy a Cloud VPS S or M from the n8n VPS page, pick Ubuntu 24.04, and paste the Compose file above. UPI, cards and NetBanking are accepted, a GST invoice is issued on every payment, and the first payment is covered by a 48-hour money-back credit. If you would like n8n deployed via Docker for you at provisioning, mention it in your order notes; the Ollama half takes you about ten more minutes with the steps above.
—


