Securing My n8n Workflows: A Deep Dive into DNS and TLS

Objective

Establish reliable and encrypted access to n8n (and associated services) either publicly (Let’s Encrypt DNS-01 challenge) or on LAN (Split-DNS + local certificate).

Why Secure n8n?

n8n is a powerful automation platform that often handles sensitive credentials, API keys, and business-critical workflows. Securing access with proper DNS and TLS ensures:

  • Data Protection: Encrypted connections prevent credential interception
  • Authentication: Verified certificates prevent man-in-the-middle attacks
  • Compliance: Meets security best practices for workflow automation
  • Professional Setup: Demonstrates infrastructure maturity

Architecture Overview

Internet/LAN Clients
       ↓
   pfSense (DNS + Firewall)
       ↓
Nginx Proxy Manager (TLS Termination)
       ↓
   n8n Docker Container (5678)

Option A: Public Domain + Cloudflare + DNS Challenge (Let’s Encrypt)

Prerequisites

  • Public domain (can use free services like Freenom)
  • Cloudflare account (free tier sufficient)
  • Nginx Proxy Manager deployed
  • n8n running in Docker

Step 1: Domain Setup with Cloudflare

Register Free Domain (Optional)

# Visit Freenom.com
# Register domain: my-portfolio.tk (or similar)
# Note: Free domains may have limitations

Add Domain to Cloudflare

  1. Create Cloudflare account at cloudflare.com
  2. Click “Add a site”
  3. Enter your domain name
  4. Choose Free plan
  5. Copy Cloudflare nameservers

Update Nameservers at Registrar

  1. Login to your domain registrar (Freenom, Namecheap, etc.)

  2. Navigate to DNS Management

  3. Replace existing nameservers with Cloudflare nameservers:

    ns1.cloudflare.com
    ns2.cloudflare.com
  4. Wait for propagation (can take up to 24 hours)

Step 2: Generate Cloudflare API Token

  1. In Cloudflare dashboard, click profile icon
  2. Navigate to “My Profile”“API Tokens”
  3. Click “Create Token”
  4. Use template: “Edit zone DNS”
  5. Configure permissions:
    • Zone: DNS Edit
    • Include: Specific zone (your domain)
  6. Click “Continue to summary”“Create Token”
  7. Save this token securely - you’ll only see it once!

Step 3: Configure Nginx Proxy Manager

Create DNS Record in Cloudflare

  1. In Cloudflare, go to DNS tab
  2. Add A record:
    • Type: A
    • Name: n8n (or @ for root domain)
    • IPv4 address: Your public IP or use Cloudflare proxy
    • Proxy status: ✓ Proxied (orange cloud)

Add Proxy Host in NPM

  1. Access Nginx Proxy Manager: http://<npm-ip>:81
  2. Click “Proxy Hosts”“Add Proxy Host”
  3. Details Tab:
    • Domain Names: n8n.my-portfolio.tk
    • Scheme: http
    • Forward Hostname/IP: n8n (Docker container name) or IP
    • Forward Port: 5678
    • Websockets Support: ✓ CRITICAL for n8n
    • Block Common Exploits: ✓
  4. SSL Tab:
    • Select “Request a new SSL Certificate”

    • Toggle “Use a DNS Challenge”

    • DNS Provider: Select Cloudflare

    • Credentials File Content:

      dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN
    • Email Address: Your email for Let’s Encrypt

    • Options:

      • ✓ Force SSL
      • ✓ HTTP/2 Support
      • ✓ HSTS Enabled
  5. Click Save

Step 4: Verify Access

# Test DNS resolution
nslookup n8n.my-portfolio.tk

# Test HTTPS access
curl -I https://n8n.my-portfolio.tk

# Access in browser
https://n8n.my-portfolio.tk

Advantages and Limitations

✅ Advantages: - Valid public SSL certificate - Automatic renewal every 90 days - No need to open ports 80/443 for HTTP-01 validation - Works from anywhere with internet access

⚠️ Limitations: - Requires public domain and DNS propagation - Depends on external services (Cloudflare, Let’s Encrypt) - Potential privacy concerns with public exposure

Option B: Local DNS (pfSense) + Local Certificate

Use Case

Perfect for: - Internal homelab access only - No public domain desired - Offline or air-gapped environments - Development and testing

Step 1: Split-DNS Configuration in pfSense

Configure DNS Resolver Host Overrides

  1. Login to pfSense web interface
  2. Navigate to ServicesDNS Resolver
  3. Ensure DNS Resolver is enabled
  4. Scroll to Host Overrides
  5. Click “Add”:
    • Host: n8n
    • Domain: local.home (or your choice)
    • IP Address: IP of host running NPM
    • Description: n8n automation platform
  6. Click SaveApply Changes

Test DNS Resolution

From a client on your network:

# Should resolve to your NPM host IP
nslookup n8n.local.home

# Or using dig
dig n8n.local.home

Step 2: Generate Local SSL Certificate

Option A: Self-Signed Certificate (OpenSSL)

# Generate private key
openssl genrsa -out n8n-local.key 2048

# Generate certificate signing request
openssl req -new -key n8n-local.key -out n8n-local.csr \
  -subj "/C=US/ST=State/L=City/O=Homelab/CN=n8n.local.home"

