Skip to main content
18 min read

Build a Self-Hosted VPS Stack for AI Agent Development

Learn how to size RAM, CPU, and storage for custom AI agent development. Discover our complete self-hosted VPS setup guide for a production-ready stack.

Build a Self-Hosted VPS Stack for AI Agent Development

1. Introduction - Sizing Your Self-Hosted Moat

Teams scaling their automation operations and custom AI agent development inevitably face a critical infrastructure decision: when to move from cloud-hosted SaaS platforms to a self-hosted Virtual Private Server (VPS). You have hit per-execution SaaS pricing ceilings, you require rigorous data residency control, or you are running enough agentic systems that the flat-rate VPS math definitively wins. However, the sizing and setup guidance available online is fundamentally flawed. It is either too generic—recommending "enough RAM"—or too narrow, focusing on one specific workflow.

Sizing a VPS for custom AI agent development is fundamentally different from sizing a VPS for a website. The resource bottleneck is not concurrent HTTP requests. It is a combination of persistent memory for agent state and vector databases, concurrent long-running processes like webhook listeners and background jobs, strict AI agent security requirements, and—if hosting local models—GPU memory and inference throughput. Applying traditional web-hosting sizing rules to this AI agent VPS guide 2026 framework produces either wasted spend or production incidents.

This guide delivers concrete execution logic for workload profiling, RAM/CPU/storage sizing frameworks, provider selection tied directly to your workload profile, and the end-to-end setup path from a provisioned server to a production agent stack. We will cover the implementation of n8n alongside PostgreSQL, Redis, and optionally Ollama. We will not cover multi-node Kubernetes orchestration, as that requires a different architectural approach. GPU hosting for large local models (70B+) is treated as a specific scenario within our framework, rather than the default path.

Self-hosting is a protective moat. Per-execution SaaS pricing scales linearly with agent adoption; self-hosted VPS pricing does not. The sizing and setup decisions in this guide require one-time technical implementation that pays back exponentially for every new agent workflow deployed. (Note: For a category-level comparison of the leading VPS providers, see our Top 7 VPS Hosting Providers for AI Agents in 2026. This guide picks up where that comparison ends—how to actually size and set up the infrastructure.)

2. Prerequisites & Tools

Before deploying your infrastructure, you must define the operational scope of your AI agent development stack. Establish whether you are deploying n8n exclusively, pairing it with LangChain/CrewAI, or adding Ollama for local model inference. Determine your data residency requirements (EU-only, US-only, or global) and honestly assess your team's DevOps capacity.

Tools & Accounts Needed

  • VPS Provider Account: Active billing configured (most providers require this for initial provisioning). Budget $20–50/month for a baseline Hetzner/Contabo setup, $50–150/month for DigitalOcean/Vultr general compute, and $150+/month for GPU-enabled instances.
  • Domain Name: Required for routing webhook URLs, obtaining Let's Encrypt TLS certificates, and securing monitoring dashboards.
  • SSH Key Pair: Generated on your local machine. Never rely on password authentication for production servers.
  • DNS Access: Ability to create A records pointing to your new server's IP address.

Skills Required

  • Linux Administration: Comfort navigating the command line, editing configuration files via nano or vim, and understanding system services.
  • Docker Fundamentals: Understanding of containerization, volume mounting, and docker-compose configuration.
  • n8n Architecture: Familiarity with environment variables, webhook structures, and external API authentication.

3. Workflow Architecture Overview

A production-ready self-hosted AI agent stack relies on a decoupled, containerized architecture. Instead of running services directly on the host OS, we utilize Docker to orchestrate an ecosystem of specialized components.

Visual Diagram Flow:

[Screenshot: Architecture Diagram showing VPS Provider -> OS Layer -> Docker Runtime -> Caddy Reverse Proxy -> n8n / PostgreSQL / Redis / Ollama]

  1. Ingress Layer (Caddy/Nginx): Terminates external TLS traffic, requests Let's Encrypt certificates automatically, and securely routes external webhooks to the internal Docker network.
  2. Orchestration Layer (n8n): The core engine processing workflows, evaluating logic, and triggering downstream actions.
  3. State Persistence (PostgreSQL): Replaces n8n's default SQLite database to handle concurrent read/write operations without database locking, storing workflow definitions and execution histories safely.
  4. Queuing Layer (Redis): Manages job distribution. When n8n operates in queue mode, Redis holds incoming webhook triggers and distributes them to available worker nodes to prevent memory exhaustion during traffic spikes.
  5. Inference Layer (Ollama - Optional): Hosts local LLMs. Kept on a separate internal port, communicating locally with n8n to avoid public exposure of the model API.

