Open-source project
giongto35/cloud-game avatar
giongto35/cloud-game

CloudRetro (giongto35/cloud-game): self-hosting a WebRTC retro game streaming service

Web-based Cloud Gaming service for Retro Game

2,479 stars385 forksGoApache-2.0

At a glance

What is it?
CloudRetro splits retro game streaming into a coordinator and GStreamer workers that speak WebRTC to the browser. This is what the repository documents, what it leaves open, and who should run it.
Who is it for?
Adopt CloudRetro if you already operate Linux servers with Docker and want retro titles playable in a browser tab without shipping an emulator to players. Do not adopt it if you need a supported product with a release cadence, or if your games depend on OpenGL cores and you are unwilling to configure an X server.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 26 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem CloudRetro solves is distribution, not emulation

Emulators already exist and already run retro titles well. What does not exist by default is a way to hand a running game to a player who has nothing installed. CloudRetro targets that gap: the game process stays on a server, and the player receives video and audio in a browser tab. The README describes the intent plainly, calling it an open-source cloud gaming platform for retro games that started as an experiment for testing cloud gaming performance with WebRTC and Libretro. The audience is therefore narrow and specific. It is for people who control Linux machines, are comfortable with Docker and Go, and want a browser-playable retro library. It is not for someone who wants to play a game tonight; the project hosts a public instance at cloudretro.io, but the README warns that it runs on limited servers in US East, US West, EU and Singapore, and that latency and connection problems are possible. Self-hosting is presented as the way to get a better sense of performance.

Coordinator and worker: the two-process architecture

The repository is explicit that two binaries must run at the same time. The README states that the coordinator and workers need to run simultaneously, and that workers connect to the coordinator. That is the whole topology: one coordinator, one or more workers, and a WebRTC connection from each player's browser to a worker. The worker is the heavy side. Its build target in the Makefile carries CGO flags and a PGO flag, and go.mod pulls in github.com/go-gst/go-gst, so the worker links against GStreamer and does the capture and encoding. The coordinator is built with a plain go build and no CGO flags, which fits a process that tracks rooms and routes players rather than encodes frames. The browser side is Pion, the Go WebRTC implementation, listed in go.mod as github.com/pion/webrtc/v4. The README also points at DESIGNv2.md for the design document and at a webrtchacks write-up, so the architecture is documented beyond the README. Horizontal scaling is claimed as a feature: the README says the infrastructure is designed to be able to scale under high traffic by adding more instances. That claim rests on the worker being stateless enough to add more of, and the README does not describe what the coordinator does when a worker disappears mid-session.

Installing CloudRetro with Docker Compose

The README gives two paths: a manual Go build and Docker. The Docker path is the shortest. The repository ships a docker-compose.yml with two services, cloud-game and xvfb, and the README says the compose route will spawn a docker environment and you can access the service on localhost:8000.

bash
docker compose up --build

The compose file maps three ports: 8000, 9000, and 8443/udp. It sets CLOUD_GAME_WEBRTC_SINGLEPORT=8443 and CLOUD_GAME_ENCODER_VIDEO_CODEC=vp8 in the environment, and it starts the container with a command that launches the coordinator in the background, waits for the X11 socket at /tmp/.X11-unix/X99, then starts the worker. Two host directories are mounted into the container, ./assets/cores at /usr/local/share/cloud-game/assets/cores and ./assets/games at /usr/local/share/cloud-game/assets/games. If those directories are empty on your machine, the container starts but has nothing to run.

For a manual run, the README lists two separate commands, one per process, with the worker told where the coordinator lives.

bash
go run cmd/coordinator/main.go
go run cmd/worker/main.go --coordinatorhost localhost:8000

There is also a Makefile shortcut, make dev.run, which the README says spawns two processes, one in the background and one in the foreground. The README notes that you may need to install and configure an X Server display to run OpenGL cores, and points at docker-compose.yml for the Xvfb example. That is not optional polish: the compose file's xvfb service runs Xvfb :99 -screen 0 320x240x16, and the cloud-game service waits for that socket before starting the worker.

Configuration is embedded, then overridden

The default configuration lives in pkg/config/config.yaml, and the README states it is embedded into the applications and loaded automatically at startup. Overrides come from two directions. Environment variables carry the CLOUD_GAME_ prefix, which is why the compose file uses keys like CLOUD_GAME_COORDINATOR_DEBUG and CLOUD_GAME_WORKER_DEBUG. Alternatively, a custom config.yaml can be placed next to the application, in a .cr folder in the user's home directory, or in a directory named with the -w-conf parameter, for example worker -w-conf /usr/conf. That layering is conventional and readable. The gap is that the README does not enumerate the keys inside config.yaml, so discovering what can be tuned means reading the file rather than the documentation. Two knobs are visible only because they appear in the compose file: the single-port WebRTC mode on 8443/udp, and the VP8 video codec. Anyone deploying behind a firewall will care about the first, because a single UDP port is far easier to open than a dynamic port range, and the compose file also shows a commented-out CLOUD_GAME_WEBRTC_ICEIPMAP=127.0.0.1 line, which hints at the NAT and address-mapping problem the project expects you to hit. That line is commented out and the README does not explain it.

Crowd play and shared sessions change the hosting maths

