Copy version: "3.8"
# vim: autoindent tabstop=2 shiftwidth=2 expandtab softtabstop=2 filetype=yaml fileencoding=utf-8
networks:
oc-prod-public: # usata per pubblicare servizi
external: true
oc-prod-internal: # usata per la comunicazione tra i componenti dello stack
external: true
x-deploy: &deploy-snippet
endpoint_mode: dnsrr
placement:
max_replicas_per_node: 2
constraints: [ node.labels.apps == true ]
replicas: 1
update_config:
parallelism: 1
order: start-first
delay: 30s
failure_action: rollback
monitor: 10s
rollback_config:
parallelism: 1
delay: 10s
failure_action: pause # default: pause or continue
monitor: 10s # default: 5s
order: start-first
restart_policy:
condition: any
delay: 15s # default: 5s, between attempts
max_attempts: 50
window: 20s # time to decide if the restart has been sucessfull
resources:
limits:
cpus: '0.2'
memory: 512M
reservations:
memory: 32M
x-sdc-env: &sdc-env
ENV: prod
APP_ENV: prod
DB_DRIVER: pdo_pgsql
DB_HOST: 'postgres'
DB_PORT: 5432
DB_NAME: oc
DB_USER: oc
DB_VERSION: 14
DB_PASSWORD: 'oc'
MAILER_URL: 'smtp://mailserver:1025'
SECRET: change_me
DEFAULT_FROM_EMAIL_ADDRESS: [email protected]
EZ_PASSWORD: change_me
OCSDC_SCHEME: https
OCSDC_HOST: app.localtest.me
LOGS_PATH: php://stderr
ENABLE_MIGRATIONS: 'false'
ENABLE_INSTANCE_CONFIG: 'false'
# accesso in scrittura da PHP
FORMSERVER_PRIVATE_URL: http://form-server:8000
# accesso con cache varnish
FORMSERVER_PUBLIC_URL: http://form.localtest.me
# accesso readonly per admin
FORMSERVER_ADMIN_URL: http://forms-readonly.localtest.me
WKHTMLTOPDF_SERVICE: http://gotenberg:3000
PHP_FPM_USER: wodby
PHP_FPM_GROUP: wodby
PHP_APCU_ENABLED: 1
PHP_OPCACHE_ENABLE: 1
PHP_FPM_CLEAR_ENV: 'no'
PHP_FPM_PM_MAX_CHILDREN: 50
PHP_FPM_PM_MAX_REQUESTS: 2000
PHP_FPM_PM_MAX_SPARE_SERVERS: 8
PHP_FPM_PM_MIN_SPARE_SERVERS: 2
PHP_FPM_REQUEST_SLOWLOG_TIMEOUT: 4000
PHP_FPM_PM_START_SERVERS: 5
PHP_DISPLAY_ERRORS: 'off'
PHP_DISPLAY_STARTUP_ERRORS: 'off'
PHP_ERROR_REPORTING: 'E_ERROR'
PHP_DATE_TIMEZONE: 'Europe/Rome'
PHP_SESSION_SAVE_HANDLER: redis
PHP_SESSION_SAVE_PATH: 'tcp://redis:6379'
PHP_SESSION_GC_MAXLIFETIME: 2880
RECAPTCHA_KEY: recaptcha_key
RECAPTCHA_SECRET: recaptcha_secret
EWZ_RECAPTCHA_SITE_KEY: recaptcha_key
EWZ_RECAPTCHA_SECRET: recaptcha_secret
FEATURE_NEW_OUTDATED_BROWSER: 'true'
FEATURE_APPLICATION_DETAIL: 'true'
FEATURE_CALENDAR_TYPE: 'true'
#FEATURE_DUE_AMOUNT: 'true'
#FEATURE_ANALYTICS: 'true'
TOKEN_TTL: 864000 # 10gg
CACHE_MAX_AGE: 3600
KAFKA_URL: vector
KSQLDB_URL: ksqldb-server:8088
SKIP_CACHE_WARMUP: 'false'
TRUSTED_PROXIES: '10.0.0.0/8,172.16.0.0/12,192.168.0.0/16'
DEFAULT_CACHE_REDIS_PROVIDER: 'redis://redis:6379'
DEFAULT_CACHE_LIFETIME: 3600
DEFAULT_CACHE_PREFIX_SEED: v-2.27.0
REGISTRY_API_URL: https://registry.qa.stanzadelcittadino.it
REGISTRY_API_KEY: change_me
API_USER_PASSWORD: change_me
# In assenza di una vera autenticazione basata su SPID si può simulare
# un login di un utente con le seguenti variabili d'ambiente:
shibb_pat_attribute_codicefiscale: CLNVTR76P01G822Q
shibb_pat_attribute_cognome: Coliandro
shibb_pat_attribute_nome: Vittorino
shibb_pat_attribute_sesso: M
shibb_pat_attribute_emailaddress: [email protected]
shibb_pat_attribute_datanascita: 1/9/1976
shibb_pat_attribute_luogonascita: Ponsacco
shibb_pat_attribute_provincianascita: PI
shibb_pat_attribute_telefono: 003912378945
shibb_pat_attribute_cellulare: 333 444 666 99
shibb_pat_attribute_indirizzoresidenza: 'Via Gramsci, 1'
shibb_pat_attribute_capresidenza: 56056
shibb_pat_attribute_cittaresidenza: Bugliano
shibb_pat_attribute_provinciaresidenza: PI
shibb_pat_attribute_statoresidenza: Italia
shibb_pat_attribute_spidcode: 123456789
shibb_pat_attribute_x509certificate_issuerdn: FAKE_issuerdn
shibb_pat_attribute_x509certificate_subjectdn: FAKE_subjectdn
shibb_pat_attribute_x509certificate_base64: "DQpSZXN1bHQgZ29lcyBoZXJlLi4uDQpCYXNlNjQNCg0KQmFzZTY0IGlzIGEgZ2VuZXJpYyB0ZXJtIGZvciBhIG51bWJlciBvZiBzaW1pbGFyIGVuY29kaW5nIHNjaGVtZXMgdGhhdCBlbmNvZGUgYmluYXJ5IGRhdGEgYnkgdHJlYXRpbmcgaXQgbnVtZXJpY2FsbHkgYW5kIHRyYW5zbGF0aW5nIGl0IGludG8gYSBiYXNlIDY0IHJlcHJlc2VudGF0aW9uLiBUaGUgQmFzZTY0IHRlcm0gb3JpZ2luYXRlcyBmcm9tIGEgc3BlY2lmaWMgTUlNRSBjb250ZW50IHRyYW5zZmVyIGVuY29kaW5nLg=="
shibb_Shib-Session-ID: abc123abc123abc123abc123abc123abc123abc123
shibb_Shib-Session-Index: abc123abc123abc123abc123abc123abc123abc123
shibb_Shib-Authentication-Instant: 2000-01-01T00-00Z
x-registry-env: ®istry-env
DJANGO_DATABASE: postgres:5432:oc_registry:oc:oc
DJANGO_SECRET_KEY: change_me
DJANGO_SETTINGS_MODULE: application_registry.settings_production
KAFKA_BOOTSTRAP_SERVERS: kafka:9092
SENTRY_DSN:
configs:
sf-config-instances:
name: oc-instances-v1
file: ./config/app/instances.yml
vector-api:
name: occ-kafka-http-v1
file: ./config/kafka/vector.toml
services:
# Symfony-core, esposto solo su rete interna
app:
image: registry.gitlab.com/opencity-labs/area-personale/core/app:2.27.0
stop_grace_period: 45s
configs:
- source: sf-config-instances
target: /var/www/html/config/instances_prod.yml
networks:
- oc-prod-internal
environment:
<<: *sdc-env
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80/health-check"]
interval: 1m30s
timeout: 10s
retries: 6
start_period: 5s
deploy:
<<: *deploy-snippet
endpoint_mode: vip
replicas: 1
resources:
limits:
cpus: '1'
memory: 2048M
reservations:
memory: 1024M
labels:
traefik.enable: 'false'
# Frontend del symfony-core
varnish:
image: registry.gitlab.com/opencontent/varnish:1.2
stop_grace_period: 45s
networks:
- oc-prod-public
- oc-prod-internal
healthcheck:
disable: true
deploy:
<<: *deploy-snippet
endpoint_mode: dnsrr
replicas: 1
resources:
limits:
cpus: '1'
memory: 2048M
reservations:
memory: 1024M
labels:
traefik.enable: 'true'
traefik.http.services.varnish.loadbalancer.server.port: 6081
# disabilitato altrimenti quando fallisce backend non sfrutto grace
#traefik.http.services.varnish.loadbalancer.healthcheck.path: /health-check
# Security headers
traefik.http.middlewares.security.headers.frameDeny: 'true'
traefik.http.middlewares.security.headers.customFrameOptionsValue: 'SAMEORIGIN'
traefik.http.middlewares.security.headers.stsSeconds: 31536000
traefik.http.middlewares.security.headers.stsIncludeSubdomains: 'true'
traefik.http.middlewares.security.headers.forceStsHeader: 'true'
#traefik.http.middlewares.security.headers.contentSecurityPolicy: "default-src 'self' data:; img-src 'self' data: blob: c.bing.com www.googletagmanager.com *.openstreetmap.org c.clarity.ms cartodb-basemaps-b.global.ssl.fastly.net cartodb-basemaps-c.global.ssl.fastly.net cartodb-basemaps-a.global.ssl.fastly.nett; style-src 'self' 'unsafe-inline' static.opencityitalia.it satisfy.opencontent.it widget.freshworks.com stackpath.bootstrapcdn.com unpkg.com cdn.datatables.net printjs-4de6.kxcdn.com cdnjs.cloudflare.com fonts.googleapis.com; connect-src 'self' s3.eu-west-1.amazonaws.com api.opencityitalia.it qa-genova-id.boat.opencontent.io dev-genova-id.boat.opencontent.io mappe.genova.opencityitalia.it api.opencontent.it api.qa.stanzadelcittadino.it registry.qa.stanzadelcittadino.it satisfy.boat.opencontent.io static.opencityitalia.it www.giscom.cloud nominatim.openstreetmap.org a.clarity.ms d.clarity.ms k.clarity.ms i.clarity.ms h.clarity.ms widget.freshworks.com fiscalcode.opencontent.it form-qa.stanzadelcittadino.it form-readonly-qa.stanzadelcittadino.it cdn.datatables.net satisfy.opencityitalia.it satisfy.opencontent.it satisfy.hasura.app sdc-analytics-dev-charts-exporter.boat.opencontent.io efil-proxy-qa.boat.opencontent.io pmpay-proxy-qa.boat.opencontent.io iris-proxy-qa.boat.opencontent.io mypay-proxy-qa.boat.opencontent.io www.openstreetmap.org flyimg.opencontent.it; script-src 'self' 'unsafe-inline' 'unsafe-eval' static.opencityitalia.it cdn.announcekit.app widget.freshworks.com www.clarity.ms form-qa.stanzadelcittadino.it cdnjs.cloudflare.com cdn.form.io unpkg.com code.jquery.com www.googletagmanager.com cdn.datatables.net printjs-4de6.kxcdn.com satisfy.opencityitalia.it satisfy.opencontent.it www.recaptcha.net www.gstatic.com; object-src 'none'; font-src 'self' data: satisfy.opencontent.it stackpath.bootstrapcdn.com cdnjs.cloudflare.com unpkg.com fonts.gstatic.com; worker-src 'self'; report-uri https://csp-collector.opencontent.it/csp?env=production&mode=enforce&app=sdc-qa; child-src 'self' www.youtube-nocookie.com announcekit.app"
traefik.http.middlewares.security.headers.contentTypeNosniff: 'true'
traefik.http.middlewares.security.headers.permissionsPolicy: "geolocation=(self), camera=(self), microphone=(self)"
traefik.http.middlewares.security.headers.referrerPolicy: 'strict-origin-when-cross-origin'
traefik.http.middlewares.security.headers.browserXssFilter: 'true'
# Cors generali
traefik.http.routers.https.rule: 'Method(`GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`, `PURGE`) && Host(`app.localtest.me`)'
traefik.http.routers.https.tls: 'true'
traefik.http.routers.https.tls.certresolver: 'myhttpchallenge'
traefik.http.routers.https.middlewares: 'cors, general-rl, security'
# Cors per condivisione autenticazione
traefik.http.routers.origin-https.rule: 'Method(`GET`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `PURGE`) && Host(`app.localtest.me`) && PathPrefix(`/lang/api/session-auth`)'
traefik.http.routers.origin-https.tls: 'true'
traefik.http.routers.origin-https.priority: 10001
traefik.http.routers.origin-https.tls.certresolver: 'myhttpchallenge'
traefik.http.routers.origin-https.middlewares: 'cors-origin, general-rl, security'
traefik.http.middlewares.cors.headers.accesscontrolallowcredentials: 'true'
traefik.http.middlewares.cors.headers.accesscontrolallowheaders: 'Authorization,Origin,Content-Type,Accept,access-control-allow-headers,access-control-allow-methods,access-control-allow-origin,access-control-allow-credentials,Referer,X-Hasura-Role,X-Hasura-Admin-Secret,X-Hasura-Allowed-Roles,X-Hasura-Default-Role,X-Hasura-User-Id,X-Hasura-Org-Id,X-Locale'
traefik.http.middlewares.cors.headers.accesscontrolallowmethods: 'GET,POST,HEAD,PUT,DELETE,PATCH,OPTIONS'
traefik.http.middlewares.cors.headers.accesscontrolalloworiginlist: '*'
traefik.http.middlewares.cors.headers.accesscontrolmaxage: 100
traefik.http.middlewares.cors.headers.addvaryheader: 'true'
traefik.http.middlewares.cors-origin.headers.accesscontrolallowcredentials: 'true'
traefik.http.middlewares.cors-origin.headers.accesscontrolallowheaders: 'Authorization,Origin,Content-Type,Accept,access-control-allow-headers,access-control-allow-methods,access-control-allow-origin,access-control-allow-credentials,Referer,X-Hasura-Role,X-Hasura-Admin-Secret,X-Hasura-Allowed-Roles,X-Hasura-Default-Role,X-Hasura-User-Id,X-Hasura-Org-Id,X-Locale'
traefik.http.middlewares.cors-origin.headers.accesscontrolallowmethods: 'GET,POST,HEAD,PUT,DELETE,PATCH,OPTIONS'
traefik.http.middlewares.cors-origin.headers.accesscontrolmaxage: 100
traefik.http.middlewares.cors-origin.headers.addvaryheader: 'true'
environment:
# https://github.com/wodby/varnish#environment-variables
VARNISH_BACKEND_GRACE : '2880m'
VARNISH_BACKEND_HOST: 'app'
VARNISH_BACKEND_PORT: '80'
VARNISH_BACKEND_PROBE: '/health-check'
VARNISH_KEEP_ALL_PARAMS: 1
VARNISH_CACHE_STATIC_FILES: 1
##VARNISH_MOBILE_SEPARATE_CASH: 1
#VARNISH_BIG_FILES_SIZE: 10485760
VARNISHD_MEMORY_SIZE: '1024m'
VARNISH_BACKEND_BETWEEN_BYTES_TIMEOUT: 30s
VARNISH_BACKEND_FIRST_BYTE_TIMEOUT: 30s
VARNISH_STRIP_COOKIES: 'cookies_consent|_[_a-z]+|wooTracker|VCKEY-[a-zA-Z0-9-_]+'
VARNISHD_PARAM_WORKSPACE_BACKEND: '256k'
VARNISHD_PARAM_WORKSPACE_CLIENT: '256k'
VARNISH_SECRET: 'change_me'
# Manager symfony, non è esposto su rete pubblica esegue migrazioni e script all'avvio
manager:
image: registry.gitlab.com/opencity-labs/area-personale/core/app:2.27.0
stop_grace_period: 45s
configs:
- source: sf-config-instances
target: /var/www/html/config/instances_prod.yml
networks:
- oc-prod-internal
environment:
<<: *sdc-env
DB_USER: oc # Inserire username utente manager se configurato
DB_PASSWORD: 'oc' # Inserire password utente manager se configurato
ENABLE_MIGRATIONS: 'true'
deploy:
<<: *deploy-snippet
endpoint_mode: vip
replicas: 1
resources:
limits:
cpus: '1'
memory: 1024M
reservations:
memory: 512M
# Ci sono 3 valori da tenere sempre uguali: WORKER_NUM, replicas e swam_cronjob_replicas
worker:
image: registry.gitlab.com/opencity-labs/area-personale/core/app:2.27.0
networks:
- oc-prod-internal
stop_signal: SIGQUIT
stop_grace_period: 20m
command: [ "./bin/worker-daemon.sh" ]
configs:
- source: sf-config-instances
target: /var/www/html/config/instances_prod.yml
volumes:
- ./config/worker/worker-daemon.sh:/var/www/html/bin/worker-daemon.sh:ro
healthcheck:
disable: true
environment:
<<: *sdc-env
SWARM_SERVICE: "worker"
SWARM_STACK: "oc-prod"
#DEBUG: 1
WORKER_ID: 1
WORKER_NUM: 1
MAX_EXECUTIONS: 100
MAX_ACTIONS: 50
deploy:
<<: *deploy-snippet
endpoint_mode: dnsrr
replicas: 1
update_config:
order: stop-first
restart_policy:
condition: none
resources:
limits:
cpus: '0.5'
memory: 2048M
reservations:
memory: 512M
labels:
swarm.cronjob.enable: "true"
swarm.cronjob.schedule: "*/3 * * * *"
swarm.cronjob.skip-running: "true"
swarm.cronjob.replicas: 1
# Espone delle api rest per la creazione di eventi su kafka
vector:
image: timberio/vector:0.18.1-debian
configs:
- source: vector-api
target: /etc/vector/vector.toml
healthcheck:
test: [ "CMD", "curl", "-f", "http://localhost:80/health" ]
interval: 1m30s
timeout: 10s
retries: 6
start_period: 5s
environment:
VECTOR_LOG: debug
networks:
- oc-prod-internal
deploy:
<<: *deploy-snippet
labels:
traefik.enable: 'false'
# Microservizio per la creazione di pdf
gotenberg:
image: gotenberg/gotenberg:7.9.2
networks:
- oc-prod-internal
- oc-prod-public
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 1m30s
timeout: 10s
retries: 6
start_period: 5s
deploy:
<<: *deploy-snippet
labels:
prometheus.disable: 'true'
traefik.enable: 'true'
traefik.http.services.gotenberg.loadbalancer.server.port: 3000
traefik.http.routers.gotenberg.rule: 'Host(`gotenberg.localtest.me`)'
traefik.http.routers.gotenberg.tls: 'true'
traefik.http.routers.gotenberg.tls.certresolver: 'myhttpchallenge'
traefik.http.routers.gotenberg.middlewares: 'goodheaders'
# Strumento per testare la posta elettronica
mailhog:
image: mailhog/mailhog
networks:
- oc-prod-internal
deploy:
<<: *deploy-snippet
labels:
traefik.enable: 'true'
traefik.http.services.mailhog.loadbalancer.server.port: 8025
traefik.http.routers.mailhog.rule: Host(`mail.localtest.me`)
traefik.http.routers.mailhog.tls: 'true'
traefik.http.routers.mailhog.middlewares: goodheaders
traefik.http.routers.mailhog.tls.certresolver: 'myhttpchallenge'
##############################################################################
# FORMS
##############################################################################
# Frontend per il formserver
form-varnish:
image: registry.gitlab.com/opencontent/varnish:1.2
stop_grace_period: 45s
networks:
- oc-prod-internal
- oc-prod-public
deploy:
<<: *deploy-snippet
replicas: 1
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.1'
memory: 128M
labels:
prometheus.enable: 'true'
prometheus.port: 9131
traefik.enable: 'true'
traefik.http.services.formvarnish.loadbalancer.server.port: 6081
traefik.http.services.formvarnish.loadbalancer.healthcheck.path: /.vchealthz
traefik.http.routers.formvarnish.rule: 'Method(`GET`, `HEAD`, `OPTIONS`) && Host(`form.localtest.me`)'
traefik.http.routers.formvarnish.tls: 'true'
traefik.http.routers.formvarnish.tls.certresolver: 'myhttpchallenge'
traefik.http.routers.formvarnish.middlewares: 'cors'
environment:
# https://github.com/wodby/varnish#environment-variables
VARNISH_BACKEND_HOST: 'form-server'
VARNISH_BACKEND_PORT: '8000'
VARNISH_BACKEND_GRACE: '2880m'
VARNISH_BACKEND_PROBE: '/form/5d7aa15b18fecd734051ae7f?varnish-health'
VARNISH_CACHE_STATIC_FILES: 1
VARNISHD_MEMORY_SIZE: '256m'
VARNISH_BACKEND_BETWEEN_BYTES_TIMEOUT: 10s
VARNISH_BACKEND_FIRST_BYTE_TIMEOUT: 30s
VARNISH_KEEP_ALL_PARAMS: 1
VARNISH_STRIP_COOKIES: 'cookie_consent|_[_a-z]+|wooTracker|VCKEY-[a-zA-Z0-9-_]+|_ga|_gid|_gat[a-zA-Z0-9-_]+'
VARNISH_SECRET: 'nvXq3CkK'
VARNISHD_PARAM_WORKSPACE_BACKEND: '256k'
VARNISHD_PARAM_WORKSPACE_CLIENT: '256k'
# Espone api rest per il crud dei form
form-server:
image: registry.gitlab.com/opencity-labs/area-personale/form-server:1.3.0
networks:
- oc-prod-public
- oc-prod-internal
environment:
DB_URL: mongodb://mongo:27017/formmanager
MAX_AGE: 5
S_MAX_AGE: 60
#healthcheck:
# test: [ "CMD", "wget", "--spider", "http://localhost:8000/form/5d7aa15b18fecd734051ae7f" ]
# start_period: 30s
# timeout: 1s
# retries: 1
# interval: 1m
deploy:
<<: *deploy-snippet
labels:
traefik.enable: 'true'
traefik.http.services.formserver.loadbalancer.server.port: 8000
# Espongo il formserver aperto in scrittura con oc-auth, sotto /api per il form-builder
traefik.http.routers.formserver.rule: 'Method(`GET`, `HEAD`, `OPTIONS`, `POST`, `PUT`, `PATCH`, `DELETE`) && Host(`form-builder.localtest.me`) && PathPrefix(`/api/`)'
traefik.http.routers.formserver.tls: 'true'
traefik.http.routers.formserver.tls.certresolver: 'myhttpchallenge'
traefik.http.middlewares.strip-forms-api.stripprefix.prefixes: '/api/'
traefik.http.routers.formserver.middlewares: 'strip-forms-api'
# Espongo anche readonly per gli admin da backend (per vedere subito aggiornamenti)
traefik.http.routers.formserver-ro.rule: 'Method(`GET`, `POST`, `HEAD`, `OPTIONS`) && Host(`form-readonly.localtest.me`)'
traefik.http.routers.formserver-ro.tls: 'true'
traefik.http.routers.formserver-ro.tls.certresolver: 'myhttpchallenge'
traefik.http.routers.formserver-ro.middlewares: 'oc-auth, cors'
# Microservizio per la gestione dei componenti comuni dei form (nested form)
form-builder:
image: registry.gitlab.com/opencity-labs/area-personale/formbuilderjs:0-5-2
healthcheck:
test: [ "NONE" ]
networks:
- oc-prod-public
deploy:
<<: *deploy-snippet
labels:
traefik.enable: 'true'
traefik.http.services.formbuilder.loadbalancer.server.port: 80
traefik.http.routers.formbuilder.rule: 'Method(`GET`, `HEAD`, `OPTIONS`) && Host(`form-builder.localtest.me`)'
traefik.http.routers.formbuilder.tls: 'true'
traefik.http.routers.formbuilder.tls.certresolver: 'myhttpchallenge'
traefik.http.routers.formbuilder.middlewares: 'oc-auth'
##############################################################################
# FORMS
##############################################################################
# Interroga la tabella PAYMENTS_STATUS su ksqldb e richiede info ai proxy sui pagamenti pendenti
payments-poller:
image: registry.gitlab.com/opencity-labs/area-personale/payments-poller:1.0.2
networks:
- oc-prod-internal
environment:
KSQLDB_SERVER: http://ksqldb-server:8088
LOOP_TIME: 900
LOG_LEVEL: DEBUG
HEALTHCHECK_ID: 88f0d2a5-0326-46a1-9093-42e83c3017c8
PYTHONDEBUG: 1
deploy:
<<: *deploy-snippet
resources:
reservations:
memory: 1G
limits:
cpus: '0.5'
memory: 4G
healthcheck:
test: [ NONE ]
# Legge gli eventi dal topic applications e crea un evento nel topic payments se necessario
payment-dispatcher:
image: registry.gitlab.com/opencity-labs/area-personale/payment-dispatcher:1.2.1
networks:
- oc-prod-internal
environment:
KAFKA_TOPIC_APPLICATIONS: applications
KAFKA_TOPIC_PAYMENTS: payments
KAFKA_BOOTSTRAP_SERVERS: kafka:9092
KAFKA_CONSUMER_GROUP_PREFIX: payment-dispatcher
PROMETHEUS_JOB_NAME: payment_dispatcher
APP_ID: payment-dispatcher:1.2.1
KSQLDB_SERVER: http://ksqldb-server:8088
LOG_LEVEL: INFO
healthcheck:
test: [ NONE ]
deploy:
<<: *deploy-snippet
resources:
limits:
cpus: '0.5'
memory: 1G
# Gateway proxy di iris (ambiente di test)
iris-proxy:
image: registry.gitlab.com/opencity-labs/area-personale/iris-payment-proxy:1.3.3
stop_grace_period: 5m
networks:
- oc-prod-public
environment:
CANCEL_PAYMENT: "true"
KAFKA_TOPIC_NAME: payments
KAFKA_BOOTSTRAP_SERVERS: kafka:9092
KAFKA_GROUP_ID: iris_payment_proxy
IRIS_OTF_PAYMENT_URL: https://apistage.regione.toscana.it/C01/ComunicazionePosizioniDebitorieOTF/v3/IdpAllineamentoPendenzeEnteOTF
IRIS_IUV_URL: https://iristest.rete.toscana.it/IdpBillerNdpServices/GenerazioneIUVService
IRIS_OUTCOME_URL: https://apistage.regione.toscana.it/C01/InvioNotificaPagamentoEsito/v3/IdpInformativaPagamento.Esito
IRIS_VERIFY_URL: https://apistage.regione.toscana.it/C01/VerificaStatoPagamento/v3/IdpVerificaStatoPagamento
IRIS_NOTICE_URL: https://iristest.rete.toscana.it/IdpBillerNdpServices/GenerazioneAvvisiService
EXTERNAL_API_URL: "https://iris-proxy.localtest.me"
INTERNAL_API_URL: "http://iris-proxy.localtest.me"
BASE_PATH_EVENT: "sdc-payments/iris-proxy/payments/"
BASE_PATH_CONFIG: "sdc-payments/iris-proxy/tenants/"
# STORAGE_TYPE="LOCAL|MINIO|S3"
STORAGE_TYPE: "LOCAL"
STORAGE_BUCKET_NAME: "payments"
APP_ID: "iris-proxy:1.3.3"
deploy:
<<: *deploy-snippet
labels:
traefik.enable: 'true'
traefik.http.services.iris-proxy-qa.loadbalancer.server.port: 8000
traefik.http.routers.iris-proxy.entrypoints: 'websecure, web'
traefik.http.routers.iris-proxy.rule: 'Host(`iris-proxy.localtest.me`) && PathPrefix(`/{op:(notice|online-payment|receipt|landing)}/{id:[^/]+}`, `/{op:(docs|redoc|openapi.json|tenants|services|notify-payment)}`, `/{op:(tenants|services)}/({id:[^/]+}|schema)`) && METHOD(`GET`, `POST`, `PUT` ,`PATCH`, `DELETE`, `HEAD`, `OPTIONS`)'
traefik.http.routers.iris-proxy.tls: 'true'
traefik.http.routers.iris-proxy.tls.certresolver: 'myhttpchallenge'
traefik.http.middlewares.payment-proxy-qa-cors.headers.accesscontrolallowcredentials: 'true'
traefik.http.middlewares.payment-proxy-qa-cors.headers.accesscontrolallowheaders: 'Authorization,Origin,Content-Type,Accept,access-control-allow-headers,access-control-allow-methods,access-control-allow-origin,access-control-allow-credentials,Referer'
traefik.http.middlewares.payment-proxy-qa-cors.headers.accesscontrolallowmethods: 'GET,POST,HEAD,PUT,DELETE,PATCH,OPTIONS'
# asterisco perché ognuno di essi è acceduto da tutti i domini custom che avranno gli enti
traefik.http.middlewares.payment-proxy-qa-cors.headers.accesscontrolalloworiginlist: '*'
traefik.http.middlewares.payment-proxy-qa-cors.headers.accesscontrolmaxage: 100
traefik.http.middlewares.payment-proxy-qa-cors.headers.addvaryheader: 'true'
traefik.http.routers.iris-proxy.middlewares: 'goodheaders, payment-proxy-qa-cors'
volumes:
- ./var/tenants:/app/payments/sdc-payments/iris-proxy/tenants
- ./var/payments:/app/payments/sdc-payments/iris-proxy/payments
# Aggiorna lo stato delle pratiche dopo che si sono verificati dei pagamenti
krun-process-payments:
image: registry.gitlab.com/opencity-labs/area-personale/core/app:2.27.0
configs:
- source: sf-config-instances
target: /var/www/html/config/instances_prod.yml
entrypoint: /bin/krun
stop_grace_period: 300s
healthcheck:
disable: true
volumes:
- ./config/krun/process-payment:/bin/process-payment
- ./config/krun/krun:/bin/krun
networks:
- oc-prod-internal
environment:
<<: *sdc-env
KAFKA_TOPIC: "payments"
KAFKA_SERVER: "kafka:9092"
KAFKA_CONSUMER_GROUP: "oc-prod-krun-process-payments"
COMMAND: "/bin/process-payment"
#DEBUG: 1
VERBOSE: 1
deploy:
<<: *deploy-snippet
resources:
limits:
cpus: '0.2'
memory: 1024M
update_config:
parallelism: 3
order: stop-first
##############################################################################
# REGISTRY
##############################################################################
# Espone le api per la configurazione dei vari sistemi di protocollazione
registry-rest-api:
image: registry.gitlab.com/opencity-labs/area-personale/stanzadelcittadino-application-registry:1.10.2
networks:
- oc-prod-public
- oc-prod-internal
environment:
<<: *registry-env
DJANGO_LOG_LEVEL: INFO
REGISTRY_API_KEY: change_me
deploy:
<<: *deploy-snippet
labels:
traefik.enable: "true"
traefik.http.services.registry.loadbalancer.server.port: 8000
traefik.http.routers.registry.rule: "Host(`registry.localtest.me`)"
traefik.http.routers.registry.tls: "true"
traefik.http.routers.registry.tls.certresolver: "myhttpchallenge"
traefik.http.middlewares.registry-qa-home-redir.redirectregex.regex: 'registry.localtest.me/$$'
traefik.http.middlewares.registry-qa-home-redir.redirectregex.replacement: "registry.localtest.me/admin"
traefik.http.middlewares.registry-redirect-tenants.replacepathregex.regex: '^/(d3|datagraph|dedagroup|halley|halley-cloud|hypersic|infor|insiel|maggioli|pitre|tinn)/v1/tenants/(.*)'
traefik.http.middlewares.registry-redirect-tenants.replacepathregex.replacement: '/api/v1/tenants/'
traefik.http.middlewares.registry-redirect-services.replacepathregex.regex: '^/(d3|datagraph|dedagroup|halley|halley-cloud|hypersic|infor|insiel|maggioli|pitre|tinn)/v1/services/'
traefik.http.middlewares.registry-redirect-services.replacepathregex.replacement: '/api/v1/services/$$1/'
traefik.http.middlewares.registry-redirect-service.replacepathregex.regex: '^/(d3|datagraph|dedagroup|halley|halley-cloud|hypersic|infor|insiel|maggioli|pitre|tinn)/v1/services/(.+)'
traefik.http.middlewares.registry-redirect-service.replacepathregex.replacement: '/api/v1/services/$$1/$$2/'
traefik.http.middlewares.registry-redirect-service-schema.replacepathregex.regex: '^/(d3|datagraph|dedagroup|halley|halley-cloud|hypersic|infor|insiel|maggioli|pitre|tinn)/v1/schema'
traefik.http.middlewares.registry-redirect-service-schema.replacepathregex.replacement: '/api/v1/services-schema/$$1'
traefik.http.middlewares.registry-cors.headers.accesscontrolallowcredentials: 'true'
traefik.http.middlewares.registry-cors.headers.accesscontrolallowheaders: '*'
traefik.http.middlewares.registry-cors.headers.accesscontrolallowmethods: 'GET,POST,HEAD,PUT,OPTIONS'
traefik.http.middlewares.registry-cors.headers.accesscontrolalloworiginlist: '*'
traefik.http.middlewares.registry-cors.headers.accesscontrolmaxage: 100
traefik.http.middlewares.registry-cors.headers.addvaryheader: 'true'
traefik.http.routers.registry.middlewares: "goodheaders, registry-qa-home-redir, registry-redirect-tenants, registry-redirect-services, registry-redirect-service, registry-redirect-service-schema, registry-cors"
prometheus.enable: "true"
prometheus.port: 8000
# Gestisce il sistema di retry della protocollazione
registry-retry-scheduler:
image: registry.gitlab.com/opencity-labs/area-personale/stanzadelcittadino-application-registry:1.10.2
command: /app/venv/bin/python3.9 manage.py run_retry_scheduler
networks:
- oc-prod-internal
environment:
<<: *registry-env
ENABLE_SENTRY_EVENT_FILTER: "true"
deploy:
<<: *deploy-snippet
##############################################################################
# PDND
##############################################################################
pdnd-connector:
image: registry.gitlab.com/opencity-labs/area-personale/pdnd-connector:x.x.x
networks:
- oc-prod-internal
deploy:
<<: *deploy-snippet
environment:
ENVIRONMENT: app_environment
SENTRY_TOKEN: sentry DSN
HTTP_EXTERNAL_BASEPATH: https://api.qa.stanzadelcittadino.it/pdnd
SDC_PUBLIC_KEY_ENDPOINT: https://core/.well-known/jwks.json
CACHE_EXPIRATION: 5m
CACHE_EVICTION: 10m
STORAGE_TYPE: s3
STORAGE_BUCKET: s3_bucket
STORAGE_BASE_PATH: pdnd
STORAGE_LOCAL_PATH: /data/pdnd
STORAGE_S3_KEY: S3_key
STORAGE_S3_SECRET: s3_secret
STORAGE_S3_REGION: eu-west-1
STORAGE_S3_ENDPOINT: https://s3.eu-west-1.amazonaws.com
STORAGE_S3_SSL: "false"
labels:
prometheus.enable: 'true'
prometheus.port: 8000
traefik.enable: 'true'
traefik.docker.network: 'oc-prod-internal'
traefik.http.services.pdnd-connector.loadbalancer.server.port: 8000
traefik.http.routers.pdnd-connector.entrypoints: 'websecure, web'
traefik.http.routers.pdnd-connector.rule: 'Host(`api.qa.stanzadelcittadino.it`) && PathPrefix(`/pdnd/{op:(status|metrics|docs|anpr/accertamento-residenza|anpr/stato-famiglia|tenants|keys|tenants/configs|tenants/clients|e-services)}`, `/pdnd/{op:(status|metrics|docs|anpr/accertamento-residenza|anpr/stato-famiglia|tenants|keys|tenants/configs|tenants/clients|e-services)}/({id:[^/]+})`) && METHOD(`GET`, `POST`, `PUT` ,`PATCH`, `DELETE`, `HEAD`, `OPTIONS`)'
traefik.http.routers.pdnd-connector.tls: 'true'
traefik.http.middlewares.pdnd-connector-stripper.stripprefix.prefixes: '/pdnd/'
traefik.http.routers.pdnd-connector.tls.certresolver: 'myhttpchallenge'
traefik.http.routers.pdnd-connector.middlewares: 'goodheaders, cors-free-all, pdnd-connector-stripper'
##############################################################################
# PROTOCOL PROXY
##############################################################################
protocol-proxy-sigedo:
image: registry.gitlab.com/opencity-labs/area-personale/protocol-proxy-sigedo:1.1.0-x86
networks:
- oc-prod-internal
- oc-prod-public
environment:
ENVIRONMENT: PROD
DEBUG: "false"
SERVER_ADDRESS_PORT: https://api.opencityitalia.055055.it/registry-proxy/sigedo/v1
CACHE_EXPIRATION: 5m
CACHE_EVICTION: 10m
SDC_AUTH_TOKEN_USER: user
SDC_AUTH_TOKEN_PASSWORD: password
KAFKA_BOOTSTRAP_SERVERS: kafka:9092
KAFKA_CONSUMER_GROUP: protocol-proxy-sigedo
KAFKA_CONSUMER_TOPIC: documents
KAFKA_PRODUCER_TOPIC: documents
KAFKA_RETRY_TOPIC: retry_prod_queue_dispatcher
STORAGE_ENDPOINT: https://storage.opencityitalia.055055.it
STORAGE_TYPE: s3
STORAGE_BUCKET: documents
STORAGE_ACCESS_S3_KEY: user
STORAGE_KEY_S3_ACCESS_SECRET: password
STORAGE_S3_REGION: eu-south-1
PREFIX_API: /registry-proxy/sigedo/v1/
#healthcheck:
#test: wget -O /dev/null http://0.0.0.0:8000/status || exit 1
#interval: 5s
#retries: 5
#start_period: 20s
#timeout: 10s
deploy:
<<: *deploy-snippet
replicas: 1
resources:
limits:
cpus: '0.3'
memory: 512M
reservations:
memory: 64M
labels:
prometheus.enable: 'true'
prometheus.port: 8000
traefik.enable: 'true'
traefik.docker.network: 'oc-prod-internal'
traefik.http.services.protocol-proxy-sigedo-prod.loadbalancer.server.port: 8000
traefik.http.services.protocol-proxy-sigedo-prod.loadbalancer.healthcheck.path: '/status'
traefik.http.routers.protocol-proxy-sigedo-prod.entrypoints: 'websecure, web'
traefik.http.routers.protocol-proxy-sigedo-prod.rule: 'Host(`api.opencityitalia.055055.it`) && PathPrefix(`/registry-proxy/sigedo/v1/{op:(status|metrics|schema|tenants|services)}`, `/registry-proxy/sigedo/v1/{op:(tenants|services)}/({id:[^/]+})`) && METHOD(`GET`, `POST`, `PUT` ,`PATCH`, `DELETE`, `HEAD`, `OPTIONS`)'
traefik.http.routers.protocol-proxy-sigedo-prod.tls: 'true'
traefik.http.middlewares.protocol-proxy-sigedo-prod-stripper.stripprefix.prefixes: '/registry-proxy/sigedo/v1/'
traefik.http.routers.protocol-proxy-sigedo-prod.tls.certresolver: 'myhttpchallenge'
traefik.http.routers.protocol-proxy-sigedo-prod.middlewares: 'goodheaders, cors-free-all, protocol-proxy-sigedo-prod-stripper'
traefik.http.routers.protocol-proxy-sigedo-prod-docs.entrypoints: 'websecure, web'
traefik.http.routers.protocol-proxy-sigedo-prod-docs.rule: 'Host(`api.opencityitalia.055055.it`) && Path(`/registry-proxy/sigedo/v1/{op:(docs|openapi.json)}`) && METHOD(`GET`, `HEAD`, `OPTIONS`)'
traefik.http.routers.protocol-proxy-sigedo-prod-docs.tls: 'true'
traefik.http.routers.protocol-proxy-sigedo-prod-docs.tls.certresolver: 'myhttpchallenge'
traefik.http.routers.protocol-proxy-sigedo-prod-docs.middlewares: 'goodheaders, cors-free-all'
retry-orchestrator-prod:
image: registry.gitlab.com/opencity-labs/retry-orchestrator:1.0.23-x86
networks:
- oc-prod-internal
deploy:
<<: *deploy-snippet
replicas: 1
labels:
prometheus.enable: "true"
prometheus.port: 8000
com.centurylinklabs.watchtower.scope: 'autoupdate'
resources:
reservations:
memory: 128M
limits:
cpus: '0.1'
memory: 256M
environment:
KAFKA_SERVER: kafka:9092
KAFKA_RETRY_QUEUE_TOPIC: retry_prod_queue_dispatcher
KAFKA_DISPATCHER_POLICY: 3x1m,4x15m,3x180m,6x720m
KAFKA_RETRY_QUEUE_PREFIX: retry_prod_queue_
KAFKA_DEAD_LETTER_QUEUE: retry_prod_dead_letter_queue
KAFKA_RETRY_QUEUE_CONSUMER_GROUP: retry-orchestrator-prod
ENVIRONMENT: boat-prod
SERVER_ADDRESS_PORT: 0.0.0.0:8000
SENTRY_DSN: https://example.com/4505402356858880
SERVER_DEBUG: "false"
CACHE_EXPIRATION: 5m
CACHE_EVICTION: 5m
healthcheck:
test: curl --fail http://0.0.0.0:8000/status
interval: 30s
retries: 2
start_period: 10s
timeout: 5s