# Generate self-signed certificate
openssl x509 -req -days 365 -in n8n-local.csr \
  -signkey n8n-local.key -out n8n-local.crt

Why mkcert? Automatically trusted by browsers after CA installation.

# Install mkcert
# On Ubuntu/Debian:
sudo apt install libnss3-tools
wget https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-amd64
sudo mv mkcert-v1.4.4-linux-amd64 /usr/local/bin/mkcert
sudo chmod +x /usr/local/bin/mkcert

# Install local CA
mkcert -install

# Generate certificate for n8n
mkcert n8n.local.home "*.local.home"

# This creates:
# n8n.local.home+1.pem (certificate)
# n8n.local.home+1-key.pem (private key)

Step 3: Import Certificate into NPM

  1. In Nginx Proxy Manager, go to SSL Certificates
  2. Click “Add SSL Certificate”“Custom”
  3. Upload files:
    • Certificate Key: n8n.local.home+1-key.pem
    • Certificate: n8n.local.home+1.pem
  4. Click Save

Step 4: Create Proxy Host

  1. Click “Proxy Hosts”“Add Proxy Host”
  2. Details Tab:
    • Domain Names: n8n.local.home
    • Scheme: http
    • Forward Hostname/IP: n8n or container IP
    • Forward Port: 5678
    • Websockets Support: ✓
    • Block Common Exploits: ✓
  3. SSL Tab:
    • SSL Certificate: Select your custom certificate
    • Force SSL: ✓
    • HTTP/2 Support: ✓
  4. Click Save

Step 5: Install CA on Client Devices

For mkcert:

Linux:

mkcert -install

Windows:

# Run mkcert installer
mkcert-v1.4.4-windows-amd64.exe -install

macOS:

mkcert -install

Mobile Devices: - Export CA certificate from mkcert -CAROOT - Transfer to device - Install as trusted certificate

Advantages and Limitations

✅ Advantages: - No external dependencies - Works offline - Full control over certificates - No public exposure

⚠️ Limitations: - Requires CA installation on all client devices - Manual certificate renewal - Only accessible on local network

Troubleshooting Common Issues

Problem: n8n requires HTTPS for secure cookies

Solutions:

# Option 1: Use HTTPS (recommended)
# Follow steps above

# Option 2: Disable secure cookie (TESTING ONLY)
docker run -e N8N_SECURE_COOKIE=false n8nio/n8n

Issue 2: NPM Cannot Resolve Container Name

Problem: Nginx Proxy Manager can’t reach n8n container

Solutions:

# Option 1: Use Docker network
# Ensure both containers are on same Docker network

# Option 2: Use host IP instead of container name
# In NPM proxy host, use: 192.168.x.x instead of "n8n"

# Option 3: Use Docker bridge IP
docker inspect n8n | grep IPAddress
# Use that IP in NPM configuration

Issue 3: Internal DNS Not Resolving

Problem: Clients can’t resolve n8n.local.home

Solutions:

  1. Verify pfSense DNS Resolver is running:

    • Services → DNS Resolver → Status
  2. Check client DNS settings:

    # Linux/macOS
    cat /etc/resolv.conf
    # Should show pfSense IP
    
    # Windows
    ipconfig /all
    # Check DNS Servers
  3. Test from pfSense itself:

    # Diagnostics → Command Prompt
    nslookup n8n.local.home

Issue 4: Let’s Encrypt DNS-01 Challenge Fails

Problem: Certificate request fails

Solutions:

  1. Verify API Token Permissions:

    • Must have Zone:DNS:Edit for specific zone
    • Cannot use global API key
  2. Check TXT Record Propagation:

    dig _acme-challenge.n8n.my-portfolio.tk TXT
  3. Review NPM Logs:

    docker logs nginx-proxy-manager

Security Best Practices

1. Enable Authentication in n8n

# docker-compose.yml
environment:
  - N8N_BASIC_AUTH_ACTIVE=true
  - N8N_BASIC_AUTH_USER=admin
  - N8N_BASIC_AUTH_PASSWORD=secure_password_here

2. Restrict Access by IP

In NPM, add Access List: - Allow: Your trusted IPs - Deny: All others

3. Use Strong Cloudflare Settings

  • Enable Bot Fight Mode
  • Add Page Rules for rate limiting
  • Enable Always Use HTTPS

4. Monitor Access Logs

# View NPM access logs
docker exec -it nginx-proxy-manager tail -f /data/logs/proxy-host-*.log

5. Regular Certificate Monitoring

  • Set calendar reminder for certificate expiry
  • Monitor NPM renewal logs
  • Test access after renewals

Validation Checklist

For Public Domain Setup:

For Local Setup:

Conclusion

Securing n8n with proper DNS and TLS configuration transforms a vulnerable automation platform into a production-ready system. Whether you choose the public domain approach with Let’s Encrypt or the local certificate method, both provide strong encryption and professional access management.

The key is understanding your requirements: - Public access needed? → Option A (Cloudflare + Let’s Encrypt) - Internal only? → Option B (pfSense + Local Certs)

Both approaches demonstrate infrastructure maturity and security awareness, critical skills for any homelab administrator or security professional.

Remember: Security is layers. DNS and TLS are just the beginning - add authentication, monitoring, and regular audits for comprehensive protection.