{
  "manifest_version": "1.0.0",
  "template": {
    "id": "cdec193b-cc2e-4188-b1a5-cf33901f4df3",
    "slug": "skyvern-browser-agent-auth-gateway",
    "name": "Skyvern Browser Agent + Auth Gateway",
    "description": "Skyvern browser agent with a password protected UI gateway",
    "url": "https://railway.com/deploy/skyvern-browser-agent-auth-gateway",
    "upstream": {
      "image": "public.ecr.aws/skyvern/skyvern:v1.0.53"
    }
  },
  "services": [
    {
      "name": "skyvern-ui",
      "source": {
        "image": "public.ecr.aws/skyvern/skyvern-ui:v1.0.53"
      },
      "needs_volume": false,
      "http": false
    },
    {
      "name": "Postgres",
      "source": {
        "image": "ghcr.io/railwayapp-templates/postgres-ssl:17"
      },
      "needs_volume": true,
      "volume_mount_path": "/var/lib/postgresql/data",
      "tcp_ports": [
        5432
      ],
      "http": false
    },
    {
      "name": "Skyvern",
      "source": {
        "image": "public.ecr.aws/skyvern/skyvern:v1.0.53"
      },
      "needs_volume": true,
      "volume_mount_path": "/data",
      "http": true
    },
    {
      "name": "skyvern-gateway",
      "source": {
        "image": "caddy:2.11-alpine"
      },
      "needs_volume": false,
      "http": true
    }
  ],
  "required_inputs": [
    {
      "key": "PORT",
      "service": "skyvern-ui",
      "description": "The bundled static server hardcodes port 8080; this variable exists so Railway's healthcheck and edge proxy probe 8080 as well. Do not change it.",
      "secret": false,
      "strategy": "default",
      "default": "8080"
    },
    {
      "key": "VITE_API_BASE_URL",
      "service": "skyvern-ui",
      "description": "API address baked into the browser bundle at container start. Must be the public HTTPS URL of the Skyvern service. Update it if you attach a custom domain.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_domain"
    },
    {
      "key": "VITE_WSS_BASE_URL",
      "service": "skyvern-ui",
      "description": "Websocket address for the live browser view and streaming logs. Same host as VITE_API_BASE_URL with the wss scheme.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_domain"
    },
    {
      "key": "SKYVERN_API_BASE_URL",
      "service": "skyvern-ui",
      "description": "API address used by the UI server itself. It has to be the public HTTPS URL: the Skyvern API binds 0.0.0.0 (IPv4 only), so it is not reachable over Railway's IPv6 private network.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_domain"
    },
    {
      "key": "VITE_ENABLE_CODE_BLOCK",
      "service": "skyvern-ui",
      "description": "Shows the code block node in the workflow editor. Keep it equal to ENABLE_CODE_BLOCK on the Skyvern service.",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "VITE_ENABLE_LOG_ARTIFACTS",
      "service": "skyvern-ui",
      "description": "Shows per-run log artifacts in the UI. Only useful when ENABLE_LOG_ARTIFACTS is also true on the Skyvern service.",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "VITE_BROWSER_STREAMING_MODE",
      "service": "skyvern-ui",
      "description": "Live browser view transport in the browser. Keep it equal to BROWSER_STREAMING_MODE on the Skyvern service.",
      "secret": false,
      "strategy": "default",
      "default": "cdp"
    },
    {
      "key": "VITE_ENABLE_2FA_NOTIFICATIONS",
      "service": "skyvern-ui",
      "description": "Toasts, sounds and websocket streaming for 2FA verification codes. Set to false for high task volume.",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "PGDATA",
      "service": "Postgres",
      "description": "Provide a value for PGDATA.",
      "secret": false,
      "strategy": "default",
      "default": "/var/lib/postgresql/data/pgdata"
    },
    {
      "key": "PGHOST",
      "service": "Postgres",
      "description": "Provide a value for PGHOST.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "PGPORT",
      "service": "Postgres",
      "description": "Provide a value for PGPORT.",
      "secret": false,
      "strategy": "default",
      "default": "5432"
    },
    {
      "key": "PGUSER",
      "service": "Postgres",
      "description": "Provide a value for PGUSER.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "PGDATABASE",
      "service": "Postgres",
      "description": "Provide a value for PGDATABASE.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "PGPASSWORD",
      "service": "Postgres",
      "description": "Provide a value for PGPASSWORD.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "POSTGRES_DB",
      "service": "Postgres",
      "description": "Database name.",
      "secret": false,
      "strategy": "default",
      "default": "skyvern"
    },
    {
      "key": "DATABASE_URL",
      "service": "Postgres",
      "description": "Private-network connection string (IPv6, includes port).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "POSTGRES_USER",
      "service": "Postgres",
      "description": "Database superuser.",
      "secret": false,
      "strategy": "default",
      "default": "skyvern"
    },
    {
      "key": "SSL_CERT_DAYS",
      "service": "Postgres",
      "description": "Provide a value for SSL_CERT_DAYS.",
      "secret": false,
      "strategy": "default",
      "default": "820"
    },
    {
      "key": "POSTGRES_PASSWORD",
      "service": "Postgres",
      "description": "Generated database password.",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "DATABASE_PUBLIC_URL",
      "service": "Postgres",
      "description": "Public URL via the TCP proxy (for psql / GUI clients).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "DATABASE_PRIVATE_URL",
      "service": "Postgres",
      "description": "Provide a value for DATABASE_PRIVATE_URL.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "RAILWAY_DEPLOYMENT_DRAINING_SECONDS",
      "service": "Postgres",
      "description": "Provide a value for RAILWAY_DEPLOYMENT_DRAINING_SECONDS.",
      "secret": false,
      "strategy": "default",
      "default": "60"
    },
    {
      "key": "ENV",
      "service": "Skyvern",
      "description": "Self-hosted deployment mode, exactly as upstream docker-compose runs it. Live browser view and the local credential vault take the self-hosted code paths only when this is local. Uvicorn auto-reload is turned off separately by SKYVERN_DEV_NO_RELOAD.",
      "secret": false,
      "strategy": "default",
      "default": "local"
    },
    {
      "key": "PORT",
      "service": "Skyvern",
      "description": "API listen port. uvicorn reads PORT and Railway probes $PORT for the healthcheck, so keep it equal to the domain target port (8000).",
      "secret": false,
      "strategy": "default",
      "default": "8000"
    },
    {
      "key": "LLM_KEY",
      "service": "Skyvern",
      "description": "Which registered model the agent uses. Other valid values include OPENAI_GPT5_4, ANTHROPIC_CLAUDE5_OPUS and GEMINI_3_PRO; the provider for the key you pick must be enabled.",
      "secret": true,
      "strategy": "default",
      "default": "OPENAI_GPT5_5"
    },
    {
      "key": "LOG_LEVEL",
      "service": "Skyvern",
      "description": "Application log level. Use DEBUG when diagnosing a failing run.",
      "secret": false,
      "strategy": "default",
      "default": "INFO"
    },
    {
      "key": "SECRET_KEY",
      "service": "Skyvern",
      "description": "Signs the organization API keys (HS256 JWTs). Generated once. Rotating it invalidates every API key that was already issued, including the one the Skyvern UI service uses.",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "BROWSER_TYPE",
      "service": "Skyvern",
      "description": "The browser runs inside this container on a virtual X display (Xvfb + x11vnc), exactly as in upstream docker-compose. No separate browser service is needed. Use chromium-headless only if you do not need the live browser view.",
      "secret": false,
      "strategy": "default",
      "default": "chromium-headful"
    },
    {
      "key": "ENABLE_OPENAI",
      "service": "Skyvern",
      "description": "Registers the OpenAI models in the LLM registry. Set it to false and enable another provider if you switch LLM_KEY.",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "OPENAI_API_KEY",
      "service": "Skyvern",
      "description": "Required. Your OpenAI API key. Skyvern boots without it but every task and workflow run fails, because the agent falls back to a dummy LLM handler. To use a different provider instead, leave this blank, set ENABLE_OPENAI=false and configure that provider plus LLM_KEY.",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "DATABASE_STRING",
      "service": "Skyvern",
      "description": "Postgres connection string over the private network. Skyvern needs the postgresql+psycopg:// driver prefix, so this is built by hand instead of reusing DATABASE_PRIVATE_URL. Alembic migrations run on every boot.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "ENABLE_ANTHROPIC",
      "service": "Skyvern",
      "description": "Optional. Set to true together with ANTHROPIC_API_KEY and an ANTHROPIC_* LLM_KEY to run the agent on Claude instead of OpenAI.",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "ENABLE_CODE_BLOCK",
      "service": "Skyvern",
      "description": "Enables the code block node in workflows, as in upstream docker-compose.",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "MAX_STEPS_PER_RUN",
      "service": "Skyvern",
      "description": "Upper bound on agent steps per run. Lower it to cap LLM spend per task.",
      "secret": false,
      "strategy": "default",
      "default": "50"
    },
    {
      "key": "SECONDARY_LLM_KEY",
      "service": "Skyvern",
      "description": "Cheaper model used for small helper calls such as option selection and SVG conversion. Leave blank to reuse LLM_KEY.",
      "secret": true,
      "strategy": "default",
      "default": "OPENAI_GPT5_4_MINI"
    },
    {
      "key": "SKYVERN_TELEMETRY",
      "service": "Skyvern",
      "description": "Upstream anonymous usage analytics. Set to false to disable.",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "CREDENTIAL_VAULT_TYPE",
      "service": "Skyvern",
      "description": "Use the built-in encrypted credential vault. The encryption key is generated into /data/credential_vault/.fernet_key on the volume, so treat the volume as secret material.",
      "secret": false,
      "strategy": "default",
      "default": "skyvern"
    },
    {
      "key": "SKYVERN_DEV_NO_RELOAD",
      "service": "Skyvern",
      "description": "Disables uvicorn's file-watching auto-reload supervisor, which ENV=local would otherwise switch on. Leave it true: the reloader doubles memory use and can wedge on long browser cleanups.",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "SKYVERN_PRINT_API_KEY",
      "service": "Skyvern",
      "description": "Prints the generated organization API key into this service's deploy logs once the credentials file exists, so you can copy it into the Skyvern UI service. Set it to false after you have copied the key if you do not want it in the logs.",
      "secret": true,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "BROWSER_STREAMING_MODE",
      "service": "Skyvern",
      "description": "Live browser view transport. cdp streams through this service's own websocket, so no extra port has to be exposed. Must match VITE_BROWSER_STREAMING_MODE on the Skyvern UI service.",
      "secret": false,
      "strategy": "default",
      "default": "cdp"
    },
    {
      "key": "SKYVERN_CREDENTIALS_FILE",
      "service": "Skyvern",
      "description": "Where the generated organization API key is stored. It must live on the volume: if the file is missing at boot Skyvern creates a brand new organization and API key, so an ephemeral path would orphan your workflows on every redeploy.",
      "secret": false,
      "strategy": "default",
      "default": "/data/.skyvern/credentials.toml"
    },
    {
      "key": "ENABLE_LOCAL_CREDENTIAL_VAULT",
      "service": "Skyvern",
      "description": "Stores workflow credentials in the built-in vault on the volume instead of Bitwarden or a cloud secret manager.",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "PORT",
      "service": "skyvern-gateway",
      "description": "Port the gateway listens on.",
      "secret": false,
      "strategy": "default",
      "default": "8080"
    },
    {
      "key": "UPSTREAM",
      "service": "skyvern-gateway",
      "description": "Private address of the Skyvern UI service.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "UI_PASSWORD",
      "service": "skyvern-gateway",
      "description": "Password for the Skyvern UI login prompt. Generated on deploy, change it here at any time.",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "UI_USERNAME",
      "service": "skyvern-gateway",
      "description": "Username for the Skyvern UI login prompt.",
      "secret": false,
      "strategy": "default",
      "default": "admin"
    }
  ],
  "deploy": {
    "mcp": {
      "server": "railway",
      "tool": "deploy_template",
      "args": {
        "template_code": "skyvern-browser-agent-auth-gateway"
      }
    },
    "cli": "railway deploy --template skyvern-browser-agent-auth-gateway",
    "api": {
      "method": "POST",
      "path": "/graphql/v2",
      "body": {
        "query": "mutation templateDeploy($input: TemplateDeployV2Input!) { templateDeployV2(input: $input) { projectId workflowId } }",
        "variables": {
          "input": {
            "templateId": "cdec193b-cc2e-4188-b1a5-cf33901f4df3",
            "serializedConfig": {
              "services": {
                "2cd219ec-d726-47b2-a602-026ff18f6a32": {
                  "icon": "https://raw.githubusercontent.com/Skyvern-AI/skyvern/v1.0.53/skyvern-frontend/public/logo-small.png",
                  "name": "skyvern-ui",
                  "deploy": {
                    "restartPolicyType": "ON_FAILURE",
                    "healthcheckTimeout": 300,
                    "restartPolicyMaxRetries": 5
                  },
                  "source": {
                    "image": "public.ecr.aws/skyvern/skyvern-ui:v1.0.53"
                  },
                  "variables": {
                    "PORT": {
                      "description": "The bundled static server hardcodes port 8080; this variable exists so Railway's healthcheck and edge proxy probe 8080 as well. Do not change it.",
                      "defaultValue": "8080"
                    },
                    "SKYVERN_API_KEY": {
                      "isOptional": true,
                      "description": "Organization API key the UI uses to mint short-lived browser sessions. Leave blank on the first deploy, then copy the cred value printed in the Skyvern service deploy logs (or read /data/.skyvern/credentials.toml) and paste it here. Until it is set the dashboard loads but every API call is rejected, which also means an unset key keeps the public UI inert.",
                      "defaultValue": ""
                    },
                    "VITE_API_BASE_URL": {
                      "description": "API address baked into the browser bundle at container start. Must be the public HTTPS URL of the Skyvern service. Update it if you attach a custom domain.",
                      "defaultValue": "https://${{Skyvern.RAILWAY_PUBLIC_DOMAIN}}/api/v1"
                    },
                    "VITE_WSS_BASE_URL": {
                      "description": "Websocket address for the live browser view and streaming logs. Same host as VITE_API_BASE_URL with the wss scheme.",
                      "defaultValue": "wss://${{Skyvern.RAILWAY_PUBLIC_DOMAIN}}/api/v1"
                    },
                    "SKYVERN_API_BASE_URL": {
                      "description": "API address used by the UI server itself. It has to be the public HTTPS URL: the Skyvern API binds 0.0.0.0 (IPv4 only), so it is not reachable over Railway's IPv6 private network.",
                      "defaultValue": "https://${{Skyvern.RAILWAY_PUBLIC_DOMAIN}}/api/v1"
                    },
                    "VITE_ENABLE_CODE_BLOCK": {
                      "description": "Shows the code block node in the workflow editor. Keep it equal to ENABLE_CODE_BLOCK on the Skyvern service.",
                      "defaultValue": "true"
                    },
                    "VITE_ENABLE_LOG_ARTIFACTS": {
                      "isOptional": true,
                      "description": "Shows per-run log artifacts in the UI. Only useful when ENABLE_LOG_ARTIFACTS is also true on the Skyvern service.",
                      "defaultValue": "false"
                    },
                    "VITE_ARTIFACT_API_BASE_URL": {
                      "isOptional": true,
                      "description": "Optional. Base URL of the file-backed artifact server used to render screenshots and recordings stored as local files. Railway cannot share the Skyvern volume with this service, so leave it blank and set SKYVERN_STORAGE_TYPE=s3 (or gcs/azureblob) on the Skyvern service if you want stored screenshots and recordings to render.",
                      "defaultValue": ""
                    },
                    "VITE_BROWSER_STREAMING_MODE": {
                      "description": "Live browser view transport in the browser. Keep it equal to BROWSER_STREAMING_MODE on the Skyvern service.",
                      "defaultValue": "cdp"
                    },
                    "VITE_ENABLE_2FA_NOTIFICATIONS": {
                      "isOptional": true,
                      "description": "Toasts, sounds and websocket streaming for 2FA verification codes. Set to false for high task volume.",
                      "defaultValue": "true"
                    }
                  },
                  "networking": {
                    "tcpProxies": {},
                    "serviceDomains": {}
                  }
                },
                "50be234b-1137-4ba4-802f-a50bf3f6c465": {
                  "icon": "https://devicons.railway.app/i/postgresql.svg",
                  "name": "Postgres",
                  "build": {},
                  "deploy": {
                    "requiredMountPath": "/var/lib/postgresql/data"
                  },
                  "source": {
                    "image": "ghcr.io/railwayapp-templates/postgres-ssl:17"
                  },
                  "variables": {
                    "PGDATA": {
                      "defaultValue": "/var/lib/postgresql/data/pgdata"
                    },
                    "PGHOST": {
                      "defaultValue": "${{RAILWAY_PRIVATE_DOMAIN}}"
                    },
                    "PGPORT": {
                      "defaultValue": "5432"
                    },
                    "PGUSER": {
                      "defaultValue": "${{POSTGRES_USER}}"
                    },
                    "PGDATABASE": {
                      "defaultValue": "${{POSTGRES_DB}}"
                    },
                    "PGPASSWORD": {
                      "defaultValue": "${{POSTGRES_PASSWORD}}"
                    },
                    "POSTGRES_DB": {
                      "description": "Database name.",
                      "defaultValue": "skyvern"
                    },
                    "DATABASE_URL": {
                      "description": "Private-network connection string (IPv6, includes port).",
                      "defaultValue": "postgresql://${{PGUSER}}:${{POSTGRES_PASSWORD}}@${{RAILWAY_PRIVATE_DOMAIN}}:5432/${{PGDATABASE}}"
                    },
                    "POSTGRES_USER": {
                      "description": "Database superuser.",
                      "defaultValue": "skyvern"
                    },
                    "SSL_CERT_DAYS": {
                      "isOptional": true,
                      "defaultValue": "820"
                    },
                    "POSTGRES_PASSWORD": {
                      "description": "Generated database password.",
                      "defaultValue": "{{POSTGRES_PASSWORD}}"
                    },
                    "DATABASE_PUBLIC_URL": {
                      "description": "Public URL via the TCP proxy (for psql / GUI clients).",
                      "defaultValue": "postgresql://${{PGUSER}}:${{POSTGRES_PASSWORD}}@${{RAILWAY_TCP_PROXY_DOMAIN}}:${{RAILWAY_TCP_PROXY_PORT}}/${{PGDATABASE}}"
                    },
                    "DATABASE_PRIVATE_URL": {
                      "defaultValue": "postgresql://${{PGUSER}}:${{POSTGRES_PASSWORD}}@${{RAILWAY_PRIVATE_DOMAIN}}:5432/${{PGDATABASE}}"
                    },
                    "RAILWAY_DEPLOYMENT_DRAINING_SECONDS": {
                      "isOptional": true,
                      "defaultValue": "60"
                    }
                  },
                  "networking": {
                    "tcpProxies": {
                      "5432": {}
                    },
                    "serviceDomains": {}
                  },
                  "volumeMounts": {
                    "67e6d399-e559-4dfd-897c-47a422e6aecb": {
                      "mountPath": "/var/lib/postgresql/data"
                    }
                  }
                },
                "725f108f-ee94-491d-9701-04efbd8a1021": {
                  "icon": "https://raw.githubusercontent.com/Skyvern-AI/skyvern/v1.0.53/skyvern-frontend/public/logo-small.png",
                  "name": "Skyvern",
                  "deploy": {
                    "startCommand": "sh -c 'if [ \"$SKYVERN_PRINT_API_KEY\" = \"true\" ]; then (i=0; while [ $i -lt 90 ]; do i=$((i+1)); sleep 10; if [ -s \"$SKYVERN_CREDENTIALS_FILE\" ]; then echo \"===== Skyvern API key: copy the cred value below into SKYVERN_API_KEY on the Skyvern UI service =====\"; cat \"$SKYVERN_CREDENTIALS_FILE\"; echo \"===== end Skyvern API key =====\"; break; fi; done) & fi; exec /bin/bash /app/entrypoint-skyvern.sh'",
                    "healthcheckPath": "/api/v1/heartbeat",
                    "requiredMountPath": "/data",
                    "restartPolicyType": "ON_FAILURE",
                    "healthcheckTimeout": 300,
                    "restartPolicyMaxRetries": 5
                  },
                  "source": {
                    "image": "public.ecr.aws/skyvern/skyvern:v1.0.53"
                  },
                  "variables": {
                    "ENV": {
                      "description": "Self-hosted deployment mode, exactly as upstream docker-compose runs it. Live browser view and the local credential vault take the self-hosted code paths only when this is local. Uvicorn auto-reload is turned off separately by SKYVERN_DEV_NO_RELOAD.",
                      "defaultValue": "local"
                    },
                    "PORT": {
                      "description": "API listen port. uvicorn reads PORT and Railway probes $PORT for the healthcheck, so keep it equal to the domain target port (8000).",
                      "defaultValue": "8000"
                    },
                    "LLM_KEY": {
                      "description": "Which registered model the agent uses. Other valid values include OPENAI_GPT5_4, ANTHROPIC_CLAUDE5_OPUS and GEMINI_3_PRO; the provider for the key you pick must be enabled.",
                      "defaultValue": "OPENAI_GPT5_5"
                    },
                    "LOG_LEVEL": {
                      "isOptional": true,
                      "description": "Application log level. Use DEBUG when diagnosing a failing run.",
                      "defaultValue": "INFO"
                    },
                    "SECRET_KEY": {
                      "description": "Signs the organization API keys (HS256 JWTs). Generated once. Rotating it invalidates every API key that was already issued, including the one the Skyvern UI service uses.",
                      "defaultValue": "{{SECRET_KEY}}"
                    },
                    "BROWSER_TYPE": {
                      "description": "The browser runs inside this container on a virtual X display (Xvfb + x11vnc), exactly as in upstream docker-compose. No separate browser service is needed. Use chromium-headless only if you do not need the live browser view.",
                      "defaultValue": "chromium-headful"
                    },
                    "ENABLE_OPENAI": {
                      "description": "Registers the OpenAI models in the LLM registry. Set it to false and enable another provider if you switch LLM_KEY.",
                      "defaultValue": "true"
                    },
                    "OPENAI_API_KEY": {
                      "description": "Required. Your OpenAI API key. Skyvern boots without it but every task and workflow run fails, because the agent falls back to a dummy LLM handler. To use a different provider instead, leave this blank, set ENABLE_OPENAI=false and configure that provider plus LLM_KEY.",
                      "defaultValue": "{{OPENAI_API_KEY}}"
                    },
                    "DATABASE_STRING": {
                      "description": "Postgres connection string over the private network. Skyvern needs the postgresql+psycopg:// driver prefix, so this is built by hand instead of reusing DATABASE_PRIVATE_URL. Alembic migrations run on every boot.",
                      "defaultValue": "postgresql+psycopg://${{Postgres.PGUSER}}:${{Postgres.POSTGRES_PASSWORD}}@${{Postgres.RAILWAY_PRIVATE_DOMAIN}}:5432/${{Postgres.PGDATABASE}}"
                    },
                    "ENABLE_ANTHROPIC": {
                      "isOptional": true,
                      "description": "Optional. Set to true together with ANTHROPIC_API_KEY and an ANTHROPIC_* LLM_KEY to run the agent on Claude instead of OpenAI.",
                      "defaultValue": "false"
                    },
                    "ANTHROPIC_API_KEY": {
                      "isOptional": true,
                      "description": "Optional. Anthropic API key, used only when ENABLE_ANTHROPIC is true.",
                      "defaultValue": ""
                    },
                    "ENABLE_CODE_BLOCK": {
                      "description": "Enables the code block node in workflows, as in upstream docker-compose.",
                      "defaultValue": "true"
                    },
                    "MAX_STEPS_PER_RUN": {
                      "isOptional": true,
                      "description": "Upper bound on agent steps per run. Lower it to cap LLM spend per task.",
                      "defaultValue": "50"
                    },
                    "SECONDARY_LLM_KEY": {
                      "description": "Cheaper model used for small helper calls such as option selection and SVG conversion. Leave blank to reuse LLM_KEY.",
                      "defaultValue": "OPENAI_GPT5_4_MINI"
                    },
                    "SKYVERN_TELEMETRY": {
                      "isOptional": true,
                      "description": "Upstream anonymous usage analytics. Set to false to disable.",
                      "defaultValue": "true"
                    },
                    "CREDENTIAL_VAULT_TYPE": {
                      "description": "Use the built-in encrypted credential vault. The encryption key is generated into /data/credential_vault/.fernet_key on the volume, so treat the volume as secret material.",
                      "defaultValue": "skyvern"
                    },
                    "SKYVERN_DEV_NO_RELOAD": {
                      "description": "Disables uvicorn's file-watching auto-reload supervisor, which ENV=local would otherwise switch on. Leave it true: the reloader doubles memory use and can wedge on long browser cleanups.",
                      "defaultValue": "true"
                    },
                    "SKYVERN_PRINT_API_KEY": {
                      "description": "Prints the generated organization API key into this service's deploy logs once the credentials file exists, so you can copy it into the Skyvern UI service. Set it to false after you have copied the key if you do not want it in the logs.",
                      "defaultValue": "true"
                    },
                    "BROWSER_STREAMING_MODE": {
                      "description": "Live browser view transport. cdp streams through this service's own websocket, so no extra port has to be exposed. Must match VITE_BROWSER_STREAMING_MODE on the Skyvern UI service.",
                      "defaultValue": "cdp"
                    },
                    "SKYVERN_CREDENTIALS_FILE": {
                      "description": "Where the generated organization API key is stored. It must live on the volume: if the file is missing at boot Skyvern creates a brand new organization and API key, so an ephemeral path would orphan your workflows on every redeploy.",
                      "defaultValue": "/data/.skyvern/credentials.toml"
                    },
                    "ENABLE_LOCAL_CREDENTIAL_VAULT": {
                      "description": "Stores workflow credentials in the built-in vault on the volume instead of Bitwarden or a cloud secret manager.",
                      "defaultValue": "true"
                    }
                  },
                  "networking": {
                    "tcpProxies": {},
                    "serviceDomains": {
                      "skyvern-dom": {
                        "port": 8000
                      }
                    }
                  },
                  "volumeMounts": {
                    "5320f96a-1b1c-4aa3-80e8-5f365b5c2053": {
                      "mountPath": "/data"
                    }
                  }
                },
                "a40fadf7-34ad-4177-a92b-213c46df549a": {
                  "icon": "https://raw.githubusercontent.com/Skyvern-AI/skyvern/v1.0.53/skyvern-frontend/public/logo-small.png",
                  "name": "skyvern-gateway",
                  "build": {},
                  "deploy": {
                    "startCommand": "sh -c 'echo c2V0IC1lCjogIiR7UE9SVDo/UE9SVCBpcyByZXF1aXJlZH0iCjogIiR7VUlfVVNFUk5BTUU6P1VJX1VTRVJOQU1FIGlzIHJlcXVpcmVkfSIKOiAiJHtVSV9QQVNTV09SRDo/VUlfUEFTU1dPUkQgaXMgcmVxdWlyZWR9Igo6ICIke1VQU1RSRUFNOj9VUFNUUkVBTSBpcyByZXF1aXJlZH0iCkhBU0g9IiQoY2FkZHkgaGFzaC1wYXNzd29yZCAtLXBsYWludGV4dCAiJFVJX1BBU1NXT1JEIikiCnByaW50ZiAnJXNcbicgXAogICd7JyBcCiAgJyAgYXV0b19odHRwcyBvZmYnIFwKICAnICBhZG1pbiBvZmYnIFwKICAnICBzZXJ2ZXJzIHsnIFwKICAnICAgIHByb3RvY29scyBoMSBoMmMnIFwKICAnICB9JyBcCiAgJ30nIFwKICAiOiRQT1JUIHsiIFwKICAnICBoYW5kbGUgL2dhdGV3YXktaGVhbHRoIHsnIFwKICAnICAgIHJlc3BvbmQgIm9rIiAyMDAnIFwKICAnICB9JyBcCiAgJyAgaGFuZGxlIHsnIFwKICAnICAgIGJhc2ljX2F1dGggeycgXAogICIgICAgICAkVUlfVVNFUk5BTUUgJEhBU0giIFwKICAnICAgIH0nIFwKICAiICAgIHJldmVyc2VfcHJveHkgJFVQU1RSRUFNIiBcCiAgJyAgfScgXAogICd9JyA+IC9ldGMvY2FkZHkvQ2FkZHlmaWxlCmV4ZWMgY2FkZHkgcnVuIC0tY29uZmlnIC9ldGMvY2FkZHkvQ2FkZHlmaWxlIC0tYWRhcHRlciBjYWRkeWZpbGUK | base64 -d > /tmp/start.sh && exec sh /tmp/start.sh'",
                    "healthcheckPath": "/gateway-health",
                    "restartPolicyType": "ON_FAILURE"
                  },
                  "source": {
                    "image": "caddy:2.11-alpine"
                  },
                  "variables": {
                    "PORT": {
                      "description": "Port the gateway listens on.",
                      "defaultValue": "8080"
                    },
                    "UPSTREAM": {
                      "description": "Private address of the Skyvern UI service.",
                      "defaultValue": "${{skyvern-ui.RAILWAY_PRIVATE_DOMAIN}}:8080"
                    },
                    "UI_PASSWORD": {
                      "description": "Password for the Skyvern UI login prompt. Generated on deploy, change it here at any time.",
                      "defaultValue": "{{UI_PASSWORD}}"
                    },
                    "UI_USERNAME": {
                      "description": "Username for the Skyvern UI login prompt.",
                      "defaultValue": "admin"
                    }
                  },
                  "networking": {
                    "tcpProxies": {},
                    "serviceDomains": {
                      "skyvern-gateway-dom": {}
                    }
                  },
                  "volumeMounts": {}
                }
              }
            }
          }
        }
      }
    }
  },
  "post_deploy": {
    "healthcheck": {
      "service": "Skyvern",
      "method": "GET",
      "path": "/api/v1/heartbeat",
      "expect_status": 200
    }
  },
  "resources": {
    "expected_services": 4,
    "needs_volume": true
  },
  "generated_at": "2026-09-21T04:14:46.774Z",
  "generator_version": "0.1.0",
  "status": "validated",
  "validated_at": "2026-09-21T02:58:00.325Z",
  "success_rate_30d": 1,
  "validation": {
    "last_run_id": "run_76013d14f6cb49e9a53e",
    "checks": [
      {
        "name": "workflow_completed",
        "passed": true
      },
      {
        "name": "all_services_deployed",
        "passed": true
      },
      {
        "name": "healthcheck",
        "passed": true
      },
      {
        "name": "stays_up",
        "passed": true
      }
    ],
    "typical_ready_seconds": 129,
    "typical_build_seconds": 0,
    "typical_start_seconds": 10,
    "slowest_service": "skyvern-gateway"
  }
}