The feature list includes collaborate gameplay, described as following the idea of crowdplay and TwitchPlaysPokemon, where multiple players join the same game by addressing the same deeplink. The README links several live examples, including Pokemon Emerald and Samurai Showdown 4. This is the most interesting part of the design because it inverts the usual resource model. In a one-player-per-session setup, each additional player costs a worker slot. In crowd play, many players share one running game, so the marginal cost of a viewer is a WebRTC stream rather than an emulator process. The README also claims online multiplayer for retro games and points at Samurai Showdown with two players as a fighting game example. Treat those two claims as distinct: crowd play is many inputs into one session, multiplayer is a different arrangement, and the README does not spell out how the second is wired. The same deeplink mechanism is what makes a permanent share link possible from the hosted site's share button.

Where CloudRetro is the wrong tool

The first limitation is stated by the project itself and is easy to miss. The release list shows v2.6.1 from 2021-09-06 labelled Outdated, and the README's opening section redirects attention to CloudMorph as the author's current focus for a generic cloud gaming solution. The last push to the repository was on 2026-09-05, so the code has moved since that release, but the release channel has not. Anyone who needs versioned artifacts and a changelog should read that as a signal about what the project is. The second limitation is environmental. OpenGL cores need an X server, and the compose file solves that with Xvfb at a 320x240x16 screen. That is a software rendering path, and the README does not make claims about how OpenGL cores perform under it. The third is latency, which is inherent to the model rather than a bug: the README attributes rough performance on the public instance to limited server locations. If your players are far from your worker, no configuration fixes that. Finally, the README does not document rollback, session recovery, or what happens to a running game when a worker restarts. The docker-compose.yml mounts cores and games but no persistent state volume, and the README's cloud storage feature is described as storing game state online without naming the backend, though go.mod does include github.com/minio/minio-go/v7.

How it compares to RetroArch's netplay and to hosted services

The closest open-source alternative in spirit is RetroArch's netplay, and the difference is where the game runs. RetroArch netplay runs the emulator on every participant's machine and synchronises inputs, so each player needs the emulator, the core and the ROM, and the experience degrades when one machine falls behind. CloudRetro runs one emulator on the server and sends encoded video, so the player needs a browser and nothing else. That trade is not free: you pay in server CPU and GPU for encoding, and in network latency between player and worker, in exchange for zero client setup and a single authoritative game state. Against commercial services the comparison is about control rather than features. The README's own framing is a self-hosted platform you can run on your own Debian-based servers, with a deployment script in .github/workflows/cd that the README says pushes a configured application to a group of servers automatically. If you want someone else to run the infrastructure, CloudRetro is the wrong category of tool.

Licence, maintenance and upgrade cost

The repository is Apache-2.0, which permits commercial use and modification and includes an explicit patent grant. The practical implication for a self-hoster is that shipping a modified CloudRetro as part of a service is permitted under the licence terms, but you inherit the obligation to preserve notices and state changes. That is a summary of the licence's shape, not legal advice, and the LICENSE file is the authority. Upgrade cost is the harder question. The Dockerfile pins Go 1.27.1 and GStreamer 1.29.2 as build arguments and builds GStreamer from source with a long list of disabled features, including bad, ugly, libav, rtsp_server, python and introspection plugins. That build is reproducible but expensive, and it means the worker's media capabilities are a deliberate subset. The go.mod requires Go 1.26.0 and pins Pion WebRTC v4, so a Go toolchain upgrade and a Pion major-version bump are the two changes most likely to break a build. Because the last tagged release is from 2021 while the code has moved, upgrading means tracking master or a commit, and the README gives no supported upgrade path between versions.

Editorial conclusion

Adopt CloudRetro if you already operate Linux servers with Docker and want retro titles playable in a browser tab without shipping an emulator to players. Do not adopt it if you need a supported product with a release cadence, or if your games depend on OpenGL cores and you are unwilling to configure an X server. Before committing, run docker compose up --build and confirm the service answers on localhost:8000, then check that the cores and games you care about are present under assets/cores and assets/games, because the compose file mounts those directories and nothing else.

Frequently asked questions

How do I install cloud-game?

The README gives a Docker path and a manual path. Docker Compose is the shorter one: run docker compose up --build and the service becomes reachable on localhost:8000. The manual path requires Go and GStreamer, then two processes, go run cmd/coordinator/main.go and go run cmd/worker/main.go --coordinatorhost localhost:8000.

How do I play cloud games with cloud-game?

The game runs on a worker and the browser receives the stream over WebRTC, so the player only needs a browser. The README also describes crowd play, where several people join the same running game through a shared deeplink, and lists example links for Pokemon Emerald and Samurai Showdown 4.

Is cloud-game free?

The source is published under Apache-2.0, so you can run and modify it yourself at no licence cost. Hosting is not free in practice, because the worker encodes video and needs server resources, and the README notes the public instance runs on a limited set of servers.

What is the downside to cloud gaming with cloud-game?

The README attributes latency and connection problems on the public instance to the small number of host locations, and latency between player and worker is inherent to the model. OpenGL cores additionally require an X server, which the compose file provides through Xvfb at a 320x240x16 screen.

How much does cloud-game cost to run?

The repository does not publish cost figures. What it does document is the resource shape: one worker process per running game, built with CGO against GStreamer, plus a coordinator. The README also notes the author hosts the public instance on limited servers in US East, US West, EU and Singapore.

What is cloud-game?

CloudRetro is an open-source cloud gaming platform for retro games, written in Go. Games run on remote servers with Libretro and are streamed to a browser over WebRTC, with a coordinator process and one or more worker processes.

Official sources

  1. giongto35/cloud-game on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/giongto35-cloud-game.svg)](https://hysenlabs.com/projects/giongto35-cloud-game)