Контекст: В deploy/ есть docker-compose.prod.yml, deploy.sh, env.prod. Локально — docker-compose.yml + Makefile. Обновлено 2026-06 — добавлен Caddy reverse proxy, но есть ещё проблемы.
Проект разворачивается, Caddy настроен как reverse proxy с health headers и безопасными заголовками. Однако есть риски безопасности, надёжности и операционности.
| Проблема | Файл | Риск |
|---|---|---|
| Secrets в plain text | env.prod, docker-compose.yml |
Утечка БД, JWT, S3 при коммите / доступе к серверу |
| Миграции не гарантированно накатываются | docker-compose.prod.yml:52 |
migrate/migrate sidecar без retry логики |
| Single instance БД/Redis/MinIO | docker-compose.prod.yml |
SPOF, нет HA, нет бэкапов |
| Hardcoded IP в env.prod | env.prod |
Не переносимо, не работает за доменом |
CSP с unsafe-inline и unsafe-eval |
Caddyfile:40 |
XSS-защита ослаблена (см. [[atomic-csp-hardening]]) |
| Redis — SPOF для rate limiter | fail-closed в production (503 при падении) | [[atomic-redis-rate-limiter-failopen-failclosed]] |
# deploy/Caddyfile — уже работает как reverse proxy
http://api.{$DOMAIN} {
reverse_proxy backend:8080
header { ... }
}
http://{$DOMAIN} {
reverse_proxy frontend:3000
header {
Content-Security-Policy "..."
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
}
encode zstd gzip
}
Что уже хорошо:
unsafe-inline)Что нужно исправить:
http://, а не HTTPS (Caddy умеет авто-HTTPS через Let's Encrypt)unsafe-inline и unsafe-eval (см. [[atomic-csp-hardening]])# Не хранить секреты в репозитории!
# Использовать:
# - Docker secrets (swarm mode)
# - HashiCorp Vault / AWS Secrets Manager / 1Password CLI
# - .env файл только на сервере (chmod 600), в .gitignore
http:// из Caddyfile)# Caddyfile — авто-HTTPS через Let's Encrypt
photoplaces.ru {
reverse_proxy frontend:3000
}
api.photoplaces.ru {
reverse_proxy backend:8080
}
Caddy автоматически получит сертификаты для перечисленных доменов.
backend:
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/api/v1/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
postgres-backup:
image: prodrigestivill/postgres-backup-local
environment:
SCHEDULE: "@daily"
BACKUP_KEEP_DAYS: 30
В текущем docker-compose.yml есть проблема: backend healthcheck использует curl к самому себе на /api/v1/health, но этот эндпоинт доступен только после старта Go приложения. Это может создать циклическое ожидание с depends_on из frontend. Рекомендуется:
/health на уровне Caddy/Router перед Go-обработчикамиhttp:// из Caddyfile — перейти на доменыunsafe-inline, strict-dynamic ([[atomic-csp-hardening]])Code review PhotoPlaces 2026-06. Проверка production readiness + обновление после внедрения Caddy.
#deploy #docker #production #security #monitoring #best-practice