468 lines
15 KiB
YAML
468 lines
15 KiB
YAML
name: han-processing
|
|
|
|
x-hardening: &hardening
|
|
read_only: true
|
|
security_opt:
|
|
- no-new-privileges:true
|
|
cap_drop:
|
|
- ALL
|
|
restart: unless-stopped
|
|
|
|
x-postgres-ca-volume: &postgres-ca-volume
|
|
type: bind
|
|
source: ${PG_CA_HOST_PATH:?set PostgreSQL CA host path}
|
|
target: /run/config/postgresql-ca.pem
|
|
read_only: true
|
|
|
|
x-message-safety-environment: &message-safety-environment
|
|
APP_ENV: ${APP_ENV:?set APP_ENV}
|
|
MESSAGE_SAFETY_HOST: ${MESSAGE_SAFETY_HOST:-0.0.0.0}
|
|
MESSAGE_SAFETY_PORT: ${MESSAGE_SAFETY_PORT:-8080}
|
|
MESSAGE_SAFETY_WORKER_CONCURRENCY: ${MESSAGE_SAFETY_WORKER_CONCURRENCY:-5}
|
|
MESSAGE_SAFETY_DNS_RESOLVERS: ${MESSAGE_SAFETY_DNS_RESOLVERS:?set trusted DNS resolvers}
|
|
MESSAGE_SAFETY_CLAMAV_HOST: ${MESSAGE_SAFETY_CLAMAV_HOST:-clamd}
|
|
MESSAGE_SAFETY_CLAMAV_PORT: ${MESSAGE_SAFETY_CLAMAV_PORT:-3310}
|
|
MESSAGE_SAFETY_ARTIFACTS_DIR: ${MESSAGE_SAFETY_ARTIFACTS_DIR:-/app/app/artifacts}
|
|
MESSAGE_SAFETY_MODE_FILE: /etc/han-chat/message-safety-mode.env
|
|
PG_CA_FILE: /run/config/postgresql-ca.pem
|
|
SELECTEL_S3_ENDPOINT_URL: ${SELECTEL_S3_ENDPOINT_URL:?set S3 endpoint}
|
|
SELECTEL_S3_BUCKET_QUARANTINE: ${SELECTEL_S3_BUCKET_QUARANTINE:?set quarantine bucket}
|
|
OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_OTLP_ENDPOINT:-http://otel-collector:4317}
|
|
MESSAGE_SAFETY_DATABASE_URL_FILE: /run/secrets/message_safety_database_url
|
|
MESSAGE_SAFETY_REDIS_URL_FILE: /run/secrets/message_safety_redis_url
|
|
MESSAGE_SAFETY_SERVICE_TOKEN_FILE: /run/secrets/message_safety_service_token
|
|
SELECTEL_S3_QUARANTINE_READ_ACCESS_KEY_FILE: /run/secrets/s3_quarantine_read_access_key
|
|
SELECTEL_S3_QUARANTINE_READ_SECRET_KEY_FILE: /run/secrets/s3_quarantine_read_secret_key
|
|
|
|
x-bitrix-sync-environment: &bitrix-sync-environment
|
|
APP_ENV: ${APP_ENV:?set APP_ENV}
|
|
BITRIX_SYNC_ENABLED: ${BITRIX_SYNC_ENABLED:-false}
|
|
BITRIX_SYNC_MODE: ${BITRIX_SYNC_MODE:-disabled}
|
|
BITRIX_SYNC_PORTAL_HOST: ${BITRIX_SYNC_PORTAL_HOST:?set approved portal}
|
|
BITRIX_SYNC_PORTAL_MEMBER_ID: ${BITRIX_SYNC_PORTAL_MEMBER_ID:?set member id}
|
|
BITRIX_SYNC_PUBLIC_BASE_URL: ${BITRIX_SYNC_PUBLIC_BASE_URL:?set public base URL}
|
|
BITRIX_SYNC_CONTACT_USER_ID_FIELD: ${BITRIX_SYNC_CONTACT_USER_ID_FIELD:?set contact field}
|
|
BITRIX_SYNC_CONTACT_REGISTERED_FIELD: ${BITRIX_SYNC_CONTACT_REGISTERED_FIELD:?set registration field}
|
|
BITRIX_SYNC_CONTACT_CITIZENSHIP_FIELD: ${BITRIX_SYNC_CONTACT_CITIZENSHIP_FIELD:?set citizenship field}
|
|
BITRIX_SYNC_CONTACT_SOURCE: ${BITRIX_SYNC_CONTACT_SOURCE:?set contact source}
|
|
BITRIX_SYNC_WEBHOOK_ALLOWED_CIDRS: ${BITRIX_WEBHOOK_ALLOWED_CIDRS:-}
|
|
BITRIX_SYNC_HTTP_TIMEOUT_SEC: ${BITRIX_SYNC_HTTP_TIMEOUT_SEC:-10}
|
|
BITRIX_SYNC_DB_POOL_SIZE: ${BITRIX_SYNC_DB_POOL_SIZE:-5}
|
|
PG_CA_FILE: /run/config/postgresql-ca.pem
|
|
OTEL_EXPORTER_OTLP_ENDPOINT: ${OTEL_EXPORTER_OTLP_ENDPOINT:-http://otel-collector:4317}
|
|
BITRIX_SYNC_DATABASE_URL_FILE: /run/secrets/bitrix_sync_database_url
|
|
BITRIX_SYNC_CRM_REST_WEBHOOK_URL_FILE: /run/secrets/bitrix_sync_crm_rest_webhook_url
|
|
BITRIX_SYNC_CONTACT_RECEIVER_TOKEN_FILE: /run/secrets/bitrix_sync_contact_receiver_token
|
|
BITRIX_SYNC_ALERT_RECEIVER_TOKEN_FILE: /run/secrets/bitrix_sync_alert_receiver_token
|
|
BITRIX_SYNC_SERVICE_TOKEN_FILE: /run/secrets/bitrix_sync_service_token
|
|
|
|
services:
|
|
nginx:
|
|
<<: *hardening
|
|
image: ${NGINX_IMAGE:?set immutable nginx image digest}
|
|
user: "101:11001"
|
|
environment:
|
|
PROCESSING_PUBLIC_HOST: ${PROCESSING_PUBLIC_HOST:?set PROCESSING_PUBLIC_HOST}
|
|
MESSAGE_SAFETY_UPSTREAM_HOST: message-safety-api
|
|
BITRIX_SYNC_UPSTREAM_HOST: bitrix-sync
|
|
ports:
|
|
- "80:8080"
|
|
- "443:8444"
|
|
- "${PROCESSING_PRIVATE_BIND_ADDRESS:?set private bind IP}:8443:8443"
|
|
volumes:
|
|
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
|
- ./nginx/templates:/etc/nginx/templates:ro
|
|
- ./nginx/allowlists:/etc/nginx/allowlists:ro
|
|
- /var/lib/han-chat/public-tls:/run/public-tls:ro
|
|
- /var/lib/han-chat/acme:/var/www/certbot:ro
|
|
secrets:
|
|
- source: internal_tls_certificate
|
|
target: internal_tls_certificate
|
|
mode: 0444
|
|
- source: internal_tls_private_key
|
|
target: internal_tls_private_key
|
|
mode: 0444
|
|
tmpfs:
|
|
- /tmp:rw,noexec,nosuid,nodev,size=64m
|
|
- /var/cache/nginx:rw,noexec,nosuid,nodev,size=64m,uid=101,gid=11001,mode=0750
|
|
- /var/run:rw,noexec,nosuid,nodev,size=8m,uid=101,gid=11001,mode=0750
|
|
- /etc/nginx/conf.d:rw,noexec,nosuid,nodev,size=8m,uid=101,gid=11001,mode=0750
|
|
ulimits:
|
|
nofile:
|
|
soft: 4096
|
|
hard: 4096
|
|
networks: [public, backend]
|
|
depends_on:
|
|
message-safety-api:
|
|
condition: service_started
|
|
bitrix-sync:
|
|
condition: service_started
|
|
healthcheck:
|
|
test: ["CMD", "nginx", "-t", "-q", "-c", "/etc/nginx/nginx.conf"]
|
|
interval: 15s
|
|
timeout: 3s
|
|
retries: 3
|
|
start_period: 10s
|
|
pids_limit: 200
|
|
mem_limit: 256m
|
|
cpus: 1.0
|
|
|
|
redis-safety:
|
|
<<: *hardening
|
|
image: ${REDIS_IMAGE:?set immutable Redis image digest}
|
|
user: "999:999"
|
|
command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
|
|
volumes:
|
|
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf:ro
|
|
- redis-safety-data:/data
|
|
secrets:
|
|
- source: redis_safety_acl
|
|
target: redis-safety.acl
|
|
mode: 0444
|
|
networks: [backend]
|
|
expose: ["6379"]
|
|
healthcheck:
|
|
test: ["CMD", "redis-cli", "--no-auth-warning", "PING"]
|
|
interval: 15s
|
|
timeout: 3s
|
|
retries: 3
|
|
pids_limit: 100
|
|
mem_limit: 640m
|
|
cpus: 1.0
|
|
|
|
clamd:
|
|
<<: *hardening
|
|
image: ${CLAMAV_IMAGE:?set immutable ClamAV image digest}
|
|
entrypoint: ["/init-unprivileged"]
|
|
user: "100:101"
|
|
command: ["clamd", "--foreground=true"]
|
|
volumes:
|
|
- clamav-signatures:/var/lib/clamav:ro
|
|
- clamav-runtime:/run/clamav
|
|
tmpfs:
|
|
- /tmp:rw,noexec,nosuid,nodev,size=64m
|
|
- /var/log/clamav:rw,noexec,nosuid,nodev,size=32m,uid=100,gid=101,mode=0750
|
|
networks: [backend]
|
|
expose: ["3310"]
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "clamdscan --ping 1 >/dev/null 2>&1"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 5
|
|
start_period: 60s
|
|
pids_limit: 300
|
|
mem_limit: 2g
|
|
cpus: 2.0
|
|
|
|
freshclam:
|
|
<<: *hardening
|
|
image: ${CLAMAV_IMAGE:?set immutable ClamAV image digest}
|
|
entrypoint: ["/init-unprivileged"]
|
|
user: "100:101"
|
|
command: ["freshclam", "--daemon", "--foreground", "--checks=12"]
|
|
volumes:
|
|
- clamav-signatures:/var/lib/clamav
|
|
- clamav-runtime:/run/clamav
|
|
tmpfs:
|
|
- /tmp:rw,noexec,nosuid,nodev,size=64m
|
|
- /var/log/clamav:rw,noexec,nosuid,nodev,size=32m,uid=100,gid=101,mode=0750
|
|
healthcheck:
|
|
disable: true
|
|
networks: [signature-egress]
|
|
pids_limit: 100
|
|
mem_limit: 256m
|
|
cpus: 0.5
|
|
|
|
otel-queue-init:
|
|
<<: *hardening
|
|
image: ${REDIS_IMAGE:?set immutable Redis image digest}
|
|
entrypoint: ["sh", "-c"]
|
|
command: ["chown 10001:10001 /queue && chmod 0700 /queue"]
|
|
user: "0:0"
|
|
restart: "no"
|
|
network_mode: none
|
|
volumes:
|
|
- otel-queue:/queue
|
|
cap_add:
|
|
- CHOWN
|
|
- FOWNER
|
|
pids_limit: 20
|
|
mem_limit: 32m
|
|
cpus: 0.1
|
|
|
|
otel-collector:
|
|
<<: *hardening
|
|
image: ${OTEL_COLLECTOR_IMAGE:?set immutable Collector image digest}
|
|
user: "10001:10001"
|
|
command: ["--config=/etc/otelcol-contrib/config.yaml"]
|
|
environment:
|
|
APP_ENV: ${APP_ENV:?set APP_ENV}
|
|
RELEASE_VERSION: ${RELEASE_VERSION:?set RELEASE_VERSION}
|
|
OTEL_REMOTE_ENDPOINT: ${OTEL_REMOTE_ENDPOINT:?set private OTLP endpoint}
|
|
OTEL_REMOTE_TLS_INSECURE: ${OTEL_REMOTE_TLS_INSECURE:?set OTLP TLS mode}
|
|
volumes:
|
|
- ./observability/otel-collector.yaml:/etc/otelcol-contrib/config.yaml:ro
|
|
- otel-queue:/var/lib/otelcol/queue
|
|
networks:
|
|
observability: {}
|
|
telemetry-egress:
|
|
gw_priority: 1
|
|
depends_on:
|
|
otel-queue-init:
|
|
condition: service_completed_successfully
|
|
expose: ["4317", "4318"]
|
|
healthcheck:
|
|
test: ["CMD", "/otelcol-contrib", "components"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
pids_limit: 200
|
|
mem_limit: 512m
|
|
cpus: 1.0
|
|
|
|
message-safety-api:
|
|
<<: *hardening
|
|
image: ${MESSAGE_SAFETY_IMAGE:?set immutable message-safety image digest}
|
|
command: ["message-safety"]
|
|
user: "10001:10001"
|
|
environment:
|
|
<<: *message-safety-environment
|
|
MESSAGE_SAFETY_PROCESS_ROLE: api
|
|
volumes:
|
|
- /etc/han-chat/message-safety-mode.env:/etc/han-chat/message-safety-mode.env:ro
|
|
- *postgres-ca-volume
|
|
tmpfs:
|
|
- /tmp:rw,noexec,nosuid,nodev,size=64m
|
|
networks:
|
|
backend: {}
|
|
observability: {}
|
|
safety-egress:
|
|
gw_priority: 1
|
|
expose: ["8080"]
|
|
secrets:
|
|
- message_safety_database_url
|
|
- message_safety_redis_url
|
|
- message_safety_service_token
|
|
depends_on:
|
|
redis-safety:
|
|
condition: service_healthy
|
|
healthcheck:
|
|
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/health/live',timeout=2)"]
|
|
interval: 15s
|
|
timeout: 3s
|
|
retries: 3
|
|
start_period: 20s
|
|
pids_limit: 200
|
|
mem_limit: 512m
|
|
cpus: 1.0
|
|
|
|
message-safety-worker:
|
|
<<: *hardening
|
|
image: ${MESSAGE_SAFETY_IMAGE:?set immutable message-safety image digest}
|
|
command: ["message-safety-worker"]
|
|
user: "10001:10001"
|
|
environment:
|
|
<<: *message-safety-environment
|
|
MESSAGE_SAFETY_PROCESS_ROLE: worker
|
|
volumes:
|
|
- /etc/han-chat/message-safety-mode.env:/etc/han-chat/message-safety-mode.env:ro
|
|
- *postgres-ca-volume
|
|
tmpfs:
|
|
- /tmp:rw,noexec,nosuid,nodev,size=256m
|
|
networks:
|
|
backend: {}
|
|
observability: {}
|
|
safety-egress:
|
|
gw_priority: 1
|
|
secrets:
|
|
- message_safety_database_url
|
|
- message_safety_redis_url
|
|
- s3_quarantine_read_access_key
|
|
- s3_quarantine_read_secret_key
|
|
depends_on:
|
|
redis-safety:
|
|
condition: service_healthy
|
|
clamd:
|
|
condition: service_healthy
|
|
pids_limit: 400
|
|
mem_limit: 2g
|
|
cpus: 2.0
|
|
|
|
message-safety-migrate:
|
|
<<: *hardening
|
|
image: ${MESSAGE_SAFETY_IMAGE:?set immutable message-safety image digest}
|
|
entrypoint: ["alembic"]
|
|
command: ["upgrade", "head"]
|
|
user: "10001:10001"
|
|
restart: "no"
|
|
profiles: ["ops"]
|
|
environment:
|
|
MESSAGE_SAFETY_CONFIG_ADMIN_DATABASE_URL_FILE: /run/secrets/message_safety_config_admin_database_url
|
|
PG_CA_FILE: /run/config/postgresql-ca.pem
|
|
volumes:
|
|
- *postgres-ca-volume
|
|
networks:
|
|
safety-egress:
|
|
gw_priority: 1
|
|
secrets:
|
|
- message_safety_config_admin_database_url
|
|
tmpfs:
|
|
- /tmp:rw,noexec,nosuid,nodev,size=32m
|
|
pids_limit: 100
|
|
mem_limit: 256m
|
|
cpus: 0.5
|
|
|
|
bitrix-sync:
|
|
<<: *hardening
|
|
image: ${BITRIX_SYNC_IMAGE:?set immutable bitrix-sync image digest}
|
|
command: ["han-bitrix-sync-api"]
|
|
user: "10001:10001"
|
|
environment: *bitrix-sync-environment
|
|
volumes:
|
|
- *postgres-ca-volume
|
|
networks:
|
|
backend: {}
|
|
observability: {}
|
|
bitrix-egress:
|
|
gw_priority: 1
|
|
expose: ["8080"]
|
|
secrets:
|
|
- bitrix_sync_database_url
|
|
- bitrix_sync_crm_rest_webhook_url
|
|
- bitrix_sync_contact_receiver_token
|
|
- bitrix_sync_alert_receiver_token
|
|
- bitrix_sync_service_token
|
|
tmpfs:
|
|
- /tmp:rw,noexec,nosuid,nodev,size=32m
|
|
healthcheck:
|
|
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/health/live',timeout=2)"]
|
|
interval: 15s
|
|
timeout: 3s
|
|
retries: 3
|
|
start_period: 20s
|
|
pids_limit: 200
|
|
mem_limit: 384m
|
|
cpus: 1.0
|
|
|
|
bitrix-sync-worker:
|
|
<<: *hardening
|
|
image: ${BITRIX_SYNC_IMAGE:?set immutable bitrix-sync image digest}
|
|
command: ["han-bitrix-sync-worker"]
|
|
user: "10001:10001"
|
|
environment: *bitrix-sync-environment
|
|
volumes:
|
|
- *postgres-ca-volume
|
|
networks:
|
|
observability: {}
|
|
bitrix-egress:
|
|
gw_priority: 1
|
|
secrets:
|
|
- bitrix_sync_database_url
|
|
- bitrix_sync_crm_rest_webhook_url
|
|
- bitrix_sync_contact_receiver_token
|
|
- bitrix_sync_alert_receiver_token
|
|
- bitrix_sync_service_token
|
|
tmpfs:
|
|
- /tmp:rw,noexec,nosuid,nodev,size=32m
|
|
pids_limit: 200
|
|
mem_limit: 512m
|
|
cpus: 1.0
|
|
|
|
bitrix-sync-reconciliation:
|
|
<<: *hardening
|
|
image: ${BITRIX_SYNC_IMAGE:?set immutable bitrix-sync image digest}
|
|
command: ["han-bitrix-sync-reconciliation"]
|
|
user: "10001:10001"
|
|
restart: "no"
|
|
environment: *bitrix-sync-environment
|
|
volumes:
|
|
- *postgres-ca-volume
|
|
networks:
|
|
observability: {}
|
|
bitrix-egress:
|
|
gw_priority: 1
|
|
secrets:
|
|
- bitrix_sync_database_url
|
|
- bitrix_sync_crm_rest_webhook_url
|
|
- bitrix_sync_contact_receiver_token
|
|
- bitrix_sync_alert_receiver_token
|
|
- bitrix_sync_service_token
|
|
tmpfs:
|
|
- /tmp:rw,noexec,nosuid,nodev,size=32m
|
|
pids_limit: 150
|
|
mem_limit: 384m
|
|
cpus: 0.75
|
|
|
|
bitrix-sync-migrate:
|
|
<<: *hardening
|
|
image: ${BITRIX_SYNC_IMAGE:?set immutable bitrix-sync image digest}
|
|
entrypoint: ["alembic"]
|
|
command: ["upgrade", "head"]
|
|
user: "10001:10001"
|
|
restart: "no"
|
|
profiles: ["ops"]
|
|
environment:
|
|
BITRIX_SYNC_MIGRATION_DATABASE_URL_FILE: /run/secrets/bitrix_sync_migration_database_url
|
|
PG_CA_FILE: /run/config/postgresql-ca.pem
|
|
volumes:
|
|
- *postgres-ca-volume
|
|
networks:
|
|
bitrix-egress:
|
|
gw_priority: 1
|
|
secrets:
|
|
- bitrix_sync_migration_database_url
|
|
tmpfs:
|
|
- /tmp:rw,noexec,nosuid,nodev,size=32m
|
|
pids_limit: 100
|
|
mem_limit: 256m
|
|
cpus: 0.5
|
|
|
|
networks:
|
|
public:
|
|
backend:
|
|
internal: true
|
|
observability:
|
|
internal: true
|
|
safety-egress:
|
|
bitrix-egress:
|
|
signature-egress:
|
|
telemetry-egress:
|
|
|
|
volumes:
|
|
redis-safety-data:
|
|
clamav-signatures:
|
|
clamav-runtime:
|
|
otel-queue:
|
|
|
|
secrets:
|
|
message_safety_database_url:
|
|
file: /run/han-chat/secrets/MESSAGE_SAFETY_DATABASE_URL
|
|
message_safety_config_admin_database_url:
|
|
file: /run/han-chat/secrets/MESSAGE_SAFETY_CONFIG_ADMIN_DATABASE_URL
|
|
message_safety_redis_url:
|
|
file: /run/han-chat/secrets/MESSAGE_SAFETY_REDIS_URL
|
|
message_safety_service_token:
|
|
file: /run/han-chat/secrets/MESSAGE_SAFETY_SERVICE_TOKEN
|
|
s3_quarantine_read_access_key:
|
|
file: /run/han-chat/secrets/SELECTEL_S3_QUARANTINE_READ_ACCESS_KEY
|
|
s3_quarantine_read_secret_key:
|
|
file: /run/han-chat/secrets/SELECTEL_S3_QUARANTINE_READ_SECRET_KEY
|
|
internal_tls_certificate:
|
|
file: /run/han-chat/secrets/VM2_INTERNAL_TLS_CERTIFICATE
|
|
internal_tls_private_key:
|
|
file: /run/han-chat/secrets/VM2_INTERNAL_TLS_PRIVATE_KEY
|
|
bitrix_sync_database_url:
|
|
file: /run/han-chat/secrets/BITRIX_SYNC_DATABASE_URL
|
|
bitrix_sync_migration_database_url:
|
|
file: /run/han-chat/secrets/BITRIX_SYNC_MIGRATION_DATABASE_URL
|
|
bitrix_sync_crm_rest_webhook_url:
|
|
file: /run/han-chat/secrets/BITRIX_SYNC_CRM_REST_WEBHOOK_URL
|
|
bitrix_sync_contact_receiver_token:
|
|
file: /run/han-chat/secrets/BITRIX_SYNC_CONTACT_RECEIVER_TOKEN
|
|
bitrix_sync_alert_receiver_token:
|
|
file: /run/han-chat/secrets/BITRIX_SYNC_ALERT_RECEIVER_TOKEN
|
|
bitrix_sync_service_token:
|
|
file: /run/han-chat/secrets/BITRIX_SYNC_SERVICE_TOKEN
|
|
redis_safety_acl:
|
|
file: /run/han-chat/secrets/REDIS_SAFETY_ACL
|