Data enters via HTTPS webhooks through the reverse proxy, hits the n8n webhook listener, queues in Redis, executes in an n8n worker, logs state to PostgreSQL, and calls either external cloud LLMs or the local Ollama instance for inference.

4. Step-by-Step Implementation

Step 1: Profile Your Workload Against the Five-Question Framework

What We're Building: A definitive workload profile document. Sizing decisions cascade from this profile. Skipping this step leads to immediate overspending or catastrophic resource exhaustion.

Detailed Instructions:

Document precise answers to these five metrics:

  1. Execution Volume: Estimate executions per day at steady state and identify peak burst rates (e.g., 5,000 daily executions, bursting to 100 concurrent during a 9 AM batch job).
  2. Concurrency Profile: Are executions serial (processing one email at a time) or concurrent (receiving 50 external webhook updates simultaneously)?
  3. Model Hosting: Are you relying entirely on cloud LLM APIs (OpenAI, Anthropic), or do you require Ollama for local model inference?
  4. State Persistence: Do your workflows generate large binary payloads, process PDFs, or store high-dimensional embeddings in a vector database?
  5. Reliability Requirement: Is this an internal staging environment (restarts acceptable) or a customer-facing production endpoint requiring a 99.9% uptime SLA?
Pro Tip: Size for your current reality plus three months of growth headroom. Over-provisioning for aspirational scale that has not materialized is a primary source of wasted capital.

Step 2: Size RAM Based on Workload Profile

What We're Building: The total memory requirement for your VPS. RAM is the most common bottleneck in AI agent infrastructure.

Configuration Reference:

Component Baseline RAM High-Volume RAM
Host OS / Docker 1GB 2GB
n8n Instance 1GB 4GB+ (scaling with concurrency)
PostgreSQL 1GB 4GB (large execution logs)
Redis 512MB 1GB
Ollama (8B Model) 8GB 12GB (high context windows)

Detailed Instructions:

Calculate your tier based on your Step 1 profile:

  • Tier 1 (API-Orchestration, Moderate Volume): 4–8GB total RAM. Sufficient for n8n, PostgreSQL, and Redis calling cloud APIs.
  • Tier 2 (High Concurrency + Vector DB): 8–16GB total RAM. Handles large queue backlogs, pgvector queries, and concurrent data parsing.
  • Tier 3 (Local Inference + Full Stack): 16–32GB+ total RAM. Required if loading an 8B–13B parameter model into memory via Ollama alongside the agent stack.

Step 3: Size CPU (vCPUs) Based on Concurrency

What We're Building: The computational capacity required to process webhook listeners, parse heavy payloads, and run inference.

Detailed Instructions:

Unlike standard web servers, n8n spends most of its execution time waiting for API responses. CPU becomes the bottleneck under three conditions: high webhook concurrency, heavy cryptographic/PDF processing, or local model inference.

  • Tier 1 (Low-Concurrency API): 2–4 vCPUs.
  • Tier 2 (High-Concurrency / Vector Search): 4–8 vCPUs. Prioritize dedicated vCPUs over shared threads to prevent noisy-neighbor performance drops.
  • Tier 3 (Local Inference without GPU): 8+ dedicated vCPUs. Warning: Running even small models (8B) on CPU inference produces high latency. Real-time conversational agents require GPU acceleration.

Step 4: Size Storage (NVMe Capacity and IOPS)

What We're Building: High-throughput disk architecture. Agent execution logs and model weights consume storage rapidly. NVMe drives are mandatory; standard SSDs will choke on PostgreSQL write IOPS under heavy load.

Detailed Instructions:

  • Base Stack + Moderate Logging: 40–80GB NVMe. Requires aggressive n8n execution pruning.
  • Production Stack + Vector DB: 100–200GB NVMe. Embeddings scale dynamically with your corpus.
  • Local Model Hosting: 250GB+ NVMe. An 8B model requires ~5GB on disk; a 70B requires 40GB+.

Step 5: Evaluate GPU Requirement

What We're Building: The decision matrix for hardware acceleration.

Detailed Instructions:

Honestly evaluate your inference volume for your custom AI agent development. Cloud LLM APIs remain more economical and higher-quality than self-hosted models for most growth-stage teams. GPU infrastructure (NVIDIA A100/H100/L40S) is economically viable only when: 1) Data residency strictly forbids cloud APIs, or 2) You are running continuous, high-volume inference where per-token SaaS costs exceed $200/month. If utilizing an 8B model for asynchronous batch classification, heavy CPU inference may suffice. For real-time agents, select a provider offering dedicated vGPUs.

