n8n Community Edition Cost-Effectively on Azure: Complete Hosting Guide

n8n is an open-source workflow automation platform that serves as an alternative to Zapier or Make. The Community Edition can be self-hosted - on Azure for approximately 45-90 EUR/month, significantly cheaper than the cloud version.

Architecture Overview

                    ┌─────────────────────┐
                    │   Azure Front Door  │
                    │  (HTTPS/SSL/WAF)    │
                    └──────────┬──────────┘

┌──────────────────────────────┼──────────────────────────────────┐
│                    Azure Container Instances                     │
│                              │                                   │
│  ┌───────────────────────────▼───┐  ┌─────────────────┐         │
│  │        n8n-main               │  │   n8n-runner    │         │
│  │  (UI/API/Webhooks/Broker)     │  │ (Task Runner)   │         │
│  │       Port 5678               │  │                 │         │
│  └───────────────────────────────┘  └─────────────────┘         │
│                        │                                         │
│               Azure Files Share (/home/node/.n8n)                │
└────────────────────────┼─────────────────────────────────────────┘

                  ┌──────▼──────┐
                  │ PostgreSQL  │
                  │ Flexible    │
                  └─────────────┘

Components and Costs

ComponentAzure ServiceSKU~Cost/Month
n8n ContainerContainer Instances2x 1 vCPU, 2 GB RAM30-60 EUR
DatabasePostgreSQL Flexible ServerB_Standard_B1ms15-25 EUR
PersistenceStorage Account + File ShareStandard LRS1-5 EUR
Reverse ProxyAzure Front DoorStandardincl.
SecretsAzure Key VaultStandard<1 EUR
MonitoringLog Analytics30 days retentionincl.
BackupRecovery Services VaultDaily, 7 days<5 EUR
Total45-90 EUR

Container Configuration (n8n 2.x)

n8n 2.x uses two containers:

n8n-main - Main container for UI, API, Webhooks and Task Broker:

  • Image: n8nio/n8n:2.2.3
  • Port: 5678 (external), 5679 (Task Broker internal)
  • Resources: 1 vCPU, 2 GB RAM

n8n-runner - Isolated code execution for Task Runner:

  • Image: n8nio/n8n-runner:2.2.3
  • Connects to broker at http://127.0.0.1:5679
  • Resources: 1 vCPU, 2 GB RAM

Essential Environment Variables

# Database
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=<postgres-server>.postgres.database.azure.com
DB_POSTGRESDB_DATABASE=n8n
DB_POSTGRESDB_USER=n8nadmin
DB_POSTGRESDB_PASSWORD=<from-key-vault>
DB_POSTGRESDB_SSL_ENABLED=true

# URLs (important for webhooks!)
N8N_HOST=n8n.example.com
N8N_PROTOCOL=https
N8N_PORT=443
WEBHOOK_URL=https://n8n.example.com/
N8N_EDITOR_BASE_URL=https://n8n.example.com/

# Security
N8N_ENCRYPTION_KEY=<from-key-vault>
N8N_SECURE_COOKIE=true

# Task Runner (n8n 2.x)
N8N_RUNNERS_ENABLED=true
N8N_RUNNERS_MODE=internal_launcher
N8N_RUNNERS_BROKER_LISTEN_ADDRESS=127.0.0.1

# Runner Container
N8N_RUNNERS_AUTH_TOKEN=<from-key-vault>
N8N_RUNNER_TASK_BROKER_URI=http://127.0.0.1:5679

# Timezone
GENERIC_TIMEZONE=Europe/Berlin

Azure Front Door Configuration

Front Door handles HTTPS termination, SSL certificate management, and WAF.

Origin Group:

  • Health Probe: GET /healthz every 30 seconds via HTTP
  • Load Balancing: Latency-based

Origin:

  • Host: <container-name>.<region>.azurecontainer.io
  • HTTP Port: 5678
  • Forwarding Protocol: HTTP Only (container has no SSL)

Route:

  • Custom Domain with Managed Certificate
  • HTTPS Redirect enabled
  • Caching disabled (SPA compatibility)

Fixing HTTP/2 Protocol Errors

