This commit is contained in:
Fedor
2026-02-16 18:18:13 +03:00
commit eb458d687b
8 changed files with 225 additions and 0 deletions

10
.env.example Normal file
View File

@@ -0,0 +1,10 @@
# PostgreSQL для n8n (не коммитить .env в репозиторий)
POSTGRES_USER=n8n
POSTGRES_PASSWORD=<сгенерировать_надёжный_пароль>
POSTGRES_DB=n8n
# Внешний прокси: только домены из proxy/squid.conf идут через него
EXTERNAL_PROXY_HOST=proxy.example.com
EXTERNAL_PROXY_PORT=3128
EXTERNAL_PROXY_USER=
EXTERNAL_PROXY_PASS=

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.env

54
README.md Normal file
View File

@@ -0,0 +1,54 @@
# n8n на n8n.clientright.ru
Развёртывание n8n в Docker с PostgreSQL, SSL (Let's Encrypt) и выборочным прокси для части доменов (OpenAI, Anthropic и др.).
## Состав
- **n8n** (n8nio/n8n:2.7.5) — за Nginx по HTTPS
- **PostgreSQL 16** — хранилище n8n
- **Squid** — локальный прокси: часть доменов идёт через внешний прокси, остальное — напрямую
## Требования
- Docker и Docker Compose
- Nginx как reverse proxy с SSL для `n8n.clientright.ru`
- Файл `.env` (см. ниже)
## Быстрый старт
1. Скопировать `.env.example` в `.env` и заполнить значения (пароли, внешний прокси при необходимости).
2. Запуск:
```bash
docker compose up -d
```
3. Открыть https://n8n.clientright.ru и создать первого пользователя.
## Переменные окружения (.env)
Файл `.env` не коммитится в репозиторий. Пример структуры — в `.env.example`.
- **POSTGRES_*** — пользователь, пароль и БД для PostgreSQL.
- **EXTERNAL_PROXY_*** — внешний HTTP-прокси (host, port, при необходимости user/pass). Через него идут только домены из `proxy/squid.conf` (по умолчанию openai.com, anthropic.com, googleapis.com).
- Остальной трафик n8n выходит в интернет напрямую.
## Прокси
- n8n использует только локальный Squid (`http://proxy:3128`).
- В `proxy/squid.conf` заданы домены (acl `to_parent_proxy`), которые маршрутизируются во внешний прокси; для них включён `never_direct allow to_parent_proxy`.
- Добавить домен: дописать в `proxy/squid.conf` строку вида `acl to_parent_proxy dstdomain .example.com`, пересобрать и перезапустить proxy:
`docker compose build proxy && docker compose up -d proxy`.
## Обновление n8n
Изменить тег образа в `docker-compose.yml` (например, `n8nio/n8n:2.7.6`), затем:
```bash
docker compose pull n8n
docker compose up -d n8n
```
## Файлы
- `docker-compose.yml` — сервисы n8n, postgres, proxy
- `proxy/` — образ и конфиг Squid (Dockerfile, squid.conf, entrypoint.sh)
- `n8n.clientright.ru.conf` — пример конфига Nginx (реальный конфиг на сервере в `/etc/nginx/conf.d/`)

59
docker-compose.yml Normal file
View File

@@ -0,0 +1,59 @@
services:
proxy:
build: ./proxy
restart: always
env_file: .env
environment:
EXTERNAL_PROXY_HOST: ${EXTERNAL_PROXY_HOST:-}
EXTERNAL_PROXY_PORT: ${EXTERNAL_PROXY_PORT:-}
EXTERNAL_PROXY_USER: ${EXTERNAL_PROXY_USER:-}
EXTERNAL_PROXY_PASS: ${EXTERNAL_PROXY_PASS:-}
# Порт только внутри Docker-сети, наружу не светим
postgres:
image: postgres:16-alpine
restart: always
env_file: .env
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- n8n_postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -h localhost -U ${POSTGRES_USER:-n8n} -d ${POSTGRES_DB:-n8n}"]
interval: 5s
timeout: 5s
retries: 10
n8n:
image: n8nio/n8n:2.7.5
restart: always
depends_on:
postgres:
condition: service_healthy
proxy:
condition: service_started
env_file: .env
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_PROTOCOL: https
N8N_HOST: n8n.clientright.ru
WEBHOOK_URL: https://n8n.clientright.ru/
# Весь трафик n8n — через локальный Squid; выборочно домены идут во внешний прокси
HTTP_PROXY: http://proxy:3128
HTTPS_PROXY: http://proxy:3128
NO_PROXY: postgres,127.0.0.1,localhost,n8n.clientright.ru
ports:
- "127.0.0.1:5678:5678"
volumes:
- n8n_data:/home/node/.n8n
volumes:
n8n_postgres_data:
n8n_data:

38
n8n.clientright.ru.conf Normal file
View File

@@ -0,0 +1,38 @@
# n8n.clientright.ru
server {
listen 147.45.146.17:80;
server_name n8n.clientright.ru;
location /.well-known/acme-challenge/ {
root /var/www/fastuser/data/www/n8n.clientright.ru;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 147.45.146.17:443 ssl http2;
server_name n8n.clientright.ru;
ssl_certificate /etc/letsencrypt/live/n8n.clientright.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/n8n.clientright.ru/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/n8n.clientright.ru/chain.pem;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
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 300;
proxy_connect_timeout 60;
proxy_buffering off;
}
}

9
proxy/Dockerfile Normal file
View File

@@ -0,0 +1,9 @@
FROM alpine:3.19
RUN apk add --no-cache squid \
&& mkdir -p /var/log/squid /var/cache/squid /var/run/squid \
&& chown -R squid:squid /var/log/squid /var/cache/squid /var/run/squid
COPY squid.conf /etc/squid/squid.conf
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
EXPOSE 3128
ENTRYPOINT ["/entrypoint.sh"]

15
proxy/entrypoint.sh Normal file
View File

@@ -0,0 +1,15 @@
#!/bin/sh
set -e
mkdir -p /etc/squid/conf.d
# Родительский прокси: host и port из .env (генерируем одну строку конфига)
if [ -n "$EXTERNAL_PROXY_HOST" ] && [ -n "$EXTERNAL_PROXY_PORT" ]; then
_auth=""
if [ -n "$EXTERNAL_PROXY_USER" ] && [ -n "$EXTERNAL_PROXY_PASS" ]; then
_auth=" login=${EXTERNAL_PROXY_USER}:${EXTERNAL_PROXY_PASS}"
fi
echo "cache_peer ${EXTERNAL_PROXY_HOST} parent ${EXTERNAL_PROXY_PORT} 0 no-query default name=parent${_auth}" > /etc/squid/conf.d/parent.conf
else
echo "# Внешний прокси не задан (EXTERNAL_PROXY_HOST/PORT). Заполни .env и перезапусти." > /etc/squid/conf.d/parent.conf
echo "cache_peer no-proxy.invalid parent 1 0 no-query default name=parent" >> /etc/squid/conf.d/parent.conf
fi
exec squid -f /etc/squid/squid.conf -N

39
proxy/squid.conf Normal file
View File

@@ -0,0 +1,39 @@
# Локальный прокси для n8n: часть доменов — через внешний прокси, остальное — напрямую
# Внешний прокси задаётся в .env: EXTERNAL_PROXY_HOST, EXTERNAL_PROXY_PORT
# Домены для внешнего прокси — список ниже (acl to_parent_proxy)
http_port 3128
# Доступ только из Docker-сети (n8n)
acl localnet src 10.0.0.0/8
acl localnet src 172.16.0.0/12
acl localnet src 192.168.0.0/16
acl SSL_ports port 443
acl Safe_ports port 80 443
acl CONNECT method CONNECT
# Подключаем сгенерированный конфиг с cache_peer (host/port из env)
include /etc/squid/conf.d/parent.conf
# Домены, которые идут через внешний прокси (остальные — напрямую)
acl to_parent_proxy dstdomain .openai.com
acl to_parent_proxy dstdomain .anthropic.com
acl to_parent_proxy dstdomain .googleapis.com
# Добавь при необходимости: .azure.com, .aws.amazon.com и т.д.
# Родительский прокси только для этих доменов
cache_peer_access parent allow to_parent_proxy
cache_peer_access parent deny all
# Важно: CONNECT (HTTPS) по умолчанию Squid может слать напрямую, а не в parent.
# Запрещаем прямой доступ для этих доменов — только через parent.
never_direct allow to_parent_proxy
# Таймауты при работе через родительский прокси (увеличить при медленном прокси)
connect_timeout 30 seconds
read_timeout 60 seconds
# Разрешаем запросы из нашей сети
http_access allow localnet
http_access deny all