Step 6: Match Workload Profile to Provider

What We're Building: The selection of the physical host environment based on your derived metrics.

Detailed Instructions:

  • EU Data Residency + CPU-Only + Budget Priority: Select Hetzner Cloud (CPX31 or CPX41 tier).
  • Developer Experience + Managed Volumes: Select DigitalOcean (General Purpose Droplets).
  • RAM-Heavy Consolidation: Select Contabo (VPS M or L tiers).
  • GPU Inference Required: Select Vultr (Cloud GPU tier).

Step 7: Provision the Server and Complete Initial Hardening

What We're Building: A secure, Ubuntu-based Linux foundation ready for Docker orchestration.

Detailed Instructions:

  1. 1.1 Deploy Instance: Provision an Ubuntu 22.04 or 24.04 LTS instance with your SSH public key injected during creation.
  2. 1.2 Connect and Update: SSH into your root account and update all system packages.
    ssh root@your_server_ip
    apt update && apt upgrade -y
  3. 1.3 Configure Firewall (UFW): Lock down all ports except SSH, HTTP, and HTTPS.
    ufw default deny incoming
    ufw default allow outgoing
    ufw allow 22/tcp
    ufw allow 80/tcp
    ufw allow 443/tcp
    ufw enable
  4. 1.4 Install fail2ban: Protect SSH from brute-force attacks.
    apt install fail2ban -y
    systemctl enable fail2ban
    systemctl start fail2ban
Pro Tip: Never leave password authentication enabled. Edit /etc/ssh/sshd_config, ensure PasswordAuthentication no is set, and restart the SSH service. "Just for now" turns into months of vulnerability.

Step 8: Install Docker and Set Up the Agent Stack

What We're Building: The containerized n8n ecosystem utilizing Docker Compose.

Detailed Instructions:

  1. 8.1 Install Docker Engine: Follow the official Docker repository installation instructions for Ubuntu.
    curl -fsSL https://get.docker.com -o get-docker.sh
    sh get-docker.sh
  2. 8.2 Create Working Directory:
    mkdir -p /opt/n8n/data
    cd /opt/n8n
  3. 8.3 Define Environment Variables: Create a .env file in /opt/n8n.
    # /opt/n8n/.env
    POSTGRES_USER=n8n_db_user
    POSTGRES_PASSWORD=your_secure_db_password
    POSTGRES_DB=n8n
    N8N_ENCRYPTION_KEY=your_secure_encryption_key
    DOMAIN_NAME=n8n.yourdomain.com
    WEBHOOK_URL=https://n8n.yourdomain.com

Step 9: Set Up Reverse Proxy with TLS

What We're Building: Caddy server configuration to handle Let's Encrypt SSL/TLS automation and port forwarding.

Detailed Instructions:

  1. 9.1 Point DNS: Ensure your domain's A record points to your VPS IP address.
  2. 9.2 Configure Caddy: Caddy will read your domain from the `.env` file and automatically provision TLS. It routes traffic securely to n8n on port 5678.

Step 10: Set Up Backups and Monitoring

What We're Building: Disaster recovery and telemetry before production traffic flows.

Detailed Instructions:

  1. 10.1 Monitoring: Deploy Uptime Kuma on a separate, lightweight VPS to monitor your primary server's HTTPS endpoint. Self-monitoring fails when the entire server crashes.
  2. 10.2 PostgreSQL Dumps: Implement a cron job running pg_dump daily, pushing the encrypted archive to an S3-compatible bucket (AWS, Backblaze B2).
    docker exec -t n8n-postgres pg_dump -U n8n_db_user -F c n8n > /path/to/backup/n8n_backup.dump

5. Complete Workflow JSON (Infrastructure Configuration)

Because we are building infrastructure, the equivalent of your "Complete Workflow JSON" is your master docker-compose.yml file. This declarative file imports your entire architecture into the Docker engine.

Import Instructions:

  1. Copy the YAML configuration below.
  2. Paste it into a file named docker-compose.yml inside your /opt/n8n directory.
  3. Ensure your .env file is populated as described in Step 8.
  4. Run docker compose up -d to pull images and start the stack.
version: '3.8'

volumes:
  db_storage:
  n8n_storage:
  caddy_data:
  caddy_config:

