---
title: "Deploy EmulatorJS"
description: "Play retro console games in the browser and host your own EmulatorJS CDN."
category: "Other"
url: https://railway.com/deploy/emulatorjs-retro-games
---

# Deploy EmulatorJS

Play retro console games in the browser and host your own EmulatorJS CDN.

**[Deploy EmulatorJS on Railway](https://railway.com/template/emulatorjs-retro-games)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/emulatorjs-retro-games/manifest.json

- **Creator:** blueorange
- **Category:** Other

## Template content

### emulatorjs https://cdn.jsdelivr.net/gh/EmulatorJS/EmulatorJS@main/docs/Logo-light.png

- **Source:** https://github.com/gridalpha/emulatorjs-railway
- **Health check:** /healthz
- **Public domain:** Yes

## Documentation

# Deploy and Host EmulatorJS on Railway

![EmulatorJS logo](https://cdn.jsdelivr.net/gh/EmulatorJS/EmulatorJS@main/docs/Logo-light.png)

EmulatorJS is an open source, **browser-based frontend for RetroArch** that runs retro console emulators as WebAssembly, right on the visitor's device. It covers about forty systems, including NES, SNES, Nintendo 64, Game Boy, Game Boy Advance, Nintendo DS, PlayStation, PSP, Sega Genesis, Saturn, Atari, Commodore, arcade boards and DOS, with save states, shaders, cheats, touch controls and gamepad support. The project is GPL-3.0 and has about 4,300 GitHub stars. Upstream ships it as a JavaScript library, not a website, so there is no official container. This template fills that gap: one Railway service that serves the complete library as **your own CDN** and a simple player page where you pick a file from your device and it starts. Nothing is uploaded or stored on the server. It costs about $1–5/month on Railway, mostly bandwidth for the emulator cores.

---

## What This Template Deploys

| Service | Purpose |
|---|---|
| **emulatorjs** | A Caddy web server built from the `gridalpha/emulatorjs-railway` repository on port `8080` with a public domain. Serves the player at `/` and the full EmulatorJS library at `/data/`. |

There is no database and no volume. ROMs are read by the browser from the visitor's own disk, and save states live in the visitor's browser storage (IndexedDB).

The build downloads the newest stable EmulatorJS release (currently 4.2.3) and checks that every core arrived, so a broken build fails instead of quietly loading files from the public EmulatorJS CDN.

---

## About Hosting EmulatorJS

EmulatorJS does the heavy lifting in the browser. The server only hands out static files: the loader script, the compressed cores for each system, shaders and translations. There is no game server and no per-player process, so one small container can serve many players at once. That makes hosting cheap, but a few details matter.

**Your own CDN.** Most sites that embed EmulatorJS point `EJS_pathtodata` at the project's public CDN. This deployment serves the same files from your domain, with cross-origin headers already set, so your own game pages, portfolio demos or homebrew showcases can load the library from you instead of from a third party.

**Threads need isolation.** Some cores, such as PSP and DOSBox Pure, need `SharedArrayBuffer`, which browsers only enable on cross-origin isolated pages. The player page sends the required `Cross-Origin-Opener-Policy` and `Cross-Origin-Embedder-Policy` headers, so those systems work out of the box.

**No ROMs, ever.** The template includes no games and no BIOS files, and the server has no upload endpoint. Players choose a file they own from their device. Supply only files you're entitled to use.

**Controllers and mobile.** EmulatorJS reads USB and Bluetooth gamepads through the browser's Gamepad API and shows on-screen buttons on touch screens, so the same link works on a TV browser, a tablet or a phone.

**Private or public.** Leave `AUTH_USER` and `AUTH_PASSWORD` empty for a public player and CDN. Set both to put HTTP basic auth in front of everything; the `/healthz` health check stays open so Railway can still monitor it.

Typical cost: **~$1–5/month** on Railway. The container is idle most of the time; each new player downloads the core for their system once, and Railway charges $0.05 per GB of egress.

---

## Deploy EmulatorJS in Under 5 Minutes

1. Click **Deploy on Railway**. The build downloads the EmulatorJS release (the image is around 350 MB), then the service starts.
2. Optionally set `AUTH_USER` and `AUTH_PASSWORD` first if the player should be private.
3. Open the public domain. The player page asks for a game file.
4. Pick a ROM you own from your computer or phone. EmulatorJS detects the system and starts the right core.
5. Use the menu to save states, remap controls or switch shaders.

To embed it elsewhere, set `EJS_pathtodata` on your page to `https://your-domain/data/`. A minimal embed sets `EJS_player`, `EJS_core`, `EJS_gameUrl` and `EJS_pathtodata`, then loads `loader.js` from the same `/data/` path.

---

## Common Use Cases

- **Play your own cartridge dumps anywhere.** Open the player on a laptop, tablet or phone without installing an emulator.
- **Homebrew game showcases.** Let visitors play your NES, Game Boy or Genesis homebrew in the browser.
- **Self-hosted EmulatorJS CDN.** Serve the library for your own site instead of relying on the public CDN.
- **Museum and archive exhibits.** Run interactive displays of preserved software on a kiosk browser.
- **Teaching and game history.** Show students how classic games and hardware worked.
- **Retro game jams.** Give judges a link to play every entry in the browser.
- **Speedrun practice.** Use save states to drill a hard section again and again.
- **Private family arcade.** Put basic auth on it and share one URL with the household.

---

## Configuration

| Variable | Required | Description |
|---|---|---|
| `PORT` | ✅ Set | `8080`, where Caddy listens. |
| `AUTH_USER` | Optional | Basic-auth username. Leave empty for a public site. |
| `AUTH_PASSWORD` | Optional | Basic-auth password in plain text; it's hashed when the container starts. |
| `EJS_VERSION` | Optional | Pin an EmulatorJS release such as `4.2.3`. Empty tracks the latest stable release. |
| `RAILWAY_DOCKERFILE_PATH` | ✅ Set | `Dockerfile` at the repository root. |

**Auth closes the CDN too.** With basic auth on, pages on other domains can no longer load `/data/`. If you want a public library and a private player, deploy the template twice.

**Custom domain.** Add your domain to the service in Railway. The player and the `/data/` path move with it; embedding pages only need the new URL in `EJS_pathtodata`.

**Pinning versions.** Set `EJS_VERSION` and redeploy to stay on a known release; clear it to move to the newest stable one on the next build.

---

## EmulatorJS on Railway vs. Alternatives

| | EmulatorJS on Railway | Public EmulatorJS CDN | RetroArch desktop | Game streaming services |
|---|---|---|---|---|
| **Monthly cost** | ~$1–5 usage | Free | Free | Subscription |
| **Runs in a browser** | ✅ Yes | ✅ Yes | ❌ Install required | ✅ Yes |
| **Your own domain** | ✅ Yes | ❌ No | ❌ N/A | ❌ No |
| **Works on phones and tablets** | ✅ Touch controls | ✅ Touch controls | ⚠️ Per platform | ✅ Yes |
| **Bring your own ROMs** | ✅ Yes | ✅ Yes | ✅ Yes | ❌ Their catalogue |
| **Private access option** | ✅ Basic auth | ❌ No | ✅ Local | ⚠️ Account |
| **License** | ✅ GPL-3.0 | ✅ GPL-3.0 | ✅ GPL-3.0 | ❌ Proprietary |

---

## Dependencies for EmulatorJS Hosting

- Railway account. Hobby is plenty.
- Game files you own, kept on your own device.
- Optional: a USB or Bluetooth gamepad for a console feel.
- A modern browser; Chrome, Edge, Firefox and Safari all run the WebAssembly cores.

### Deployment Dependencies

- [EmulatorJS on GitHub](https://github.com/EmulatorJS/EmulatorJS): the library and releases
- [EmulatorJS docs](https://emulatorjs.org/docs/): embedding options and systems
- [emulatorjs-railway](https://github.com/gridalpha/emulatorjs-railway): the container and player used here
- [Railway Pricing](https://railway.com/pricing): egress and usage rates

### Implementation Details

The image is Caddy on Alpine with the EmulatorJS release unpacked into it. The page's Content-Security-Policy only allows connections to the same site, so if a file were missing, you'd see a console error rather than silent traffic to the public CDN. The `/data/` path sends `Access-Control-Allow-Origin` and `Cross-Origin-Resource-Policy` headers so other sites can load it.

Because nothing is stored server-side, redeploys are safe: players keep their save states in their own browsers, and the server can be rebuilt at any time.

The first time someone plays a system, the browser downloads that core and caches it, so later sessions start much faster. Cores for 3D systems such as PlayStation or Nintendo 64 are larger than those for 8-bit consoles, which is where most of the bandwidth goes.

---

## Frequently Asked Questions

**What is EmulatorJS?**
A GPL-3.0 web frontend for RetroArch that runs retro console emulators as WebAssembly in the browser, with save states, shaders and gamepad support.

**Does this template include games?**
No. It includes no ROMs and no BIOS files. You choose a file you own from your device, and it never leaves your browser.

**How much does it cost?**
About $1–5/month on Railway. Most of the cost is bandwidth when visitors download emulator cores, at $0.05 per GB.

**Where are my save states?**
In your browser's storage on each device. Clearing site data removes them, so export saves you care about.

**Can I make it private?**
Yes. Set `AUTH_USER` and `AUTH_PASSWORD` and redeploy to require a login for the player and the library.

**Which systems work?**
About forty, from NES and SNES through Nintendo 64, PlayStation, PSP, Nintendo DS, Sega consoles, Atari, arcade and DOS. Some systems also need a BIOS file you supply.

---

## Why Deploy and Host EmulatorJS on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.

By deploying EmulatorJS on Railway, you get your own retro game player and EmulatorJS CDN on your own domain, with nothing stored on the server and a tiny monthly bill.


## Similar templates

- [Rocky Linux](https://railway.com/deploy/rocky-linux) — Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀
- [Foundry Virtual Tabletop](https://railway.com/deploy/X5tR6G) — A Self-Hosted & Modern Roleplaying Platform
- [Letta Code Remote](https://railway.com/deploy/letta-code-remote) — Run a Letta Code agent 24/7. No inbound ports, just deploy.

Open this page in a browser: https://railway.com/deploy/emulatorjs-retro-games
