n8n, Open WebUI and AI apps#
The hosted versions of these tools are convenient, right up until one of three things happens: you hit the quota, the price scales with usage, or you would rather not send the data you are processing to someone else's server.
All three are solved by running them yourself. This page shows how.
The shortcut: one-click install
Most of these are available as one-click installs from the VeriTeknik VPS panel - n8n, Open WebUI, LibreChat and others. Once you have a server, just pick the application; none of the steps below are needed.
This page is for installing something not on that list, or for understanding how it works.
How much server do you need?#
| Application | Minimum | Comfortable |
|---|---|---|
| n8n (automation) | 1 vCPU / 2 GB | 2 vCPU / 4 GB |
| Open WebUI (external API) | 1 vCPU / 2 GB | 2 vCPU / 4 GB |
| Open WebUI + Ollama (local model) | 4 vCPU / 16 GB | needs a GPU |
If you want to run a local model
You can run a 7B model on CPU with Ollama, but it is slow - a few tokens per second. Serious use needs a GPU.
Alternative: install Open WebUI and point it at the OpenAI-compatible API on VeriTeknik AI Cloud. The model power is ours, the interface and your data stay yours. See AI Cloud (PaaS).
Installing n8n#
Compose is the cleanest way. /opt/n8n/docker-compose.yml:
services:
n8n:
image: docker.n8n.io/n8nio/n8n:latest
restart: unless-stopped
ports:
- "127.0.0.1:5678:5678"
environment:
- N8N_HOST=n8n.example.com
- N8N_PORT=5678
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://n8n.example.com/
- GENERIC_TIMEZONE=Europe/Istanbul
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
volumes:
- n8n_data:/home/node/.n8n
volumes:
n8n_data:
Generate the encryption key into .env:
cd /opt/n8n
echo "N8N_ENCRYPTION_KEY=$(openssl rand -hex 32)" > .env
chmod 600 .env
docker compose up -d
Do not lose N8N_ENCRYPTION_KEY
n8n encrypts the credentials of every service you connect with this key. Lose it and every stored credential becomes unreadable and has to be re-entered. Back it up.
The 127.0.0.1:5678 binding is deliberate - see why it matters.
Installing Open WebUI#
/opt/openwebui/docker-compose.yml:
services:
open-webui:
image: ghcr.io/open-webui/open-webui:main
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080"
environment:
- OPENAI_API_BASE_URL=https://api.veriteknik.com/v1
- OPENAI_API_KEY=${OPENAI_API_KEY}
- WEBUI_SECRET_KEY=${WEBUI_SECRET_KEY}
volumes:
- openwebui_data:/app/backend/data
volumes:
openwebui_data:
cd /opt/openwebui
{
echo "OPENAI_API_KEY=sk-..."
echo "WEBUI_SECRET_KEY=$(openssl rand -hex 32)"
} > .env
chmod 600 .env
docker compose up -d
Put a domain in front#
A subdomain per application is cleanest: n8n.example.com, chat.example.com.
Create an A record for each, then Nginx:
server {
listen 80;
server_name n8n.example.com;
location / {
proxy_pass http://127.0.0.1:5678;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 300s;
}
}
WebSockets and long requests
The Upgrade / Connection headers are required for n8n's live execution view and Open WebUI's streaming responses. proxy_read_timeout must be raised too; the 60 second default cuts off a long AI response mid-stream.
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d n8n.example.com
Do these, without exception#
Turn on authentication. Both applications ask you to create an admin account on first load. Do it immediately - an n8n left open to the internet is a machine anyone can run workflows on, as you.
Take backups. The data lives in Docker volumes:
docker run --rm \
-v n8n_n8n_data:/data \
-v /opt/backup:/backup \
alpine tar czf /backup/n8n-$(date +%F).tar.gz -C /data .
A panel snapshot is also an option, and easier.
Keep them updated. These projects move fast:
cd /opt/n8n && docker compose pull && docker compose up -d && docker image prune -f
With Morpheus
"update n8n and clean up the old images"
"back up n8n on the first of every month and let me know"
Checklist#
- [ ]
docker compose ps→Up - [ ]
sudo ss -tlnp→ app ports on127.0.0.1only - [ ] Admin account created, the app is not left open
- [ ]
https://n8n.example.comopens with the padlock - [ ] Live execution / streaming responses work (WebSocket headers correct)
- [ ]
N8N_ENCRYPTION_KEYand.envfiles backed up - [ ] A backup method is chosen and has been tested once