services:
  postgres:
    image: postgres:16
    restart: always
    environment:
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=${POSTGRES_DB}
    volumes:
      - db_storage:/var/lib/postgresql/data
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}']
      interval: 5s
      timeout: 5s
      retries: 10

  n8n:
    image: docker.n8n.io/n8nio/n8n
    restart: always
    environment:
      - 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_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - WEBHOOK_URL=${WEBHOOK_URL}
      - EXECUTIONS_DATA_PRUNE=true
      - EXECUTIONS_DATA_MAX_AGE=168
      - EXECUTIONS_DATA_PRUNE_MAX_COUNT=50000
    volumes:
      - n8n_storage:/home/node/.n8n
    depends_on:
      postgres:
        condition: service_healthy

  caddy:
    image: caddy:latest
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - caddy_data:/data
      - caddy_config:/config
    command: sh -c 'echo "${DOMAIN_NAME} { reverse_proxy n8n:5678 }" > /etc/caddy/Caddyfile && caddy run --config /etc/caddy/Caddyfile'
    depends_on:
      - n8n

6. Testing Your Workflow

Test Scenario 1: Webhook Ingress and TLS

  • Input: Send a POST request via Postman or cURL to https://n8n.yourdomain.com/webhook-test/test-path.
  • Expected Output: A 200 OK status containing the n8n default JSON response: {"message":"Workflow was started"} (if workflow is active) or a specific 404 from n8n (proving Caddy routed traffic successfully to the container).
  • What to Look For: Verify the SSL certificate shows as valid and issued by Let's Encrypt.

Test Scenario 2: Database Connectivity

  • Input: Create a new Workflow in the UI, add an explicit "Set" node, and click "Execute Workflow".
  • Expected Behavior: The workflow runs, and upon refreshing the browser, the execution log appears in the "Executions" tab.
  • How to Verify: If the log appears, PostgreSQL is successfully committing data. If the UI hangs, check the Docker logs for Postgres authentication failures.

Test Scenario 3: Resource Exhaustion (Edge Case)

  • Input: Flood the webhook endpoint with 500 concurrent requests using a load testing tool like Apache Benchmark (ab).
  • Expected Behavior: CPU spikes, but RAM usage should stabilize. If RAM hits 100%, the OS OOM (Out of Memory) killer will terminate the n8n container.
  • How to Verify: Run htop on the server during the test. Watch memory utilization. This dictates if you need to implement Redis queue mode.

7. Production Deployment Checklist

Do not route production API keys or customer data through this instance until you verify:

  • Credential Security: Ensure N8N_ENCRYPTION_KEY is backed up securely offline. If you lose this key, all authenticated connections in n8n are permanently lost.
  • Log Rotation: Confirm EXECUTIONS_DATA_PRUNE=true is set in your `.env` file to prevent disk exhaustion.
  • Firewall Audit: Run ufw status to verify port 5678 is blocked externally. All traffic must route through Caddy on ports 80/443.
  • Monitoring Alert: Trigger a test alert in Uptime Kuma to verify Slack/Email notifications arrive successfully.

8. Optimization & Scaling

Performance Optimization

If your AI agent development workload scales beyond 5,000 executions daily, implement n8n's Queue Mode. This architecture separates the webhook listener (main n8n process) from the execution processors (worker nodes). Redis manages the job queue, allowing you to spin up multiple worker containers on the same VPS, drastically increasing concurrent processing capacity without dropping incoming webhooks.

Cost Optimization

Right-size your instance after 30 days of production monitoring. Actual resource utilization frequently diverges from initial estimates. If your vCPUs idle at 5%, downgrade your compute tier. To minimize external API calls, cache static LLM responses using Redis or n8n's built-in static data features, effectively reducing both latency and token costs.

Reliability Optimization

Set connection pooling correctly in PostgreSQL to match your concurrency profile. If using Queue Mode, ensure Redis persistence (RDB snapshots) is configured so pending webhook triggers survive a container restart.

9. Troubleshooting Guide

Issue 1: n8n webhook returns 404 when called from external service

  • Error Message: 404 Not Found or standard Caddy blank response.
  • Root Cause: The reverse proxy is failing to route to n8n, or n8n's WEBHOOK_URL environment variable does not perfectly match the external domain.
  • Solution Steps: 1. Verify WEBHOOK_URL in `.env` includes `https://`. 2. Restart the n8n container: docker compose restart n8n. 3. Check Caddy logs: docker compose logs caddy to verify the request arrived at the proxy.

Issue 2: PostgreSQL disk usage grew massively

  • Error Message: Server stops responding; No space left on device.
  • Root Cause: n8n logs every execution payload by default. Without pruning, binary data and massive JSON arrays consume the entire NVMe drive.
  • Solution Steps: 1. Exec into the server, clear temporary files to gain CLI space. 2. Ensure EXECUTIONS_DATA_PRUNE=true and EXECUTIONS_DATA_MAX_AGE=168 (7 days) are active. 3. Manually run the prune command inside the container to clear backlogs.

