{
  "manifest_version": "1.0.0",
  "template": {
    "id": "61259ab1-f7e3-4a63-9837-271bd7d03660",
    "slug": "ragflow-engine",
    "name": "RAGFlow | Open-Source RAG Engine with Elasticsearch & MySQL",
    "description": "Deep-document RAG engine: chat with PDFs, docs and sheets, with citations",
    "url": "https://railway.com/deploy/ragflow-engine",
    "upstream": {
      "image": "infiniflow/ragflow:v0.27.2"
    }
  },
  "services": [
    {
      "name": "Elasticsearch",
      "source": {
        "image": "elasticsearch:8.11.3"
      },
      "needs_volume": true,
      "volume_mount_path": "/usr/share/elasticsearch/data",
      "http": false
    },
    {
      "name": "RAGFlow",
      "source": {
        "image": "infiniflow/ragflow:v0.27.2"
      },
      "needs_volume": false,
      "http": true
    },
    {
      "name": "MySQL",
      "source": {
        "image": "mysql:8.0.40"
      },
      "needs_volume": true,
      "volume_mount_path": "/var/lib/mysql",
      "http": false
    },
    {
      "name": "Redis",
      "source": {
        "image": "redis:8.10.2-alpine"
      },
      "needs_volume": true,
      "volume_mount_path": "/data",
      "http": false
    },
    {
      "name": "MinIO",
      "source": {
        "image": "pgsty/silo:RELEASE.2026-08-06T00-00-00Z"
      },
      "needs_volume": true,
      "volume_mount_path": "/data",
      "http": false
    }
  ],
  "required_inputs": [
    {
      "key": "ES_JAVA_OPTS",
      "service": "Elasticsearch",
      "description": "JVM heap. 1 GB suits small and medium knowledge bases; raise it (and the service RAM) for large ones",
      "secret": false,
      "strategy": "default",
      "default": "-Xms1g -Xmx1g"
    },
    {
      "key": "discovery.type",
      "service": "Elasticsearch",
      "description": "Single-node cluster",
      "secret": false,
      "strategy": "default",
      "default": "single-node"
    },
    {
      "key": "RAILWAY_RUN_UID",
      "service": "Elasticsearch",
      "description": "Start as root to fix volume ownership, then Elasticsearch drops to its own user",
      "secret": false,
      "strategy": "default",
      "default": "0"
    },
    {
      "key": "ELASTIC_PASSWORD",
      "service": "Elasticsearch",
      "description": "Auto-generated password of the elastic user (only applied on first boot)",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "xpack.ml.enabled",
      "service": "Elasticsearch",
      "description": "Machine-learning node features are not used by RAGFlow; off saves memory",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "bootstrap.memory_lock",
      "service": "Elasticsearch",
      "description": "Memory locking is not available on Railway",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "xpack.security.enabled",
      "service": "Elasticsearch",
      "description": "Require the elastic password",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "ingest.geoip.downloader.enabled",
      "service": "Elasticsearch",
      "description": "GeoIP database downloads are not needed",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "xpack.security.http.ssl.enabled",
      "service": "Elasticsearch",
      "description": "Plain HTTP inside the private network",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "xpack.security.transport.ssl.enabled",
      "service": "Elasticsearch",
      "description": "Single node, no transport TLS needed",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "cluster.routing.allocation.disk.threshold_enabled",
      "service": "Elasticsearch",
      "description": "Disk watermarks would make the index read-only on small Railway volumes",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "TZ",
      "service": "RAGFlow",
      "description": "Server time zone",
      "secret": false,
      "strategy": "default",
      "default": "UTC"
    },
    {
      "key": "PORT",
      "service": "RAGFlow",
      "description": "Port of RAGFlow's built-in nginx (web UI + API) - leave as is",
      "secret": false,
      "strategy": "default",
      "default": "80"
    },
    {
      "key": "ES_HOST",
      "service": "RAGFlow",
      "description": "Elasticsearch on the private network",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "DOC_ENGINE",
      "service": "RAGFlow",
      "description": "Full-text + vector index backend",
      "secret": false,
      "strategy": "default",
      "default": "elasticsearch"
    },
    {
      "key": "MINIO_HOST",
      "service": "RAGFlow",
      "description": "MinIO (uploaded files) on the private network, port 9000",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "MINIO_USER",
      "service": "RAGFlow",
      "description": "MinIO access key",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "MYSQL_HOST",
      "service": "RAGFlow",
      "description": "MySQL on the private network",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "REDIS_HOST",
      "service": "RAGFlow",
      "description": "Redis (task queue + cache) on the private network",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "MYSQL_DBNAME",
      "service": "RAGFlow",
      "description": "MySQL database",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "MINIO_PASSWORD",
      "service": "RAGFlow",
      "description": "MinIO secret key",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "MYSQL_PASSWORD",
      "service": "RAGFlow",
      "description": "MySQL root password",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "REDIS_PASSWORD",
      "service": "RAGFlow",
      "description": "Redis password",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "API_PROXY_SCHEME",
      "service": "RAGFlow",
      "description": "Serve the API with the Python server (upstream default)",
      "secret": false,
      "strategy": "default",
      "default": "python"
    },
    {
      "key": "ELASTIC_PASSWORD",
      "service": "RAGFlow",
      "description": "Elasticsearch password",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "ENABLE_DATA_SYNC",
      "service": "RAGFlow",
      "description": "true = run the data-source sync worker for connectors like Confluence, Notion, Google Drive or S3 (about +0.8 GB RAM). File uploads work without it",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "REGISTER_ENABLED",
      "service": "RAGFlow",
      "description": "1 = anyone who reaches the URL can sign up (each user gets their own workspace). Set to 0 after creating your accounts",
      "secret": false,
      "strategy": "default",
      "default": "1"
    },
    {
      "key": "RAGFLOW_SECRET_KEY",
      "service": "RAGFlow",
      "description": "Signs login sessions and API tokens. Changing it logs everyone out",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "ENABLE_ADMIN_SERVER",
      "service": "RAGFlow",
      "description": "true = also run the admin server: the /admin panel and the built-in superuser below (about +1 GB RAM)",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "ADMIN_DEFAULT_PASSWORD",
      "service": "RAGFlow",
      "description": "Password of the built-in superuser (DEFAULT_SUPERUSER_EMAIL), created when the admin server first starts (ENABLE_ADMIN_SERVER=true). Changing this later does not change an existing account",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "DEFAULT_SUPERUSER_EMAIL",
      "service": "RAGFlow",
      "description": "Email of the built-in superuser created when the admin server first starts",
      "secret": false,
      "strategy": "default",
      "default": "admin@ragflow.io"
    },
    {
      "key": "RAILWAY_HEALTHCHECK_TIMEOUT_SEC",
      "service": "RAGFlow",
      "description": "The image is ~13 GB and first boot creates the database schema, so allow a slow first start",
      "secret": false,
      "strategy": "default",
      "default": "900"
    },
    {
      "key": "MYSQL_DATABASE",
      "service": "MySQL",
      "description": "Database created on first boot",
      "secret": false,
      "strategy": "default",
      "default": "rag_flow"
    },
    {
      "key": "MYSQL_ROOT_PASSWORD",
      "service": "MySQL",
      "description": "Auto-generated MySQL root password",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "RAILWAY_DEPLOYMENT_DRAINING_SECONDS",
      "service": "MySQL",
      "description": "Time for MySQL to shut down cleanly on redeploy",
      "secret": false,
      "strategy": "default",
      "default": "60"
    },
    {
      "key": "REDIS_PASSWORD",
      "service": "Redis",
      "description": "Auto-generated Redis password",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "MINIO_ROOT_USER",
      "service": "MinIO",
      "description": "MinIO access key",
      "secret": false,
      "strategy": "default",
      "default": "ragflow"
    },
    {
      "key": "MINIO_ROOT_PASSWORD",
      "service": "MinIO",
      "description": "Auto-generated MinIO secret key",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    }
  ],
  "deploy": {
    "mcp": {
      "server": "railway",
      "tool": "deploy_template",
      "args": {
        "template_code": "ragflow-engine"
      }
    },
    "cli": "railway deploy --template ragflow-engine",
    "api": {
      "method": "POST",
      "path": "/graphql/v2",
      "body": {
        "query": "mutation templateDeploy($input: TemplateDeployV2Input!) { templateDeployV2(input: $input) { projectId workflowId } }",
        "variables": {
          "input": {
            "templateId": "61259ab1-f7e3-4a63-9837-271bd7d03660",
            "serializedConfig": {
              "services": {
                "1e97deb0-b436-4f8a-8deb-c89b84293928": {
                  "icon": "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/elasticsearch.svg",
                  "name": "Elasticsearch",
                  "build": {},
                  "deploy": {
                    "startCommand": "/bin/bash -c \"chown -R 1000:0 /usr/share/elasticsearch/data && exec env HOME=/usr/share/elasticsearch setpriv --reuid=1000 --regid=0 --clear-groups /usr/local/bin/docker-entrypoint.sh eswrapper\"",
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "elasticsearch:8.11.3"
                  },
                  "variables": {
                    "ES_JAVA_OPTS": {
                      "isOptional": false,
                      "description": "JVM heap. 1 GB suits small and medium knowledge bases; raise it (and the service RAM) for large ones",
                      "defaultValue": "-Xms1g -Xmx1g"
                    },
                    "discovery.type": {
                      "isOptional": false,
                      "description": "Single-node cluster",
                      "defaultValue": "single-node"
                    },
                    "RAILWAY_RUN_UID": {
                      "isOptional": false,
                      "description": "Start as root to fix volume ownership, then Elasticsearch drops to its own user",
                      "defaultValue": "0"
                    },
                    "ELASTIC_PASSWORD": {
                      "isOptional": false,
                      "description": "Auto-generated password of the elastic user (only applied on first boot)",
                      "defaultValue": "{{ELASTIC_PASSWORD}}"
                    },
                    "xpack.ml.enabled": {
                      "isOptional": false,
                      "description": "Machine-learning node features are not used by RAGFlow; off saves memory",
                      "defaultValue": "false"
                    },
                    "bootstrap.memory_lock": {
                      "isOptional": false,
                      "description": "Memory locking is not available on Railway",
                      "defaultValue": "false"
                    },
                    "xpack.security.enabled": {
                      "isOptional": false,
                      "description": "Require the elastic password",
                      "defaultValue": "true"
                    },
                    "ingest.geoip.downloader.enabled": {
                      "isOptional": false,
                      "description": "GeoIP database downloads are not needed",
                      "defaultValue": "false"
                    },
                    "xpack.security.http.ssl.enabled": {
                      "isOptional": false,
                      "description": "Plain HTTP inside the private network",
                      "defaultValue": "false"
                    },
                    "xpack.security.transport.ssl.enabled": {
                      "isOptional": false,
                      "description": "Single node, no transport TLS needed",
                      "defaultValue": "false"
                    },
                    "cluster.routing.allocation.disk.threshold_enabled": {
                      "isOptional": false,
                      "description": "Disk watermarks would make the index read-only on small Railway volumes",
                      "defaultValue": "false"
                    }
                  },
                  "networking": {
                    "serviceDomains": {}
                  },
                  "volumeMounts": {
                    "f496a597-1656-4fbe-94d8-94cdfdb58411": {
                      "mountPath": "/usr/share/elasticsearch/data"
                    }
                  }
                },
                "7453e10c-ab22-4e25-b694-2e2b0411be6e": {
                  "icon": "https://raw.githubusercontent.com/nomideusz/ragflow-railway/main/icon.svg",
                  "name": "RAGFlow",
                  "build": {},
                  "deploy": {
                    "startCommand": "/bin/bash -c \"a=--init-model-provider-tables; [ x$ENABLE_ADMIN_SERVER = xtrue ] && a=$a' --enable-adminserver'; [ x$ENABLE_DATA_SYNC = xtrue ] || a=$a' --disable-datasync'; exec /ragflow/entrypoint.sh $a\"",
                    "healthcheckPath": "/api/v1/system/healthz",
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "infiniflow/ragflow:v0.27.2"
                  },
                  "variables": {
                    "TZ": {
                      "isOptional": false,
                      "description": "Server time zone",
                      "defaultValue": "UTC"
                    },
                    "PORT": {
                      "isOptional": false,
                      "description": "Port of RAGFlow's built-in nginx (web UI + API) - leave as is",
                      "defaultValue": "80"
                    },
                    "ES_HOST": {
                      "isOptional": false,
                      "description": "Elasticsearch on the private network",
                      "defaultValue": "${{Elasticsearch.RAILWAY_PRIVATE_DOMAIN}}"
                    },
                    "DOC_ENGINE": {
                      "isOptional": false,
                      "description": "Full-text + vector index backend",
                      "defaultValue": "elasticsearch"
                    },
                    "MINIO_HOST": {
                      "isOptional": false,
                      "description": "MinIO (uploaded files) on the private network, port 9000",
                      "defaultValue": "${{MinIO.RAILWAY_PRIVATE_DOMAIN}}"
                    },
                    "MINIO_USER": {
                      "isOptional": false,
                      "description": "MinIO access key",
                      "defaultValue": "${{MinIO.MINIO_ROOT_USER}}"
                    },
                    "MYSQL_HOST": {
                      "isOptional": false,
                      "description": "MySQL on the private network",
                      "defaultValue": "${{MySQL.RAILWAY_PRIVATE_DOMAIN}}"
                    },
                    "REDIS_HOST": {
                      "isOptional": false,
                      "description": "Redis (task queue + cache) on the private network",
                      "defaultValue": "${{Redis.RAILWAY_PRIVATE_DOMAIN}}"
                    },
                    "MYSQL_DBNAME": {
                      "isOptional": false,
                      "description": "MySQL database",
                      "defaultValue": "${{MySQL.MYSQL_DATABASE}}"
                    },
                    "MINIO_PASSWORD": {
                      "isOptional": false,
                      "description": "MinIO secret key",
                      "defaultValue": "${{MinIO.MINIO_ROOT_PASSWORD}}"
                    },
                    "MYSQL_PASSWORD": {
                      "isOptional": false,
                      "description": "MySQL root password",
                      "defaultValue": "${{MySQL.MYSQL_ROOT_PASSWORD}}"
                    },
                    "REDIS_PASSWORD": {
                      "isOptional": false,
                      "description": "Redis password",
                      "defaultValue": "${{Redis.REDIS_PASSWORD}}"
                    },
                    "API_PROXY_SCHEME": {
                      "isOptional": false,
                      "description": "Serve the API with the Python server (upstream default)",
                      "defaultValue": "python"
                    },
                    "ELASTIC_PASSWORD": {
                      "isOptional": false,
                      "description": "Elasticsearch password",
                      "defaultValue": "${{Elasticsearch.ELASTIC_PASSWORD}}"
                    },
                    "ENABLE_DATA_SYNC": {
                      "isOptional": false,
                      "description": "true = run the data-source sync worker for connectors like Confluence, Notion, Google Drive or S3 (about +0.8 GB RAM). File uploads work without it",
                      "defaultValue": "false"
                    },
                    "REGISTER_ENABLED": {
                      "isOptional": false,
                      "description": "1 = anyone who reaches the URL can sign up (each user gets their own workspace). Set to 0 after creating your accounts",
                      "defaultValue": "1"
                    },
                    "RAGFLOW_SECRET_KEY": {
                      "isOptional": false,
                      "description": "Signs login sessions and API tokens. Changing it logs everyone out",
                      "defaultValue": "{{RAGFLOW_SECRET_KEY}}"
                    },
                    "ENABLE_ADMIN_SERVER": {
                      "isOptional": false,
                      "description": "true = also run the admin server: the /admin panel and the built-in superuser below (about +1 GB RAM)",
                      "defaultValue": "false"
                    },
                    "ADMIN_DEFAULT_PASSWORD": {
                      "isOptional": false,
                      "description": "Password of the built-in superuser (DEFAULT_SUPERUSER_EMAIL), created when the admin server first starts (ENABLE_ADMIN_SERVER=true). Changing this later does not change an existing account",
                      "defaultValue": "{{ADMIN_DEFAULT_PASSWORD}}"
                    },
                    "DEFAULT_SUPERUSER_EMAIL": {
                      "isOptional": false,
                      "description": "Email of the built-in superuser created when the admin server first starts",
                      "defaultValue": "admin@ragflow.io"
                    },
                    "RAILWAY_HEALTHCHECK_TIMEOUT_SEC": {
                      "isOptional": false,
                      "description": "The image is ~13 GB and first boot creates the database schema, so allow a slow first start",
                      "defaultValue": "900"
                    }
                  },
                  "networking": {
                    "serviceDomains": {
                      "<hasDomain>": {}
                    }
                  },
                  "volumeMounts": {}
                },
                "a197ee86-0e6a-4fbe-ae6f-da194ec8fb3b": {
                  "icon": "https://devicons.railway.app/i/mysql.svg",
                  "name": "MySQL",
                  "build": {},
                  "deploy": {
                    "startCommand": "docker-entrypoint.sh mysqld --datadir=/var/lib/mysql/data --max_connections=1000 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --default-authentication-plugin=mysql_native_password --skip-log-bin --performance-schema=OFF",
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "mysql:8.0.40"
                  },
                  "variables": {
                    "MYSQL_DATABASE": {
                      "isOptional": false,
                      "description": "Database created on first boot",
                      "defaultValue": "rag_flow"
                    },
                    "MYSQL_ROOT_PASSWORD": {
                      "isOptional": false,
                      "description": "Auto-generated MySQL root password",
                      "defaultValue": "{{MYSQL_ROOT_PASSWORD}}"
                    },
                    "RAILWAY_DEPLOYMENT_DRAINING_SECONDS": {
                      "isOptional": false,
                      "description": "Time for MySQL to shut down cleanly on redeploy",
                      "defaultValue": "60"
                    }
                  },
                  "networking": {
                    "serviceDomains": {}
                  },
                  "volumeMounts": {
                    "73343c72-8fa5-4172-a7f6-cc3553e64045": {
                      "mountPath": "/var/lib/mysql"
                    }
                  }
                },
                "d11c0314-4741-4b3e-aadb-78678a9e0cb1": {
                  "icon": "https://devicons.railway.app/i/redis.svg",
                  "name": "Redis",
                  "build": {},
                  "deploy": {
                    "startCommand": "/bin/sh -c \"chown -R redis:redis /data && exec docker-entrypoint.sh redis-server --requirepass $REDIS_PASSWORD --appendonly yes --maxmemory 128mb --maxmemory-policy volatile-lru\"",
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "redis:8.10.2-alpine"
                  },
                  "variables": {
                    "REDIS_PASSWORD": {
                      "isOptional": false,
                      "description": "Auto-generated Redis password",
                      "defaultValue": "{{REDIS_PASSWORD}}"
                    }
                  },
                  "networking": {
                    "serviceDomains": {}
                  },
                  "volumeMounts": {
                    "680f85c8-1316-4886-ad20-9560fd1905e9": {
                      "mountPath": "/data"
                    }
                  }
                },
                "d1d528d5-0212-4753-93f1-6e8e64712b46": {
                  "icon": "https://devicons.railway.app/i/minio.svg",
                  "name": "MinIO",
                  "build": {},
                  "deploy": {
                    "startCommand": "/usr/bin/docker-entrypoint.sh server /data --address :9000 --console-address :9001",
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "pgsty/silo:RELEASE.2026-08-06T00-00-00Z"
                  },
                  "variables": {
                    "MINIO_ROOT_USER": {
                      "isOptional": false,
                      "description": "MinIO access key",
                      "defaultValue": "ragflow"
                    },
                    "MINIO_ROOT_PASSWORD": {
                      "isOptional": false,
                      "description": "Auto-generated MinIO secret key",
                      "defaultValue": "{{MINIO_ROOT_PASSWORD}}"
                    }
                  },
                  "networking": {
                    "serviceDomains": {}
                  },
                  "volumeMounts": {
                    "18f3b98a-4447-4363-a23f-5f3139a696af": {
                      "mountPath": "/data"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "post_deploy": {
    "healthcheck": {
      "service": "RAGFlow",
      "method": "GET",
      "path": "/api/v1/system/healthz",
      "expect_status": 200
    }
  },
  "resources": {
    "expected_services": 5,
    "needs_volume": true
  },
  "generated_at": "2026-10-12T04:14:37.344Z",
  "generator_version": "0.1.0",
  "status": "validated",
  "validated_at": "2026-10-12T01:07:51.745Z",
  "success_rate_30d": 1,
  "validation": {
    "last_run_id": "run_3e68b88303ca49b59091",
    "checks": [
      {
        "name": "workflow_completed",
        "passed": true
      },
      {
        "name": "all_services_deployed",
        "passed": true
      },
      {
        "name": "healthcheck",
        "passed": true
      },
      {
        "name": "stays_up",
        "passed": true
      }
    ],
    "typical_ready_seconds": 158,
    "typical_build_seconds": 0,
    "typical_start_seconds": 101,
    "slowest_service": "RAGFlow"
  }
}
