Run your own matchmaking and leaderboard server for statically recompiled PS3 games: one small binary, no accounts, no cloud.
Important
Bring your own game. This repository has no game code, assets, keys, firmware or BIOS, and you need none from it. Play only games you own. re-psn is not affiliated with or endorsed by Sony Interactive Entertainment.
| 1 static server binary | the server uses only Go's standard library; the optional desktop app uses third-party modules (app/README.md) |
| 1 port | TCP and UDP 36100 for players (ports) |
| 1 C file | the client: no third-party libraries and no threads (client/psnr.c) |
| Linux and Windows | amd64 and arm64 on Linux, amd64 on Windows (releases) |
| 1 desktop app | a terminal UI to watch a server's rooms and leaderboards; release archives from v0.5.0, or build it from source (app/README.md) |
The steps for hosting a server. A game still has to be recompiled to use the client; no shipped game is claimed to work yet; see the features list for what is tested.
Linux
- Download the archive for your CPU from the releases page and check it:
sha256sum -c SHA256SUMS --ignore-missing. - Unpack it and run
./re-psn. It listens on TCP and UDP 36100. - Give your players your address and port 36100 (they must not use
127.0.0.1).
Caveat: the newest release is a pre-release; behind a router you must forward TCP and UDP 36100 (ways to connect).
Windows
- Download the
.zipfrom the releases page and compareGet-FileHashwith the line inSHA256SUMS. - Unzip it and run
re-psn.exe. - Allow TCP and UDP 36100 in the firewall, then give your players your address and port.
Caveat: the release's Windows binary is cross-built and has not been run by us; the server's tests do run on Windows in CI.
More ways to install (container, install script, from source) are under Install; the wiki has short guides for players and hosts.
| Claim | Proof |
|---|---|
| Nothing to sign up for: no accounts or passwords, and nothing is stored on disk except the log file if you set one | Security and privacy |
| The server uses only Go's standard library | go.mod has no require line, and CI enforces it (ci.yml) |
| Players behind routers get connected, with an optional relay | tested in Docker by the NAT lab |
| The client is one C file | client/psnr.c, tested against the server by client/test_psnr.c |
| Hardened and checked | fuzz tests, race detector, vulnerability and secret scans in CI |
| A lobby you can read: games by name, verified player counts and player-reported latency | in v0.5.0: features list, /api/stats |
| Every feature says how far it got | features list with status and evidence |
Not built yet; each is in the features list and the roadmap with its status: friends, presence and invites, private rooms, an opt-in SQLite store, connection checks, a graphical desktop client, a metrics endpoint, signed releases.
- Quick start: host a server
- What makes it different
- Coming soon
- About this fork
- Overview
- Example
- Features
- Desktop app
- For recomp developers
- Install
- Configuration
- Security and privacy
- More
- Website
- Credits, Licence, How AI was used
re-psn is a fork of psnr by sp00nz, who wrote the original server, the C client and the
protocol; LICENSE keeps upstream's MIT licence and copyright line, and NOTICE.md credits the upstream work.
This fork adds hardened CI and fuzz tests, invite-only rooms, limits, logging, reverse proxy support, a UDP source check, container
files and release tooling; the features list and CHANGELOG.md have the details. v0.5.0
added a lobby view with game names, verified player counts and player-reported latency, -relay-force for testing the relay from
one network, LAN discovery (-discover), the server half of opt-in peer keys, and archives of the desktop app.
A recompiled PS3 game that wants to play online needs someone to answer its matchmaking and leaderboard calls. re-psn is that someone, for a group running its own server: a LAN, a VPN, or friends connecting to one person's machine. The server keeps rooms and leaderboards and tells each player where the others are; the game traffic itself goes directly between players, and through the server only when two players cannot reach each other and the host has turned the relay on.
The message flow of a session, as a diagram
sequenceDiagram
participant A as player A (title + client/psnr.c)
participant S as re-psn server
participant B as player B (title + client/psnr.c)
A->>S: TCP 36100: HELLO (title, name, P2P port)
S-->>A: HELLO_ACK (user id, address seen, token, flags)
A->>S: UDP 36100 from the P2P socket: PROBE (token)
S-->>A: PROBE_REPLY (public address and port)
A->>S: CREATE_ROOM
S-->>A: ROOM_JOINED
B->>S: HELLO, PROBE, SEARCH_ROOMS, JOIN_ROOM
S-->>B: ROOM_JOINED with A's address and P2P port
S-->>A: MEMBER_JOINED with B's address and P2P port
A->>B: PUNCH, then game traffic, peer to peer
B->>A: PUNCH, then game traffic, peer to peer
Note over A,B: if nothing direct gets through and the server runs with -relay,<br/>datagrams and streams go through the server instead
- The host starts re-psn, listening on TCP and UDP 36100 (and, with
-http 127.0.0.1:36101, a status page there). - A game connects through the C client (
client/psnr.c): HELLO with the game's ID, the player's name and P2P port; HELLO_ACK returns a user id, the address the server sees, a token and flags (relay on, invite-only rooms). - A UDP PROBE from the game's P2P socket tells the server its public address and port (accepted only from the TCP address).
- Rooms: one player creates a room, others search and join, or join with a code. Each member entry carries the address and P2P port that work from where the receiving player is.
- Direct: both sides send PUNCH packets to open their routers, then play peer to peer.
- Relay, if needed: when nothing direct gets through and the server runs with
-relay, traffic goes through the server. Without it, players need port forwarding or a shared VPN.
Leaderboards use the same TCP connection. More in docs/architecture.md (the parts, the relay) and docs/api.md (every message).
Games are recompiled with ps3recomp, whose NP modules talk to re-psn through the C client.
That side is upstream's work and not part of this repository: it needs a ps3recomp build with
ps3recomp#200 (merged into ps3recomp on 2026-10-07), where PS3_NET_ONLINE=1 and PSNR_SERVER=host[:port]
point a game at the server (its docs/ONLINE.md lists the rest). With it, upstream has played Simpsons Arcade online, two players
from lobby to Stage 1 in sync, on one machine and later across two with either player behind a NAT.
Two test players meet in a room and connect directly, and the C client's test leaves a score; all captured from real local runs.
The transcripts: the server, two players, the status page and the C client test
Two test players meet in a room and connect directly. They are lab/natcheck.c, the NAT lab's player, which does what the
runtime does for a game (HELLO, probe, room, punch, ping, a stream) without one. Built from a fresh clone with the commands shown.
Captured from a local run on loopback with an early build (the version= field shows 0.2.0; the current release is 0.6.0): start the server with the defaults.
$ ./re-psn
time=2026-11-06T01:44:42.396Z level=INFO msg=storage backend=memory
time=2026-11-06T01:44:42.396Z level=INFO msg=started version=0.2.0 clients=[::]:36100 udp=[::]:36100 relay=false
The status page is off by default. The rest comes from a second run of the same build, started as
./re-psn -v -http 127.0.0.1:36101 (debug log, status page on).
Captured from a local run on loopback: build the test player, and let alice host a room in one terminal.
$ gcc -std=gnu11 -o natcheck client/psnr.c lab/natcheck.c
$ ./natcheck 127.0.0.1 alice host 3658
alice: P2P socket seen at 127.0.0.1:3658
alice: the other player is at 127.0.0.1:3659
PASS alice: "PONG bob" direct
PASS alice: stream direct, got "ACK from bob"
Captured from a local run on loopback: in a second terminal, while alice waits, the status page shows her room; then bob joins.
$ curl -s http://127.0.0.1:36101/api/stats
{"uptime":"2s","clients":1,"connections_total":1,"rooms":[{"id":1,"title":"NPWR00001_00","members":["alice"],"max":2,"age":"1s"}],"unlisted_rooms":0,"boards":[]}
$ ./natcheck 127.0.0.1 bob join 3659
bob: P2P socket seen at 127.0.0.1:3659
bob: the other player is at 127.0.0.1:3658
PASS bob: "PONG alice" direct
PASS bob: stream direct, got "SETUP from alice"
Captured from a local run on loopback: the C client's own test (client/test_psnr.c: HELLO, a room joined by a second client,
a room message, a score), then the leaderboard it left on the status page.
$ gcc -std=gnu11 -o test_psnr client/psnr.c client/test_psnr.c
$ ./test_psnr 127.0.0.1 36100
test_psnr: all passed
$ curl -s http://127.0.0.1:36101/api/stats
{"uptime":"6s","clients":0,"connections_total":4,"rooms":[],"unlisted_rooms":0,"boards":[{"title":"NPWR00001_00","board":1,"entries":1,"leader":"alice","best":100}]}
With -http 127.0.0.1:36101, http://127.0.0.1:36101/ shows a terminal-style status page. Overview shows both tables;
Rooms and Leaderboards open either table separately. Below, alice is hosting a room and leads the leaderboard with 100.
The screenshot uses the old image's 1000 px width, with enough height to show both tables, and comes from a real loopback server
and protocol clients (tools/art/capture-status.sh can capture another).
System/Light/Dark, text size, spacing and custom colours are browser-local appearance settings.
Routers and the relay are tested in Docker by the
NAT lab.
Available on main today; docs/features.md has every feature with its status, evidence and notes.
- Rooms: create, search, join and leave, room and member data, owner handoff, and invite-only rooms with an 8-character code.
- Leaderboards: each player's best score, higher- or lower-is-better, ranked by range or by name; kept in memory for now.
- NAT traversal: address probes and hole punching, an optional relay, and a UDP source address check.
- Hosting: limits, log levels, a status page with an optional token, reverse proxy support,
RE_PSN_*settings, Docker and Podman files, and deployment examples. - Lobby view (v0.5.0): the status page and
/api/statsname known games, count verified players and show the round trip each player reports, labelled as reported and unverified. - Peer keys (v0.5.0, server side only): an opt-in way for the server to give each pair of players in a room a shared key for tagging their direct packets. No client uses it yet, and it gives no confidentiality (docs/api.md).
- C client: one file, no third-party libraries, no threads.
- Checks: fuzz tests; CI with the race detector, vulnerability and secret scans, the NAT lab and code scanning.
Partial, unverified and planned work (release archives and the AppImage, the nginx and HAProxy examples, storage backends, the desktop apps and more) is in ROADMAP.md too.
app/ holds the start of the desktop app, a separate Go module: a Go client for the protocol, tested against the
real server, a settings file reader, re-psn-app check HOST:PORT, which connects, says HELLO and reports what the server answered,
and a terminal UI (re-psn-app with no arguments). The UI asks on first start whether this machine plays, hosts or both, then
shows the server's rooms and one leaderboard at a time over the game protocol, and edits the settings; dark or light theme in the
website's colours. The server's version, uptime and connection counts are not available over the protocol, so the UI says so.
An explicitly configured HTTP status source adds uptime, connection totals,
public-room members and board summaries natively, with the existing token rules and no browser. It falls back to the
game protocol when HTTP is unavailable; the server version remains unshared.
From v0.5.0 a release carries the app as re-psn-app-vX.Y.Z-<os>-<arch> archives (see Release archives); you can also build it from source (see app/README.md). On Linux desktops, starting without a terminal can open a supported terminal; the Windows build uses its console.
See the desktop startup instructions and the limits of local testing.
The terminal UI uses Bubble Tea and Lip Gloss
(MIT); the server module stays standard-library only. The app module needs Go 1.26 or newer; the server and the C client keep
their own requirements.
Start with Integrating re-psn into a recompiled game: existing ps3recomp bridge setup, direct C/C++ integration, callback ownership, peer/relay transport and failure handling. The minimal C example is compiled and exercised against a loopback server by the required native-client check. Source-level runtime findings are pinned; synthetic checks do not certify a title's gameplay or NAT behavior.
Recommended: download an official release archive or AppImage from the
releases page and verify it against SHA256SUMS.
Releases are pre-releases for now: the newest, v0.6.0, is on the releases page (see Release archives). Its container image is ghcr.io/undecuple/re-psn:0.6.0 (see Container).
The installer downloads the packaged release and checks it against SHA256SUMS. Download this pinned script, verify
its hash and read it before running it. Each && stops the sequence if the previous command fails:
curl -fsSL --proto '=https' --proto-redir '=https' --tlsv1.2 \
-o install.sh https://raw.githubusercontent.com/undecuple/re-psn/dc0238c2407570837ab4e14b803fb260ff77742e/scripts/install.sh &&
printf '%s install.sh\n' 'fef1f7f9a424275e45cbca80398477b4440c82b87c106ce6aa7626f3bbce1772' | sha256sum -c - &&
less install.sh &&
sh install.sh --version v0.4.0This installs into ~/.local/bin for the current user. The script comes from a pinned repository revision; the v0.4.0 release carries the same install.sh (identical SHA-256) as a release asset, listed in SHA256SUMS. See
docs/installing.md for options and the Windows installer.
The same idea for Windows (amd64): download the pinned script with the curl.exe that ships with Windows 10 and 11, check
its hash and read it before running it. In PowerShell:
curl.exe -fsSL --proto '=https' --proto-redir '=https' --tlsv1.2 -o install.ps1 https://raw.githubusercontent.com/undecuple/re-psn/2eb988b63eaebbe3a9bc7e7aa81c9daa3370780c/scripts/install.ps1
if ((Get-FileHash install.ps1 -Algorithm SHA256).Hash -ine '98ab633eeeffaecc6968e2fa342830ad4ceed4a5d2397a19dfcfb28e16d9d3a7') { throw 'install.ps1 does not match the pinned hash' }
notepad install.ps1
powershell -ExecutionPolicy Bypass -File install.ps1 -Version v0.4.0This installs the server only (re-psn.exe into %LOCALAPPDATA%\re-psn\bin, no administrator rights, no PATH change unless you add
-AddToPath); -App installs the desktop app instead (v0.5.0 and later). The script comes from a pinned repository revision, and the v0.4.0 release carries the same
install.ps1 (identical SHA-256) as a release asset. It has been tested on PowerShell 7 only and, like the Windows binary, has not been run on Windows by us. See
docs/installing.md for options.
Prerequisites: Go 1.22 or newer (as in go.mod); a C compiler only for the C client and its tests. The quick way is Setup.cmd
(Windows; it offers to install Go with winget) or ./setup.sh (Linux, macOS): both build the server in server/ and leave a
Start re-psn.cmd or start-re-psn.sh launcher, which turns the status page on at 127.0.0.1:36101. By hand from the repository root, captured from a local run on loopback (the
build prints nothing when it succeeds):
$ go version
go version go1.26.10 linux/amd64
$ go build -o re-psn ./server
Run the tests with go vet ./... and go test ./... (on Linux with a C compiler, this also builds and runs the C client test).
The 0.6.0 image is on GitHub's container registry for amd64 and arm64: docker pull ghcr.io/undecuple/re-psn:0.6.0; 0.5.0, 0.4.0, 0.3.0 and 0.2.0 are still there. It is unsigned, and
the arm64 image has been built but not run. You can also build it from this repository with Docker or Podman.
docker/README.md covers ports, the status page and Podman.
Build and run commands
docker build -f docker/Dockerfile -t re-psn . # or: podman build -f docker/Dockerfile -t re-psn .
docker run --rm -p 36100:36100 -p 36100:36100/udp re-psn
docker compose -f docker/docker-compose.yml up -d # the same, with a restart policyIt is configured only by RE_PSN_* variables.
Note
v0.6.0 is a pre-release (GitHub marks none as "latest" yet, so use the releases page): archives for Linux (amd64, arm64) and Windows (amd64), and an x86_64 AppImage, all unsigned. The Windows and arm64 binaries are cross-built and have not been run on those systems.
What each release carries, and how to check a download
Each release carries re-psn-vX.Y.Z-windows-amd64.zip, re-psn-vX.Y.Z-linux-amd64.tar.gz and
re-psn-vX.Y.Z-linux-arm64.tar.gz (built by scripts/release-build.sh): a static re-psn binary
(re-psn.exe on Windows), LICENSE, NOTICE.md and the deployment examples in examples/. From v0.4.0 it also carries the
install scripts install.sh and install.ps1 (docs/installing.md), seven assets in all (v0.3.0 has
five, without the scripts). From v0.5.0 a release adds three archives of the desktop app, re-psn-app-vX.Y.Z-<os>-<arch> (same
three platforms: the re-psn-app binary, LICENSE, NOTICE.md and the app's README), ten assets in all; the install scripts
install the app only when asked (install.sh --app, install.ps1 -App). SHA256SUMS lists the archives and the AppImage, and from v0.4.0 the scripts. Check a download with sha256sum -c SHA256SUMS --ignore-missing on Linux, or compare the output of
Get-FileHash <archive> with the line in SHA256SUMS on Windows.
Linux x86_64 also gets re-psn-vX.Y.Z-x86_64.AppImage, the same binary as one runnable file (unsigned): check it with
sha256sum -c SHA256SUMS --ignore-missing, then chmod +x it and run it like the binary. It needs FUSE to mount;
without it, add --appimage-extract-and-run as the first argument. The tarball needs neither. See
docs/releasing.md.
re-psn runs with no settings at all. docs/running.md has the full text, and deploy/re-psn.env.example lists every variable with a comment.
Each of the 35 flags can also be set as a RE_PSN_<FLAG> variable. A flag on the command line wins, then the variable; a value
that does not parse stops the server at start.
Every flag, its variable and its default
Variables are upper case, with dashes as underscores. Defaults are those of ./re-psn -h.
| Flag | Variable | Default | What it does |
|---|---|---|---|
-addr |
RE_PSN_ADDR |
:36100 |
TCP and UDP address for game clients |
-tcp-addr |
RE_PSN_TCP_ADDR |
-addr |
TCP address for game clients, if different |
-udp-addr |
RE_PSN_UDP_ADDR |
-addr |
UDP address for game clients, if different |
-http |
RE_PSN_HTTP |
none (off) | Status page and /api/stats on this address, for example 127.0.0.1:36101 |
-http-token |
RE_PSN_HTTP_TOKEN |
none | Token the status page requires (Authorization: Bearer, or ?token=) |
-admin |
RE_PSN_ADMIN |
none (off) | Experimental. A read-only admin API on its own address; needs -admin-read-token-file, and an address that is not loopback also needs -admin-tls-cert and -admin-tls-key (admin-api.md); not in v0.5.0 |
-admin-read-token-file |
RE_PSN_ADMIN_READ_TOKEN_FILE |
none | File holding the admin read token (at least 32 characters, mode 0600), read again on SIGHUP; not in v0.5.0 |
-admin-tls-cert |
RE_PSN_ADMIN_TLS_CERT |
none | Certificate file for the admin listener (TLS 1.2 or newer); not in v0.5.0 |
-admin-tls-key |
RE_PSN_ADMIN_TLS_KEY |
none | Private key file for the admin listener; not in v0.5.0 |
-max-rooms |
RE_PSN_MAX_ROOMS |
1000 |
Rooms across all titles |
-max-player-rooms |
RE_PSN_MAX_PLAYER_ROOMS |
8 |
Rooms one player may be in at once (0: no limit) |
-max-conns |
RE_PSN_MAX_CONNS |
4096 |
Open TCP connections in total, players and relay legs (0: no limit); not in v0.5.0 |
-max-conns-per-addr |
RE_PSN_MAX_CONNS_PER_ADDR |
32 |
Open connections per remote address; an IPv6 address counts as its /64 (0: no limit) |
-max-req-rate |
RE_PSN_MAX_REQ_RATE |
200 |
Requests per second per connection before it is closed (0: no limit) |
-max-udp-rate |
RE_PSN_MAX_UDP_RATE |
1000 |
UDP packets per second per source (IPv4 address or IPv6 /64), shared by probes and relay traffic; same-size burst (0: no limit); since v0.4.0 |
-v |
RE_PSN_V |
off | Same as -log-level debug |
-log-level |
RE_PSN_LOG_LEVEL |
info |
debug (room events), info, warn or error |
-log-format |
RE_PSN_LOG_FORMAT |
text |
text or json |
-log-file |
RE_PSN_LOG_FILE |
none | Also append the log to this file (mode 0600) |
-trusted-proxies |
RE_PSN_TRUSTED_PROXIES |
none | Reverse proxies allowed to name the real client (CIDRs or addresses) |
-proxy-protocol |
RE_PSN_PROXY_PROTOCOL |
off | Require a PROXY v1/v2 header from a trusted proxy on the game TCP port |
-udp-any-source |
RE_PSN_UDP_ANY_SOURCE |
off | Accept UDP probes and relay packets from another address than the player's TCP one |
-relay |
RE_PSN_RELAY |
off | Carry traffic for players who cannot reach each other (uses the host's bandwidth) |
-relay-idle |
RE_PSN_RELAY_IDLE |
600 |
With -relay, close a relay stream after this many seconds with no bytes in either direction (0: never); not in v0.5.0 |
-relay-force |
RE_PSN_RELAY_FORCE |
off | With -relay, send every stream through the relay, even between players who could connect directly. For testing the relay from one network; uses the host's bandwidth |
-no-peer-titles |
RE_PSN_NO_PEER_TITLES |
none | Comma-separated communication IDs of titles that use no peer traffic. For their players the server answers no UDP probe, relays nothing and routes nothing, and HELLO_ACK says the relay is off; rooms and scores work as usual. Other titles are unaffected; not in v0.5.0 |
-discover |
RE_PSN_DISCOVER |
off | Answer LAN discovery broadcasts on the game UDP port, from private-network senders only (connecting.md) |
-name |
RE_PSN_NAME |
none | Server name shown in LAN discovery: at most 24 printable ASCII bytes; shown only with -discover |
-lan-public-addr |
RE_PSN_LAN_PUBLIC_ADDR |
none | IPv4 address given to players outside the LAN as the address of players who connected over a private, carrier-grade NAT or link-local address; the host must forward each such player's P2P port |
-medius |
RE_PSN_MEDIUS |
off | Medius compatibility switch. No Medius protocol is implemented (scope): it opens the -medius-port listener, which closes every connection; not in v0.5.0 |
-medius-port |
RE_PSN_MEDIUS_PORT |
10071 |
TCP port of the Medius listener; a value other than the default needs -medius; not in v0.5.0 |
-medius-addr |
RE_PSN_MEDIUS_ADDR |
127.0.0.1 |
Address of the Medius listener: a loopback, private or link-local IP address, or 0.0.0.0 / :: in a container; a value other than the default needs -medius; not in v0.5.0 |
-db |
RE_PSN_DB |
off |
Score storage: off or memory |
-db-file |
RE_PSN_DB_FILE |
none | Read the -db setting from this file instead |
-replace |
RE_PSN_REPLACE |
off | If an earlier re-psn of this user holds the game port, stop it (SIGTERM) and start in its place (Linux only) |
Nothing breaks: the old PSNR_<FLAG> names still work, with a warning at start, and the binary is now re-psn.
The old names, the binary, the service unit and the image
Nothing breaks. The old PSNR_<FLAG> names are still read after RE_PSN_<FLAG>; when one is used, the server logs a warning at
start naming the old and the new variable, never the value. If both are set and differ, RE_PSN_<FLAG> wins, with a warning.
Captured from a local run on loopback:
$ PSNR_MAX_ROOMS=50 ./re-psn
time=2026-11-05T22:37:03.659Z level=WARN msg="old variable name; it still works, rename it when convenient" old=PSNR_MAX_ROOMS new=RE_PSN_MAX_ROOMS
The binary is now re-psn (re-psn.exe); no psnr copy is built. The unit re-psn.service reads /etc/psnr/psnr.env, then
/etc/re-psn/re-psn.env (run systemctl disable --now psnr first); the image and compose service are re-psn (use
--remove-orphans once). The Go module path, the C client's psnr_* API and the wire format keep upstream's names.
| Port | Protocol | Open to |
|---|---|---|
| 36100 | TCP and UDP | Every player: game connection and address probes |
| 36101 | TCP | You only, when -http turns the status page on: it lists every online ID |
each player's P2P port (3658 unless the game's PS3_NET_P2P_PORT says otherwise) |
UDP and TCP | The other players; the game opens it |
Players on one LAN or VPN need nothing forwarded. Firewall commands are in docs/running.md.
What to set before the server goes behind a proxy or on the internet.
Reverse proxy, the status page token, limits and storage
- Reverse proxy: off by default. With
-trusted-proxiesand-proxy-protocol, the real player address counts for the limits, the name rule and the address other players receive. UDP is never proxied: publish it straight to the host. See docs/running.md and deploy/README.md (Traefik tested; nginx and HAProxy not yet run). - Status page: off by default;
-http 127.0.0.1:36101turns it on. Set-http-tokenwhenever-httpis not on localhost; the server warns at start if it is reachable without one. - Limits: room data is capped at 4096 bytes; the
-max-*settings above also bound rooms, connections and request rates. UDP admission uses a bounded per-source-IP packet allowance, shared by players behind one NAT; see UDP guardrails. UDP drops are counted in/api/statswithout per-packet refusal logs. - Storage:
-dbaccepts onlyoff(the default) andmemory, which both keep scores in memory; a restart empties every board. Database backends are planned (docs/features.md); a database setting stops the server at start.
- What the server stores: nothing on disk. Rooms, names and scores live in memory; the only file is the log, if you set
-log-file(it holds online IDs and addresses, never tokens). - What other players learn: everyone in a room receives the other members' IP addresses and P2P ports, because that is how they
connect. The status page lists every connected online ID, which is why it is off unless
-httpis set, and then stays on localhost or behind a token. - No accounts: a name is not authenticated; anyone who can reach TCP 36100 can join. Run it for people you would let onto your network.
Limits, the UDP source check and how to report a vulnerability privately are in SECURITY.md.
ROADMAP.md lists what is done, what is planned (storage, health checks, desktop apps, private rooms and more) and what is out of scope: re-psn is for groups running their own server, not a public PSN replacement. Issues and pull requests are welcome; CONTRIBUTING.md has the ground rules and the tests to run.
| Document | What is in it |
|---|---|
| docs/integrating.md | Developer integration paths, a tested C example, runtime startup/callback details and acceptance checks |
| docs/architecture.md | The parts, the threadless client, why game traffic is peer to peer, the relay |
| docs/api.md | The protocol: framing, session, rooms, leaderboards, UDP, relay, HTTP |
| docs/running.md | Flags, variables, UDP source check, reverse proxy, logging, ports, firewall, storage |
| docs/fail2ban.md | Optional status-token jail, JSON journal logging, firewall placement, tests and recovery; host enforcement unverified |
| docs/features.md | Every feature with its status and evidence (generated from docs/features.tsv) |
| docs/connecting.md | Ways players connect: LAN, port forwarding, a public server, Tailscale or ZeroTier |
| docs/releasing.md | The version, the bump and cutting a pre-release (for maintainers) |
| deploy/README.md | Settings file, systemd unit, Traefik, nginx and HAProxy examples |
| docker/README.md | Building and running the container with Docker or Podman |
| lab/README.md | The NAT lab: players behind routers in Docker |
| CHANGELOG.md, NOTICE.md | What changed; third-party components and credits |
The project page is built from site/ by tools/site.py out of the features list, VERSION, the settings table above and
CHANGELOG.md. It works without script; site/terminal.js (no dependencies) adds a terminal-style interface with commands such as features, settings and install, and the plain view link switches it off. Nothing is loaded from another site, and the only request is for data.json on the same site. It is published at https://undecuple.github.io/re-psn/.
Command output has a file header, line-number gutter and syntax-style colours. See docs/website.md for controls and contributor browser checks.
- sp00nz (sp00nznet) wrote psnr: the server, the C client, the protocol, NAT traversal, the relay and the NAT lab. Thanks to everyone in upstream's contributors.
- undecuple (undecuple) maintains re-psn and wrote everything added since the fork, listed in CHANGELOG.md: the release and container tooling, the AppImage, hardening and limits, rooms and invite codes, the desktop app, the website, the documentation and the tests.
- ps3recomp is the recompiler whose NP modules use the client, and re-psn follows the model of xlive: the server handles discovery, game traffic goes peer to peer.
MIT, see LICENSE; upstream's copyright line is kept and a line for the fork's changes is added. PlayStation, PS3 and PSN are trademarks of Sony Interactive Entertainment, used only to say what the server stands in for.
Developed with AI agent assistance. Every change is reviewed and tested before it is merged: CI runs gofmt, go vet, the Go tests with the race detector on Linux (including the C client against the server) and on Windows, the features list check, a vulnerability scan, a secret scan over the full history and the NAT lab, and code scanning runs on its own workflow.

