# Proxy relay

One public voice port for a whole Velocity or BungeeCord network

Source: https://socketsvc.vercel.app/proxy
By default every SocketSVC-enabled backend (Paper plugin or server mod) opens its own public WebSocket port, so a proxied network with N backend servers needs N ports forwarded. The optional proxy relay plugin is the alternative: a small proxy-side plugin that opens **one** public WebSocket port for the whole network and relays each connecting player to whichever backend they are currently on.

It ships as a single jar (`proxy/plugin`, built as `socketsvc-proxy-<version>.jar`) installable on **either** Velocity or BungeeCord/Waterfall. The jar carries both platforms' plugin descriptors and main classes, and each platform's loader only ever reads its own descriptor, so the jar you install is the same regardless of which proxy you run.

## What it does, and does not, do

- **It is a byte-level relay, not a voice server.** It never terminates the WebSocket handshake, never decodes audio, and has no spatial-audio logic — all of that still runs on each backend's own voice server, unchanged.
- **It reads only the player's `uuid` query parameter.** Every SocketSVC client already sends it when connecting (see [Voice protocol](/server/voice-protocol#connection-and-capability-negotiation)). The relay uses it to decide which backend to dial, then pipes bytes through untouched.
- **It is not a cross-server voice system.** Players on different backends never hear each other, are never in the same [voice group](/server/groups), and never appear in each other's player list. Each backend runs its own voice server with its own roster, its own groups and its own mutes; the relay only saves you from opening one public port per backend. If you want one voice space spanning a network, this is not it, and installing it will not get you closer to it — see [What one public port buys you](#what-one-public-port-buys-you).
- **No persistent voice session across server switches.** When a player changes backend server, the client reconnects the same way it does on a single-server setup — a fresh token, a fresh WebSocket connection — just through the same public port. This is an explicit non-goal, not a limitation to work around.
- **TLS works the same way as without the relay.** Put an external reverse proxy/tunnel in front of the relay's single port for `wss://`; the relay plugin itself only speaks plain `ws://`.

### What one public port buys you

The relay solves exactly one problem: a network with N SocketSVC backends otherwise needs N public
ports, N firewall rules and N tunnel hostnames. With the relay there is one of each, and the
per-backend voice ports stay internal.

It solves nothing else, and in particular it does not merge the backends into one voice space. Every
routing decision — who is in range, who is in which group, who is muted — is made by the backend the
player is currently on, out of state that backend alone holds. Two players on different backends are
as unrelated to each other as two players on two unconnected servers.

<Callout type="warn" title="Cross-server voice is not planned">
  Making groups or proximity span backends would mean the relay decoding audio and holding routing state, which is the one thing it is built not to do — it pipes bytes and reads a UUID. Doing it properly is a different component, not a setting on this one. It is tracked as a candidate in [the plan list](https://github.com/HippoDev03/SocketSVC/blob/main/docs/plan/list.md), currently with no decision to build it.
</Callout>

## Installing

<Steps>
<Step>

### Get the jar

Get it from [the download page](/download?side=proxy) or the `@proxy` file on Modrinth, or build it yourself (see [Building the proxy jar](/proxy/commands#building-the-proxy-jar)):

| Artifact | File to install | Modrinth version number |
| --- | --- | --- |
| Proxy relay plugin (optional) | `proxy/plugin/build/libs/socketsvc-proxy-<proxy>.jar`; the same jar installs on Velocity or BungeeCord/Waterfall | `<proxy>@proxy` |

</Step>
<Step>

### Point every backend at the relay

On each backend, bind the SocketSVC listener to an internal address and set `public-host`/`public-url` to the relay's public address. See [Backend configuration](/proxy/configuration#backend-configuration).

</Step>
<Step>

### Install the relay

Drop `socketsvc-proxy-<version>.jar` into your proxy's `plugins/` folder and start the proxy. On first run it writes a default `config.yml` into its data folder.

</Step>
<Step>

### Map server names to backends

Add every backend under `servers:` in the relay's `config.yml`, then run `/ssvc-proxy reload`. See [Relay configuration](/proxy/configuration#relay-configuration).

</Step>
</Steps>

Only the relay's `listen.port` needs to be open in your firewall; the per-backend voice ports stay internal.

<Cards>
  <Card title="Configuration" href="/proxy/configuration">
    Backend settings and the relay's config.yml
  </Card>
  <Card title="Commands" href="/proxy/commands">
    `/ssvc-proxy status`/`reload`, failure behaviour and building the jar
  </Card>
  <Card title="Server setup" href="/server">
    Installing the Paper plugin or server mod on each backend
  </Card>
</Cards>