{
  "manifest_version": "1.0.0",
  "template": {
    "id": "a03aad75-a19f-497e-9aec-313da6f40e37",
    "slug": "langwatch-llm-observability",
    "name": "LangWatch | Open Source LangSmith Alternative for Agent Testing",
    "description": "Self-hosted LangWatch: LLM tracing, evals, guardrails and agent testing",
    "url": "https://railway.com/deploy/langwatch-llm-observability",
    "upstream": {
      "image": "langwatch/langwatch:3.17.0"
    }
  },
  "services": [
    {
      "name": "LangWatch",
      "source": {
        "image": "langwatch/langwatch:3.17.0"
      },
      "needs_volume": false,
      "http": true
    },
    {
      "name": "Valkey",
      "source": {
        "image": "valkey/valkey:9.1.2-alpine"
      },
      "needs_volume": true,
      "volume_mount_path": "/data",
      "http": false
    },
    {
      "name": "ClickHouse",
      "source": {
        "image": "langwatch/clickhouse-serverless:0.4.0"
      },
      "needs_volume": true,
      "volume_mount_path": "/var/lib/clickhouse",
      "http": false
    },
    {
      "name": "NLP",
      "source": {
        "image": "langwatch/langwatch_nlp:3.17.0"
      },
      "needs_volume": false,
      "http": false
    },
    {
      "name": "Postgres",
      "source": {
        "image": "postgres:18.6-alpine"
      },
      "needs_volume": true,
      "volume_mount_path": "/var/lib/postgresql/data",
      "http": false
    },
    {
      "name": "LangEvals",
      "source": {
        "image": "langwatch/langevals:3.17.0"
      },
      "needs_volume": false,
      "http": false
    },
    {
      "name": "Workers",
      "source": {
        "image": "langwatch/langwatch:3.17.0"
      },
      "needs_volume": false,
      "http": false
    }
  ],
  "required_inputs": [
    {
      "key": "PORT",
      "service": "LangWatch",
      "description": "Port the LangWatch server listens on. Railway routes the public domain here.",
      "secret": false,
      "strategy": "default",
      "default": "5560"
    },
    {
      "key": "NODE_ENV",
      "service": "LangWatch",
      "description": "Runs the production build. Do not change.",
      "secret": false,
      "strategy": "default",
      "default": "production"
    },
    {
      "key": "WAIT_FOR",
      "service": "LangWatch",
      "description": "Databases the start command waits for before running migrations (host:port, space-separated).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "BASE_HOST",
      "service": "LangWatch",
      "description": "Public URL of this deployment.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_domain"
    },
    {
      "key": "REDIS_URL",
      "service": "LangWatch",
      "description": "Valkey connection for the job queue, with its generated password.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "S3_REGION",
      "service": "LangWatch",
      "description": "Railway bucket region.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "S3_ENDPOINT",
      "service": "LangWatch",
      "description": "Railway bucket S3 endpoint.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "DATABASE_URL",
      "service": "LangWatch",
      "description": "PostgreSQL connection over the private network.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "NEXTAUTH_URL",
      "service": "LangWatch",
      "description": "Public URL used for login callbacks. Same as BASE_HOST.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_domain"
    },
    {
      "key": "CLICKHOUSE_URL",
      "service": "LangWatch",
      "description": "ClickHouse HTTP connection over the private network (traces, spans, analytics).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "INSTALL_METHOD",
      "service": "LangWatch",
      "description": "Install method reported by the app, as in upstream's Docker Compose file.",
      "secret": false,
      "strategy": "default",
      "default": "docker"
    },
    {
      "key": "S3_BUCKET_NAME",
      "service": "LangWatch",
      "description": "Railway bucket for datasets and stored objects.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "NEXTAUTH_SECRET",
      "service": "LangWatch",
      "description": "Session signing secret. Generated on deploy.",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "S3_ACCESS_KEY_ID",
      "service": "LangWatch",
      "description": "Railway bucket access key.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "NEXTAUTH_PROVIDER",
      "service": "LangWatch",
      "description": "Login method. 'email' is email and password; set auth0, azure-ad, okta, cognito, onelogin or oidc (plus that provider's variables) for SSO.",
      "secret": false,
      "strategy": "default",
      "default": "email"
    },
    {
      "key": "CREDENTIALS_SECRET",
      "service": "LangWatch",
      "description": "AES-256 key for API keys and project secrets stored in the database. Must be exactly 64 hex characters. Do not change it after deploying, or stored secrets can no longer be decrypted.",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "LANGEVALS_ENDPOINT",
      "service": "LangWatch",
      "description": "LangEvals evaluators and guardrails over the private network.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "LANGWATCH_ENDPOINT",
      "service": "LangWatch",
      "description": "Private URL of the LangWatch server, used by the other services to call it back.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "DISABLE_USAGE_STATS",
      "service": "LangWatch",
      "description": "Anonymous usage statistics are off. Remove this variable to send them to the LangWatch team.",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "SKIP_ENV_VALIDATION",
      "service": "LangWatch",
      "description": "Skips the build-time env schema check, as upstream's Docker Compose does. Runtime checks still apply.",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "API_TOKEN_JWT_SECRET",
      "service": "LangWatch",
      "description": "Signing secret for API tokens. Generated on deploy.",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "S3_SECRET_ACCESS_KEY",
      "service": "LangWatch",
      "description": "Railway bucket secret key.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LANGWATCH_NLP_SERVICE",
      "service": "LangWatch",
      "description": "NLP engine (Optimization Studio, workflows, code evaluators) over the private network.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "LW_GATEWAY_JWT_SECRET",
      "service": "LangWatch",
      "description": "Signing key for AI Gateway virtual-key tokens. 64 hex characters, generated on deploy.",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "LW_VIRTUAL_KEY_PEPPER",
      "service": "LangWatch",
      "description": "Pepper for hashing AI Gateway virtual keys at rest. 64 hex characters, generated on deploy.",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "LW_GATEWAY_INTERNAL_SECRET",
      "service": "LangWatch",
      "description": "Shared HMAC secret for the AI Gateway's internal calls. 64 hex characters, generated on deploy.",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "CLICKHOUSE_BACKUP_METRICS_ENABLED",
      "service": "LangWatch",
      "description": "This ClickHouse has no backups configured, so system.backup_log does not exist; leaving collection on fails a query on every stats tick.",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "REDIS_PASSWORD",
      "service": "Valkey",
      "description": "Valkey password (requirepass). Generated on deploy.",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "RAILWAY_RUN_UID",
      "service": "Valkey",
      "description": "Starts as root so Valkey can write its append-only file to the Railway volume.",
      "secret": false,
      "strategy": "default",
      "default": "0"
    },
    {
      "key": "PORT",
      "service": "ClickHouse",
      "description": "ClickHouse HTTP port, for Railway.",
      "secret": false,
      "strategy": "default",
      "default": "8123"
    },
    {
      "key": "CH_CPU",
      "service": "ClickHouse",
      "description": "CPU cores ClickHouse sizes its thread pools and merges for. Raise together with CH_RAM for large trace volumes.",
      "secret": false,
      "strategy": "default",
      "default": "2"
    },
    {
      "key": "CH_RAM",
      "service": "ClickHouse",
      "description": "Memory ClickHouse sizes its limits and caches for (85% server limit, 25% per query). Railway bills actual use, not this value.",
      "secret": false,
      "strategy": "default",
      "default": "4Gi"
    },
    {
      "key": "RAILWAY_RUN_UID",
      "service": "ClickHouse",
      "description": "Starts as root so the entrypoint can take ownership of the Railway volume before dropping to the clickhouse user.",
      "secret": false,
      "strategy": "default",
      "default": "0"
    },
    {
      "key": "CLICKHOUSE_PASSWORD",
      "service": "ClickHouse",
      "description": "Password of the ClickHouse default user. Generated on deploy.",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "PORT",
      "service": "NLP",
      "description": "Port the NLP engine listens on (SERVER_ADDR in the image).",
      "secret": false,
      "strategy": "default",
      "default": "5561"
    },
    {
      "key": "LANGWATCH_ENDPOINT",
      "service": "NLP",
      "description": "Private URL of the LangWatch server, for evaluator and workflow callbacks.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "PGDATA",
      "service": "Postgres",
      "description": "Data directory one level below the volume mount, so the volume's lost+found does not block initdb.",
      "secret": false,
      "strategy": "default",
      "default": "/var/lib/postgresql/data/pgdata"
    },
    {
      "key": "POSTGRES_DB",
      "service": "Postgres",
      "description": "Database name.",
      "secret": false,
      "strategy": "default",
      "default": "langwatch"
    },
    {
      "key": "POSTGRES_USER",
      "service": "Postgres",
      "description": "Database user.",
      "secret": false,
      "strategy": "default",
      "default": "langwatch"
    },
    {
      "key": "POSTGRES_PASSWORD",
      "service": "Postgres",
      "description": "Database password. Generated on deploy.",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "PORT",
      "service": "LangEvals",
      "description": "Port the evaluators server listens on.",
      "secret": false,
      "strategy": "default",
      "default": "5562"
    },
    {
      "key": "CPU_COUNT",
      "service": "LangEvals",
      "description": "Number of evaluator worker processes. Each one loads the full evaluator stack, about 1.8 GB of RAM; raise it only if evaluations queue up.",
      "secret": false,
      "strategy": "default",
      "default": "1"
    },
    {
      "key": "DISABLE_EVALUATORS_PRELOAD",
      "service": "LangEvals",
      "description": "Load evaluators on first use instead of at boot, for a faster start.",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "PORT",
      "service": "Workers",
      "description": "Kept equal to the app's PORT: the worker's health listener binds PORT - 2561 (2999).",
      "secret": false,
      "strategy": "default",
      "default": "5560"
    },
    {
      "key": "NODE_ENV",
      "service": "Workers",
      "description": "Runs the production build. Do not change.",
      "secret": false,
      "strategy": "default",
      "default": "production"
    },
    {
      "key": "BASE_HOST",
      "service": "Workers",
      "description": "Public URL of this deployment.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_domain"
    },
    {
      "key": "REDIS_URL",
      "service": "Workers",
      "description": "Valkey connection for the job queue, with its generated password.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "S3_REGION",
      "service": "Workers",
      "description": "Railway bucket region.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "S3_ENDPOINT",
      "service": "Workers",
      "description": "Railway bucket S3 endpoint.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "DATABASE_URL",
      "service": "Workers",
      "description": "PostgreSQL connection over the private network.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "NEXTAUTH_URL",
      "service": "Workers",
      "description": "Public URL used for login callbacks. Same as BASE_HOST.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_domain"
    },
    {
      "key": "CLICKHOUSE_URL",
      "service": "Workers",
      "description": "ClickHouse HTTP connection over the private network (traces, spans, analytics).",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "INSTALL_METHOD",
      "service": "Workers",
      "description": "Install method reported by the app, as in upstream's Docker Compose file.",
      "secret": false,
      "strategy": "default",
      "default": "docker"
    },
    {
      "key": "S3_BUCKET_NAME",
      "service": "Workers",
      "description": "Railway bucket for datasets and stored objects.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "NEXTAUTH_SECRET",
      "service": "Workers",
      "description": "Shared with the LangWatch service.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "S3_ACCESS_KEY_ID",
      "service": "Workers",
      "description": "Railway bucket access key.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "NEXTAUTH_PROVIDER",
      "service": "Workers",
      "description": "Login method. 'email' is email and password; set auth0, azure-ad, okta, cognito, onelogin or oidc (plus that provider's variables) for SSO.",
      "secret": false,
      "strategy": "default",
      "default": "email"
    },
    {
      "key": "CREDENTIALS_SECRET",
      "service": "Workers",
      "description": "Shared with the LangWatch service, so the worker can decrypt stored secrets.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LANGEVALS_ENDPOINT",
      "service": "Workers",
      "description": "LangEvals evaluators and guardrails over the private network.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "LANGWATCH_ENDPOINT",
      "service": "Workers",
      "description": "Private URL of the LangWatch server, used by the other services to call it back.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "DISABLE_USAGE_STATS",
      "service": "Workers",
      "description": "Anonymous usage statistics are off. Remove this variable to send them to the LangWatch team.",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "SKIP_ENV_VALIDATION",
      "service": "Workers",
      "description": "Skips the build-time env schema check, as upstream's Docker Compose does. Runtime checks still apply.",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "API_TOKEN_JWT_SECRET",
      "service": "Workers",
      "description": "Shared with the LangWatch service.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "S3_SECRET_ACCESS_KEY",
      "service": "Workers",
      "description": "Railway bucket secret key.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LANGWATCH_NLP_SERVICE",
      "service": "Workers",
      "description": "NLP engine (Optimization Studio, workflows, code evaluators) over the private network.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "LW_GATEWAY_JWT_SECRET",
      "service": "Workers",
      "description": "Shared with the LangWatch service.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LW_VIRTUAL_KEY_PEPPER",
      "service": "Workers",
      "description": "Shared with the LangWatch service.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LW_GATEWAY_INTERNAL_SECRET",
      "service": "Workers",
      "description": "Shared with the LangWatch service.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "CLICKHOUSE_BACKUP_METRICS_ENABLED",
      "service": "Workers",
      "description": "This ClickHouse has no backups configured, so system.backup_log does not exist; leaving collection on fails a query on every stats tick.",
      "secret": false,
      "strategy": "default",
      "default": "false"
    }
  ],
  "deploy": {
    "mcp": {
      "server": "railway",
      "tool": "deploy_template",
      "args": {
        "template_code": "langwatch-llm-observability"
      }
    },
    "cli": "railway deploy --template langwatch-llm-observability",
    "api": {
      "method": "POST",
      "path": "/graphql/v2",
      "body": {
        "query": "mutation templateDeploy($input: TemplateDeployV2Input!) { templateDeployV2(input: $input) { projectId workflowId } }",
        "variables": {
          "input": {
            "templateId": "a03aad75-a19f-497e-9aec-313da6f40e37",
            "serializedConfig": {
              "buckets": {
                "3a34b88e-b85b-4090-984c-643150af70cc": {
                  "name": "Storage"
                }
              },
              "services": {
                "6beaabb0-f079-4691-a13a-cbe47cdfa538": {
                  "icon": "https://cdn.jsdelivr.net/gh/langwatch/langwatch@60515a6de93c2c6361b438eae49b067076bd9b12/docs/favicon.svg",
                  "name": "LangWatch",
                  "deploy": {
                    "startCommand": "bash -c 'for hp in $WAIT_FOR; do for i in $(seq 1 90); do (echo > /dev/tcp/${hp%:*}/${hp##*:}) 2>/dev/null && break; echo \"waiting for $hp ($i/90)\"; sleep 2; done; done; cd /app/platform/app && exec pnpm start'",
                    "healthcheckPath": "/api/health",
                    "restartPolicyType": "ON_FAILURE",
                    "healthcheckTimeout": 600,
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "langwatch/langwatch:3.17.0"
                  },
                  "variables": {
                    "PORT": {
                      "isOptional": false,
                      "description": "Port the LangWatch server listens on. Railway routes the public domain here.",
                      "defaultValue": "5560"
                    },
                    "NODE_ENV": {
                      "isOptional": false,
                      "description": "Runs the production build. Do not change.",
                      "defaultValue": "production"
                    },
                    "WAIT_FOR": {
                      "isOptional": false,
                      "description": "Databases the start command waits for before running migrations (host:port, space-separated).",
                      "defaultValue": "${{Postgres.RAILWAY_PRIVATE_DOMAIN}}:5432 ${{ClickHouse.RAILWAY_PRIVATE_DOMAIN}}:8123"
                    },
                    "BASE_HOST": {
                      "isOptional": false,
                      "description": "Public URL of this deployment.",
                      "defaultValue": "https://${{LangWatch.RAILWAY_PUBLIC_DOMAIN}}"
                    },
                    "REDIS_URL": {
                      "isOptional": false,
                      "description": "Valkey connection for the job queue, with its generated password.",
                      "defaultValue": "redis://default:${{Valkey.REDIS_PASSWORD}}@${{Valkey.RAILWAY_PRIVATE_DOMAIN}}:6379"
                    },
                    "S3_REGION": {
                      "isOptional": false,
                      "description": "Railway bucket region.",
                      "defaultValue": "${{Storage.REGION}}"
                    },
                    "S3_ENDPOINT": {
                      "isOptional": false,
                      "description": "Railway bucket S3 endpoint.",
                      "defaultValue": "${{Storage.ENDPOINT}}"
                    },
                    "DATABASE_URL": {
                      "isOptional": false,
                      "description": "PostgreSQL connection over the private network.",
                      "defaultValue": "postgresql://langwatch:${{Postgres.POSTGRES_PASSWORD}}@${{Postgres.RAILWAY_PRIVATE_DOMAIN}}:5432/langwatch?schema=public&connection_limit=5"
                    },
                    "NEXTAUTH_URL": {
                      "isOptional": false,
                      "description": "Public URL used for login callbacks. Same as BASE_HOST.",
                      "defaultValue": "https://${{LangWatch.RAILWAY_PUBLIC_DOMAIN}}"
                    },
                    "CLICKHOUSE_URL": {
                      "isOptional": false,
                      "description": "ClickHouse HTTP connection over the private network (traces, spans, analytics).",
                      "defaultValue": "http://default:${{ClickHouse.CLICKHOUSE_PASSWORD}}@${{ClickHouse.RAILWAY_PRIVATE_DOMAIN}}:8123/langwatch"
                    },
                    "INSTALL_METHOD": {
                      "isOptional": false,
                      "description": "Install method reported by the app, as in upstream's Docker Compose file.",
                      "defaultValue": "docker"
                    },
                    "S3_BUCKET_NAME": {
                      "isOptional": false,
                      "description": "Railway bucket for datasets and stored objects.",
                      "defaultValue": "${{Storage.BUCKET}}"
                    },
                    "NEXTAUTH_SECRET": {
                      "isOptional": false,
                      "description": "Session signing secret. Generated on deploy.",
                      "defaultValue": "{{NEXTAUTH_SECRET}}"
                    },
                    "S3_ACCESS_KEY_ID": {
                      "isOptional": false,
                      "description": "Railway bucket access key.",
                      "defaultValue": "${{Storage.ACCESS_KEY_ID}}"
                    },
                    "NEXTAUTH_PROVIDER": {
                      "isOptional": false,
                      "description": "Login method. 'email' is email and password; set auth0, azure-ad, okta, cognito, onelogin or oidc (plus that provider's variables) for SSO.",
                      "defaultValue": "email"
                    },
                    "CREDENTIALS_SECRET": {
                      "isOptional": false,
                      "description": "AES-256 key for API keys and project secrets stored in the database. Must be exactly 64 hex characters. Do not change it after deploying, or stored secrets can no longer be decrypted.",
                      "defaultValue": "{{CREDENTIALS_SECRET}}"
                    },
                    "LANGEVALS_ENDPOINT": {
                      "isOptional": false,
                      "description": "LangEvals evaluators and guardrails over the private network.",
                      "defaultValue": "http://${{LangEvals.RAILWAY_PRIVATE_DOMAIN}}:5562"
                    },
                    "LANGWATCH_ENDPOINT": {
                      "isOptional": false,
                      "description": "Private URL of the LangWatch server, used by the other services to call it back.",
                      "defaultValue": "http://${{LangWatch.RAILWAY_PRIVATE_DOMAIN}}:5560"
                    },
                    "DISABLE_USAGE_STATS": {
                      "isOptional": false,
                      "description": "Anonymous usage statistics are off. Remove this variable to send them to the LangWatch team.",
                      "defaultValue": "true"
                    },
                    "SKIP_ENV_VALIDATION": {
                      "isOptional": false,
                      "description": "Skips the build-time env schema check, as upstream's Docker Compose does. Runtime checks still apply.",
                      "defaultValue": "true"
                    },
                    "API_TOKEN_JWT_SECRET": {
                      "isOptional": false,
                      "description": "Signing secret for API tokens. Generated on deploy.",
                      "defaultValue": "{{API_TOKEN_JWT_SECRET}}"
                    },
                    "S3_SECRET_ACCESS_KEY": {
                      "isOptional": false,
                      "description": "Railway bucket secret key.",
                      "defaultValue": "${{Storage.SECRET_ACCESS_KEY}}"
                    },
                    "LANGWATCH_NLP_SERVICE": {
                      "isOptional": false,
                      "description": "NLP engine (Optimization Studio, workflows, code evaluators) over the private network.",
                      "defaultValue": "http://${{NLP.RAILWAY_PRIVATE_DOMAIN}}:5561"
                    },
                    "LW_GATEWAY_JWT_SECRET": {
                      "isOptional": false,
                      "description": "Signing key for AI Gateway virtual-key tokens. 64 hex characters, generated on deploy.",
                      "defaultValue": "{{LW_GATEWAY_JWT_SECRET}}"
                    },
                    "LW_VIRTUAL_KEY_PEPPER": {
                      "isOptional": false,
                      "description": "Pepper for hashing AI Gateway virtual keys at rest. 64 hex characters, generated on deploy.",
                      "defaultValue": "{{LW_VIRTUAL_KEY_PEPPER}}"
                    },
                    "LW_GATEWAY_INTERNAL_SECRET": {
                      "isOptional": false,
                      "description": "Shared HMAC secret for the AI Gateway's internal calls. 64 hex characters, generated on deploy.",
                      "defaultValue": "{{LW_GATEWAY_INTERNAL_SECRET}}"
                    },
                    "CLICKHOUSE_BACKUP_METRICS_ENABLED": {
                      "isOptional": false,
                      "description": "This ClickHouse has no backups configured, so system.backup_log does not exist; leaving collection on fails a query on every stats tick.",
                      "defaultValue": "false"
                    }
                  },
                  "networking": {
                    "serviceDomains": {
                      "<hasDomain>": {}
                    }
                  }
                },
                "9a996193-656f-4107-b357-515c85beb847": {
                  "icon": "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/valkey.svg",
                  "name": "Valkey",
                  "deploy": {
                    "startCommand": "sh -c 'exec valkey-server --requirepass \"$REDIS_PASSWORD\" --appendonly yes --maxmemory-policy noeviction --dir /data'",
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "valkey/valkey:9.1.2-alpine"
                  },
                  "variables": {
                    "REDIS_PASSWORD": {
                      "isOptional": false,
                      "description": "Valkey password (requirepass). Generated on deploy.",
                      "defaultValue": "{{REDIS_PASSWORD}}"
                    },
                    "RAILWAY_RUN_UID": {
                      "isOptional": false,
                      "description": "Starts as root so Valkey can write its append-only file to the Railway volume.",
                      "defaultValue": "0"
                    }
                  },
                  "volumeMounts": {
                    "9a996193-656f-4107-b357-515c85beb847": {
                      "mountPath": "/data"
                    }
                  }
                },
                "a949f1ab-b3d8-445a-9c28-24e210b17ebe": {
                  "icon": "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/clickhouse.svg",
                  "name": "ClickHouse",
                  "deploy": {
                    "startCommand": null,
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 2
                  },
                  "source": {
                    "image": "langwatch/clickhouse-serverless:0.4.0"
                  },
                  "variables": {
                    "PORT": {
                      "isOptional": false,
                      "description": "ClickHouse HTTP port, for Railway.",
                      "defaultValue": "8123"
                    },
                    "CH_CPU": {
                      "isOptional": false,
                      "description": "CPU cores ClickHouse sizes its thread pools and merges for. Raise together with CH_RAM for large trace volumes.",
                      "defaultValue": "2"
                    },
                    "CH_RAM": {
                      "isOptional": false,
                      "description": "Memory ClickHouse sizes its limits and caches for (85% server limit, 25% per query). Railway bills actual use, not this value.",
                      "defaultValue": "4Gi"
                    },
                    "RAILWAY_RUN_UID": {
                      "isOptional": false,
                      "description": "Starts as root so the entrypoint can take ownership of the Railway volume before dropping to the clickhouse user.",
                      "defaultValue": "0"
                    },
                    "CLICKHOUSE_PASSWORD": {
                      "isOptional": false,
                      "description": "Password of the ClickHouse default user. Generated on deploy.",
                      "defaultValue": "{{CLICKHOUSE_PASSWORD}}"
                    }
                  },
                  "volumeMounts": {
                    "a949f1ab-b3d8-445a-9c28-24e210b17ebe": {
                      "mountPath": "/var/lib/clickhouse"
                    }
                  }
                },
                "ba9527ea-f49b-4c26-b435-6cc35debecd5": {
                  "icon": "https://cdn.jsdelivr.net/gh/langwatch/langwatch@60515a6de93c2c6361b438eae49b067076bd9b12/docs/favicon.svg",
                  "name": "NLP",
                  "deploy": {
                    "startCommand": null,
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "langwatch/langwatch_nlp:3.17.0"
                  },
                  "variables": {
                    "PORT": {
                      "isOptional": false,
                      "description": "Port the NLP engine listens on (SERVER_ADDR in the image).",
                      "defaultValue": "5561"
                    },
                    "LANGWATCH_ENDPOINT": {
                      "isOptional": false,
                      "description": "Private URL of the LangWatch server, for evaluator and workflow callbacks.",
                      "defaultValue": "http://${{LangWatch.RAILWAY_PRIVATE_DOMAIN}}:5560"
                    }
                  }
                },
                "bb108f79-6bee-4124-a518-18e38136fe26": {
                  "icon": "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/postgresql.svg",
                  "name": "Postgres",
                  "deploy": {
                    "startCommand": null,
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 2
                  },
                  "source": {
                    "image": "postgres:18.6-alpine"
                  },
                  "variables": {
                    "PGDATA": {
                      "isOptional": false,
                      "description": "Data directory one level below the volume mount, so the volume's lost+found does not block initdb.",
                      "defaultValue": "/var/lib/postgresql/data/pgdata"
                    },
                    "POSTGRES_DB": {
                      "isOptional": false,
                      "description": "Database name.",
                      "defaultValue": "langwatch"
                    },
                    "POSTGRES_USER": {
                      "isOptional": false,
                      "description": "Database user.",
                      "defaultValue": "langwatch"
                    },
                    "POSTGRES_PASSWORD": {
                      "isOptional": false,
                      "description": "Database password. Generated on deploy.",
                      "defaultValue": "{{POSTGRES_PASSWORD}}"
                    }
                  },
                  "volumeMounts": {
                    "bb108f79-6bee-4124-a518-18e38136fe26": {
                      "mountPath": "/var/lib/postgresql/data"
                    }
                  }
                },
                "d24b07a2-2d4d-4b52-8856-d98dcb13816d": {
                  "icon": "https://cdn.jsdelivr.net/gh/langwatch/langwatch@60515a6de93c2c6361b438eae49b067076bd9b12/docs/favicon.svg",
                  "name": "LangEvals",
                  "deploy": {
                    "startCommand": null,
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "langwatch/langevals:3.17.0"
                  },
                  "variables": {
                    "PORT": {
                      "isOptional": false,
                      "description": "Port the evaluators server listens on.",
                      "defaultValue": "5562"
                    },
                    "CPU_COUNT": {
                      "isOptional": false,
                      "description": "Number of evaluator worker processes. Each one loads the full evaluator stack, about 1.8 GB of RAM; raise it only if evaluations queue up.",
                      "defaultValue": "1"
                    },
                    "DISABLE_EVALUATORS_PRELOAD": {
                      "isOptional": false,
                      "description": "Load evaluators on first use instead of at boot, for a faster start.",
                      "defaultValue": "true"
                    }
                  }
                },
                "da01e844-f3a5-4f8d-ba8c-23a91cd4155f": {
                  "icon": "https://cdn.jsdelivr.net/gh/langwatch/langwatch@60515a6de93c2c6361b438eae49b067076bd9b12/docs/favicon.svg",
                  "name": "Workers",
                  "deploy": {
                    "startCommand": "bash -c 'cd /app/platform/app && exec node --enable-source-maps dist/server/workers.cjs'",
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "langwatch/langwatch:3.17.0"
                  },
                  "variables": {
                    "PORT": {
                      "isOptional": false,
                      "description": "Kept equal to the app's PORT: the worker's health listener binds PORT - 2561 (2999).",
                      "defaultValue": "5560"
                    },
                    "NODE_ENV": {
                      "isOptional": false,
                      "description": "Runs the production build. Do not change.",
                      "defaultValue": "production"
                    },
                    "BASE_HOST": {
                      "isOptional": false,
                      "description": "Public URL of this deployment.",
                      "defaultValue": "https://${{LangWatch.RAILWAY_PUBLIC_DOMAIN}}"
                    },
                    "REDIS_URL": {
                      "isOptional": false,
                      "description": "Valkey connection for the job queue, with its generated password.",
                      "defaultValue": "redis://default:${{Valkey.REDIS_PASSWORD}}@${{Valkey.RAILWAY_PRIVATE_DOMAIN}}:6379"
                    },
                    "S3_REGION": {
                      "isOptional": false,
                      "description": "Railway bucket region.",
                      "defaultValue": "${{Storage.REGION}}"
                    },
                    "S3_ENDPOINT": {
                      "isOptional": false,
                      "description": "Railway bucket S3 endpoint.",
                      "defaultValue": "${{Storage.ENDPOINT}}"
                    },
                    "DATABASE_URL": {
                      "isOptional": false,
                      "description": "PostgreSQL connection over the private network.",
                      "defaultValue": "postgresql://langwatch:${{Postgres.POSTGRES_PASSWORD}}@${{Postgres.RAILWAY_PRIVATE_DOMAIN}}:5432/langwatch?schema=public&connection_limit=5"
                    },
                    "NEXTAUTH_URL": {
                      "isOptional": false,
                      "description": "Public URL used for login callbacks. Same as BASE_HOST.",
                      "defaultValue": "https://${{LangWatch.RAILWAY_PUBLIC_DOMAIN}}"
                    },
                    "CLICKHOUSE_URL": {
                      "isOptional": false,
                      "description": "ClickHouse HTTP connection over the private network (traces, spans, analytics).",
                      "defaultValue": "http://default:${{ClickHouse.CLICKHOUSE_PASSWORD}}@${{ClickHouse.RAILWAY_PRIVATE_DOMAIN}}:8123/langwatch"
                    },
                    "INSTALL_METHOD": {
                      "isOptional": false,
                      "description": "Install method reported by the app, as in upstream's Docker Compose file.",
                      "defaultValue": "docker"
                    },
                    "S3_BUCKET_NAME": {
                      "isOptional": false,
                      "description": "Railway bucket for datasets and stored objects.",
                      "defaultValue": "${{Storage.BUCKET}}"
                    },
                    "NEXTAUTH_SECRET": {
                      "isOptional": false,
                      "description": "Shared with the LangWatch service.",
                      "defaultValue": "${{LangWatch.NEXTAUTH_SECRET}}"
                    },
                    "S3_ACCESS_KEY_ID": {
                      "isOptional": false,
                      "description": "Railway bucket access key.",
                      "defaultValue": "${{Storage.ACCESS_KEY_ID}}"
                    },
                    "NEXTAUTH_PROVIDER": {
                      "isOptional": false,
                      "description": "Login method. 'email' is email and password; set auth0, azure-ad, okta, cognito, onelogin or oidc (plus that provider's variables) for SSO.",
                      "defaultValue": "email"
                    },
                    "CREDENTIALS_SECRET": {
                      "isOptional": false,
                      "description": "Shared with the LangWatch service, so the worker can decrypt stored secrets.",
                      "defaultValue": "${{LangWatch.CREDENTIALS_SECRET}}"
                    },
                    "LANGEVALS_ENDPOINT": {
                      "isOptional": false,
                      "description": "LangEvals evaluators and guardrails over the private network.",
                      "defaultValue": "http://${{LangEvals.RAILWAY_PRIVATE_DOMAIN}}:5562"
                    },
                    "LANGWATCH_ENDPOINT": {
                      "isOptional": false,
                      "description": "Private URL of the LangWatch server, used by the other services to call it back.",
                      "defaultValue": "http://${{LangWatch.RAILWAY_PRIVATE_DOMAIN}}:5560"
                    },
                    "DISABLE_USAGE_STATS": {
                      "isOptional": false,
                      "description": "Anonymous usage statistics are off. Remove this variable to send them to the LangWatch team.",
                      "defaultValue": "true"
                    },
                    "SKIP_ENV_VALIDATION": {
                      "isOptional": false,
                      "description": "Skips the build-time env schema check, as upstream's Docker Compose does. Runtime checks still apply.",
                      "defaultValue": "true"
                    },
                    "API_TOKEN_JWT_SECRET": {
                      "isOptional": false,
                      "description": "Shared with the LangWatch service.",
                      "defaultValue": "${{LangWatch.API_TOKEN_JWT_SECRET}}"
                    },
                    "S3_SECRET_ACCESS_KEY": {
                      "isOptional": false,
                      "description": "Railway bucket secret key.",
                      "defaultValue": "${{Storage.SECRET_ACCESS_KEY}}"
                    },
                    "LANGWATCH_NLP_SERVICE": {
                      "isOptional": false,
                      "description": "NLP engine (Optimization Studio, workflows, code evaluators) over the private network.",
                      "defaultValue": "http://${{NLP.RAILWAY_PRIVATE_DOMAIN}}:5561"
                    },
                    "LW_GATEWAY_JWT_SECRET": {
                      "isOptional": false,
                      "description": "Shared with the LangWatch service.",
                      "defaultValue": "${{LangWatch.LW_GATEWAY_JWT_SECRET}}"
                    },
                    "LW_VIRTUAL_KEY_PEPPER": {
                      "isOptional": false,
                      "description": "Shared with the LangWatch service.",
                      "defaultValue": "${{LangWatch.LW_VIRTUAL_KEY_PEPPER}}"
                    },
                    "LW_GATEWAY_INTERNAL_SECRET": {
                      "isOptional": false,
                      "description": "Shared with the LangWatch service.",
                      "defaultValue": "${{LangWatch.LW_GATEWAY_INTERNAL_SECRET}}"
                    },
                    "CLICKHOUSE_BACKUP_METRICS_ENABLED": {
                      "isOptional": false,
                      "description": "This ClickHouse has no backups configured, so system.backup_log does not exist; leaving collection on fails a query on every stats tick.",
                      "defaultValue": "false"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "post_deploy": {
    "healthcheck": {
      "service": "LangWatch",
      "method": "GET",
      "path": "/api/health",
      "expect_status": 200
    }
  },
  "resources": {
    "expected_services": 7,
    "needs_volume": true
  },
  "generated_at": "2026-10-06T04:14:42.626Z",
  "generator_version": "0.1.0",
  "status": "degraded",
  "validated_at": "2026-10-05T10:55:14.751Z",
  "success_rate_30d": 0,
  "validation": {
    "last_run_id": "run_546c2a63cee64a0997c0",
    "checks": [
      {
        "name": "workflow_completed",
        "passed": false,
        "detail": "Your workspace has been restricted. Please contact support to resolve this."
      }
    ]
  }
}
