{
  "manifest_version": "1.0.0",
  "template": {
    "id": "46ceae2a-09c7-47cc-9b8a-49a29dcf0ea0",
    "slug": "firecrawl-v2-web-data-api-for-ai",
    "name": "Firecrawl v2 Web Data API for AI",
    "description": "Turn websites into clean markdown and JSON for LLMs. Self-hosted workers.",
    "url": "https://railway.com/deploy/firecrawl-v2-web-data-api-for-ai",
    "upstream": {
      "repo_url": "https://github.com/baranberkay96/firecrawl-railway"
    }
  },
  "services": [
    {
      "name": "playwright-service",
      "source": {
        "image": "ghcr.io/firecrawl/playwright-service:latest@sha256:717699bf8a61d94451926c810d19ca1d36278192907e307bf5229a558b08fcc6"
      },
      "needs_volume": false,
      "http": false
    },
    {
      "name": "Redis",
      "source": {
        "image": "redis:8.2"
      },
      "needs_volume": true,
      "volume_mount_path": "/data",
      "http": false
    },
    {
      "name": "nuq-postgres",
      "source": {
        "image": "ghcr.io/firecrawl/nuq-postgres:latest@sha256:9b638af78d99873bc0ba2b57c9cbcd01df6ce96efeaa72d36cfbe0f76521e8fc"
      },
      "needs_volume": true,
      "volume_mount_path": "/var/lib/postgresql/data",
      "http": false
    },
    {
      "name": "firecrawl-api",
      "source": {
        "image": "ghcr.io/firecrawl/firecrawl:2.11.504"
      },
      "needs_volume": false,
      "http": false
    },
    {
      "name": "firecrawl",
      "source": {
        "repo": "https://github.com/baranberkay96/firecrawl-railway"
      },
      "needs_volume": false,
      "http": true
    },
    {
      "name": "firecrawl-worker",
      "source": {
        "repo": "https://github.com/baranberkay96/firecrawl-railway"
      },
      "needs_volume": false,
      "http": false
    },
    {
      "name": "RabbitMQ",
      "source": {
        "image": "rabbitmq:4.3.6-alpine"
      },
      "needs_volume": false,
      "http": false
    },
    {
      "name": "firecrawl-nuq-worker",
      "source": {
        "repo": "https://github.com/baranberkay96/firecrawl-railway"
      },
      "needs_volume": false,
      "http": false
    }
  ],
  "required_inputs": [
    {
      "key": "PORT",
      "service": "playwright-service",
      "description": "HTTP port of the Playwright scrape service (private).",
      "secret": false,
      "strategy": "default",
      "default": "3000"
    },
    {
      "key": "BLOCK_MEDIA",
      "service": "playwright-service",
      "description": "Set true to block images/video downloads (less bandwidth, faster pages).",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "PROXY_SERVER",
      "service": "playwright-service",
      "description": "Optional outbound proxy (shared with firecrawl-api).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "PROXY_PASSWORD",
      "service": "playwright-service",
      "description": "Optional proxy password.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "PROXY_USERNAME",
      "service": "playwright-service",
      "description": "Optional proxy username.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "ALLOW_LOCAL_WEBHOOKS",
      "service": "playwright-service",
      "description": "Keep false so pages cannot be pointed at private addresses.",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "MAX_CONCURRENT_PAGES",
      "service": "playwright-service",
      "description": "Concurrent browser pages; follows CRAWL_CONCURRENT_REQUESTS like upstream.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "REDISHOST",
      "service": "Redis",
      "description": "Private network hostname of the Redis service, only resolvable from services in the same environment",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "REDISPORT",
      "service": "Redis",
      "description": "Port that Redis listens on",
      "secret": false,
      "strategy": "default",
      "default": "6379"
    },
    {
      "key": "REDISUSER",
      "service": "Redis",
      "description": "Username for authenticating with Redis",
      "secret": false,
      "strategy": "default",
      "default": "default"
    },
    {
      "key": "REDIS_URL",
      "service": "Redis",
      "description": "Connection string for connecting to Redis using the private network",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "REDISPASSWORD",
      "service": "Redis",
      "description": "Alias of REDIS_PASSWORD for clients that expect the unseparated name",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "REDIS_PASSWORD",
      "service": "Redis",
      "description": "Randomly generated password for authenticating with Redis",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "PGDATA",
      "service": "nuq-postgres",
      "description": "Data directory inside the volume (avoids the volume's lost+found).",
      "secret": false,
      "strategy": "default",
      "default": "/var/lib/postgresql/data/pgdata"
    },
    {
      "key": "POSTGRES_DB",
      "service": "nuq-postgres",
      "description": "Must stay 'postgres': the image configures cron.database_name = 'postgres' and installs the NuQ schema there.",
      "secret": false,
      "strategy": "default",
      "default": "postgres"
    },
    {
      "key": "POSTGRES_USER",
      "service": "nuq-postgres",
      "description": "Superuser created on first boot (pg_cron jobs run in the postgres database).",
      "secret": false,
      "strategy": "default",
      "default": "postgres"
    },
    {
      "key": "POSTGRES_PASSWORD",
      "service": "nuq-postgres",
      "description": "Database password, generated.",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "RAILWAY_DEPLOYMENT_DRAINING_SECONDS",
      "service": "nuq-postgres",
      "description": "Allow Postgres to shut down cleanly.",
      "secret": false,
      "strategy": "default",
      "default": "60"
    },
    {
      "key": "ENV",
      "service": "firecrawl-api",
      "description": "Self-hosted mode (same value as the upstream docker-compose).",
      "secret": false,
      "strategy": "default",
      "default": "local"
    },
    {
      "key": "HOST",
      "service": "firecrawl-api",
      "description": "Bind address; :: accepts IPv4 and IPv6 from the gateway.",
      "secret": false,
      "strategy": "default",
      "default": "::"
    },
    {
      "key": "PORT",
      "service": "firecrawl-api",
      "description": "API port (private).",
      "secret": false,
      "strategy": "default",
      "default": "3002"
    },
    {
      "key": "REDIS_URL",
      "service": "firecrawl-api",
      "description": "Redis for BullMQ queues and crawl state.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "BULL_AUTH_KEY",
      "service": "firecrawl-api",
      "description": "Secret path segment for the queue dashboard: /admin/<BULL_AUTH_KEY>/queues.",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "LOGGING_LEVEL",
      "service": "firecrawl-api",
      "description": "Log level.",
      "secret": false,
      "strategy": "default",
      "default": "INFO"
    },
    {
      "key": "NUQ_DATABASE_URL",
      "service": "firecrawl-api",
      "description": "NuQ job queue database (nuq-postgres, private network).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "NUQ_RABBITMQ_URL",
      "service": "firecrawl-api",
      "description": "RabbitMQ used by NuQ to wake workers when jobs arrive.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "BROWSER_POOL_SIZE",
      "service": "firecrawl-api",
      "description": "Browser pool size (upstream default).",
      "secret": false,
      "strategy": "default",
      "default": "5"
    },
    {
      "key": "MAX_CONCURRENT_JOBS",
      "service": "firecrawl-api",
      "description": "Max concurrent jobs per team (upstream default).",
      "secret": false,
      "strategy": "default",
      "default": "5"
    },
    {
      "key": "REDIS_RATE_LIMIT_URL",
      "service": "firecrawl-api",
      "description": "Redis for rate limiting.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "NUM_WORKERS_PER_QUEUE",
      "service": "firecrawl-api",
      "description": "BullMQ concurrency per queue (upstream default).",
      "secret": false,
      "strategy": "default",
      "default": "8"
    },
    {
      "key": "USE_DB_AUTHENTICATION",
      "service": "firecrawl-api",
      "description": "Supabase auth is not available for self-hosting; the firecrawl gateway enforces the API key instead.",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "NUQ_DATABASE_URL_LISTEN",
      "service": "firecrawl-api",
      "description": "Direct connection used for LISTEN/NOTIFY (same database).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "CRAWL_CONCURRENT_REQUESTS",
      "service": "firecrawl-api",
      "description": "Concurrent requests per crawl (upstream default).",
      "secret": false,
      "strategy": "default",
      "default": "10"
    },
    {
      "key": "PLAYWRIGHT_MICROSERVICE_URL",
      "service": "firecrawl-api",
      "description": "Browser rendering service (private network).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "RAILWAY_DEPLOYMENT_DRAINING_SECONDS",
      "service": "firecrawl-api",
      "description": "Let in-flight scrape requests finish during redeploys.",
      "secret": false,
      "strategy": "default",
      "default": "60"
    },
    {
      "key": "PORT",
      "service": "firecrawl",
      "description": "Gateway listen port (public domain target).",
      "secret": false,
      "strategy": "default",
      "default": "8080"
    },
    {
      "key": "FIRECRAWL_API_KEY",
      "service": "firecrawl",
      "description": "API key clients must send as 'Authorization: Bearer <key>'. Use it as the SDK api_key.",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "FIRECRAWL_UPSTREAM",
      "service": "firecrawl",
      "description": "Private address of firecrawl-api.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "ENV",
      "service": "firecrawl-worker",
      "description": "Self-hosted mode (same value as the upstream docker-compose).",
      "secret": false,
      "strategy": "default",
      "default": "local"
    },
    {
      "key": "PORT",
      "service": "firecrawl-worker",
      "description": "Liveness port of the queue-worker (Railway healthcheck).",
      "secret": false,
      "strategy": "default",
      "default": "3005"
    },
    {
      "key": "REDIS_URL",
      "service": "firecrawl-worker",
      "description": "Redis for BullMQ queues and crawl state.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "MODEL_NAME",
      "service": "firecrawl-worker",
      "description": "Shared with firecrawl-api (MODEL_NAME).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "WORKER_PORT",
      "service": "firecrawl-worker",
      "description": "queue-worker liveness port.",
      "secret": false,
      "strategy": "default",
      "default": "3005"
    },
    {
      "key": "PROXY_SERVER",
      "service": "firecrawl-worker",
      "description": "Shared with firecrawl-api (PROXY_SERVER).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "BULL_AUTH_KEY",
      "service": "firecrawl-worker",
      "description": "Shared with firecrawl-api (BULL_AUTH_KEY).",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "IS_KUBERNETES",
      "service": "firecrawl-worker",
      "description": "Use container (cgroup v2) CPU/RAM figures for job back-pressure instead of host-wide numbers.",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "LOGGING_LEVEL",
      "service": "firecrawl-worker",
      "description": "Log level.",
      "secret": false,
      "strategy": "default",
      "default": "INFO"
    },
    {
      "key": "OPENAI_API_KEY",
      "service": "firecrawl-worker",
      "description": "Shared with firecrawl-api (OPENAI_API_KEY).",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "PROXY_PASSWORD",
      "service": "firecrawl-worker",
      "description": "Shared with firecrawl-api (PROXY_PASSWORD).",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "PROXY_USERNAME",
      "service": "firecrawl-worker",
      "description": "Shared with firecrawl-api (PROXY_USERNAME).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "OLLAMA_BASE_URL",
      "service": "firecrawl-worker",
      "description": "Shared with firecrawl-api (OLLAMA_BASE_URL).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "OPENAI_BASE_URL",
      "service": "firecrawl-worker",
      "description": "Shared with firecrawl-api (OPENAI_BASE_URL).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "NUQ_DATABASE_URL",
      "service": "firecrawl-worker",
      "description": "NuQ job queue database (nuq-postgres, private network).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "NUQ_RABBITMQ_URL",
      "service": "firecrawl-worker",
      "description": "RabbitMQ used by NuQ to wake workers when jobs arrive.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "SEARXNG_ENDPOINT",
      "service": "firecrawl-worker",
      "description": "Shared with firecrawl-api (SEARXNG_ENDPOINT).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "BROWSER_POOL_SIZE",
      "service": "firecrawl-worker",
      "description": "Shared with firecrawl-api (BROWSER_POOL_SIZE).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "EXTRACT_WORKER_PORT",
      "service": "firecrawl-worker",
      "description": "extract-worker health port.",
      "secret": false,
      "strategy": "default",
      "default": "3004"
    },
    {
      "key": "MAX_CONCURRENT_JOBS",
      "service": "firecrawl-worker",
      "description": "Shared with firecrawl-api (MAX_CONCURRENT_JOBS).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "MODEL_EMBEDDING_NAME",
      "service": "firecrawl-worker",
      "description": "Shared with firecrawl-api (MODEL_EMBEDDING_NAME).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "REDIS_RATE_LIMIT_URL",
      "service": "firecrawl-worker",
      "description": "Redis for rate limiting.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "FIRECRAWL_WORKER_ROLE",
      "service": "firecrawl-worker",
      "description": "Process group run by services/firecrawl-workers/railway-workers.sh: queue-worker, extract-worker, NuQ prefetch and reconciler.",
      "secret": false,
      "strategy": "default",
      "default": "worker"
    },
    {
      "key": "NUM_WORKERS_PER_QUEUE",
      "service": "firecrawl-worker",
      "description": "Shared with firecrawl-api (NUM_WORKERS_PER_QUEUE).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "USE_DB_AUTHENTICATION",
      "service": "firecrawl-worker",
      "description": "Supabase auth is not available for self-hosting; the firecrawl gateway enforces the API key instead.",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "NUQ_DATABASE_URL_LISTEN",
      "service": "firecrawl-worker",
      "description": "Direct connection used for LISTEN/NOTIFY (same database).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "NUQ_PREFETCH_WORKER_PORT",
      "service": "firecrawl-worker",
      "description": "NuQ prefetch worker health port.",
      "secret": false,
      "strategy": "default",
      "default": "3011"
    },
    {
      "key": "CRAWL_CONCURRENT_REQUESTS",
      "service": "firecrawl-worker",
      "description": "Shared with firecrawl-api (CRAWL_CONCURRENT_REQUESTS).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "NUQ_RECONCILER_WORKER_PORT",
      "service": "firecrawl-worker",
      "description": "NuQ reconciler health port.",
      "secret": false,
      "strategy": "default",
      "default": "3012"
    },
    {
      "key": "PLAYWRIGHT_MICROSERVICE_URL",
      "service": "firecrawl-worker",
      "description": "Browser rendering service (private network).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "RAILWAY_DEPLOYMENT_DRAINING_SECONDS",
      "service": "firecrawl-worker",
      "description": "Let running jobs finish during redeploys.",
      "secret": false,
      "strategy": "default",
      "default": "60"
    },
    {
      "key": "RABBITMQ_DEFAULT_PASS",
      "service": "RabbitMQ",
      "description": "RabbitMQ password, generated.",
      "secret": false,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "RABBITMQ_DEFAULT_USER",
      "service": "RabbitMQ",
      "description": "RabbitMQ user for NuQ.",
      "secret": false,
      "strategy": "default",
      "default": "firecrawl"
    },
    {
      "key": "ENV",
      "service": "firecrawl-nuq-worker",
      "description": "Self-hosted mode (same value as the upstream docker-compose).",
      "secret": false,
      "strategy": "default",
      "default": "local"
    },
    {
      "key": "PORT",
      "service": "firecrawl-nuq-worker",
      "description": "Health port of the first executor (Railway healthcheck).",
      "secret": false,
      "strategy": "default",
      "default": "3006"
    },
    {
      "key": "REDIS_URL",
      "service": "firecrawl-nuq-worker",
      "description": "Redis for BullMQ queues and crawl state.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "MODEL_NAME",
      "service": "firecrawl-nuq-worker",
      "description": "Shared with firecrawl-api (MODEL_NAME).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "PROXY_SERVER",
      "service": "firecrawl-nuq-worker",
      "description": "Shared with firecrawl-api (PROXY_SERVER).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "BULL_AUTH_KEY",
      "service": "firecrawl-nuq-worker",
      "description": "Shared with firecrawl-api (BULL_AUTH_KEY).",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LOGGING_LEVEL",
      "service": "firecrawl-nuq-worker",
      "description": "Log level.",
      "secret": false,
      "strategy": "default",
      "default": "INFO"
    },
    {
      "key": "OPENAI_API_KEY",
      "service": "firecrawl-nuq-worker",
      "description": "Shared with firecrawl-api (OPENAI_API_KEY).",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "PROXY_PASSWORD",
      "service": "firecrawl-nuq-worker",
      "description": "Shared with firecrawl-api (PROXY_PASSWORD).",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "PROXY_USERNAME",
      "service": "firecrawl-nuq-worker",
      "description": "Shared with firecrawl-api (PROXY_USERNAME).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "OLLAMA_BASE_URL",
      "service": "firecrawl-nuq-worker",
      "description": "Shared with firecrawl-api (OLLAMA_BASE_URL).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "OPENAI_BASE_URL",
      "service": "firecrawl-nuq-worker",
      "description": "Shared with firecrawl-api (OPENAI_BASE_URL).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "NUQ_DATABASE_URL",
      "service": "firecrawl-nuq-worker",
      "description": "NuQ job queue database (nuq-postgres, private network).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "NUQ_RABBITMQ_URL",
      "service": "firecrawl-nuq-worker",
      "description": "RabbitMQ used by NuQ to wake workers when jobs arrive.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "NUQ_WORKER_COUNT",
      "service": "firecrawl-nuq-worker",
      "description": "Scrape executor processes in this container (upstream harness default 5). Each handles one job at a time.",
      "secret": false,
      "strategy": "default",
      "default": "5"
    },
    {
      "key": "SEARXNG_ENDPOINT",
      "service": "firecrawl-nuq-worker",
      "description": "Shared with firecrawl-api (SEARXNG_ENDPOINT).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "BROWSER_POOL_SIZE",
      "service": "firecrawl-nuq-worker",
      "description": "Shared with firecrawl-api (BROWSER_POOL_SIZE).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "MAX_CONCURRENT_JOBS",
      "service": "firecrawl-nuq-worker",
      "description": "Shared with firecrawl-api (MAX_CONCURRENT_JOBS).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "MODEL_EMBEDDING_NAME",
      "service": "firecrawl-nuq-worker",
      "description": "Shared with firecrawl-api (MODEL_EMBEDDING_NAME).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "REDIS_RATE_LIMIT_URL",
      "service": "firecrawl-nuq-worker",
      "description": "Redis for rate limiting.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "FIRECRAWL_WORKER_ROLE",
      "service": "firecrawl-nuq-worker",
      "description": "Runs NUQ_WORKER_COUNT scrape-executor processes (services/firecrawl-workers/railway-workers.sh).",
      "secret": false,
      "strategy": "default",
      "default": "nuq-worker"
    },
    {
      "key": "NUM_WORKERS_PER_QUEUE",
      "service": "firecrawl-nuq-worker",
      "description": "Shared with firecrawl-api (NUM_WORKERS_PER_QUEUE).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "NUQ_WORKER_START_PORT",
      "service": "firecrawl-nuq-worker",
      "description": "First health port; process i listens on start+i.",
      "secret": false,
      "strategy": "default",
      "default": "3006"
    },
    {
      "key": "USE_DB_AUTHENTICATION",
      "service": "firecrawl-nuq-worker",
      "description": "Supabase auth is not available for self-hosting; the firecrawl gateway enforces the API key instead.",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "NUQ_DATABASE_URL_LISTEN",
      "service": "firecrawl-nuq-worker",
      "description": "Direct connection used for LISTEN/NOTIFY (same database).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "CRAWL_CONCURRENT_REQUESTS",
      "service": "firecrawl-nuq-worker",
      "description": "Shared with firecrawl-api (CRAWL_CONCURRENT_REQUESTS).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "PLAYWRIGHT_MICROSERVICE_URL",
      "service": "firecrawl-nuq-worker",
      "description": "Browser rendering service (private network).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "RAILWAY_DEPLOYMENT_DRAINING_SECONDS",
      "service": "firecrawl-nuq-worker",
      "description": "Let running scrapes finish during redeploys.",
      "secret": false,
      "strategy": "default",
      "default": "60"
    }
  ],
  "deploy": {
    "mcp": {
      "server": "railway",
      "tool": "deploy_template",
      "args": {
        "template_code": "firecrawl-v2-web-data-api-for-ai"
      }
    },
    "cli": "railway deploy --template firecrawl-v2-web-data-api-for-ai",
    "api": {
      "method": "POST",
      "path": "/graphql/v2",
      "body": {
        "query": "mutation templateDeploy($input: TemplateDeployV2Input!) { templateDeployV2(input: $input) { projectId workflowId } }",
        "variables": {
          "input": {
            "templateId": "46ceae2a-09c7-47cc-9b8a-49a29dcf0ea0",
            "serializedConfig": {
              "buckets": {},
              "services": {
                "48bec0c1-6413-5510-9fa9-c49c93ea556a": {
                  "icon": "https://playwright.dev/img/playwright-logo.svg",
                  "name": "playwright-service",
                  "deploy": {
                    "healthcheckPath": "/health",
                    "restartPolicyType": "ON_FAILURE",
                    "healthcheckTimeout": 300,
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "ghcr.io/firecrawl/playwright-service:latest@sha256:717699bf8a61d94451926c810d19ca1d36278192907e307bf5229a558b08fcc6"
                  },
                  "variables": {
                    "PORT": {
                      "isOptional": true,
                      "description": "HTTP port of the Playwright scrape service (private).",
                      "defaultValue": "3000"
                    },
                    "BLOCK_MEDIA": {
                      "isOptional": true,
                      "description": "Set true to block images/video downloads (less bandwidth, faster pages).",
                      "defaultValue": "false"
                    },
                    "PROXY_SERVER": {
                      "isOptional": true,
                      "description": "Optional outbound proxy (shared with firecrawl-api).",
                      "defaultValue": "${{firecrawl-api.PROXY_SERVER}}"
                    },
                    "PROXY_PASSWORD": {
                      "isOptional": true,
                      "description": "Optional proxy password.",
                      "defaultValue": "${{firecrawl-api.PROXY_PASSWORD}}"
                    },
                    "PROXY_USERNAME": {
                      "isOptional": true,
                      "description": "Optional proxy username.",
                      "defaultValue": "${{firecrawl-api.PROXY_USERNAME}}"
                    },
                    "ALLOW_LOCAL_WEBHOOKS": {
                      "isOptional": true,
                      "description": "Keep false so pages cannot be pointed at private addresses.",
                      "defaultValue": "false"
                    },
                    "MAX_CONCURRENT_PAGES": {
                      "isOptional": true,
                      "description": "Concurrent browser pages; follows CRAWL_CONCURRENT_REQUESTS like upstream.",
                      "defaultValue": "${{firecrawl-api.CRAWL_CONCURRENT_REQUESTS}}"
                    }
                  },
                  "networking": {
                    "tcpProxies": {},
                    "serviceDomains": {}
                  }
                },
                "5d477031-3c9b-5604-adc7-cfe673787e81": {
                  "icon": "https://cdn.sanity.io/images/sy1jschh/production/0ce0bfdcfbdbf69662b1116671f97c2dd788b655-157x157.svg",
                  "name": "Redis",
                  "deploy": {
                    "startCommand": "/bin/sh -c \"rm -rf $RAILWAY_VOLUME_MOUNT_PATH/lost+found/ && exec docker-entrypoint.sh redis-server --requirepass $REDIS_PASSWORD --save 60 1 --dir $RAILWAY_VOLUME_MOUNT_PATH\"",
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "redis:8.2"
                  },
                  "variables": {
                    "REDISHOST": {
                      "isOptional": true,
                      "description": "Private network hostname of the Redis service, only resolvable from services in the same environment",
                      "defaultValue": "${{RAILWAY_PRIVATE_DOMAIN}}"
                    },
                    "REDISPORT": {
                      "isOptional": true,
                      "description": "Port that Redis listens on",
                      "defaultValue": "6379"
                    },
                    "REDISUSER": {
                      "isOptional": true,
                      "description": "Username for authenticating with Redis",
                      "defaultValue": "default"
                    },
                    "REDIS_URL": {
                      "isOptional": true,
                      "description": "Connection string for connecting to Redis using the private network",
                      "defaultValue": "redis://${{ REDISUSER }}:${{ REDIS_PASSWORD }}@${{ REDISHOST }}:${{ REDISPORT }}"
                    },
                    "REDISPASSWORD": {
                      "isOptional": true,
                      "description": "Alias of REDIS_PASSWORD for clients that expect the unseparated name",
                      "defaultValue": "${{REDIS_PASSWORD}}"
                    },
                    "REDIS_PASSWORD": {
                      "isOptional": true,
                      "description": "Randomly generated password for authenticating with Redis",
                      "defaultValue": "{{REDIS_PASSWORD}}"
                    }
                  },
                  "networking": {
                    "tcpProxies": {},
                    "serviceDomains": {}
                  },
                  "volumeMounts": {
                    "56365220-bbf5-5fa9-9b53-64ea7164a6d1": {
                      "mountPath": "/data"
                    }
                  }
                },
                "6fa66885-76bb-5840-b32b-ebed60db805a": {
                  "icon": "https://devicons.railway.app/i/postgresql.svg",
                  "name": "nuq-postgres",
                  "deploy": {
                    "startCommand": "docker-entrypoint.sh postgres -c max_wal_size=1GB -c min_wal_size=128MB -c wal_buffers=16MB",
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "ghcr.io/firecrawl/nuq-postgres:latest@sha256:9b638af78d99873bc0ba2b57c9cbcd01df6ce96efeaa72d36cfbe0f76521e8fc"
                  },
                  "variables": {
                    "PGDATA": {
                      "isOptional": true,
                      "description": "Data directory inside the volume (avoids the volume's lost+found).",
                      "defaultValue": "/var/lib/postgresql/data/pgdata"
                    },
                    "POSTGRES_DB": {
                      "isOptional": true,
                      "description": "Must stay 'postgres': the image configures cron.database_name = 'postgres' and installs the NuQ schema there.",
                      "defaultValue": "postgres"
                    },
                    "POSTGRES_USER": {
                      "isOptional": true,
                      "description": "Superuser created on first boot (pg_cron jobs run in the postgres database).",
                      "defaultValue": "postgres"
                    },
                    "POSTGRES_PASSWORD": {
                      "isOptional": true,
                      "description": "Database password, generated.",
                      "defaultValue": "{{POSTGRES_PASSWORD}}"
                    },
                    "RAILWAY_DEPLOYMENT_DRAINING_SECONDS": {
                      "isOptional": true,
                      "description": "Allow Postgres to shut down cleanly.",
                      "defaultValue": "60"
                    }
                  },
                  "networking": {
                    "tcpProxies": {},
                    "serviceDomains": {}
                  },
                  "volumeMounts": {
                    "86891de3-1a37-51c6-b590-3d9864e20ea2": {
                      "mountPath": "/var/lib/postgresql/data"
                    }
                  }
                },
                "95eb7e55-d773-5b8c-93cd-c475fbe90f87": {
                  "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/svg/firecrawl.svg",
                  "name": "firecrawl-api",
                  "deploy": {
                    "startCommand": "node dist/src/index.js",
                    "healthcheckPath": "/v0/health/readiness",
                    "restartPolicyType": "ON_FAILURE",
                    "healthcheckTimeout": 300,
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "ghcr.io/firecrawl/firecrawl:2.11.504"
                  },
                  "variables": {
                    "ENV": {
                      "isOptional": true,
                      "description": "Self-hosted mode (same value as the upstream docker-compose).",
                      "defaultValue": "local"
                    },
                    "HOST": {
                      "isOptional": true,
                      "description": "Bind address; :: accepts IPv4 and IPv6 from the gateway.",
                      "defaultValue": "::"
                    },
                    "PORT": {
                      "isOptional": true,
                      "description": "API port (private).",
                      "defaultValue": "3002"
                    },
                    "REDIS_URL": {
                      "isOptional": true,
                      "description": "Redis for BullMQ queues and crawl state.",
                      "defaultValue": "${{Redis.REDIS_URL}}"
                    },
                    "MODEL_NAME": {
                      "isOptional": true,
                      "description": "Optional. Model used for extraction (e.g. gpt-4o-mini).",
                      "defaultValue": ""
                    },
                    "PROXY_SERVER": {
                      "isOptional": true,
                      "description": "Optional. Outbound HTTP proxy for fetches (http://host:port).",
                      "defaultValue": ""
                    },
                    "BULL_AUTH_KEY": {
                      "isOptional": true,
                      "description": "Secret path segment for the queue dashboard: /admin/<BULL_AUTH_KEY>/queues.",
                      "defaultValue": "{{BULL_AUTH_KEY}}"
                    },
                    "LOGGING_LEVEL": {
                      "isOptional": true,
                      "description": "Log level.",
                      "defaultValue": "INFO"
                    },
                    "OPENAI_API_KEY": {
                      "isOptional": true,
                      "description": "Optional. Enables LLM features (JSON/extract formats, /extract). Leave empty to disable.",
                      "defaultValue": ""
                    },
                    "PROXY_PASSWORD": {
                      "isOptional": true,
                      "description": "Optional. Proxy password.",
                      "defaultValue": ""
                    },
                    "PROXY_USERNAME": {
                      "isOptional": true,
                      "description": "Optional. Proxy username.",
                      "defaultValue": ""
                    },
                    "OLLAMA_BASE_URL": {
                      "isOptional": true,
                      "description": "Optional (experimental upstream). Ollama API base URL instead of OpenAI.",
                      "defaultValue": ""
                    },
                    "OPENAI_BASE_URL": {
                      "isOptional": true,
                      "description": "Optional. OpenAI-compatible base URL (e.g. a LiteLLM gateway).",
                      "defaultValue": ""
                    },
                    "NUQ_DATABASE_URL": {
                      "isOptional": true,
                      "description": "NuQ job queue database (nuq-postgres, private network).",
                      "defaultValue": "postgresql://postgres:${{nuq-postgres.POSTGRES_PASSWORD}}@${{nuq-postgres.RAILWAY_PRIVATE_DOMAIN}}:5432/postgres"
                    },
                    "NUQ_RABBITMQ_URL": {
                      "isOptional": true,
                      "description": "RabbitMQ used by NuQ to wake workers when jobs arrive.",
                      "defaultValue": "amqp://firecrawl:${{RabbitMQ.RABBITMQ_DEFAULT_PASS}}@${{RabbitMQ.RAILWAY_PRIVATE_DOMAIN}}:5672"
                    },
                    "SEARXNG_ENDPOINT": {
                      "isOptional": true,
                      "description": "Optional. SearXNG instance (JSON enabled) for /search instead of direct Google.",
                      "defaultValue": ""
                    },
                    "BROWSER_POOL_SIZE": {
                      "isOptional": true,
                      "description": "Browser pool size (upstream default).",
                      "defaultValue": "5"
                    },
                    "MAX_CONCURRENT_JOBS": {
                      "isOptional": true,
                      "description": "Max concurrent jobs per team (upstream default).",
                      "defaultValue": "5"
                    },
                    "MODEL_EMBEDDING_NAME": {
                      "isOptional": true,
                      "description": "Optional. Embedding model name.",
                      "defaultValue": ""
                    },
                    "REDIS_RATE_LIMIT_URL": {
                      "isOptional": true,
                      "description": "Redis for rate limiting.",
                      "defaultValue": "${{Redis.REDIS_URL}}"
                    },
                    "NUM_WORKERS_PER_QUEUE": {
                      "isOptional": true,
                      "description": "BullMQ concurrency per queue (upstream default).",
                      "defaultValue": "8"
                    },
                    "USE_DB_AUTHENTICATION": {
                      "isOptional": true,
                      "description": "Supabase auth is not available for self-hosting; the firecrawl gateway enforces the API key instead.",
                      "defaultValue": "false"
                    },
                    "NUQ_DATABASE_URL_LISTEN": {
                      "isOptional": true,
                      "description": "Direct connection used for LISTEN/NOTIFY (same database).",
                      "defaultValue": "${{NUQ_DATABASE_URL}}"
                    },
                    "CRAWL_CONCURRENT_REQUESTS": {
                      "isOptional": true,
                      "description": "Concurrent requests per crawl (upstream default).",
                      "defaultValue": "10"
                    },
                    "PLAYWRIGHT_MICROSERVICE_URL": {
                      "isOptional": true,
                      "description": "Browser rendering service (private network).",
                      "defaultValue": "http://${{playwright-service.RAILWAY_PRIVATE_DOMAIN}}:3000/scrape"
                    },
                    "RAILWAY_DEPLOYMENT_DRAINING_SECONDS": {
                      "isOptional": true,
                      "description": "Let in-flight scrape requests finish during redeploys.",
                      "defaultValue": "60"
                    }
                  },
                  "networking": {
                    "tcpProxies": {},
                    "serviceDomains": {}
                  }
                },
                "c765706c-bdca-5518-b8f2-a2c13d8cf9d0": {
                  "icon": "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/caddy.svg",
                  "name": "firecrawl",
                  "build": {
                    "builder": "DOCKERFILE"
                  },
                  "deploy": {
                    "healthcheckPath": "/healthz",
                    "restartPolicyType": "ON_FAILURE",
                    "healthcheckTimeout": 60,
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "repo": "baranberkay96/firecrawl-railway",
                    "branch": "main",
                    "rootDirectory": "/services/gateway"
                  },
                  "variables": {
                    "PORT": {
                      "isOptional": true,
                      "description": "Gateway listen port (public domain target).",
                      "defaultValue": "8080"
                    },
                    "FIRECRAWL_API_KEY": {
                      "isOptional": true,
                      "description": "API key clients must send as 'Authorization: Bearer <key>'. Use it as the SDK api_key.",
                      "defaultValue": "{{FIRECRAWL_API_KEY}}"
                    },
                    "FIRECRAWL_UPSTREAM": {
                      "isOptional": true,
                      "description": "Private address of firecrawl-api.",
                      "defaultValue": "${{firecrawl-api.RAILWAY_PRIVATE_DOMAIN}}:3002"
                    }
                  },
                  "networking": {
                    "tcpProxies": {},
                    "serviceDomains": {
                      "<hasDomain>:8080": {
                        "port": 8080
                      }
                    }
                  }
                },
                "e4936c8d-e53f-51a0-afd2-246d776403b0": {
                  "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/svg/firecrawl.svg",
                  "name": "firecrawl-worker",
                  "build": {
                    "builder": "DOCKERFILE"
                  },
                  "deploy": {
                    "healthcheckPath": "/liveness",
                    "restartPolicyType": "ON_FAILURE",
                    "healthcheckTimeout": 300,
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "repo": "baranberkay96/firecrawl-railway",
                    "branch": "main",
                    "rootDirectory": "/services/firecrawl-workers"
                  },
                  "variables": {
                    "ENV": {
                      "isOptional": true,
                      "description": "Self-hosted mode (same value as the upstream docker-compose).",
                      "defaultValue": "local"
                    },
                    "PORT": {
                      "isOptional": true,
                      "description": "Liveness port of the queue-worker (Railway healthcheck).",
                      "defaultValue": "3005"
                    },
                    "REDIS_URL": {
                      "isOptional": true,
                      "description": "Redis for BullMQ queues and crawl state.",
                      "defaultValue": "${{Redis.REDIS_URL}}"
                    },
                    "MODEL_NAME": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (MODEL_NAME).",
                      "defaultValue": "${{firecrawl-api.MODEL_NAME}}"
                    },
                    "WORKER_PORT": {
                      "isOptional": true,
                      "description": "queue-worker liveness port.",
                      "defaultValue": "3005"
                    },
                    "PROXY_SERVER": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (PROXY_SERVER).",
                      "defaultValue": "${{firecrawl-api.PROXY_SERVER}}"
                    },
                    "BULL_AUTH_KEY": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (BULL_AUTH_KEY).",
                      "defaultValue": "${{firecrawl-api.BULL_AUTH_KEY}}"
                    },
                    "IS_KUBERNETES": {
                      "isOptional": true,
                      "description": "Use container (cgroup v2) CPU/RAM figures for job back-pressure instead of host-wide numbers.",
                      "defaultValue": "true"
                    },
                    "LOGGING_LEVEL": {
                      "isOptional": true,
                      "description": "Log level.",
                      "defaultValue": "INFO"
                    },
                    "OPENAI_API_KEY": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (OPENAI_API_KEY).",
                      "defaultValue": "${{firecrawl-api.OPENAI_API_KEY}}"
                    },
                    "PROXY_PASSWORD": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (PROXY_PASSWORD).",
                      "defaultValue": "${{firecrawl-api.PROXY_PASSWORD}}"
                    },
                    "PROXY_USERNAME": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (PROXY_USERNAME).",
                      "defaultValue": "${{firecrawl-api.PROXY_USERNAME}}"
                    },
                    "OLLAMA_BASE_URL": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (OLLAMA_BASE_URL).",
                      "defaultValue": "${{firecrawl-api.OLLAMA_BASE_URL}}"
                    },
                    "OPENAI_BASE_URL": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (OPENAI_BASE_URL).",
                      "defaultValue": "${{firecrawl-api.OPENAI_BASE_URL}}"
                    },
                    "NUQ_DATABASE_URL": {
                      "isOptional": true,
                      "description": "NuQ job queue database (nuq-postgres, private network).",
                      "defaultValue": "postgresql://postgres:${{nuq-postgres.POSTGRES_PASSWORD}}@${{nuq-postgres.RAILWAY_PRIVATE_DOMAIN}}:5432/postgres"
                    },
                    "NUQ_RABBITMQ_URL": {
                      "isOptional": true,
                      "description": "RabbitMQ used by NuQ to wake workers when jobs arrive.",
                      "defaultValue": "amqp://firecrawl:${{RabbitMQ.RABBITMQ_DEFAULT_PASS}}@${{RabbitMQ.RAILWAY_PRIVATE_DOMAIN}}:5672"
                    },
                    "SEARXNG_ENDPOINT": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (SEARXNG_ENDPOINT).",
                      "defaultValue": "${{firecrawl-api.SEARXNG_ENDPOINT}}"
                    },
                    "BROWSER_POOL_SIZE": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (BROWSER_POOL_SIZE).",
                      "defaultValue": "${{firecrawl-api.BROWSER_POOL_SIZE}}"
                    },
                    "EXTRACT_WORKER_PORT": {
                      "isOptional": true,
                      "description": "extract-worker health port.",
                      "defaultValue": "3004"
                    },
                    "MAX_CONCURRENT_JOBS": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (MAX_CONCURRENT_JOBS).",
                      "defaultValue": "${{firecrawl-api.MAX_CONCURRENT_JOBS}}"
                    },
                    "MODEL_EMBEDDING_NAME": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (MODEL_EMBEDDING_NAME).",
                      "defaultValue": "${{firecrawl-api.MODEL_EMBEDDING_NAME}}"
                    },
                    "REDIS_RATE_LIMIT_URL": {
                      "isOptional": true,
                      "description": "Redis for rate limiting.",
                      "defaultValue": "${{Redis.REDIS_URL}}"
                    },
                    "FIRECRAWL_WORKER_ROLE": {
                      "isOptional": true,
                      "description": "Process group run by services/firecrawl-workers/railway-workers.sh: queue-worker, extract-worker, NuQ prefetch and reconciler.",
                      "defaultValue": "worker"
                    },
                    "NUM_WORKERS_PER_QUEUE": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (NUM_WORKERS_PER_QUEUE).",
                      "defaultValue": "${{firecrawl-api.NUM_WORKERS_PER_QUEUE}}"
                    },
                    "USE_DB_AUTHENTICATION": {
                      "isOptional": true,
                      "description": "Supabase auth is not available for self-hosting; the firecrawl gateway enforces the API key instead.",
                      "defaultValue": "false"
                    },
                    "NUQ_DATABASE_URL_LISTEN": {
                      "isOptional": true,
                      "description": "Direct connection used for LISTEN/NOTIFY (same database).",
                      "defaultValue": "${{NUQ_DATABASE_URL}}"
                    },
                    "NUQ_PREFETCH_WORKER_PORT": {
                      "isOptional": true,
                      "description": "NuQ prefetch worker health port.",
                      "defaultValue": "3011"
                    },
                    "CRAWL_CONCURRENT_REQUESTS": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (CRAWL_CONCURRENT_REQUESTS).",
                      "defaultValue": "${{firecrawl-api.CRAWL_CONCURRENT_REQUESTS}}"
                    },
                    "NUQ_RECONCILER_WORKER_PORT": {
                      "isOptional": true,
                      "description": "NuQ reconciler health port.",
                      "defaultValue": "3012"
                    },
                    "PLAYWRIGHT_MICROSERVICE_URL": {
                      "isOptional": true,
                      "description": "Browser rendering service (private network).",
                      "defaultValue": "http://${{playwright-service.RAILWAY_PRIVATE_DOMAIN}}:3000/scrape"
                    },
                    "RAILWAY_DEPLOYMENT_DRAINING_SECONDS": {
                      "isOptional": true,
                      "description": "Let running jobs finish during redeploys.",
                      "defaultValue": "60"
                    }
                  },
                  "networking": {
                    "tcpProxies": {},
                    "serviceDomains": {}
                  }
                },
                "eb229f86-488c-502b-a375-3f3f17307f53": {
                  "icon": "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/rabbitmq.svg",
                  "name": "RabbitMQ",
                  "deploy": {
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "rabbitmq:4.3.6-alpine"
                  },
                  "variables": {
                    "RABBITMQ_DEFAULT_PASS": {
                      "isOptional": true,
                      "description": "RabbitMQ password, generated.",
                      "defaultValue": "{{RABBITMQ_DEFAULT_PASS}}"
                    },
                    "RABBITMQ_DEFAULT_USER": {
                      "isOptional": true,
                      "description": "RabbitMQ user for NuQ.",
                      "defaultValue": "firecrawl"
                    }
                  },
                  "networking": {
                    "tcpProxies": {},
                    "serviceDomains": {}
                  }
                },
                "f9e51be5-98bd-5f07-8790-d6910204481e": {
                  "icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/svg/firecrawl.svg",
                  "name": "firecrawl-nuq-worker",
                  "build": {
                    "builder": "DOCKERFILE"
                  },
                  "deploy": {
                    "healthcheckPath": "/health",
                    "restartPolicyType": "ON_FAILURE",
                    "healthcheckTimeout": 300,
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "repo": "baranberkay96/firecrawl-railway",
                    "branch": "main",
                    "rootDirectory": "/services/firecrawl-workers"
                  },
                  "variables": {
                    "ENV": {
                      "isOptional": true,
                      "description": "Self-hosted mode (same value as the upstream docker-compose).",
                      "defaultValue": "local"
                    },
                    "PORT": {
                      "isOptional": true,
                      "description": "Health port of the first executor (Railway healthcheck).",
                      "defaultValue": "3006"
                    },
                    "REDIS_URL": {
                      "isOptional": true,
                      "description": "Redis for BullMQ queues and crawl state.",
                      "defaultValue": "${{Redis.REDIS_URL}}"
                    },
                    "MODEL_NAME": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (MODEL_NAME).",
                      "defaultValue": "${{firecrawl-api.MODEL_NAME}}"
                    },
                    "PROXY_SERVER": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (PROXY_SERVER).",
                      "defaultValue": "${{firecrawl-api.PROXY_SERVER}}"
                    },
                    "BULL_AUTH_KEY": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (BULL_AUTH_KEY).",
                      "defaultValue": "${{firecrawl-api.BULL_AUTH_KEY}}"
                    },
                    "LOGGING_LEVEL": {
                      "isOptional": true,
                      "description": "Log level.",
                      "defaultValue": "INFO"
                    },
                    "OPENAI_API_KEY": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (OPENAI_API_KEY).",
                      "defaultValue": "${{firecrawl-api.OPENAI_API_KEY}}"
                    },
                    "PROXY_PASSWORD": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (PROXY_PASSWORD).",
                      "defaultValue": "${{firecrawl-api.PROXY_PASSWORD}}"
                    },
                    "PROXY_USERNAME": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (PROXY_USERNAME).",
                      "defaultValue": "${{firecrawl-api.PROXY_USERNAME}}"
                    },
                    "OLLAMA_BASE_URL": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (OLLAMA_BASE_URL).",
                      "defaultValue": "${{firecrawl-api.OLLAMA_BASE_URL}}"
                    },
                    "OPENAI_BASE_URL": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (OPENAI_BASE_URL).",
                      "defaultValue": "${{firecrawl-api.OPENAI_BASE_URL}}"
                    },
                    "NUQ_DATABASE_URL": {
                      "isOptional": true,
                      "description": "NuQ job queue database (nuq-postgres, private network).",
                      "defaultValue": "postgresql://postgres:${{nuq-postgres.POSTGRES_PASSWORD}}@${{nuq-postgres.RAILWAY_PRIVATE_DOMAIN}}:5432/postgres"
                    },
                    "NUQ_RABBITMQ_URL": {
                      "isOptional": true,
                      "description": "RabbitMQ used by NuQ to wake workers when jobs arrive.",
                      "defaultValue": "amqp://firecrawl:${{RabbitMQ.RABBITMQ_DEFAULT_PASS}}@${{RabbitMQ.RAILWAY_PRIVATE_DOMAIN}}:5672"
                    },
                    "NUQ_WORKER_COUNT": {
                      "isOptional": true,
                      "description": "Scrape executor processes in this container (upstream harness default 5). Each handles one job at a time.",
                      "defaultValue": "5"
                    },
                    "SEARXNG_ENDPOINT": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (SEARXNG_ENDPOINT).",
                      "defaultValue": "${{firecrawl-api.SEARXNG_ENDPOINT}}"
                    },
                    "BROWSER_POOL_SIZE": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (BROWSER_POOL_SIZE).",
                      "defaultValue": "${{firecrawl-api.BROWSER_POOL_SIZE}}"
                    },
                    "MAX_CONCURRENT_JOBS": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (MAX_CONCURRENT_JOBS).",
                      "defaultValue": "${{firecrawl-api.MAX_CONCURRENT_JOBS}}"
                    },
                    "MODEL_EMBEDDING_NAME": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (MODEL_EMBEDDING_NAME).",
                      "defaultValue": "${{firecrawl-api.MODEL_EMBEDDING_NAME}}"
                    },
                    "REDIS_RATE_LIMIT_URL": {
                      "isOptional": true,
                      "description": "Redis for rate limiting.",
                      "defaultValue": "${{Redis.REDIS_URL}}"
                    },
                    "FIRECRAWL_WORKER_ROLE": {
                      "isOptional": true,
                      "description": "Runs NUQ_WORKER_COUNT scrape-executor processes (services/firecrawl-workers/railway-workers.sh).",
                      "defaultValue": "nuq-worker"
                    },
                    "NUM_WORKERS_PER_QUEUE": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (NUM_WORKERS_PER_QUEUE).",
                      "defaultValue": "${{firecrawl-api.NUM_WORKERS_PER_QUEUE}}"
                    },
                    "NUQ_WORKER_START_PORT": {
                      "isOptional": true,
                      "description": "First health port; process i listens on start+i.",
                      "defaultValue": "3006"
                    },
                    "USE_DB_AUTHENTICATION": {
                      "isOptional": true,
                      "description": "Supabase auth is not available for self-hosting; the firecrawl gateway enforces the API key instead.",
                      "defaultValue": "false"
                    },
                    "NUQ_DATABASE_URL_LISTEN": {
                      "isOptional": true,
                      "description": "Direct connection used for LISTEN/NOTIFY (same database).",
                      "defaultValue": "${{NUQ_DATABASE_URL}}"
                    },
                    "CRAWL_CONCURRENT_REQUESTS": {
                      "isOptional": true,
                      "description": "Shared with firecrawl-api (CRAWL_CONCURRENT_REQUESTS).",
                      "defaultValue": "${{firecrawl-api.CRAWL_CONCURRENT_REQUESTS}}"
                    },
                    "PLAYWRIGHT_MICROSERVICE_URL": {
                      "isOptional": true,
                      "description": "Browser rendering service (private network).",
                      "defaultValue": "http://${{playwright-service.RAILWAY_PRIVATE_DOMAIN}}:3000/scrape"
                    },
                    "RAILWAY_DEPLOYMENT_DRAINING_SECONDS": {
                      "isOptional": true,
                      "description": "Let running scrapes finish during redeploys.",
                      "defaultValue": "60"
                    }
                  },
                  "networking": {
                    "tcpProxies": {},
                    "serviceDomains": {}
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "post_deploy": {
    "healthcheck": {
      "service": "firecrawl",
      "method": "GET",
      "path": "/healthz",
      "expect_status": 200
    }
  },
  "resources": {
    "expected_services": 8,
    "needs_volume": true
  },
  "generated_at": "2026-10-11T16:14:40.554Z",
  "generator_version": "0.1.0",
  "status": "validated",
  "validated_at": "2026-10-11T14:41:13.577Z",
  "success_rate_30d": 1,
  "validation": {
    "last_run_id": "run_323b7ac32d8546f58b2b",
    "checks": [
      {
        "name": "workflow_completed",
        "passed": true
      },
      {
        "name": "all_services_deployed",
        "passed": true
      },
      {
        "name": "healthcheck",
        "passed": true
      },
      {
        "name": "stays_up",
        "passed": true
      }
    ],
    "typical_ready_seconds": 150,
    "typical_build_seconds": 50,
    "typical_start_seconds": 30,
    "slowest_service": "firecrawl-nuq-worker"
  }
}
