{
  "manifest_version": "1.0.0",
  "template": {
    "id": "f0353502-b2cd-4e42-a5de-c17541f696f9",
    "slug": "langfuse-v3",
    "name": "Langfuse v3",
    "description": "Self-hosted LLM observability: tracing, evals & prompt management",
    "url": "https://railway.com/deploy/langfuse-v3",
    "upstream": {
      "image": "minio/minio:RELEASE.2025-09-07T16-13-09Z"
    }
  },
  "services": [
    {
      "name": "clickhouse",
      "source": {
        "image": "clickhouse/clickhouse-server:25.12"
      },
      "needs_volume": true,
      "volume_mount_path": "/var/lib/clickhouse",
      "http": false
    },
    {
      "name": "postgres",
      "source": {
        "image": "postgres:17"
      },
      "needs_volume": true,
      "volume_mount_path": "/var/lib/postgresql",
      "http": false
    },
    {
      "name": "langfuse-worker",
      "source": {
        "repo": "https://github.com/INAPP-Mobile/railway-langfuse-v3"
      },
      "needs_volume": false,
      "http": false
    },
    {
      "name": "redis",
      "source": {
        "repo": "https://github.com/INAPP-Mobile/railway-langfuse-v3"
      },
      "needs_volume": true,
      "volume_mount_path": "/data",
      "http": false
    },
    {
      "name": "minio",
      "source": {
        "image": "minio/minio:RELEASE.2025-09-07T16-13-09Z"
      },
      "needs_volume": true,
      "volume_mount_path": "/data",
      "http": true
    },
    {
      "name": "langfuse-web",
      "source": {
        "repo": "https://github.com/INAPP-Mobile/railway-langfuse-v3"
      },
      "needs_volume": false,
      "http": true
    }
  ],
  "required_inputs": [
    {
      "key": "CLICKHOUSE_DB",
      "service": "clickhouse",
      "description": "Default ClickHouse database. Langfuse uses this for analytics data. Referenced as ${{clickhouse.CLICKHOUSE_DB}}.",
      "secret": false,
      "strategy": "default",
      "default": "default"
    },
    {
      "key": "CLICKHOUSE_USER",
      "service": "clickhouse",
      "description": "ClickHouse username. Referenced by Langfuse as ${{clickhouse.CLICKHOUSE_USER}}.",
      "secret": false,
      "strategy": "default",
      "default": "clickhouse"
    },
    {
      "key": "CLICKHOUSE_PASSWORD",
      "service": "clickhouse",
      "description": "ClickHouse password. Auto-generated at deploy time. Referenced by Langfuse as ${{clickhouse.CLICKHOUSE_PASSWORD}}.",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT",
      "service": "clickhouse",
      "description": "Allow the default user to manage access control so Langfuse can create its tables.",
      "secret": false,
      "strategy": "default",
      "default": "1"
    },
    {
      "key": "PGDATA",
      "service": "postgres",
      "description": "Data directory inside the volume. Points below the mount root to avoid the lost+found conflict.",
      "secret": false,
      "strategy": "default",
      "default": "/var/lib/postgresql/data/pgdata"
    },
    {
      "key": "POSTGRES_DB",
      "service": "postgres",
      "description": "Default database name. Langfuse uses this database for all its data.",
      "secret": false,
      "strategy": "default",
      "default": "langfuse"
    },
    {
      "key": "DATABASE_URL",
      "service": "postgres",
      "description": "Self-referencing connection string. Consumed by the postgres service itself and referenced by Langfuse as ${{postgres.DATABASE_URL}}.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "POSTGRES_PORT",
      "service": "postgres",
      "description": "Port PostgreSQL listens on inside the container. Must stay 5432.",
      "secret": false,
      "strategy": "default",
      "default": "5432"
    },
    {
      "key": "POSTGRES_USER",
      "service": "postgres",
      "description": "PostgreSQL superuser username. Referenced by langfuse-web and langfuse-worker as ${{postgres.POSTGRES_USER}}.",
      "secret": false,
      "strategy": "default",
      "default": "postgres"
    },
    {
      "key": "POSTGRES_PASSWORD",
      "service": "postgres",
      "description": "PostgreSQL superuser password. Auto-generated at deploy time. Referenced in DATABASE_URL as ${{POSTGRES_PASSWORD}}.",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "PORT",
      "service": "langfuse-worker",
      "description": "Internal HTTP port the Langfuse worker listens on.",
      "secret": false,
      "strategy": "default",
      "default": "3030"
    },
    {
      "key": "SALT",
      "service": "langfuse-worker",
      "description": "Must match langfuse-web exactly — companion-referenced.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "REDIS_AUTH",
      "service": "langfuse-worker",
      "description": "Redis password — companion-referenced so consumer and producer always match.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "REDIS_HOST",
      "service": "langfuse-worker",
      "description": "Redis hostname, wired to the companion Redis service.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "REDIS_PORT",
      "service": "langfuse-worker",
      "description": "Redis port, companion-referenced.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "DATABASE_URL",
      "service": "langfuse-worker",
      "description": "PostgreSQL connection string, companion-referenced to the postgres service.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "NEXTAUTH_URL",
      "service": "langfuse-worker",
      "description": "Public URL of the Langfuse web service — the worker builds links against it.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_domain"
    },
    {
      "key": "CLICKHOUSE_URL",
      "service": "langfuse-worker",
      "description": "ClickHouse HTTP endpoint, wired to the companion ClickHouse service.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "ENCRYPTION_KEY",
      "service": "langfuse-worker",
      "description": "Must match langfuse-web exactly — companion-referenced. Web and worker encrypt with the same key.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "CLICKHOUSE_USER",
      "service": "langfuse-worker",
      "description": "ClickHouse username, matching the companion service.",
      "secret": false,
      "strategy": "default",
      "default": "clickhouse"
    },
    {
      "key": "NEXTAUTH_SECRET",
      "service": "langfuse-worker",
      "description": "Must match langfuse-web exactly — companion-referenced.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "TELEMETRY_ENABLED",
      "service": "langfuse-worker",
      "description": "Anonymous usage telemetry. Disabled by default in this template.",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "CLICKHOUSE_PASSWORD",
      "service": "langfuse-worker",
      "description": "ClickHouse password — companion-referenced so consumer and producer always match.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "CLICKHOUSE_MIGRATION_URL",
      "service": "langfuse-worker",
      "description": "ClickHouse native-protocol URL used by migrations. Companion-referenced, no literals.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "CLICKHOUSE_CLUSTER_ENABLED",
      "service": "langfuse-worker",
      "description": "Single-node ClickHouse: disable cluster migrations so no ZooKeeper/Keeper is required.",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "LANGFUSE_S3_BATCH_EXPORT_BUCKET",
      "service": "langfuse-worker",
      "description": "S3 bucket for batch exports.",
      "secret": false,
      "strategy": "default",
      "default": "langfuse"
    },
    {
      "key": "LANGFUSE_S3_BATCH_EXPORT_REGION",
      "service": "langfuse-worker",
      "description": "S3 region for batch exports (MinIO expects \"auto\").",
      "secret": false,
      "strategy": "default",
      "default": "auto"
    },
    {
      "key": "LANGFUSE_S3_EVENT_UPLOAD_BUCKET",
      "service": "langfuse-worker",
      "description": "S3 bucket for event uploads.",
      "secret": false,
      "strategy": "default",
      "default": "langfuse"
    },
    {
      "key": "LANGFUSE_S3_EVENT_UPLOAD_PREFIX",
      "service": "langfuse-worker",
      "description": "Key prefix for event upload objects.",
      "secret": false,
      "strategy": "default",
      "default": "events/"
    },
    {
      "key": "LANGFUSE_S3_EVENT_UPLOAD_REGION",
      "service": "langfuse-worker",
      "description": "S3 region for event uploads (MinIO expects \"auto\").",
      "secret": false,
      "strategy": "default",
      "default": "auto"
    },
    {
      "key": "LANGFUSE_S3_MEDIA_UPLOAD_BUCKET",
      "service": "langfuse-worker",
      "description": "S3 bucket for media uploads.",
      "secret": false,
      "strategy": "default",
      "default": "langfuse"
    },
    {
      "key": "LANGFUSE_S3_MEDIA_UPLOAD_PREFIX",
      "service": "langfuse-worker",
      "description": "Key prefix for media upload objects.",
      "secret": false,
      "strategy": "default",
      "default": "media/"
    },
    {
      "key": "LANGFUSE_S3_MEDIA_UPLOAD_REGION",
      "service": "langfuse-worker",
      "description": "S3 region for media uploads (MinIO expects \"auto\").",
      "secret": false,
      "strategy": "default",
      "default": "auto"
    },
    {
      "key": "LANGFUSE_S3_BATCH_EXPORT_ENABLED",
      "service": "langfuse-worker",
      "description": "Batch export to S3. Off by default; flip to true to enable.",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "LANGFUSE_S3_BATCH_EXPORT_ENDPOINT",
      "service": "langfuse-worker",
      "description": "Internal MinIO endpoint for batch exports.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT",
      "service": "langfuse-worker",
      "description": "Internal MinIO endpoint used by the server for event uploads.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT",
      "service": "langfuse-worker",
      "description": "PUBLIC MinIO endpoint used by browsers for presigned media uploads.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_domain"
    },
    {
      "key": "LANGFUSE_S3_BATCH_EXPORT_ACCESS_KEY_ID",
      "service": "langfuse-worker",
      "description": "MinIO access key for batch exports — companion-referenced.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID",
      "service": "langfuse-worker",
      "description": "MinIO access key for event uploads — companion-referenced.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LANGFUSE_S3_MEDIA_UPLOAD_ACCESS_KEY_ID",
      "service": "langfuse-worker",
      "description": "MinIO access key for media uploads — companion-referenced.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LANGFUSE_S3_BATCH_EXPORT_FORCE_PATH_STYLE",
      "service": "langfuse-worker",
      "description": "Use path-style S3 URLs (required for MinIO).",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE",
      "service": "langfuse-worker",
      "description": "Use path-style S3 URLs (required for MinIO).",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "LANGFUSE_S3_MEDIA_UPLOAD_FORCE_PATH_STYLE",
      "service": "langfuse-worker",
      "description": "Use path-style S3 URLs (required for MinIO).",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "LANGFUSE_S3_BATCH_EXPORT_EXTERNAL_ENDPOINT",
      "service": "langfuse-worker",
      "description": "Public MinIO endpoint browsers use to download export files.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_domain"
    },
    {
      "key": "LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY",
      "service": "langfuse-worker",
      "description": "MinIO secret key for batch exports — companion-referenced.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY",
      "service": "langfuse-worker",
      "description": "MinIO secret key for event uploads — companion-referenced.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY",
      "service": "langfuse-worker",
      "description": "MinIO secret key for media uploads — companion-referenced.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "REDIS_AUTH",
      "service": "redis",
      "description": "Redis password (requirepass). Auto-generated at deploy time. Referenced by langfuse-web and langfuse-worker as ${{redis.REDIS_AUTH}}.",
      "secret": false,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "REDIS_HOST",
      "service": "redis",
      "description": "Redis internal hostname. Referenced by Langfuse as ${{redis.REDIS_HOST}}.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "REDIS_PORT",
      "service": "redis",
      "description": "Redis server listening port. Referenced by Langfuse as ${{redis.REDIS_PORT}}.",
      "secret": false,
      "strategy": "default",
      "default": "6379"
    },
    {
      "key": "MINIO_ROOT_USER",
      "service": "minio",
      "description": "MinIO root username. Referenced by Langfuse as ${{minio.MINIO_ROOT_USER}}.",
      "secret": false,
      "strategy": "default",
      "default": "minio"
    },
    {
      "key": "MINIO_ROOT_PASSWORD",
      "service": "minio",
      "description": "MinIO root password. Auto-generated at deploy time. Referenced by Langfuse as ${{minio.MINIO_ROOT_PASSWORD}}.",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "PORT",
      "service": "langfuse-web",
      "description": "HTTP port Langfuse web listens on.",
      "secret": false,
      "strategy": "default",
      "default": "3000"
    },
    {
      "key": "SALT",
      "service": "langfuse-web",
      "description": "Salt used for hashing API keys. Auto-generated at deploy time. Referenced by langfuse-worker.",
      "secret": false,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "REDIS_AUTH",
      "service": "langfuse-web",
      "description": "Redis password — companion-referenced so consumer and producer always match.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "REDIS_HOST",
      "service": "langfuse-web",
      "description": "Redis hostname, wired to the companion Redis service.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "REDIS_PORT",
      "service": "langfuse-web",
      "description": "Redis port, companion-referenced.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "DATABASE_URL",
      "service": "langfuse-web",
      "description": "PostgreSQL connection string, companion-referenced to the postgres service DATABASE_URL.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "NEXTAUTH_URL",
      "service": "langfuse-web",
      "description": "Public URL of this Langfuse deployment. Auto-resolves so OAuth callbacks and email links work out of the box.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_domain"
    },
    {
      "key": "CLICKHOUSE_URL",
      "service": "langfuse-web",
      "description": "ClickHouse HTTP endpoint, wired to the companion ClickHouse service.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "ENCRYPTION_KEY",
      "service": "langfuse-web",
      "description": "64-character hex key encrypting sensitive data at rest. Must be 256 bits. Referenced by langfuse-worker.",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "CLICKHOUSE_USER",
      "service": "langfuse-web",
      "description": "ClickHouse username, matching the companion service.",
      "secret": false,
      "strategy": "default",
      "default": "clickhouse"
    },
    {
      "key": "NEXTAUTH_SECRET",
      "service": "langfuse-web",
      "description": "Cryptographic key used to sign session cookies and JWTs. Auto-generated 64-char hex at deploy time.",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "TELEMETRY_ENABLED",
      "service": "langfuse-web",
      "description": "Anonymous usage telemetry. Disabled by default in this template.",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "CLICKHOUSE_PASSWORD",
      "service": "langfuse-web",
      "description": "ClickHouse password — companion-referenced so consumer and producer always match.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "CLICKHOUSE_MIGRATION_URL",
      "service": "langfuse-web",
      "description": "ClickHouse native-protocol URL used by migrations. Companion-referenced, no literals.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "CLICKHOUSE_CLUSTER_ENABLED",
      "service": "langfuse-web",
      "description": "Single-node ClickHouse: disable cluster migrations so no ZooKeeper/Keeper is required.",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "LANGFUSE_S3_EVENT_UPLOAD_BUCKET",
      "service": "langfuse-web",
      "description": "S3 bucket for event uploads.",
      "secret": false,
      "strategy": "default",
      "default": "langfuse"
    },
    {
      "key": "LANGFUSE_S3_EVENT_UPLOAD_PREFIX",
      "service": "langfuse-web",
      "description": "Key prefix for event upload objects.",
      "secret": false,
      "strategy": "default",
      "default": "events/"
    },
    {
      "key": "LANGFUSE_S3_EVENT_UPLOAD_REGION",
      "service": "langfuse-web",
      "description": "S3 region for event uploads (MinIO expects \"auto\").",
      "secret": false,
      "strategy": "default",
      "default": "auto"
    },
    {
      "key": "LANGFUSE_S3_MEDIA_UPLOAD_BUCKET",
      "service": "langfuse-web",
      "description": "S3 bucket for media uploads.",
      "secret": false,
      "strategy": "default",
      "default": "langfuse"
    },
    {
      "key": "LANGFUSE_S3_MEDIA_UPLOAD_PREFIX",
      "service": "langfuse-web",
      "description": "Key prefix for media upload objects.",
      "secret": false,
      "strategy": "default",
      "default": "media/"
    },
    {
      "key": "LANGFUSE_S3_MEDIA_UPLOAD_REGION",
      "service": "langfuse-web",
      "description": "S3 region for media uploads (MinIO expects \"auto\").",
      "secret": false,
      "strategy": "default",
      "default": "auto"
    },
    {
      "key": "LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT",
      "service": "langfuse-web",
      "description": "Internal MinIO endpoint used by the server for event uploads.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT",
      "service": "langfuse-web",
      "description": "PUBLIC MinIO endpoint used by browsers for presigned media uploads.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_domain"
    },
    {
      "key": "LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID",
      "service": "langfuse-web",
      "description": "MinIO access key for event uploads — companion-referenced.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LANGFUSE_S3_MEDIA_UPLOAD_ACCESS_KEY_ID",
      "service": "langfuse-web",
      "description": "MinIO access key for media uploads — companion-referenced.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE",
      "service": "langfuse-web",
      "description": "Use path-style S3 URLs (required for MinIO).",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "LANGFUSE_S3_MEDIA_UPLOAD_FORCE_PATH_STYLE",
      "service": "langfuse-web",
      "description": "Use path-style S3 URLs (required for MinIO).",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY",
      "service": "langfuse-web",
      "description": "MinIO secret key for event uploads — companion-referenced.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY",
      "service": "langfuse-web",
      "description": "MinIO secret key for media uploads — companion-referenced.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    }
  ],
  "deploy": {
    "mcp": {
      "server": "railway",
      "tool": "deploy_template",
      "args": {
        "template_code": "langfuse-v3"
      }
    },
    "cli": "railway deploy --template langfuse-v3",
    "api": {
      "method": "POST",
      "path": "/graphql/v2",
      "body": {
        "query": "mutation templateDeploy($input: TemplateDeployV2Input!) { templateDeployV2(input: $input) { projectId workflowId } }",
        "variables": {
          "input": {
            "templateId": "f0353502-b2cd-4e42-a5de-c17541f696f9",
            "serializedConfig": {
              "buckets": {},
              "services": {
                "36d59eba-c6c4-42eb-815a-5df2048a9947": {
                  "icon": null,
                  "name": "clickhouse",
                  "deploy": {
                    "startCommand": null,
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "clickhouse/clickhouse-server:25.12"
                  },
                  "variables": {
                    "CLICKHOUSE_DB": {
                      "isOptional": false,
                      "description": "Default ClickHouse database. Langfuse uses this for analytics data. Referenced as ${{clickhouse.CLICKHOUSE_DB}}.",
                      "defaultValue": "default"
                    },
                    "CLICKHOUSE_USER": {
                      "isOptional": false,
                      "description": "ClickHouse username. Referenced by Langfuse as ${{clickhouse.CLICKHOUSE_USER}}.",
                      "defaultValue": "clickhouse"
                    },
                    "CLICKHOUSE_PASSWORD": {
                      "isOptional": false,
                      "description": "ClickHouse password. Auto-generated at deploy time. Referenced by Langfuse as ${{clickhouse.CLICKHOUSE_PASSWORD}}.",
                      "defaultValue": "{{CLICKHOUSE_PASSWORD}}"
                    },
                    "CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT": {
                      "description": "Allow the default user to manage access control so Langfuse can create its tables.",
                      "defaultValue": "1"
                    }
                  },
                  "volumeMounts": {
                    "36d59eba-c6c4-42eb-815a-5df2048a9947": {
                      "mountPath": "/var/lib/clickhouse"
                    }
                  }
                },
                "55430dbb-f23b-49a3-9316-c7f6c4403055": {
                  "icon": null,
                  "name": "postgres",
                  "deploy": {
                    "startCommand": null,
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "postgres:17"
                  },
                  "variables": {
                    "PGDATA": {
                      "description": "Data directory inside the volume. Points below the mount root to avoid the lost+found conflict.",
                      "defaultValue": "/var/lib/postgresql/data/pgdata"
                    },
                    "POSTGRES_DB": {
                      "isOptional": false,
                      "description": "Default database name. Langfuse uses this database for all its data.",
                      "defaultValue": "langfuse"
                    },
                    "DATABASE_URL": {
                      "isOptional": false,
                      "description": "Self-referencing connection string. Consumed by the postgres service itself and referenced by Langfuse as ${{postgres.DATABASE_URL}}.",
                      "defaultValue": "postgresql://${{POSTGRES_USER}}:${{POSTGRES_PASSWORD}}@${{RAILWAY_PRIVATE_DOMAIN}}:${{POSTGRES_PORT}}/${{POSTGRES_DB}}"
                    },
                    "POSTGRES_PORT": {
                      "isOptional": false,
                      "description": "Port PostgreSQL listens on inside the container. Must stay 5432.",
                      "defaultValue": "5432"
                    },
                    "POSTGRES_USER": {
                      "isOptional": false,
                      "description": "PostgreSQL superuser username. Referenced by langfuse-web and langfuse-worker as ${{postgres.POSTGRES_USER}}.",
                      "defaultValue": "postgres"
                    },
                    "POSTGRES_PASSWORD": {
                      "isOptional": false,
                      "description": "PostgreSQL superuser password. Auto-generated at deploy time. Referenced in DATABASE_URL as ${{POSTGRES_PASSWORD}}.",
                      "defaultValue": "{{POSTGRES_PASSWORD}}"
                    }
                  },
                  "volumeMounts": {
                    "55430dbb-f23b-49a3-9316-c7f6c4403055": {
                      "mountPath": "/var/lib/postgresql"
                    }
                  }
                },
                "bb5af4c9-111c-4f0a-87b3-85fd3aa9804c": {
                  "icon": null,
                  "name": "langfuse-worker",
                  "deploy": {
                    "startCommand": null,
                    "healthcheckPath": "",
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "repo": "https://github.com/INAPP-Mobile/railway-langfuse-v3",
                    "rootDirectory": "services/langfuse-worker"
                  },
                  "variables": {
                    "PORT": {
                      "isOptional": false,
                      "description": "Internal HTTP port the Langfuse worker listens on.",
                      "defaultValue": "3030"
                    },
                    "SALT": {
                      "isOptional": false,
                      "description": "Must match langfuse-web exactly — companion-referenced.",
                      "defaultValue": "${{langfuse-web.SALT}}"
                    },
                    "REDIS_AUTH": {
                      "isOptional": false,
                      "description": "Redis password — companion-referenced so consumer and producer always match.",
                      "defaultValue": "${{redis.REDIS_AUTH}}"
                    },
                    "REDIS_HOST": {
                      "isOptional": false,
                      "description": "Redis hostname, wired to the companion Redis service.",
                      "defaultValue": "${{redis.RAILWAY_PRIVATE_DOMAIN}}"
                    },
                    "REDIS_PORT": {
                      "isOptional": false,
                      "description": "Redis port, companion-referenced.",
                      "defaultValue": "${{redis.REDIS_PORT}}"
                    },
                    "DATABASE_URL": {
                      "isOptional": false,
                      "description": "PostgreSQL connection string, companion-referenced to the postgres service.",
                      "defaultValue": "${{postgres.DATABASE_URL}}"
                    },
                    "NEXTAUTH_URL": {
                      "isOptional": false,
                      "description": "Public URL of the Langfuse web service — the worker builds links against it.",
                      "defaultValue": "https://${{langfuse-web.RAILWAY_PUBLIC_DOMAIN}}"
                    },
                    "CLICKHOUSE_URL": {
                      "isOptional": false,
                      "description": "ClickHouse HTTP endpoint, wired to the companion ClickHouse service.",
                      "defaultValue": "http://${{clickhouse.RAILWAY_PRIVATE_DOMAIN}}:8123"
                    },
                    "ENCRYPTION_KEY": {
                      "isOptional": false,
                      "description": "Must match langfuse-web exactly — companion-referenced. Web and worker encrypt with the same key.",
                      "defaultValue": "${{langfuse-web.ENCRYPTION_KEY}}"
                    },
                    "CLICKHOUSE_USER": {
                      "isOptional": false,
                      "description": "ClickHouse username, matching the companion service.",
                      "defaultValue": "clickhouse"
                    },
                    "NEXTAUTH_SECRET": {
                      "isOptional": false,
                      "description": "Must match langfuse-web exactly — companion-referenced.",
                      "defaultValue": "${{langfuse-web.NEXTAUTH_SECRET}}"
                    },
                    "TELEMETRY_ENABLED": {
                      "isOptional": false,
                      "description": "Anonymous usage telemetry. Disabled by default in this template.",
                      "defaultValue": "false"
                    },
                    "CLICKHOUSE_PASSWORD": {
                      "isOptional": false,
                      "description": "ClickHouse password — companion-referenced so consumer and producer always match.",
                      "defaultValue": "${{clickhouse.CLICKHOUSE_PASSWORD}}"
                    },
                    "CLICKHOUSE_MIGRATION_URL": {
                      "isOptional": false,
                      "description": "ClickHouse native-protocol URL used by migrations. Companion-referenced, no literals.",
                      "defaultValue": "clickhouse://${{clickhouse.CLICKHOUSE_USER}}:${{clickhouse.CLICKHOUSE_PASSWORD}}@${{clickhouse.RAILWAY_PRIVATE_DOMAIN}}:9000/${{clickhouse.CLICKHOUSE_DB}}"
                    },
                    "CLICKHOUSE_CLUSTER_ENABLED": {
                      "isOptional": false,
                      "description": "Single-node ClickHouse: disable cluster migrations so no ZooKeeper/Keeper is required.",
                      "defaultValue": "false"
                    },
                    "LANGFUSE_S3_BATCH_EXPORT_BUCKET": {
                      "isOptional": false,
                      "description": "S3 bucket for batch exports.",
                      "defaultValue": "langfuse"
                    },
                    "LANGFUSE_S3_BATCH_EXPORT_REGION": {
                      "isOptional": false,
                      "description": "S3 region for batch exports (MinIO expects \"auto\").",
                      "defaultValue": "auto"
                    },
                    "LANGFUSE_S3_EVENT_UPLOAD_BUCKET": {
                      "isOptional": false,
                      "description": "S3 bucket for event uploads.",
                      "defaultValue": "langfuse"
                    },
                    "LANGFUSE_S3_EVENT_UPLOAD_PREFIX": {
                      "isOptional": false,
                      "description": "Key prefix for event upload objects.",
                      "defaultValue": "events/"
                    },
                    "LANGFUSE_S3_EVENT_UPLOAD_REGION": {
                      "isOptional": false,
                      "description": "S3 region for event uploads (MinIO expects \"auto\").",
                      "defaultValue": "auto"
                    },
                    "LANGFUSE_S3_MEDIA_UPLOAD_BUCKET": {
                      "isOptional": false,
                      "description": "S3 bucket for media uploads.",
                      "defaultValue": "langfuse"
                    },
                    "LANGFUSE_S3_MEDIA_UPLOAD_PREFIX": {
                      "isOptional": false,
                      "description": "Key prefix for media upload objects.",
                      "defaultValue": "media/"
                    },
                    "LANGFUSE_S3_MEDIA_UPLOAD_REGION": {
                      "isOptional": false,
                      "description": "S3 region for media uploads (MinIO expects \"auto\").",
                      "defaultValue": "auto"
                    },
                    "LANGFUSE_S3_BATCH_EXPORT_ENABLED": {
                      "isOptional": false,
                      "description": "Batch export to S3. Off by default; flip to true to enable.",
                      "defaultValue": "false"
                    },
                    "LANGFUSE_S3_BATCH_EXPORT_ENDPOINT": {
                      "isOptional": false,
                      "description": "Internal MinIO endpoint for batch exports.",
                      "defaultValue": "http://${{minio.RAILWAY_PRIVATE_DOMAIN}}:9000"
                    },
                    "LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT": {
                      "isOptional": false,
                      "description": "Internal MinIO endpoint used by the server for event uploads.",
                      "defaultValue": "http://${{minio.RAILWAY_PRIVATE_DOMAIN}}:9000"
                    },
                    "LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT": {
                      "isOptional": false,
                      "description": "PUBLIC MinIO endpoint used by browsers for presigned media uploads.",
                      "defaultValue": "https://${{minio.RAILWAY_PUBLIC_DOMAIN}}"
                    },
                    "LANGFUSE_S3_BATCH_EXPORT_ACCESS_KEY_ID": {
                      "isOptional": false,
                      "description": "MinIO access key for batch exports — companion-referenced.",
                      "defaultValue": "${{minio.MINIO_ROOT_USER}}"
                    },
                    "LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID": {
                      "isOptional": false,
                      "description": "MinIO access key for event uploads — companion-referenced.",
                      "defaultValue": "${{minio.MINIO_ROOT_USER}}"
                    },
                    "LANGFUSE_S3_MEDIA_UPLOAD_ACCESS_KEY_ID": {
                      "isOptional": false,
                      "description": "MinIO access key for media uploads — companion-referenced.",
                      "defaultValue": "${{minio.MINIO_ROOT_USER}}"
                    },
                    "LANGFUSE_S3_BATCH_EXPORT_FORCE_PATH_STYLE": {
                      "isOptional": false,
                      "description": "Use path-style S3 URLs (required for MinIO).",
                      "defaultValue": "true"
                    },
                    "LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE": {
                      "isOptional": false,
                      "description": "Use path-style S3 URLs (required for MinIO).",
                      "defaultValue": "true"
                    },
                    "LANGFUSE_S3_MEDIA_UPLOAD_FORCE_PATH_STYLE": {
                      "isOptional": false,
                      "description": "Use path-style S3 URLs (required for MinIO).",
                      "defaultValue": "true"
                    },
                    "LANGFUSE_S3_BATCH_EXPORT_EXTERNAL_ENDPOINT": {
                      "isOptional": false,
                      "description": "Public MinIO endpoint browsers use to download export files.",
                      "defaultValue": "https://${{minio.RAILWAY_PUBLIC_DOMAIN}}"
                    },
                    "LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY": {
                      "isOptional": false,
                      "description": "MinIO secret key for batch exports — companion-referenced.",
                      "defaultValue": "${{minio.MINIO_ROOT_PASSWORD}}"
                    },
                    "LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY": {
                      "isOptional": false,
                      "description": "MinIO secret key for event uploads — companion-referenced.",
                      "defaultValue": "${{minio.MINIO_ROOT_PASSWORD}}"
                    },
                    "LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY": {
                      "isOptional": false,
                      "description": "MinIO secret key for media uploads — companion-referenced.",
                      "defaultValue": "${{minio.MINIO_ROOT_PASSWORD}}"
                    }
                  }
                },
                "e4813f36-af61-4c25-925a-1e27b312b02d": {
                  "icon": null,
                  "name": "redis",
                  "deploy": {
                    "startCommand": null,
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "repo": "https://github.com/INAPP-Mobile/railway-langfuse-v3",
                    "rootDirectory": "services/redis"
                  },
                  "variables": {
                    "REDIS_AUTH": {
                      "isOptional": false,
                      "description": "Redis password (requirepass). Auto-generated at deploy time. Referenced by langfuse-web and langfuse-worker as ${{redis.REDIS_AUTH}}.",
                      "defaultValue": "{{REDIS_AUTH}}"
                    },
                    "REDIS_HOST": {
                      "isOptional": false,
                      "description": "Redis internal hostname. Referenced by Langfuse as ${{redis.REDIS_HOST}}.",
                      "defaultValue": "${{RAILWAY_PRIVATE_DOMAIN}}"
                    },
                    "REDIS_PORT": {
                      "isOptional": false,
                      "description": "Redis server listening port. Referenced by Langfuse as ${{redis.REDIS_PORT}}.",
                      "defaultValue": "6379"
                    }
                  },
                  "volumeMounts": {
                    "e4813f36-af61-4c25-925a-1e27b312b02d": {
                      "mountPath": "/data"
                    }
                  }
                },
                "e996519e-f604-4086-80aa-9cab7cb26385": {
                  "icon": null,
                  "name": "minio",
                  "deploy": {
                    "startCommand": "sh -c 'mkdir -p /data/langfuse && minio server /data --address 0.0.0.0:9000 --console-address 0.0.0.0:9001'",
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "minio/minio:RELEASE.2025-09-07T16-13-09Z"
                  },
                  "variables": {
                    "MINIO_ROOT_USER": {
                      "isOptional": false,
                      "description": "MinIO root username. Referenced by Langfuse as ${{minio.MINIO_ROOT_USER}}.",
                      "defaultValue": "minio"
                    },
                    "MINIO_ROOT_PASSWORD": {
                      "isOptional": false,
                      "description": "MinIO root password. Auto-generated at deploy time. Referenced by Langfuse as ${{minio.MINIO_ROOT_PASSWORD}}.",
                      "defaultValue": "{{MINIO_ROOT_PASSWORD}}"
                    }
                  },
                  "networking": {
                    "serviceDomains": {
                      "<hasDomain>:9000": {
                        "port": 9000
                      }
                    }
                  },
                  "volumeMounts": {
                    "e996519e-f604-4086-80aa-9cab7cb26385": {
                      "mountPath": "/data"
                    }
                  }
                },
                "ea6e1cd2-f9bf-474f-8429-b6cb07f22214": {
                  "icon": null,
                  "name": "langfuse-web",
                  "deploy": {
                    "startCommand": null,
                    "healthcheckPath": "/",
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "repo": "https://github.com/INAPP-Mobile/railway-langfuse-v3",
                    "rootDirectory": "services/langfuse-web"
                  },
                  "variables": {
                    "PORT": {
                      "isOptional": false,
                      "description": "HTTP port Langfuse web listens on.",
                      "defaultValue": "3000"
                    },
                    "SALT": {
                      "isOptional": false,
                      "description": "Salt used for hashing API keys. Auto-generated at deploy time. Referenced by langfuse-worker.",
                      "defaultValue": "{{SALT}}"
                    },
                    "REDIS_AUTH": {
                      "isOptional": false,
                      "description": "Redis password — companion-referenced so consumer and producer always match.",
                      "defaultValue": "${{redis.REDIS_AUTH}}"
                    },
                    "REDIS_HOST": {
                      "isOptional": false,
                      "description": "Redis hostname, wired to the companion Redis service.",
                      "defaultValue": "${{redis.RAILWAY_PRIVATE_DOMAIN}}"
                    },
                    "REDIS_PORT": {
                      "isOptional": false,
                      "description": "Redis port, companion-referenced.",
                      "defaultValue": "${{redis.REDIS_PORT}}"
                    },
                    "DATABASE_URL": {
                      "isOptional": false,
                      "description": "PostgreSQL connection string, companion-referenced to the postgres service DATABASE_URL.",
                      "defaultValue": "${{postgres.DATABASE_URL}}"
                    },
                    "NEXTAUTH_URL": {
                      "isOptional": false,
                      "description": "Public URL of this Langfuse deployment. Auto-resolves so OAuth callbacks and email links work out of the box.",
                      "defaultValue": "https://${{RAILWAY_PUBLIC_DOMAIN}}"
                    },
                    "CLICKHOUSE_URL": {
                      "isOptional": false,
                      "description": "ClickHouse HTTP endpoint, wired to the companion ClickHouse service.",
                      "defaultValue": "http://${{clickhouse.RAILWAY_PRIVATE_DOMAIN}}:8123"
                    },
                    "ENCRYPTION_KEY": {
                      "isOptional": false,
                      "description": "64-character hex key encrypting sensitive data at rest. Must be 256 bits. Referenced by langfuse-worker.",
                      "defaultValue": "{{ENCRYPTION_KEY}}"
                    },
                    "CLICKHOUSE_USER": {
                      "isOptional": false,
                      "description": "ClickHouse username, matching the companion service.",
                      "defaultValue": "clickhouse"
                    },
                    "NEXTAUTH_SECRET": {
                      "isOptional": false,
                      "description": "Cryptographic key used to sign session cookies and JWTs. Auto-generated 64-char hex at deploy time.",
                      "defaultValue": "{{NEXTAUTH_SECRET}}"
                    },
                    "TELEMETRY_ENABLED": {
                      "isOptional": false,
                      "description": "Anonymous usage telemetry. Disabled by default in this template.",
                      "defaultValue": "false"
                    },
                    "CLICKHOUSE_PASSWORD": {
                      "isOptional": false,
                      "description": "ClickHouse password — companion-referenced so consumer and producer always match.",
                      "defaultValue": "${{clickhouse.CLICKHOUSE_PASSWORD}}"
                    },
                    "CLICKHOUSE_MIGRATION_URL": {
                      "isOptional": false,
                      "description": "ClickHouse native-protocol URL used by migrations. Companion-referenced, no literals.",
                      "defaultValue": "clickhouse://${{clickhouse.CLICKHOUSE_USER}}:${{clickhouse.CLICKHOUSE_PASSWORD}}@${{clickhouse.RAILWAY_PRIVATE_DOMAIN}}:9000/${{clickhouse.CLICKHOUSE_DB}}"
                    },
                    "CLICKHOUSE_CLUSTER_ENABLED": {
                      "isOptional": false,
                      "description": "Single-node ClickHouse: disable cluster migrations so no ZooKeeper/Keeper is required.",
                      "defaultValue": "false"
                    },
                    "LANGFUSE_S3_EVENT_UPLOAD_BUCKET": {
                      "isOptional": false,
                      "description": "S3 bucket for event uploads.",
                      "defaultValue": "langfuse"
                    },
                    "LANGFUSE_S3_EVENT_UPLOAD_PREFIX": {
                      "isOptional": false,
                      "description": "Key prefix for event upload objects.",
                      "defaultValue": "events/"
                    },
                    "LANGFUSE_S3_EVENT_UPLOAD_REGION": {
                      "isOptional": false,
                      "description": "S3 region for event uploads (MinIO expects \"auto\").",
                      "defaultValue": "auto"
                    },
                    "LANGFUSE_S3_MEDIA_UPLOAD_BUCKET": {
                      "isOptional": false,
                      "description": "S3 bucket for media uploads.",
                      "defaultValue": "langfuse"
                    },
                    "LANGFUSE_S3_MEDIA_UPLOAD_PREFIX": {
                      "isOptional": false,
                      "description": "Key prefix for media upload objects.",
                      "defaultValue": "media/"
                    },
                    "LANGFUSE_S3_MEDIA_UPLOAD_REGION": {
                      "isOptional": false,
                      "description": "S3 region for media uploads (MinIO expects \"auto\").",
                      "defaultValue": "auto"
                    },
                    "LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT": {
                      "isOptional": false,
                      "description": "Internal MinIO endpoint used by the server for event uploads.",
                      "defaultValue": "http://${{minio.RAILWAY_PRIVATE_DOMAIN}}:9000"
                    },
                    "LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT": {
                      "isOptional": false,
                      "description": "PUBLIC MinIO endpoint used by browsers for presigned media uploads.",
                      "defaultValue": "https://${{minio.RAILWAY_PUBLIC_DOMAIN}}"
                    },
                    "LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID": {
                      "isOptional": false,
                      "description": "MinIO access key for event uploads — companion-referenced.",
                      "defaultValue": "${{minio.MINIO_ROOT_USER}}"
                    },
                    "LANGFUSE_S3_MEDIA_UPLOAD_ACCESS_KEY_ID": {
                      "isOptional": false,
                      "description": "MinIO access key for media uploads — companion-referenced.",
                      "defaultValue": "${{minio.MINIO_ROOT_USER}}"
                    },
                    "LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE": {
                      "isOptional": false,
                      "description": "Use path-style S3 URLs (required for MinIO).",
                      "defaultValue": "true"
                    },
                    "LANGFUSE_S3_MEDIA_UPLOAD_FORCE_PATH_STYLE": {
                      "isOptional": false,
                      "description": "Use path-style S3 URLs (required for MinIO).",
                      "defaultValue": "true"
                    },
                    "LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY": {
                      "isOptional": false,
                      "description": "MinIO secret key for event uploads — companion-referenced.",
                      "defaultValue": "${{minio.MINIO_ROOT_PASSWORD}}"
                    },
                    "LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY": {
                      "isOptional": false,
                      "description": "MinIO secret key for media uploads — companion-referenced.",
                      "defaultValue": "${{minio.MINIO_ROOT_PASSWORD}}"
                    }
                  },
                  "networking": {
                    "serviceDomains": {
                      "<hasDomain>": {}
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "post_deploy": {
    "healthcheck": {
      "service": "langfuse-web",
      "method": "GET",
      "path": "/",
      "expect_status": 200
    }
  },
  "resources": {
    "expected_services": 6,
    "needs_volume": true
  },
  "generated_at": "2026-09-20T10:14:37.339Z",
  "generator_version": "0.1.0",
  "status": "degraded",
  "validated_at": "2026-09-19T12:33:54.361Z",
  "success_rate_30d": 0.3333,
  "validation": {
    "last_run_id": "run_d3432486fb284139b62e",
    "checks": [
      {
        "name": "workflow_completed",
        "passed": true
      },
      {
        "name": "all_services_deployed",
        "passed": false,
        "detail": "BUILDING,BUILDING,BUILDING,FAILED,DEPLOYING,DEPLOYING"
      }
    ],
    "typical_ready_seconds": 150,
    "typical_build_seconds": 50,
    "typical_start_seconds": 10,
    "slowest_service": "langfuse-worker"
  }
}
