Running mission-critical automation workflows (n8n, PostgreSQL, Redis, web scrapers) on Windows 11 via WSL2 inevitably hits two fatal operational bottlenecks:
-
vmmemRAM Ballooning: The Linux page cache greedily eats 8 to 16 GB of host RAM, starving your IDE and browser. - Offline Webhooks: Whenever your laptop sleeps, reboots for Windows Updates, or drops Wi-Fi, incoming Stripe, GitHub, or CRM webhooks fail with silent timeouts.
In this guide, we'll execute an atomic volume snapshot in WSL2, securely transfer it to a $6/month DigitalOcean Basic Droplet, and configure production Nginx with Let's Encrypt SSL for 24/7 always-on reliability.
Migration Architecture
Here is the migration pipeline from local WSL2 to a hardened cloud droplet:
flowchart TD
subgraph LocalWSL["1. Local Development Environment (WSL2)"]
WSL["Local Windows 11 PC<br/>- vmmem RAM exhaustion<br/>- Shuts down when PC sleeps"]
DockerLocal["Local Docker Containers<br/>(n8n, Postgres, Redis)"]
Dump["Volume Snapshot Export<br/>docker run --rm -v ... tar -czf"]
end
subgraph Transit["2. Secure Network Migration"]
RSync["Encrypted SSH Sync<br/>rsync -avz -e ssh backup.tar.gz root@droplet:/srv/"]
end
subgraph DigitalOcean["3. DigitalOcean Cloud Droplet ($6/mo Standard)"]
UFW["UFW Firewall Protection<br/>(Open 22, 80, 443 | Block raw app ports)"]
DockerHost["Docker Engine + Compose<br/>(24/7 Dedicated Cloud Compute)"]
subgraph Stack["Production Microservices Stack"]
Nginx["Nginx Reverse Proxy<br/>(Let's Encrypt SSL Auto-Renewal)"]
N8nProd["n8n Automation Engine<br/>(Webhooks Active 24/7)"]
DBProd[("Restored Persistent Volumes<br/>(Fast NVMe SSD Storage)")]
end
end
DockerLocal --> Dump
Dump --> RSync
RSync --> UFW
UFW --> DockerHost
DockerHost --> Nginx
Nginx -->|HTTPS Reverse Proxy| N8nProd
N8nProd --> DBProd
Step 1: Provision and Secure the Cloud Droplet
- Spin up an Ubuntu 24.04 LTS Droplet on DigitalOcean (Basic $6/mo tier: 1 GB RAM / 1 vCPU / 25 GB NVMe SSD).
- SSH into your droplet and configure the host firewall with UFW:
ssh root@<droplet_ip>
# Restrict inbound traffic strictly to SSH, HTTP, and HTTPS
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp comment 'SSH'
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'
sudo ufw enable
Note: Never expose port 5678 (n8n) or 5432 (Postgres) directly to the public internet.
Step 2: Atomic Volume Snapshot in WSL2
Stop your local stack cleanly to guarantee zero open file-lock corruption:
# Inside local WSL2 terminal
cd ~/my-n8n-project
docker compose stop
Create a point-in-time tarball snapshot of your persistent named volume using a disposable Alpine container:
docker run --rm \
-v n8n_data:/data:ro \
-v $(pwd):/backup \
alpine tar -czf /backup/n8n_data_export.tar.gz -C /data .
Step 3: Transfer Volume & Configuration Over SSH
Push the archive, your docker-compose.yml, and your .env file directly to the Droplet:
# Run from local WSL2
scp -P 22 n8n_data_export.tar.gz root@<droplet_ip>:/srv/
scp -P 22 docker-compose.yml root@<droplet_ip>:/srv/
scp -P 22 .env root@<droplet_ip>:/srv/
Step 4: Restore Volume and Boot Production Stack
SSH into the cloud server:
ssh root@<droplet_ip>
cd /srv
# 1. Create target named volume
docker volume create n8n_data
# 2. Extract backup into cloud volume
docker run --rm \
-v n8n_data:/data \
-v /srv:/backup \
alpine tar -xzf /backup/n8n_data_export.tar.gz -C /data
Production docker-compose.yml
version: '3.8'
services:
n8n:
image: docker.n8n.io/n8nio/n8n:latest
container_name: n8n-automation
restart: always
environment:
- N8N_HOST=n8n.yourdomain.com
- N8N_PORT=5678
- N8N_PROTOCOL=https
- NODE_ENV=production
- WEBHOOK_URL=https://n8n.yourdomain.com/
- GENERIC_TIMEZONE=UTC
- N8N_PAYLOAD_SIZE_MAX=64
volumes:
- n8n_data:/home/node/.n8n
networks:
- internal-net
nginx:
image: nginx:alpine
container_name: nginx-proxy
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./certbot/conf:/etc/letsencrypt:ro
- ./certbot/www:/var/www/certbot:ro
networks:
- internal-net
depends_on:
- n8n
networks:
internal-net:
driver: bridge
volumes:
n8n_data:
external: true
Step 5: Issue SSL and Launch
- Point your domain
Arecord (n8n.yourdomain.com) to your Droplet IP. - Issue Let's Encrypt certificates:
docker run -it --rm \
-v /srv/certbot/conf:/etc/letsencrypt \
-v /srv/certbot/www:/var/www/certbot \
certbot/certbot certonly --webroot -w /var/www/certbot \
-d n8n.yourdomain.com
- Start the stack:
docker compose up -d
Your workflows, API keys, database connections, and executions are now running 24/7 in the cloud without consuming a single megabyte of memory on your local machine.
Originally published on GearFlow Lab.
Top comments (0)