name: zksync-prividium-deps # The one-shot deployers' tool image (deployments/stack-tools/Dockerfile): node, pnpm, forge/cast and # the deploy scripts' dependencies; the scripts are bind-mounted from dev/. Built from source here; # CI points STACK_TOOLS_IMAGE at main's published build when the image inputs are unchanged. x-stack-tools: &stack-tools image: quay.io/matterlabs_enterprise/prividium-stack-tools:3f45841-1792677326000 platform: linux/amd64 services: postgres: image: postgres:18 restart: unless-stopped ports: - 127.0.0.1:5432:5432 volumes: - postgres:/var/lib/postgresql/data environment: POSTGRES_PASSWORD: postgres # postgres:18 moved the default PGDATA to a version-specific subdir; pin it to the # mount path so the existing volume layout keeps working. PGDATA: /var/lib/postgresql/data healthcheck: test: ['CMD-SHELL', 'pg_isready -U postgres'] interval: 10s timeout: 5s retries: 5 entrypoint: | bash -c " cat > /docker-entrypoint-initdb.d/init.sql << 'EOF' -- Create databases for the prividium project CREATE DATABASE prividium_api; -- Create databases for block explorer CREATE DATABASE prividium_block_explorer; -- Databases created successfully EOF exec docker-entrypoint.sh postgres " l1: image: ghcr.io/foundry-rs/foundry:v1.8.4 restart: unless-stopped volumes: - ./dev/zksyncos/l1-state.json.gz:/l1-state.json.gz:ro - ./dev/zksyncos/start-anvil.sh:/start-anvil.sh:ro - l1state:/home/foundry/l1state entrypoint: '' user: 'root' ports: - '5010:5010' healthcheck: test: ['CMD', 'bash', '/start-anvil.sh', 'healthcheck', '5010'] interval: 10s timeout: 5s retries: 5 # zksync-os-server bisects L1 history on every boot; past this snapshot cap (~2-4h uptime) it # panic-loops with BlockOutOfRangeError until the l1state and zksyncos_db volumes are wiped together. command: >- bash /start-anvil.sh 5010 --state=/home/foundry/l1state/state.json --state-interval 60 --preserve-historical-states --max-persisted-states 512 --block-time 12 --mixed-mining --slots-in-an-epoch 10 zksyncos: image: quay.io/matterlabs_enterprise/zksync-os-server:v0.24.5 restart: unless-stopped platform: linux/amd64 ports: - '5050:3050' environment: L1_PROVIDER_RPC_URL: 'http://l1:5010' user: 'root' working_dir: '/app' entrypoint: '' command: ['/usr/bin/tini', '--', 'zksync-os-server', '--config', '/app/config/config.yaml'] volumes: - zksyncos_db:/db - ./dev/zksyncos/config.yaml:/app/config/config.yaml:ro - ./dev/zksyncos/genesis.json:/app/config/genesis.json:ro depends_on: l1: condition: service_healthy healthcheck: test: ['CMD', '/usr/bin/bash', '-c', 'exec 3<>/dev/tcp/127.0.0.1/3050'] interval: 10s timeout: 5s retries: 12 start_period: 30s keycloak: image: quay.io/keycloak/keycloak:26.7.2 ports: - '5080:8080' environment: KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: admin # Pin the JVM heap; Keycloak otherwise sizes it to ~70% of host RAM. JAVA_OPTS_KC_HEAP: '-Xms64m -Xmx512m' KC_HTTP_RELATIVE_PATH: / KC_HEALTH_ENABLED: 'true' KC_HTTP_ENABLED: 'true' KC_HOSTNAME_STRICT: 'false' KC_HOSTNAME_STRICT_HTTPS: 'false' KC_HOSTNAME_URL: 'http://localhost:5080' KC_HOSTNAME_ADMIN_URL: 'http://localhost:5080' command: - start-dev - --import-realm volumes: - ./dev/keycloak/realm-export.json:/opt/keycloak/data/import/realm-export.json:ro # Second realm = a sample organization's own identity provider, for the local multi-org demo. - ./dev/keycloak/acme-realm-export.json:/opt/keycloak/data/import/acme-realm-export.json:ro healthcheck: test: ['CMD-SHELL', 'exec 3<>/dev/tcp/127.0.0.1/8080;echo -e "GET /health/ready HTTP/1.1\r\nhost: 127.0.0.1:8080\r\nConnection: close\r\n\r\n" >&3;if [ $? -eq 0 ]; then echo "Healthcheck Successful";exit 0;else echo "Healthcheck Failed";exit 1;fi;'] interval: 10s timeout: 5s retries: 30 start_period: 60s prometheus: image: prom/prometheus:v2.48.0 restart: unless-stopped ports: - '9090:9090' extra_hosts: - 'host.docker.internal:host-gateway' volumes: - ./dev/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro - prometheus_data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--web.console.libraries=/etc/prometheus/console_libraries' - '--web.console.templates=/etc/prometheus/consoles' - '--storage.tsdb.retention.time=200h' - '--web.enable-lifecycle' healthcheck: test: ['CMD', 'wget', '--quiet', '--tries=1', '--spider', 'http://localhost:9090/-/healthy'] interval: 10s timeout: 5s retries: 5 grafana: image: grafana/grafana:10.2.0 restart: unless-stopped ports: - '3100:3000' volumes: - grafana_data:/var/lib/grafana - ./dev/grafana/datasources:/etc/grafana/provisioning/datasources:ro - ./dev/grafana/dashboards.yml:/etc/grafana/provisioning/dashboards/dashboards.yml:ro - ./dev/grafana/datasources/dashboards:/etc/grafana/provisioning/dashboards/files:ro environment: - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=admin - GF_USERS_ALLOW_SIGN_UP=false - GF_SERVER_ROOT_URL=http://localhost:3100 depends_on: - prometheus healthcheck: test: ['CMD-SHELL', 'wget --quiet --tries=1 --spider http://localhost:3000/api/health || exit 1'] interval: 10s timeout: 5s retries: 5 block-explorer-api: image: ghcr.io/matter-labs/block-explorer-api:latest platform: linux/amd64 extra_hosts: - 'host.docker.internal:host-gateway' environment: LOG_LEVEL: verbose NODE_ENV: development # Force cookie to be sent over HTTP DATABASE_HOST: postgres DATABASE_NAME: prividium_block_explorer DATABASE_USER: postgres DATABASE_PASSWORD: postgres DATABASE_ENABLE_SSL: 'false' # Network NETWORK_NAME: testnet # Prividium Integration PRIVIDIUM: 'true' PRIVIDIUM_APP_URL: http://localhost:3010 PRIVIDIUM_PERMISSIONS_API_URL: http://host.docker.internal:8000 PRIVIDIUM_SESSION_SECRET: QkxPQ0tfRVhQTE9SRVJfU0VTU0lPTl9TRUNSRVQ= PRIVIDIUM_SESSION_MAX_AGE: 86400000 PRIVIDIUM_SESSION_SAME_SITE: strict # Pagination LIMITED_PAGINATION_MAX_ITEMS: '10000' API_LIMITED_PAGINATION_MAX_ITEMS: '1000' DISABLE_BFF_API_SCHEMA_DOCS: 'true' ports: - '3002:3000' depends_on: postgres: condition: service_healthy block-explorer-app: image: ghcr.io/matter-labs/block-explorer-app:latest platform: linux/amd64 volumes: - ./dev/block-explorer/block-explorer-config.js:/usr/share/nginx/html/config.js:ro ports: - '3010:3010' depends_on: block-explorer-api: condition: service_started block-explorer-worker: image: ghcr.io/matter-labs/block-explorer-worker:latest platform: linux/amd64 extra_hosts: - 'host.docker.internal:host-gateway' environment: DATABASE_HOST: postgres DATABASE_NAME: prividium_block_explorer DATABASE_USER: postgres DATABASE_PASSWORD: postgres DATABASE_ENABLE_SSL: 'false' NETWORK_NAME: testnet BLOCKCHAIN_RPC_URL: http://zksyncos:3050 DATA_FETCHER_URL: http://block-explorer-data-fetcher:3040 PRIVIDIUM: 'true' PRIVIDIUM_PERMISSIONS_API_URL: http://host.docker.internal:8000/api ENABLE_TOKEN_OFFCHAIN_DATA_SAVER: 'true' BLOCKS_PROCESSING_BATCH_SIZE: '10' NUMBER_OF_BLOCKS_PER_DB_TRANSACTION: '10' depends_on: postgres: condition: service_healthy block-explorer-data-fetcher: condition: service_started block-explorer-data-fetcher: image: ghcr.io/matter-labs/block-explorer-data-fetcher:latest platform: linux/amd64 extra_hosts: - 'host.docker.internal:host-gateway' environment: NETWORK_NAME: testnet BLOCKCHAIN_RPC_URL: http://zksyncos:3050 PRIVIDIUM: 'true' PRIVIDIUM_PERMISSIONS_API_URL: http://host.docker.internal:8000/api zksync-webhook-db: image: postgres:18-alpine restart: unless-stopped environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: password POSTGRES_DB: zksync_webhook_db PGDATA: /var/lib/postgresql/data volumes: - zksync_webhook_db_data:/var/lib/postgresql/data healthcheck: test: ['CMD-SHELL', 'pg_isready -U postgres -d zksync_webhook_db'] interval: 5s timeout: 5s retries: 10 zksync-webhook-service: image: quay.io/matterlabs_enterprise/webhook-service:v0.1.28 platform: linux/amd64 pull_policy: always init: true restart: unless-stopped depends_on: zksync-webhook-db: condition: service_healthy environment: DATABASE_HOST: zksync-webhook-db DATABASE_PORT: '5432' DATABASE_NAME: zksync_webhook_db DATABASE_USER: postgres DATABASE_PASSWORD: password DATABASE_ENABLE_SSL: 'false' DATABASE_SSL_REJECT_UNAUTHORIZED: 'true' ZKSYNC_WEBHOOK_CONFIG: /app/config/config.default.toml RUST_LOG: info ENCRYPTION_KEY: a40c350fed393623dfaa54d93d96addcbf8ae845e4f1b6eeaeb444aa3645e800 ENCRYPTION_KDF_SALT: zksync-webhook-service:keycipher:v2 PRIVIDIUM_API_KEY: priv_sk_DEV000000000000000000000000000000000000000000000000000000WEBHOOK PRIVIDIUM_RPC_URL: http://host.docker.internal:8000/rpc PRIVIDIUM_PERMISSIONS_API: http://host.docker.internal:8000 ZKSYNC_WEBHOOK_API_CORS_ALLOW_ORIGIN: http://localhost:3000 ZKSYNC_WEBHOOK_ALLOW_HTTP_LOCALHOST: 'true' ZKSYNC_WEBHOOK_CHAIN_NAME: 'local_prividium' ZKSYNC_WEBHOOK_CHAIN_ID: 424242 extra_hosts: - 'host.docker.internal:host-gateway' ports: - '127.0.0.1:8080:8080' - '127.0.0.1:8081:8081' bridge-funds: <<: *stack-tools working_dir: /opt/stack-tools/contracts/src volumes: - ./dev/bundler/contracts:/opt/stack-tools/contracts/src tmpfs: - /opt/stack-tools/contracts/src/node_modules # Hides a host install; imports resolve to the image's ../node_modules environment: L1_RPC_URL: http://l1:5010 L2_RPC_URL: http://zksyncos:3050 # Key #3 = bundler executor; Key #0 = auth-server-api deployer PRIVATE_KEYS: '0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba,0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80' BRIDGE_SPONSOR_PRIVATE_KEY: '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80' command: tsx scripts/bridge-funds.ts depends_on: zksyncos: condition: service_healthy volumes: postgres: l1state: zksyncos_db: prometheus_data: grafana_data: zksync_webhook_db_data: