# documentation: https://docs.opnform.com/introduction
# slogan: OpnForm is an open-source form builder that lets you create beautiful forms and share them anywhere. It's super fast, you don't need to know how to code
# category: productivity
# tags: opnform, form, survey, cloud, open-source, self-hosted, docker, no-code, embeddable
# logo: svg/opnform.svg
# port: 80

x-shared-env: &shared-api-env
  APP_NAME: "OpnForm"
  APP_ENV: production
  APP_KEY: ${SERVICE_BASE64_APIKEY}
  APP_DEBUG: ${APP_DEBUG:-false}
  APP_URL: ${SERVICE_URL_NGINX}
  LOG_CHANNEL: errorlog
  LOG_LEVEL: ${LOG_LEVEL:-debug}
  FILESYSTEM_DRIVER: ${FILESYSTEM_DRIVER:-local}
  LOCAL_FILESYSTEM_VISIBILITY: public
  CACHE_DRIVER: redis
  QUEUE_CONNECTION: redis
  SESSION_DRIVER: redis
  SESSION_LIFETIME: 120
  MAIL_MAILER: ${MAIL_MAILER:-log}
  MAIL_HOST: ${MAIL_HOST}
  MAIL_PORT: ${MAIL_PORT}
  MAIL_USERNAME: ${MAIL_USERNAME:-your@email.com}
  MAIL_PASSWORD: ${MAIL_PASSWORD}
  MAIL_ENCRYPTION: ${MAIL_ENCRYPTION}
  MAIL_FROM_ADDRESS: ${MAIL_FROM_ADDRESS:-your@email.com}
  MAIL_FROM_NAME: ${MAIL_FROM_NAME:-OpnForm}
  AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
  AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
  AWS_DEFAULT_REGION: ${AWS_DEFAULT_REGION:-us-east-1}
  AWS_BUCKET: ${AWS_BUCKET}
  OPEN_AI_API_KEY: ${OPEN_AI_API_KEY}
  TELEGRAM_BOT_ID: ${TELEGRAM_BOT_ID}
  TELEGRAM_BOT_TOKEN: ${TELEGRAM_BOT_TOKEN}
  REDIS_HOST: redis
  REDIS_PASSWORD: ${SERVICE_PASSWORD_64_REDIS}
  # Database settings
  DB_HOST: postgresql
  DB_DATABASE: ${POSTGRESQL_DATABASE:-opnform}
  DB_USERNAME: ${SERVICE_USER_POSTGRESQL}
  DB_PASSWORD: ${SERVICE_PASSWORD_POSTGRESQL}
  DB_CONNECTION: pgsql
  # PHP Configuration
  PHP_MEMORY_LIMIT: "1G"
  PHP_MAX_EXECUTION_TIME: "600"
  PHP_UPLOAD_MAX_FILESIZE: "64M"
  PHP_POST_MAX_SIZE: "64M"

services:
  opnform-api:
    image: jhumanj/opnform-api:1.12.1
    volumes:
      - api-storage:/usr/share/nginx/html/storage
    environment:
      # Use the shared environment variables.
      <<: *shared-api-env
      JWT_TTL: ${JWT_TTL:-1440}
      JWT_SECRET: ${SERVICE_PASSWORD_JWTSECRET}
      JWT_SKIP_IP_UA_VALIDATION: ${JWT_SKIP_IP_UA_VALIDATION:-true}
      H_CAPTCHA_SITE_KEY: ${H_CAPTCHA_SITE_KEY}
      H_CAPTCHA_SECRET_KEY: ${H_CAPTCHA_SECRET_KEY}
      RE_CAPTCHA_SITE_KEY: ${RE_CAPTCHA_SITE_KEY}
      RE_CAPTCHA_SECRET_KEY: ${RE_CAPTCHA_SECRET_KEY}
      SHOW_OFFICIAL_TEMPLATES: ${SHOW_OFFICIAL_TEMPLATES:-true}
    depends_on:
      postgresql:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD-SHELL", "php /usr/share/nginx/html/artisan about || exit 1"]
      interval: 30s
      timeout: 15s
      retries: 3
      start_period: 60s

  api-worker:
    image: jhumanj/opnform-api:1.12.1
    volumes:
      - api-storage:/usr/share/nginx/html/storage
    environment:
      # Use the shared environment variables.
      <<: *shared-api-env
    command: ["php", "artisan", "queue:work"]
    depends_on:
      postgresql:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test:
        ["CMD-SHELL", "pgrep -f 'php artisan queue:work' > /dev/null || exit 1"]
      interval: 60s
      timeout: 10s
      retries: 3
      start_period: 30s

  api-scheduler:
    image: jhumanj/opnform-api:1.12.1
    volumes:
      - api-storage:/usr/share/nginx/html/storage
    environment:
      # Use the shared environment variables.
      <<: *shared-api-env
    command: ["php", "artisan", "schedule:work"]
    depends_on:
      postgresql:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "php /usr/share/nginx/html/artisan app:scheduler-status --mode=check --max-minutes=3 || exit 1",
        ]
      interval: 60s
      timeout: 30s
      retries: 3
      start_period: 70s # Allow time for first scheduled run and cache write

  opnform-ui:
    image: jhumanj/opnform-client:1.12.1
    environment:
      - NUXT_PUBLIC_APP_URL=/
      - NUXT_PUBLIC_API_BASE=/api
      - NUXT_PRIVATE_API_BASE=http://nginx/api
      - NUXT_PUBLIC_ENV=production
      - NUXT_PUBLIC_H_CAPTCHA_SITE_KEY=${H_CAPTCHA_SITE_KEY}
      - NUXT_PUBLIC_RE_CAPTCHA_SITE_KEY=${RE_CAPTCHA_SITE_KEY}
    healthcheck:
      test:
        ["CMD-SHELL", "wget --spider -q http://opnform-ui:3000/login || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 45s
    depends_on:
      opnform-api:
        condition: service_healthy

  postgresql:
    image: postgres:16
    volumes:
      - opnform-postgresql-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=${SERVICE_USER_POSTGRESQL}
      - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRESQL}
      - POSTGRES_DB=${POSTGRESQL_DATABASE:-opnform}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
      interval: 5s
      timeout: 20s
      retries: 10

  redis:
    image: redis:7
    environment:
      - REDIS_PASSWORD=${SERVICE_PASSWORD_64_REDIS}
    volumes:
      - redis-data:/data
    command: ["redis-server", "--requirepass", "${SERVICE_PASSWORD_64_REDIS}"]
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${SERVICE_PASSWORD_64_REDIS}", "PING"]
      interval: 10s
      timeout: 30s
      retries: 3

  # The nginx reverse proxy.
  # used for reverse proxying the API service and Web service.
  nginx:
    image: nginx:1.29.2
    environment:
      - SERVICE_URL_NGINX
    volumes:
      - type: bind
        source: ./nginx/nginx.conf
        target: /etc/nginx/conf.d/default.conf
        read_only: true
        content: |
          map $original_uri $api_uri {
              ~^/api(/.*$) $1;
              default $original_uri;
          }

          server {
              listen 80 default_server;
              root /usr/share/nginx/html/public;

              access_log /dev/stdout;
              error_log /dev/stderr error;

              index index.html index.htm index.php;

              location / {
                  proxy_http_version 1.1;
                  proxy_pass http://opnform-ui:3000;
                  proxy_set_header X-Real-IP $remote_addr;
                  proxy_set_header X-Forwarded-Host $host;
                  proxy_set_header X-Forwarded-Port $server_port;
                  proxy_set_header Upgrade $http_upgrade;
                  proxy_set_header Connection "Upgrade";
              }

              location ~/(api|open|local\/temp|forms\/assets)/ {
                  set $original_uri $uri;
                  try_files $uri $uri/ /index.php$is_args$args;
              }

              location ~ \.php$ {
                  fastcgi_split_path_info ^(.+\.php)(/.+)$;
                  fastcgi_pass opnform-api:9000;
                  fastcgi_index index.php;
                  include fastcgi_params;
                  fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html/public/index.php;
                  fastcgi_param REQUEST_URI $api_uri;
              }
          }
    depends_on:
      - opnform-api
      - opnform-ui
    healthcheck:
      test: ["CMD", "nginx", "-t"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
