{
  "manifest_version": "1.0.0",
  "template": {
    "id": "a115c316-f3e6-41a6-aa29-01db5c6dd1ca",
    "slug": "openvidu-meet",
    "name": "OpenVidu Meet | Open Source Zoom Alternative",
    "description": "Video calls with rooms, chat and recording, ready to use with no code",
    "url": "https://railway.com/deploy/openvidu-meet",
    "upstream": {
      "image": "openvidu/openvidu-meet:3.9.0"
    }
  },
  "status": "unvalidated",
  "validated_at": null,
  "success_rate_30d": null,
  "services": [
    {
      "name": "Redis",
      "source": {
        "image": "redis:8.10.2-alpine"
      },
      "needs_volume": false,
      "http": false
    },
    {
      "name": "MongoDB",
      "source": {
        "image": "mongo:8.0.32"
      },
      "needs_volume": true,
      "volume_mount_path": "/data/db",
      "http": false
    },
    {
      "name": "Meet",
      "source": {
        "image": "openvidu/openvidu-meet:3.9.0"
      },
      "needs_volume": false,
      "http": true
    },
    {
      "name": "Egress",
      "source": {
        "repo": "https://github.com/two-workspaces/openvidu-meet"
      },
      "needs_volume": false,
      "http": false
    },
    {
      "name": "LiveKit",
      "source": {
        "repo": "https://github.com/two-workspaces/openvidu-meet"
      },
      "needs_volume": false,
      "tcp_ports": [
        7881
      ],
      "http": true
    }
  ],
  "required_inputs": [
    {
      "key": "REDIS_PASSWORD",
      "service": "Redis",
      "description": "Redis password",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "MONGO_INITDB_ROOT_PASSWORD",
      "service": "MongoDB",
      "description": "MongoDB root password, set on first boot",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "MONGO_INITDB_ROOT_USERNAME",
      "service": "MongoDB",
      "description": "MongoDB root user, created on first boot",
      "secret": false,
      "strategy": "default",
      "default": "root"
    },
    {
      "key": "RAILWAY_DEPLOYMENT_DRAINING_SECONDS",
      "service": "MongoDB",
      "description": "Time for MongoDB to shut down cleanly",
      "secret": false,
      "strategy": "default",
      "default": "60"
    },
    {
      "key": "PORT",
      "service": "Meet",
      "description": "Port Meet listens on",
      "secret": false,
      "strategy": "default",
      "default": "6080"
    },
    {
      "key": "LIVEKIT_URL",
      "service": "Meet",
      "description": "Media server URL that browsers connect to",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_domain"
    },
    {
      "key": "SERVER_PORT",
      "service": "Meet",
      "description": "Port Meet listens on",
      "secret": false,
      "strategy": "default",
      "default": "6080"
    },
    {
      "key": "MEET_BASE_URL",
      "service": "Meet",
      "description": "Public URL used in room and recording links",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_domain"
    },
    {
      "key": "MEET_BASE_PATH",
      "service": "Meet",
      "description": "Serve Meet at the root of its domain",
      "secret": false,
      "strategy": "default",
      "default": "/"
    },
    {
      "key": "MEET_MONGO_URI",
      "service": "Meet",
      "description": "Database connection",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "MEET_S3_BUCKET",
      "service": "Meet",
      "description": "Bucket name",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LIVEKIT_API_KEY",
      "service": "Meet",
      "description": "Must match the media server",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "MEET_AWS_REGION",
      "service": "Meet",
      "description": "Bucket region",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "MEET_REDIS_HOST",
      "service": "Meet",
      "description": "Redis host",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "MEET_REDIS_PORT",
      "service": "Meet",
      "description": "Redis port",
      "secret": false,
      "strategy": "default",
      "default": "6379"
    },
    {
      "key": "LIVEKIT_API_SECRET",
      "service": "Meet",
      "description": "Must match the media server",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "MEET_COOKIE_SECURE",
      "service": "Meet",
      "description": "Railway serves the domain over HTTPS",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "MEET_S3_ACCESS_KEY",
      "service": "Meet",
      "description": "Bucket access key",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "MEET_S3_SECRET_KEY",
      "service": "Meet",
      "description": "Bucket secret key",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LIVEKIT_URL_PRIVATE",
      "service": "Meet",
      "description": "Media server URL over the private network",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "MEET_REDIS_PASSWORD",
      "service": "Meet",
      "description": "Redis password",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "MEET_INITIAL_API_KEY",
      "service": "Meet",
      "description": "REST API key, used on first boot only",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "MEET_BLOB_STORAGE_MODE",
      "service": "Meet",
      "description": "Store recordings in the bucket",
      "secret": false,
      "strategy": "default",
      "default": "s3"
    },
    {
      "key": "MEET_INITIAL_ADMIN_USER",
      "service": "Meet",
      "description": "First admin's username, used on first boot only",
      "secret": false,
      "strategy": "default",
      "default": "admin"
    },
    {
      "key": "MEET_S3_SERVICE_ENDPOINT",
      "service": "Meet",
      "description": "Bucket endpoint",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "MEET_INITIAL_ADMIN_PASSWORD",
      "service": "Meet",
      "description": "First admin's password, used on first boot only",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "MEET_S3_WITH_PATH_STYLE_ACCESS",
      "service": "Meet",
      "description": "Address the bucket by path",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "S3_BUCKET",
      "service": "Egress",
      "description": "Bucket name",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "S3_REGION",
      "service": "Egress",
      "description": "Bucket region",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "REDIS_HOST",
      "service": "Egress",
      "description": "Redis host",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "REDIS_PORT",
      "service": "Egress",
      "description": "Redis port",
      "secret": false,
      "strategy": "default",
      "default": "6379"
    },
    {
      "key": "S3_ENDPOINT",
      "service": "Egress",
      "description": "Bucket endpoint",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "S3_ACCESS_KEY",
      "service": "Egress",
      "description": "Bucket access key",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "S3_SECRET_KEY",
      "service": "Egress",
      "description": "Bucket secret key",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LIVEKIT_WS_URL",
      "service": "Egress",
      "description": "Media server that recordings join",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_domain"
    },
    {
      "key": "REDIS_PASSWORD",
      "service": "Egress",
      "description": "Redis password",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LIVEKIT_API_KEY",
      "service": "Egress",
      "description": "Must match the media server",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LIVEKIT_API_SECRET",
      "service": "Egress",
      "description": "Must match the media server",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "PORT",
      "service": "LiveKit",
      "description": "Port for signalling and the health check",
      "secret": false,
      "strategy": "default",
      "default": "7880"
    },
    {
      "key": "LIVEKIT_API_KEY",
      "service": "LiveKit",
      "description": "Key Meet and Egress sign requests with",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "MEDIA_REDIS_HOST",
      "service": "LiveKit",
      "description": "Redis host",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "MEDIA_REDIS_PORT",
      "service": "LiveKit",
      "description": "Redis port",
      "secret": false,
      "strategy": "default",
      "default": "6379"
    },
    {
      "key": "MEET_WEBHOOK_URL",
      "service": "LiveKit",
      "description": "Tells Meet when rooms and recordings change",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "LIVEKIT_API_SECRET",
      "service": "LiveKit",
      "description": "Secret Meet and Egress sign requests with",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "MEDIA_REDIS_PASSWORD",
      "service": "LiveKit",
      "description": "Redis password",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    }
  ],
  "deploy": {
    "mcp": {
      "server": "railway",
      "tool": "deploy_template",
      "args": {
        "template_code": "openvidu-meet"
      }
    },
    "cli": "railway deploy --template openvidu-meet",
    "api": {
      "method": "POST",
      "path": "/graphql/v2",
      "body": {
        "query": "mutation templateDeploy($input: TemplateDeployV2Input!) { templateDeployV2(input: $input) { projectId workflowId } }",
        "variables": {
          "input": {
            "templateId": "a115c316-f3e6-41a6-aa29-01db5c6dd1ca",
            "serializedConfig": {
              "buckets": {
                "3a4d755d-28b6-476f-a09d-0d8565fe9395": {
                  "name": "meet-files"
                }
              },
              "services": {
                "1f845317-7735-4ade-b7b7-4663f7337734": {
                  "icon": "https://devicons.railway.app/i/redis.svg",
                  "name": "Redis",
                  "build": {},
                  "deploy": {
                    "startCommand": "/bin/sh -c \"exec docker-entrypoint.sh redis-server --requirepass $REDIS_PASSWORD --save '' --appendonly no\"",
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "redis:8.10.2-alpine"
                  },
                  "variables": {
                    "REDIS_PASSWORD": {
                      "isOptional": false,
                      "description": "Redis password",
                      "defaultValue": "{{REDIS_PASSWORD}}"
                    }
                  },
                  "networking": {
                    "serviceDomains": {}
                  }
                },
                "27094dbf-9d1c-4ce2-b2a9-2a4d1d177628": {
                  "icon": "https://devicons.railway.app/i/mongodb.svg",
                  "name": "MongoDB",
                  "build": {},
                  "deploy": {
                    "startCommand": "docker-entrypoint.sh mongod --bind_ip_all --ipv6 --wiredTigerCacheSizeGB 0.25",
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "mongo:8.0.32"
                  },
                  "variables": {
                    "MONGO_INITDB_ROOT_PASSWORD": {
                      "isOptional": false,
                      "description": "MongoDB root password, set on first boot",
                      "defaultValue": "{{MONGO_INITDB_ROOT_PASSWORD}}"
                    },
                    "MONGO_INITDB_ROOT_USERNAME": {
                      "isOptional": false,
                      "description": "MongoDB root user, created on first boot",
                      "defaultValue": "root"
                    },
                    "RAILWAY_DEPLOYMENT_DRAINING_SECONDS": {
                      "isOptional": false,
                      "description": "Time for MongoDB to shut down cleanly",
                      "defaultValue": "60"
                    }
                  },
                  "networking": {
                    "serviceDomains": {}
                  },
                  "volumeMounts": {
                    "9c61a112-a1c7-4be0-a7fc-7752c43e4c24": {
                      "mountPath": "/data/db"
                    }
                  }
                },
                "83c50d4f-5eb0-4895-af99-1414d233f656": {
                  "icon": "https://raw.githubusercontent.com/OpenVidu/openvidu-meet/main/meet-ce/frontend/src/assets/images/meet_logo.png",
                  "name": "Meet",
                  "build": {},
                  "deploy": {
                    "startCommand": null,
                    "healthcheckPath": "/health",
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "openvidu/openvidu-meet:3.9.0"
                  },
                  "variables": {
                    "PORT": {
                      "isOptional": false,
                      "description": "Port Meet listens on",
                      "defaultValue": "6080"
                    },
                    "LIVEKIT_URL": {
                      "isOptional": false,
                      "description": "Media server URL that browsers connect to",
                      "defaultValue": "wss://${{LiveKit.RAILWAY_PUBLIC_DOMAIN}}"
                    },
                    "SERVER_PORT": {
                      "isOptional": false,
                      "description": "Port Meet listens on",
                      "defaultValue": "6080"
                    },
                    "MEET_BASE_URL": {
                      "isOptional": false,
                      "description": "Public URL used in room and recording links",
                      "defaultValue": "https://${{RAILWAY_PUBLIC_DOMAIN}}"
                    },
                    "MEET_BASE_PATH": {
                      "isOptional": false,
                      "description": "Serve Meet at the root of its domain",
                      "defaultValue": "/"
                    },
                    "MEET_MONGO_URI": {
                      "isOptional": false,
                      "description": "Database connection",
                      "defaultValue": "mongodb://${{MongoDB.MONGO_INITDB_ROOT_USERNAME}}:${{MongoDB.MONGO_INITDB_ROOT_PASSWORD}}@${{MongoDB.RAILWAY_PRIVATE_DOMAIN}}:27017/?authSource=admin"
                    },
                    "MEET_S3_BUCKET": {
                      "isOptional": false,
                      "description": "Bucket name",
                      "defaultValue": "${{meet-files.BUCKET}}"
                    },
                    "LIVEKIT_API_KEY": {
                      "isOptional": false,
                      "description": "Must match the media server",
                      "defaultValue": "${{LiveKit.LIVEKIT_API_KEY}}"
                    },
                    "MEET_AWS_REGION": {
                      "isOptional": false,
                      "description": "Bucket region",
                      "defaultValue": "${{meet-files.REGION}}"
                    },
                    "MEET_REDIS_HOST": {
                      "isOptional": false,
                      "description": "Redis host",
                      "defaultValue": "${{Redis.RAILWAY_PRIVATE_DOMAIN}}"
                    },
                    "MEET_REDIS_PORT": {
                      "isOptional": false,
                      "description": "Redis port",
                      "defaultValue": "6379"
                    },
                    "LIVEKIT_API_SECRET": {
                      "isOptional": false,
                      "description": "Must match the media server",
                      "defaultValue": "${{LiveKit.LIVEKIT_API_SECRET}}"
                    },
                    "MEET_COOKIE_SECURE": {
                      "isOptional": false,
                      "description": "Railway serves the domain over HTTPS",
                      "defaultValue": "true"
                    },
                    "MEET_S3_ACCESS_KEY": {
                      "isOptional": false,
                      "description": "Bucket access key",
                      "defaultValue": "${{meet-files.ACCESS_KEY_ID}}"
                    },
                    "MEET_S3_SECRET_KEY": {
                      "isOptional": false,
                      "description": "Bucket secret key",
                      "defaultValue": "${{meet-files.SECRET_ACCESS_KEY}}"
                    },
                    "LIVEKIT_URL_PRIVATE": {
                      "isOptional": false,
                      "description": "Media server URL over the private network",
                      "defaultValue": "ws://${{LiveKit.RAILWAY_PRIVATE_DOMAIN}}:7880"
                    },
                    "MEET_REDIS_PASSWORD": {
                      "isOptional": false,
                      "description": "Redis password",
                      "defaultValue": "${{Redis.REDIS_PASSWORD}}"
                    },
                    "MEET_INITIAL_API_KEY": {
                      "isOptional": false,
                      "description": "REST API key, used on first boot only",
                      "defaultValue": "{{MEET_INITIAL_API_KEY}}"
                    },
                    "MEET_BLOB_STORAGE_MODE": {
                      "isOptional": false,
                      "description": "Store recordings in the bucket",
                      "defaultValue": "s3"
                    },
                    "MEET_INITIAL_ADMIN_USER": {
                      "isOptional": false,
                      "description": "First admin's username, used on first boot only",
                      "defaultValue": "admin"
                    },
                    "MEET_S3_SERVICE_ENDPOINT": {
                      "isOptional": false,
                      "description": "Bucket endpoint",
                      "defaultValue": "${{meet-files.ENDPOINT}}"
                    },
                    "MEET_INITIAL_ADMIN_PASSWORD": {
                      "isOptional": false,
                      "description": "First admin's password, used on first boot only",
                      "defaultValue": "{{MEET_INITIAL_ADMIN_PASSWORD}}"
                    },
                    "MEET_S3_WITH_PATH_STYLE_ACCESS": {
                      "isOptional": false,
                      "description": "Address the bucket by path",
                      "defaultValue": "true"
                    }
                  },
                  "networking": {
                    "serviceDomains": {
                      "<hasDomain>:6080": {
                        "port": 6080
                      }
                    }
                  }
                },
                "e0df39dd-7685-4067-834f-2d6ec0b7ce00": {
                  "icon": "https://raw.githubusercontent.com/OpenVidu/openvidu-meet/main/meet-ce/frontend/src/assets/images/meet_logo.png",
                  "name": "Egress",
                  "build": {},
                  "deploy": {
                    "startCommand": null,
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "repo": "https://github.com/two-workspaces/openvidu-meet",
                    "rootDirectory": "/egress"
                  },
                  "variables": {
                    "S3_BUCKET": {
                      "isOptional": false,
                      "description": "Bucket name",
                      "defaultValue": "${{meet-files.BUCKET}}"
                    },
                    "S3_REGION": {
                      "isOptional": false,
                      "description": "Bucket region",
                      "defaultValue": "${{meet-files.REGION}}"
                    },
                    "REDIS_HOST": {
                      "isOptional": false,
                      "description": "Redis host",
                      "defaultValue": "${{Redis.RAILWAY_PRIVATE_DOMAIN}}"
                    },
                    "REDIS_PORT": {
                      "isOptional": false,
                      "description": "Redis port",
                      "defaultValue": "6379"
                    },
                    "S3_ENDPOINT": {
                      "isOptional": false,
                      "description": "Bucket endpoint",
                      "defaultValue": "${{meet-files.ENDPOINT}}"
                    },
                    "S3_ACCESS_KEY": {
                      "isOptional": false,
                      "description": "Bucket access key",
                      "defaultValue": "${{meet-files.ACCESS_KEY_ID}}"
                    },
                    "S3_SECRET_KEY": {
                      "isOptional": false,
                      "description": "Bucket secret key",
                      "defaultValue": "${{meet-files.SECRET_ACCESS_KEY}}"
                    },
                    "LIVEKIT_WS_URL": {
                      "isOptional": false,
                      "description": "Media server that recordings join",
                      "defaultValue": "wss://${{LiveKit.RAILWAY_PUBLIC_DOMAIN}}"
                    },
                    "REDIS_PASSWORD": {
                      "isOptional": false,
                      "description": "Redis password",
                      "defaultValue": "${{Redis.REDIS_PASSWORD}}"
                    },
                    "LIVEKIT_API_KEY": {
                      "isOptional": false,
                      "description": "Must match the media server",
                      "defaultValue": "${{LiveKit.LIVEKIT_API_KEY}}"
                    },
                    "LIVEKIT_API_SECRET": {
                      "isOptional": false,
                      "description": "Must match the media server",
                      "defaultValue": "${{LiveKit.LIVEKIT_API_SECRET}}"
                    }
                  },
                  "networking": {
                    "serviceDomains": {}
                  }
                },
                "e8275a8f-5cea-4ceb-b09e-882182b57dcd": {
                  "icon": "https://raw.githubusercontent.com/OpenVidu/openvidu-meet/main/meet-ce/frontend/src/assets/images/meet_logo.png",
                  "name": "LiveKit",
                  "build": {},
                  "deploy": {
                    "startCommand": null,
                    "healthcheckPath": "/",
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "repo": "https://github.com/two-workspaces/openvidu-meet",
                    "rootDirectory": "/livekit"
                  },
                  "variables": {
                    "PORT": {
                      "isOptional": false,
                      "description": "Port for signalling and the health check",
                      "defaultValue": "7880"
                    },
                    "LIVEKIT_API_KEY": {
                      "isOptional": false,
                      "description": "Key Meet and Egress sign requests with",
                      "defaultValue": "{{LIVEKIT_API_KEY}}"
                    },
                    "MEDIA_REDIS_HOST": {
                      "isOptional": false,
                      "description": "Redis host",
                      "defaultValue": "${{Redis.RAILWAY_PRIVATE_DOMAIN}}"
                    },
                    "MEDIA_REDIS_PORT": {
                      "isOptional": false,
                      "description": "Redis port",
                      "defaultValue": "6379"
                    },
                    "MEET_WEBHOOK_URL": {
                      "isOptional": false,
                      "description": "Tells Meet when rooms and recordings change",
                      "defaultValue": "http://${{Meet.RAILWAY_PRIVATE_DOMAIN}}:6080/livekit/webhook"
                    },
                    "LIVEKIT_API_SECRET": {
                      "isOptional": false,
                      "description": "Secret Meet and Egress sign requests with",
                      "defaultValue": "{{LIVEKIT_API_SECRET}}"
                    },
                    "MEDIA_REDIS_PASSWORD": {
                      "isOptional": false,
                      "description": "Redis password",
                      "defaultValue": "${{Redis.REDIS_PASSWORD}}"
                    }
                  },
                  "networking": {
                    "tcpProxies": {
                      "7881": {}
                    },
                    "serviceDomains": {
                      "<hasDomain>:7880": {
                        "port": 7880
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "post_deploy": {
    "healthcheck": {
      "service": "Meet",
      "method": "GET",
      "path": "/health",
      "expect_status": 200
    }
  },
  "resources": {
    "expected_services": 5,
    "needs_volume": true
  },
  "generated_at": "2026-11-04T22:15:11.317Z",
  "generator_version": "0.1.0"
}
