go-git, чистий Go без cgo. Голий репозиторій на тенанта, гілка на пристрій за ідентифікатором (ім'я змінюють, історія не має від цього розсипатись), файл за іменем. Однаковий вміст нового коміту не створює. netpulse-gitsync переливає накопичену історію й відтворює втрачений репозиторій із бази — тіла конфігів там і так лежать зашифрованими. У вебі з'явився вибір версії, з якою порівнювати: сервер це вмів (?from=), інтерфейс — ні. Дорогою виправлено чотири тести, які CI запустив уперше з базою. Серед них справжня помилка: машинний токен не міг читати мапи — ACL мап отримував порожній рядок замість uuid і давав 500. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
184 lines
6.8 KiB
YAML
184 lines
6.8 KiB
YAML
# Повний стек NetPulse: БД, кеш, міграції, API з інтерфейсом, колектор
|
||
# зондів і зворотний проксі з автоматичним TLS.
|
||
#
|
||
# Швидкий старт:
|
||
# cp deploy/.env.example .env # і заповнити секрети
|
||
# docker compose up -d
|
||
# docker compose run --rm api netpulse-user -tenant default -login admin -role owner
|
||
#
|
||
# Тільки стенд для розробки (БД і кеш, решта — з go run):
|
||
# docker compose up -d db cache
|
||
|
||
name: netpulse
|
||
|
||
x-server-env: &server-env
|
||
NETPULSE_DSN: postgres://netpulse:${POSTGRES_PASSWORD:?потрібен POSTGRES_PASSWORD}@db:5432/netpulse?sslmode=disable
|
||
NETPULSE_DEK: ${NETPULSE_DEK:?потрібен NETPULSE_DEK — див. deploy/README.md}
|
||
NETPULSE_LOG_LEVEL: ${NETPULSE_LOG_LEVEL:-info}
|
||
TZ: ${TZ:-Europe/Kyiv}
|
||
|
||
services:
|
||
db:
|
||
image: timescale/timescaledb:2.17.2-pg16
|
||
environment:
|
||
POSTGRES_USER: netpulse
|
||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?потрібен POSTGRES_PASSWORD}
|
||
POSTGRES_DB: netpulse
|
||
TIMESCALEDB_TELEMETRY: "off"
|
||
command:
|
||
- postgres
|
||
- -c
|
||
- shared_preload_libraries=timescaledb
|
||
- -c
|
||
- max_connections=200
|
||
- -c
|
||
- shared_buffers=${PG_SHARED_BUFFERS:-512MB}
|
||
- -c
|
||
- timescaledb.max_background_workers=8
|
||
volumes:
|
||
- db-data:/var/lib/postgresql/data
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "pg_isready -U netpulse -d netpulse"]
|
||
interval: 5s
|
||
timeout: 5s
|
||
retries: 20
|
||
restart: unless-stopped
|
||
|
||
cache:
|
||
image: docker.dragonflydb.io/dragonflydb/dragonfly:v1.25.5
|
||
ulimits:
|
||
memlock: -1
|
||
volumes:
|
||
- cache-data:/data
|
||
restart: unless-stopped
|
||
|
||
# Міграції окремою службою, а не на старті API.
|
||
#
|
||
# API запускається в кількох примірниках, і накочування схеми зі старту
|
||
# означало б гонку між ними. Тут же — один запуск, який мусить
|
||
# завершитись успіхом, перш ніж піднімуться API й колектор.
|
||
migrate:
|
||
build: &server-build
|
||
context: .
|
||
dockerfile: deploy/Dockerfile.server
|
||
args:
|
||
VERSION: ${NETPULSE_VERSION:-dev}
|
||
COMMIT: ${NETPULSE_COMMIT:-none}
|
||
image: netpulse/server:${NETPULSE_VERSION:-dev}
|
||
entrypoint: ["netpulse-migrate"]
|
||
environment: *server-env
|
||
depends_on:
|
||
db:
|
||
condition: service_healthy
|
||
restart: "no"
|
||
|
||
api:
|
||
build: *server-build
|
||
image: netpulse/server:${NETPULSE_VERSION:-dev}
|
||
entrypoint: ["netpulse-api"]
|
||
command:
|
||
- -listen=:8080
|
||
- -alert-interval=${NETPULSE_ALERT_INTERVAL:-30s}
|
||
environment:
|
||
<<: *server-env
|
||
NETPULSE_JWT_SECRET: ${NETPULSE_JWT_SECRET:?потрібен NETPULSE_JWT_SECRET — не менше 32 байтів}
|
||
# Історія конфігів у Git. Спільний том для API й колектора:
|
||
# колектор туди пише під час бекапу, API звідти читає для порівняння
|
||
# версій. Різні томи означали б, що половина історії видна одному
|
||
# процесу, а половина другому.
|
||
volumes:
|
||
- git-data:/var/lib/netpulse
|
||
depends_on:
|
||
migrate:
|
||
condition: service_completed_successfully
|
||
cache:
|
||
condition: service_started
|
||
healthcheck:
|
||
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8080/healthz"]
|
||
interval: 10s
|
||
timeout: 3s
|
||
retries: 6
|
||
start_period: 15s
|
||
restart: unless-stopped
|
||
|
||
# Колектор зондів. TLS знімає Caddy, всередині мережі — h2c, тому
|
||
# -insecure. Порт назовні сам не публікує: до нього ходять через
|
||
# проксі, який має справжній сертифікат.
|
||
collector:
|
||
build: *server-build
|
||
image: netpulse/server:${NETPULSE_VERSION:-dev}
|
||
entrypoint: ["netpulse-server"]
|
||
command:
|
||
- -listen=:9443
|
||
- -insecure
|
||
environment: *server-env
|
||
# Історія конфігів у Git. Спільний том для API й колектора:
|
||
# колектор туди пише під час бекапу, API звідти читає для порівняння
|
||
# версій. Різні томи означали б, що половина історії видна одному
|
||
# процесу, а половина другому.
|
||
volumes:
|
||
- git-data:/var/lib/netpulse
|
||
depends_on:
|
||
migrate:
|
||
condition: service_completed_successfully
|
||
restart: unless-stopped
|
||
|
||
proxy:
|
||
image: caddy:2.8-alpine
|
||
environment:
|
||
NETPULSE_DOMAIN: ${NETPULSE_DOMAIN:?потрібен NETPULSE_DOMAIN}
|
||
# Порожній рядок Caddy не приймає: директива email без значення —
|
||
# помилка розбору, і проксі не підніметься взагалі. Тому підстановка
|
||
# спрацьовує і на незадану змінну, і на задану порожньою.
|
||
ACME_EMAIL: ${ACME_EMAIL:-admin@${NETPULSE_DOMAIN}}
|
||
volumes:
|
||
- ./deploy/Caddyfile:/etc/caddy/Caddyfile:ro
|
||
- caddy-data:/data
|
||
- caddy-config:/config
|
||
ports:
|
||
- "80:80"
|
||
- "443:443"
|
||
# Окремий порт для зондів: вони говорять gRPC, а не HTTP, і
|
||
# ділити з ним 443 означало б розрізняти протоколи за шляхом —
|
||
# зайва крихкість там, де порт коштує нічого.
|
||
- "9443:9443"
|
||
depends_on:
|
||
- api
|
||
- collector
|
||
restart: unless-stopped
|
||
|
||
# Зонд на тому ж хості, що й сервер: базовий моніторинг самої
|
||
# інсталяції. Профіль, а не звичайна служба: у типовому розгортанні
|
||
# зонди стоять у мережах клієнтів, а не поруч із сервером.
|
||
agent:
|
||
build:
|
||
context: .
|
||
dockerfile: deploy/Dockerfile.agent
|
||
args:
|
||
VERSION: ${NETPULSE_VERSION:-dev}
|
||
COMMIT: ${NETPULSE_COMMIT:-none}
|
||
image: netpulse/agent:${NETPULSE_VERSION:-dev}
|
||
profiles: ["agent"]
|
||
command:
|
||
- -server=collector:9443
|
||
- -insecure
|
||
- -modules=icmp,snmp,topology,ncm
|
||
environment:
|
||
NETPULSE_ENROLL: ${NETPULSE_ENROLL:-}
|
||
NETPULSE_NAME: ${NETPULSE_AGENT_NAME:-локальний зонд}
|
||
TZ: ${TZ:-Europe/Kyiv}
|
||
cap_add:
|
||
- NET_RAW
|
||
volumes:
|
||
- agent-identity:/var/lib/netpulse
|
||
depends_on:
|
||
- collector
|
||
restart: unless-stopped
|
||
|
||
volumes:
|
||
db-data:
|
||
git-data:
|
||
cache-data:
|
||
caddy-data:
|
||
caddy-config:
|
||
agent-identity:
|