{"id":306,"date":"2026-11-05T17:34:38","date_gmt":"2026-11-05T17:34:38","guid":{"rendered":"https:\/\/giganodes.host\/blog\/?p=306"},"modified":"2026-11-05T17:34:38","modified_gmt":"2026-11-05T17:34:38","slug":"host-n8n-and-ollama-on-one-vps-india","status":"publish","type":"post","link":"https:\/\/giganodes.host\/blog\/host-n8n-and-ollama-on-one-vps-india","title":{"rendered":"How to Host n8n and Ollama on One VPS in India (Step by Step, 2027)"},"content":{"rendered":"<p><em>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.<\/em><\/p>\n<p>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.<\/p>\n<div class=\"tldr-box\" style=\"border:2px solid #e5e7eb;border-left:6px solid #2563eb;padding:1rem 1.25rem;margin:1.5rem 0;background:#f8fafc\">\n<p><strong>TL;DR:<\/strong> Use <strong>Cloud VPS S<\/strong> (4 vCore EPYC 7C13, 8 GB RAM, \u20b91,800\/mo or \u20b91,584\/mo annual) for n8n plus a 3B quantised model, or a 7B\/8B Q4 model with little headroom. Use <strong>Cloud VPS M<\/strong> (6 vCore, 16 GB, \u20b93,600\/mo or \u20b93,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.<\/p>\n<\/div>\n<h2>Which VPS Plan Fits n8n Plus Ollama in India?<\/h2>\n<p>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.<\/p>\n<p>These are the AMD EPYC 7C13 plans on <a href=\"https:\/\/giganodes.host\/vps\/india\">giganodes.host\/vps\/india<\/a>, which are the same plans listed on the <a href=\"https:\/\/giganodes.host\/vps\/india\/n8n-vps\">n8n VPS page<\/a>. 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 <a href=\"https:\/\/giganodes.host\/blog\/best-vps-for-n8n-vps-india\">n8n VPS India guide<\/a>, 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.<\/p>\n<div style=\"overflow-x:auto\">\n<table>\n<thead>\n<tr>\n<th>Plan<\/th>\n<th>vCores \/ RAM \/ NVMe<\/th>\n<th>Monthly<\/th>\n<th>Annual (per month)<\/th>\n<th>Model size that fits with n8n<\/th>\n<th>Our verdict<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Cloud XS<\/td>\n<td>2 \/ 4 GB \/ 40 GB<\/td>\n<td>\u20b91,000\/mo<\/td>\n<td>\u20b9880\/mo<\/td>\n<td>1B class only; not recommended for this stack<\/td>\n<td>n8n only, no Ollama<\/td>\n<\/tr>\n<tr>\n<td>Cloud VPS S<\/td>\n<td>4 \/ 8 GB \/ 60 GB<\/td>\n<td>\u20b91,800\/mo<\/td>\n<td>\u20b91,584\/mo<\/td>\n<td>3B Q4 comfortably; 7B\/8B Q4 with little headroom<\/td>\n<td>Minimum we recommend<\/td>\n<\/tr>\n<tr>\n<td>Cloud VPS M<\/td>\n<td>6 \/ 16 GB \/ 120 GB<\/td>\n<td>\u20b93,600\/mo<\/td>\n<td>\u20b93,168\/mo<\/td>\n<td>7B\/8B Q4 comfortably; room for two loaded models<\/td>\n<td>Best fit for most teams<\/td>\n<\/tr>\n<tr>\n<td>Cloud VPS L<\/td>\n<td>12 \/ 32 GB \/ 256 GB<\/td>\n<td>\u20b97,200\/mo<\/td>\n<td>\u20b96,336\/mo<\/td>\n<td>13B\/14B Q4; several models loaded at once<\/td>\n<td>Only if you need larger models<\/td>\n<\/tr>\n<tr>\n<td>Cloud VPS XL<\/td>\n<td>20 \/ 64 GB \/ 512 GB<\/td>\n<td>\u20b914,400\/mo<\/td>\n<td>\u20b912,672\/mo<\/td>\n<td>30B class Q4 (still CPU-slow)<\/td>\n<td>Compare with a dedicated server first<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p><small>Prices exclude 18% GST; a GST invoice is issued on every payment. Annual billing saves 12%.<\/small><\/p>\n<p>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 <a href=\"https:\/\/giganodes.host\/blog\/run-ollama-on-vps-india\">our Ollama on VPS guide<\/a> for the trade-offs, and <a href=\"https:\/\/giganodes.host\/blog\/how-much-ram-cpu-does-vps-need\">our VPS sizing guide<\/a> for the general method.<\/p>\n<h2>Step 1: Prepare Ubuntu 24.04 and Install Docker<\/h2>\n<p>Start from a fresh Ubuntu 24.04 LTS image, create a non-root user, and install Docker from Docker&#8217;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.<\/p>\n<pre><code>ssh root@YOUR_SERVER_IP\napt update &amp;&amp; apt upgrade -y\nadduser deploy\nusermod -aG sudo deploy\nrsync --archive --chown=deploy:deploy ~\/.ssh \/home\/deploy\n<\/code><\/pre>\n<p>Log back in as <code>deploy<\/code> and install Docker Engine and the Compose plugin.<\/p>\n<pre><code>sudo apt install -y ca-certificates curl gnupg\nsudo install -m 0755 -d \/etc\/apt\/keyrings\ncurl -fsSL https:\/\/download.docker.com\/linux\/ubuntu\/gpg | sudo gpg --dearmor -o \/etc\/apt\/keyrings\/docker.gpg\necho \"deb [arch=$(dpkg --print-architecture) signed-by=\/etc\/apt\/keyrings\/docker.gpg] https:\/\/download.docker.com\/linux\/ubuntu $(. \/etc\/os-release &amp;&amp; echo $VERSION_CODENAME) stable\" | sudo tee \/etc\/apt\/sources.list.d\/docker.list &gt; \/dev\/null\nsudo apt update\nsudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin\nsudo usermod -aG docker deploy\nnewgrp docker\ndocker compose version\n<\/code><\/pre>\n<p>Point a DNS A record at the server now, for example <code>n8n.yourdomain.in<\/code>, so Caddy can issue a certificate the moment it starts. If you proxy through Cloudflare, leave the record on &#8220;DNS only&#8221; (grey cloud) until the first certificate is issued.<\/p>\n<h2>Step 2: Create the Project and Environment File<\/h2>\n<p>Keep everything in one directory with a <code>.env<\/code> 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.<\/p>\n<pre><code>mkdir -p ~\/n8n-ollama &amp;&amp; cd ~\/n8n-ollama\nopenssl rand -hex 32   # use this for N8N_ENCRYPTION_KEY\nopenssl rand -hex 16   # use this for POSTGRES_PASSWORD\nnano .env\n<\/code><\/pre>\n<pre><code># .env\nDOMAIN=n8n.yourdomain.in\nACME_EMAIL=you@yourdomain.in\n\nN8N_ENCRYPTION_KEY=paste-64-hex-chars-here\nGENERIC_TIMEZONE=Asia\/Kolkata\nTZ=Asia\/Kolkata\n\nPOSTGRES_USER=n8n\nPOSTGRES_PASSWORD=paste-32-hex-chars-here\nPOSTGRES_DB=n8n\n\n# Ollama tuning for a CPU-only box\nOLLAMA_KEEP_ALIVE=30m\nOLLAMA_NUM_PARALLEL=1\nOLLAMA_MAX_LOADED_MODELS=1\n<\/code><\/pre>\n<p><code>OLLAMA_MAX_LOADED_MODELS=1<\/code> and <code>OLLAMA_NUM_PARALLEL=1<\/code> 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.<\/p>\n<h2>Step 3: The Docker Compose File (n8n + Ollama + PostgreSQL + Caddy)<\/h2>\n<p>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&#8217;s port 11434 is never exposed on the host, which is the single most important security decision in this whole setup.<\/p>\n<pre><code># docker-compose.yml\nservices:\n  postgres:\n    image: postgres:16-alpine\n    restart: unless-stopped\n    environment:\n      POSTGRES_USER: ${POSTGRES_USER}\n      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}\n      POSTGRES_DB: ${POSTGRES_DB}\n    volumes:\n      - postgres_data:\/var\/lib\/postgresql\/data\n    healthcheck:\n      test: [\"CMD-SHELL\", \"pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}\"]\n      interval: 10s\n      timeout: 5s\n      retries: 5\n\n  ollama:\n    image: ollama\/ollama:latest\n    restart: unless-stopped\n    environment:\n      OLLAMA_HOST: 0.0.0.0\n      OLLAMA_KEEP_ALIVE: ${OLLAMA_KEEP_ALIVE}\n      OLLAMA_NUM_PARALLEL: ${OLLAMA_NUM_PARALLEL}\n      OLLAMA_MAX_LOADED_MODELS: ${OLLAMA_MAX_LOADED_MODELS}\n    volumes:\n      - ollama_models:\/root\/.ollama\n    # No \"ports:\" block on purpose. Ollama is reachable only from n8n.\n\n  n8n:\n    image: docker.n8n.io\/n8nio\/n8n:latest\n    restart: unless-stopped\n    depends_on:\n      postgres:\n        condition: service_healthy\n    environment:\n      N8N_HOST: ${DOMAIN}\n      N8N_PORT: 5678\n      N8N_PROTOCOL: https\n      N8N_EDITOR_BASE_URL: https:\/\/${DOMAIN}\/\n      WEBHOOK_URL: https:\/\/${DOMAIN}\/\n      N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}\n      GENERIC_TIMEZONE: ${GENERIC_TIMEZONE}\n      TZ: ${TZ}\n      DB_TYPE: postgresdb\n      DB_POSTGRESDB_HOST: postgres\n      DB_POSTGRESDB_PORT: 5432\n      DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}\n      DB_POSTGRESDB_USER: ${POSTGRES_USER}\n      DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}\n      N8N_RUNNERS_ENABLED: \"true\"\n      EXECUTIONS_DATA_PRUNE: \"true\"\n      EXECUTIONS_DATA_MAX_AGE: 168\n    volumes:\n      - n8n_data:\/home\/node\/.n8n\n\n  caddy:\n    image: caddy:2\n    restart: unless-stopped\n    ports:\n      - \"80:80\"\n      - \"443:443\"\n    environment:\n      DOMAIN: ${DOMAIN}\n      ACME_EMAIL: ${ACME_EMAIL}\n    volumes:\n      - .\/Caddyfile:\/etc\/caddy\/Caddyfile:ro\n      - caddy_data:\/data\n      - caddy_config:\/config\n\nvolumes:\n  postgres_data:\n  ollama_models:\n  n8n_data:\n  caddy_data:\n  caddy_config:\n<\/code><\/pre>\n<p>The Caddyfile is three lines. Caddy requests and renews the Let&#8217;s Encrypt certificate itself.<\/p>\n<pre><code># Caddyfile\n{\n  email {$ACME_EMAIL}\n}\n\n{$DOMAIN} {\n  reverse_proxy n8n:5678\n}\n<\/code><\/pre>\n<p>Bring the stack up and watch the logs until n8n reports it is listening and Caddy reports a certificate.<\/p>\n<pre><code>docker compose up -d\ndocker compose logs -f caddy n8n\n<\/code><\/pre>\n<p>Open <code>https:\/\/n8n.yourdomain.in<\/code>, 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&#8217;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 <a href=\"https:\/\/giganodes.host\/blog\/self-host-n8n-on-vps-guide\">n8n self-hosting guide<\/a> covers the n8n-only version of this stack if you want the simpler starting point.<\/p>\n<h2>Step 4: Pull a Model into Ollama<\/h2>\n<p>Pull the model from inside the Ollama container; the weights land in the <code>ollama_models<\/code> volume and survive restarts and updates. Match the model to your plan using the table above.<\/p>\n<pre><code># Cloud VPS S (8 GB): a 3B model is the safe default\ndocker compose exec ollama ollama pull llama3.2:3b\n\n# Cloud VPS M (16 GB): 7B\/8B at Q4 runs comfortably\ndocker compose exec ollama ollama pull llama3.1:8b\ndocker compose exec ollama ollama pull qwen2.5:7b\n\n# Check what is installed and test a prompt\ndocker compose exec ollama ollama list\ndocker compose exec ollama ollama run llama3.2:3b \"Reply with one word: ready\"\n<\/code><\/pre>\n<p>The first response after a pull or a restart takes longer because the model has to load into RAM; after that, <code>OLLAMA_KEEP_ALIVE=30m<\/code> keeps it resident between workflow runs. Watch memory while the model answers: <code>docker stats --no-stream<\/code> will show you whether you are near the plan&#8217;s limit. If you see swap use in <code>free -m<\/code>, step down a model size or step up a plan. For a DeepSeek-family model instead, our <a href=\"https:\/\/giganodes.host\/blog\/host-deepseek-on-vps-india\">DeepSeek on VPS guide<\/a> has the sizing notes.<\/p>\n<h2>Step 5: Connect the n8n Ollama Node<\/h2>\n<p>n8n reaches Ollama over the Docker network at <code>http:\/\/ollama:11434<\/code>, 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 <code>http:\/\/ollama:11434<\/code>, 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.<\/p>\n<p>There are two Ollama nodes in n8n and both are sub-nodes that attach to a parent:<\/p>\n<ul>\n<li><strong>Ollama Chat Model<\/strong> plugs into a <strong>Basic LLM Chain<\/strong> or an <strong>AI Agent<\/strong> node. Use this for almost everything.<\/li>\n<li><strong>Ollama Model<\/strong> is the plain completion variant for the older LLM Chain node.<\/li>\n<\/ul>\n<p>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 <code>num_ctx<\/code> 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.<\/p>\n<h2>Step 6: A Sample Workflow (Telegram to Ollama to Google Sheets)<\/h2>\n<p>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.<\/p>\n<ol>\n<li><strong>Telegram Trigger<\/strong> (On message). Create a bot with @BotFather, paste the token into a Telegram credential. Because <code>WEBHOOK_URL<\/code> is set to your HTTPS domain, n8n registers the webhook with Telegram automatically.<\/li>\n<li><strong>Basic LLM Chain<\/strong> with the <strong>Ollama Chat Model<\/strong> attached. Prompt (Define below): <code>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 }}<\/code>. Turn on &#8220;Require Specific Output Format&#8221; and attach a <strong>Structured Output Parser<\/strong> with the schema <code>{\"category\":\"string\",\"summary\":\"string\"}<\/code>.<\/li>\n<li><strong>Google Sheets<\/strong> (Append row). Connect a Google OAuth2 credential, select the sheet, and map columns: <code>timestamp<\/code> = <code>{{ $now.toISO() }}<\/code>, <code>from<\/code> = <code>{{ $('Telegram Trigger').item.json.message.from.username }}<\/code>, <code>category<\/code> = <code>{{ $json.output.category }}<\/code>, <code>summary<\/code> = <code>{{ $json.output.summary }}<\/code>, <code>raw<\/code> = <code>{{ $('Telegram Trigger').item.json.message.text }}<\/code>.<\/li>\n<li><strong>Telegram<\/strong> (Send message). Chat ID <code>{{ $('Telegram Trigger').item.json.message.chat.id }}<\/code>, text <code>Saved as {{ $json.output.category }}: {{ $json.output.summary }}<\/code>.<\/li>\n<\/ol>\n<p>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 <strong>Webhook<\/strong> node; the URL will be <code>https:\/\/n8n.yourdomain.in\/webhook\/your-path<\/code> and the rest of the chain is identical. More patterns like this are in our <a href=\"https:\/\/giganodes.host\/blog\/ai-automation-vps-india\">AI automation VPS guide<\/a>.<\/p>\n<h2>Step 7: Back Up n8n and Ollama<\/h2>\n<p>Back up two things: the PostgreSQL database (workflows, executions, users) and the <code>n8n_data<\/code> 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.<\/p>\n<pre><code>mkdir -p ~\/backups &amp;&amp; nano ~\/backup-n8n.sh\n<\/code><\/pre>\n<pre><code>#!\/usr\/bin\/env bash\nset -euo pipefail\ncd ~\/n8n-ollama\nSTAMP=$(date +%F)\ndocker compose exec -T postgres pg_dump -U n8n -d n8n | gzip &gt; ~\/backups\/n8n-db-$STAMP.sql.gz\ndocker run --rm -v n8n-ollama_n8n_data:\/data -v ~\/backups:\/backup alpine \\\n  tar czf \/backup\/n8n-data-$STAMP.tar.gz -C \/data .\nfind ~\/backups -name \"n8n-*\" -mtime +7 -delete\n<\/code><\/pre>\n<pre><code>chmod +x ~\/backup-n8n.sh\n(crontab -l 2&gt;\/dev\/null; echo \"30 2 * * * \/home\/deploy\/backup-n8n.sh\") | crontab -\n<\/code><\/pre>\n<p>Backups on the same disk only protect you from your own mistakes, not from a lost server. Add one line with <code>rclone<\/code> to copy <code>~\/backups<\/code> 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.<\/p>\n<h2>Step 8: Secure the Server with UFW, SSH Keys and Fail2ban<\/h2>\n<p>Only three ports should answer from the internet: 22 for SSH, 80 and 443 for Caddy. n8n&#8217;s 5678 and Ollama&#8217;s 11434 stay inside Docker. Set UFW to deny everything else by default.<\/p>\n<pre><code>sudo apt install -y ufw fail2ban\nsudo ufw default deny incoming\nsudo ufw default allow outgoing\nsudo ufw allow OpenSSH\nsudo ufw allow 80\/tcp\nsudo ufw allow 443\/tcp\nsudo ufw enable\nsudo ufw status verbose\n<\/code><\/pre>\n<p>Two things trip people up here. First, Docker manipulates iptables directly and can bypass UFW for any container port you publish with <code>ports:<\/code>; that is exactly why the Compose file above publishes only Caddy. Never add <code>\"11434:11434\"<\/code> to the Ollama service &#8220;for testing&#8221;. Second, disable password logins once your key works:<\/p>\n<pre><code>sudo sed -i 's\/^#\\?PasswordAuthentication.*\/PasswordAuthentication no\/' \/etc\/ssh\/sshd_config\nsudo sed -i 's\/^#\\?PermitRootLogin.*\/PermitRootLogin no\/' \/etc\/ssh\/sshd_config\nsudo systemctl restart ssh\nsudo systemctl enable --now fail2ban\n<\/code><\/pre>\n<p>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 <code>basic_auth<\/code> block to the Caddyfile for a second login layer in front of n8n, leaving <code>\/webhook\/*<\/code> paths open so Telegram and other services can still reach your triggers. Network-layer DDoS is handled upstream by <a href=\"https:\/\/giganodes.host\/ddos-protection\">Cloudflare Magic Transit<\/a>, included on every GigaNodes plan, so public webhooks stay reachable during an attack. Our <a href=\"https:\/\/giganodes.host\/blog\/linux-vps-security-hardening-in-india\">Linux VPS hardening checklist<\/a> covers the remaining items: unattended security updates, auditd and log shipping.<\/p>\n<h2>Step 9: Update n8n, Ollama and the Models<\/h2>\n<p>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.<\/p>\n<pre><code>cd ~\/n8n-ollama\n~\/backup-n8n.sh\ndocker compose pull\ndocker compose up -d\ndocker image prune -f\ndocker compose exec ollama ollama pull llama3.2:3b   # refresh the model tag too\n<\/code><\/pre>\n<p>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 <a href=\"https:\/\/giganodes.host\/blog\/best-vps-india-ai-tools\">our VPS for AI tools roundup<\/a>.<\/p>\n<h2>How We Sized These Recommendations<\/h2>\n<ul>\n<li><strong>Plan data<\/strong> 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.<\/li>\n<li><strong>Model memory guidance<\/strong> 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.<\/li>\n<li><strong>Security choices<\/strong> follow the principle of publishing one container only. Where a convenience (exposing Ollama&#8217;s port) would have made the tutorial shorter, we left it out and said why.<\/li>\n<li><strong>Where GigaNodes loses<\/strong>: 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.<\/li>\n<\/ul>\n<h2>Frequently Asked Questions<\/h2>\n<h3>Can I run n8n and Ollama on a 4 GB VPS?<\/h3>\n<p>You can run n8n alone on Cloud XS (2 vCore, 4 GB, \u20b91,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.<\/p>\n<h3>How fast is Ollama on a CPU-only VPS in India?<\/h3>\n<p>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.<\/p>\n<h3>Should Ollama&#8217;s port be exposed so I can call it from my laptop?<\/h3>\n<p>No. Ollama has no authentication, so a published 11434 port is an open model API for the whole internet, and Docker&#8217;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 <code>ssh -L 11434:localhost:11434<\/code> instead.<\/p>\n<h3>Do I need PostgreSQL, or is SQLite enough for n8n?<\/h3>\n<p>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.<\/p>\n<h3>Which model should I pull first?<\/h3>\n<p>Pull a 3B-class instruct model such as <code>llama3.2:3b<\/code> first, test your workflow end to end, then try a 7B\/8B model only if the 3B&#8217;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.<\/p>\n<h3>Can I run OpenClaw or another agent framework on the same server?<\/h3>\n<p>Yes, as another Compose service on the same internal network pointing at <code>http:\/\/ollama:11434<\/code>, but budget RAM for it and move to Cloud VPS M or L. GigaNodes also sells a dedicated <a href=\"https:\/\/giganodes.host\/vps\/india\/openclaw-vps\">OpenClaw VPS<\/a> configuration, and our <a href=\"https:\/\/giganodes.host\/blog\/claude-code-vps-india\">Claude Code VPS guide<\/a> covers running coding agents on the same hardware.<\/p>\n<p>Ready to build it? Deploy a Cloud VPS S or M from the <a href=\"https:\/\/giganodes.host\/vps\/india\/n8n-vps\">n8n VPS page<\/a>, 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.<\/p>\n<p>&#8212;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":307,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[294,295,172,168,161],"class_list":["post-306","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-ai-automation","tag-docker-compose","tag-n8n","tag-ollama","tag-vps-hosting-india"],"_links":{"self":[{"href":"https:\/\/giganodes.host\/blog\/wp-json\/wp\/v2\/posts\/306","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/giganodes.host\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/giganodes.host\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/giganodes.host\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/giganodes.host\/blog\/wp-json\/wp\/v2\/comments?post=306"}],"version-history":[{"count":1,"href":"https:\/\/giganodes.host\/blog\/wp-json\/wp\/v2\/posts\/306\/revisions"}],"predecessor-version":[{"id":321,"href":"https:\/\/giganodes.host\/blog\/wp-json\/wp\/v2\/posts\/306\/revisions\/321"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/giganodes.host\/blog\/wp-json\/wp\/v2\/media\/307"}],"wp:attachment":[{"href":"https:\/\/giganodes.host\/blog\/wp-json\/wp\/v2\/media?parent=306"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/giganodes.host\/blog\/wp-json\/wp\/v2\/categories?post=306"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/giganodes.host\/blog\/wp-json\/wp\/v2\/tags?post=306"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}