A common issue: Browsers show ERR_HTTP2_PROTOCOL_ERROR even though curl works fine. The cause is Brotli compression by Front Door.

Solution: Create a Rule Set that removes the Accept-Encoding header:

# Create Rule Set
az afd rule-set create \
  --profile-name <profile> \
  --resource-group <rg> \
  --rule-set-name N8NNoCompression

# Add Rule
az afd rule create \
  --profile-name <profile> \
  --resource-group <rg> \
  --rule-set-name N8NNoCompression \
  --rule-name RemoveAcceptEncoding \
  --order 1 \
  --action-name ModifyRequestHeader \
  --header-action Delete \
  --header-name "Accept-Encoding"

# Connect Rule Set with Route
az afd route update \
  --profile-name <profile> \
  --resource-group <rg> \
  --endpoint-name <endpoint> \
  --route-name <route> \
  --rule-sets N8NNoCompression

PostgreSQL Configuration

  • Version: 15
  • SKU: B_Standard_B1ms (Burstable, cost-effective)
  • SSL: Required
  • Firewall: Allow Azure Services (for Container Instances)

Persistence with Azure Files

n8n stores credentials and binary data under /home/node/.n8n. Without persistent storage, these are lost on container restart.

# Storage Account
resource "azurerm_storage_account" "n8n" {
  name                     = "stn8nautomation"
  resource_group_name      = azurerm_resource_group.main.name
  location                 = azurerm_resource_group.main.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

# File Share
resource "azurerm_storage_share" "n8n" {
  name                 = "n8n-data"
  storage_account_id   = azurerm_storage_account.n8n.id
  quota                = 5 # GB
}

Mount in the container as a volume to /home/node/.n8n.

Secrets Management

Never store passwords and keys in Terraform state or environment variables in plain text:

# Generate random secrets
resource "random_password" "postgres" {
  length  = 32
  special = true
}

resource "random_password" "n8n_encryption_key" {
  length  = 64
  special = false
}

# Store in Key Vault
resource "azurerm_key_vault_secret" "postgres_password" {
  name         = "postgres-admin-password"
  value        = random_password.postgres.result
  key_vault_id = azurerm_key_vault.main.id
}

Monitoring and Alerts

Log Analytics Workspace with ContainerInsights for:

  • CPU/Memory utilization
  • Container restarts
  • Health probe status

Recommended Alerts:

  • CPU > 80% over 5 minutes
  • Memory > 85% over 5 minutes
  • Container Restart Count > 3

Backup Strategy

Recovery Services Vault for Azure File Share:

  • Daily backup
  • 7 days retention
  • Point-in-time recovery possible

n8n 2.x Specifics

  • Publish Workflow: Changes must be explicitly “Published” after saving
  • Task Runners: Enabled by default, code nodes run isolated
  • Internal User Management: Basic Auth is deprecated, create owner account on first access

Terraform Structure

terraform/
├── main.tf          # Data Sources
├── versions.tf      # Provider (azurerm >= 3.0)
├── variables.tf     # Input variables
├── locals.tf        # Tags, computed values
├── container.tf     # Container Instances (2 containers)
├── postgres.tf      # PostgreSQL Flexible Server
├── storage.tf       # Storage Account, File Share, Backup
├── keyvault.tf      # Key Vault with Secrets
├── secrets.tf       # Password generation
├── security.tf      # Defender, Budget
├── monitoring.tf    # Log Analytics, Alerts
└── outputs.tf       # URLs, Connection Strings

Cost Optimization Tips

  1. Burstable PostgreSQL instead of General Purpose (saves ~50%)
  2. LRS instead of GRS for Storage (saves ~50%)
  3. Log Retention 30 days instead of longer
  4. No Redis Cache - n8n works without it for small/medium workloads
  5. Budget Alerts to avoid surprises

Conclusion

Self-hosting n8n Community Edition on Azure provides a cost-effective alternative to the cloud version while maintaining full control over your automation workflows. The combination of Container Instances, PostgreSQL Flexible Server, and Azure Front Door offers a production-ready setup with proper security, monitoring, and backup capabilities.

The initial setup requires some effort, but the monthly savings compared to managed n8n plans make it worthwhile for teams with Azure expertise.

Further Reading