Issue 3: Workflows appear to be running twice for the same trigger

  • Error Message: Duplicate records created in downstream CRM.
  • Root Cause: External services (like Stripe or Shopify) require a 200 OK response within 3-5 seconds. If a complex n8n workflow takes 10 seconds, the external service assumes failure and retries the webhook, triggering a second parallel execution.
  • Solution Steps: Configure the Webhook node to "Respond Immediately" rather than "When Last Node Finishes".

Issue 4: Ollama inference is extremely slow after working initially

  • Error Message: Inference takes 60+ seconds per prompt.
  • Root Cause: Swap thrashing. The model weights exceed available physical RAM, forcing the OS to page memory to the NVMe disk.
  • Solution Steps: Upgrade your VPS RAM tier to physically accommodate the model parameters, or switch to a smaller quantized model.

Issue 5: SSL certificate stopped renewing

  • Error Message: Browser displays NET::ERR_CERT_DATE_INVALID.
  • Root Cause: Port 80 is blocked by your cloud provider firewall, or DNS records were changed. Let's Encrypt requires port 80 to complete the HTTP-01 challenge.
  • Solution Steps: Verify UFW allows port 80, and check provider-level network security groups.

10. Advanced Extensions

Enhancement 1: Multi-Worker Queue Mode

Transition from a single n8n container to a Redis-backed queue. This requires adding a redis service to your docker-compose.yml and defining n8n-worker containers. This drastically improves concurrency limits, allowing your infrastructure to process 10,000+ webhooks simultaneously by queuing the execution logic.

Enhancement 2: Self-Hosted Vector Database (Qdrant)

Add a Qdrant container directly to your docker network. By keeping embedding storage on the same internal network as n8n, you eliminate external API latency and secure proprietary corporate data completely within your VPS perimeter.

11. FAQ Section

  • How much RAM does n8n actually need for production agent workloads? A minimum of 2GB for the orchestrator alone, but you must provision 4-8GB total to accommodate PostgreSQL and the host operating system under moderate load.
  • Do I need a GPU VPS to run AI agents? No. If you use cloud LLM APIs (OpenAI, Anthropic), a standard CPU-based VPS is perfect. GPUs are only required if you are hosting local conversational models (13B+ parameters) via Ollama.
  • How do I keep n8n's database from filling up my disk? You must configure the execution data pruning environment variables (EXECUTIONS_DATA_PRUNE=true). We recommend keeping a maximum of 7 days of execution history for production troubleshooting.
  • Is Docker required to self-host n8n? While you can install n8n directly via npm, Docker is the industry standard for production custom AI agent development. It isolates dependencies, standardizes upgrades, and simplifies database connectivity.
  • Should I use PostgreSQL or SQLite for a self-hosted n8n instance? Always use PostgreSQL for production. SQLite locks the entire database during write operations, which causes severe bottlenecks and crashes during concurrent webhook executions.
  • When does self-hosting stop making sense and managed deployment win? If your agent stack is a small internal tool and your team lacks dedicated DevOps capacity, the operational overhead of managing security patches, backups, and uptime makes managed deployment economically superior.

12. Conclusion & Next Steps

Sizing and establishing a VPS for AI agent workloads demands discipline, not guesswork. By strictly aligning your RAM, CPU, and storage configurations to an honest workload profile, you transition from fragile, over-budget servers to a battle-tested production environment. We deployed n8n with PostgreSQL state persistence, secured the perimeter via Caddy, and established essential monitoring frameworks.

This deployment establishes your self-hosted moat. The technical effort executed today provides a foundation that processes every subsequent workflow at near-zero marginal cost, entirely changing the unit economics of your automation initiatives.

Immediate Next Steps:

  1. Provision your selected VPS and execute the hardening commands.
  2. Deploy the Docker Compose stack and verify Caddy TLS issuance.
  3. Configure your first automated backup of the PostgreSQL volume.

If your AI infrastructure is critical to revenue and you prefer to focus on building agents rather than managing Linux servers, you need strategic automation partners. Book a free automation audit with N8N Lab. We map your exact workload to the optimal infrastructure, deploy the stack with enterprise-grade security, and handle continuous incident response so you scale faster and more profitably.

n8n Lab is an independent service provider. We are not affiliated with, endorsed by, or sponsored by n8n GmbH. “n8n” is a trademark of n8n GmbH and is used here only to describe the platform-specific implementation and automation services we provide.