No description
  • JavaScript 58.1%
  • EJS 25.9%
  • CSS 9.3%
  • Lua 6.7%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-08 10:23:38 -06:00
.vscode Durrrr 2026-10-08 10:23:38 -06:00
public Durrrr 2026-10-08 10:23:38 -06:00
roblox Durrrr 2026-10-08 10:23:38 -06:00
scripts Durrrr 2026-10-08 10:23:38 -06:00
src Durrrr 2026-10-08 10:23:38 -06:00
test Durrrr 2026-10-08 10:23:38 -06:00
views Durrrr 2026-10-08 10:23:38 -06:00
.env.example Durrrr 2026-10-08 10:23:38 -06:00
.gitignore Durrrr 2026-10-08 10:23:38 -06:00
package-lock.json Durrrr 2026-10-08 10:23:38 -06:00
package.json Durrrr 2026-10-08 10:23:38 -06:00
README.md Durrrr 2026-10-08 10:23:38 -06:00

RoSocket

A Pyramus Studios project. RoSocket gives Roblox game servers WebSockets over plain HTTP.

Roblox game servers can't open WebSockets, so RoSocket opens them for you. The game sends with POST. It receives by long-polling with GET, where the request stays open until something arrives on the socket or the poll times out. Every user is a separate tenant, with their own API tokens, sockets and audit log.

Running

npm install
cp .env.example .env   # set SESSION_SECRET for production
npm start              # or: npm run dev
npm test

Open http://localhost:3000 and sign up. Create an API token on the dashboard. The full API and Luau reference are at /docs.

Admins

There are two roles: admin and user. The first account to sign up becomes an admin automatically. Existing databases are migrated so that their oldest account becomes the admin.

Admins get a Manage Users page (/admin/users) where they can:

  • create users (leave the password blank to generate one, which is shown once)
  • edit a user's email and admin flag
  • reset passwords (this signs the user out everywhere)
  • delete users (type the email to confirm). Deleting a user closes their sockets and removes their tokens and audit log.

The dashboard and audit log also have a Show all users checkbox, available to admins only. It lists every tenant's tokens, open sockets and audit entries. Revoked tokens are hidden on the dashboard by default for everyone; tick Show revoked tokens to include them. Admins who tick both see every user's revoked tokens. Admins can revoke any token or close any socket. These actions are recorded in the owner's audit log with "by": "<admin email>", and all admin.* actions are also logged under the acting admin. Admins can't demote or delete themselves, so at least one admin always exists.

To grant or remove admin from the command line (for example, to recover access):

npm run make-admin -- someone@example.com
npm run make-admin -- someone@example.com --revoke

It uses DATABASE_PATH from the environment or .env.

Roblox

  1. Turn on Game Settings → Security → Allow HTTP Requests.
  2. Download /RoSocket.lua from your server (roblox/RoSocket.lua). Add it to ServerScriptService as a ModuleScript named RoSocket.
  3. Store your token as an experience secret, or use a plain string while testing.
local RoSocket = require(game.ServerScriptService.RoSocket)
RoSocket.configure({
	BaseUrl = "https://rosocket.example.com",
	Token = game:GetService("HttpService"):GetSecret("rosocket_token"),
})

local socket = RoSocket.connect("wss://echo.websocket.org")
socket:OnMessage(function(data, isBinary) print(data) end)
socket:Send("hello")

Each socket owns two hidden (unparented) BindableEvents:

  • socket.Inbound fires with one of: ("open"), ("message", data, isBinary), ("error", msg), ("close", code, reason).
  • socket.Outbound: call :Fire(data, isBinary?) to send. You can hand this event to other scripts.

How it works

  • src/bridge.js keeps the outbound WebSockets open. It turns frames and state changes into sequenced events and answers long-polls. Clients acknowledge events with ack=<seq>, and anything not yet acknowledged is sent again. A socket that isn't polled for SOCKET_IDLE_TIMEOUT_SECONDS is closed.
  • src/targets.js only allows ws:///wss:// targets that resolve to public addresses (SSRF protection). For local development, set ALLOW_PRIVATE_TARGETS=true.
  • The audit log records signup/login, token create/revoke, and socket open/send/close/expire. Each entry includes the token, IP and Roblox Place ID (from the Roblox-Id header). Message contents are never stored.
  • Sessions and data are stored in SQLite (better-sqlite3). Passwords are hashed with bcrypt. API tokens are stored as SHA-256 hashes. Portal forms are protected by CSRF tokens.

Sockets live in memory, so a server restart closes them and RoSocket runs as a single process. See .env.example for all settings.