# Connect a server you host elsewhere

> Order a join address for a game server you run elsewhere, tell Coritan where it listens and which region carries its players, and test it.

Source: https://www.coritan.com/docs/proxies/external-servers/connect-an-external-server/

In the dashboard:

- /dashboard/order/external-server: https://www.coritan.com/dashboard/order/external-server
- /dashboard/proxies/external/…/connection: https://www.coritan.com/dashboard/proxies/external

Connect a Minecraft server that you run somewhere else, such as at home or with another host, to give it a join address under `coritan.gg`. You order an *external server* as a plan. You tell Coritan where your server listens and which region carries its players, and Coritan creates the join address once you pay. This page covers the order, the connection settings, testing the connection and what your server must allow ([How external servers work](/docs/proxies/external-servers/)).

For a server hosted here, [create a join address](/docs/proxies/join-addresses/create-a-join-address/) instead.

## Before you begin

- Your server runs Minecraft Java, or Minecraft Bedrock that accepts NetherNet connections, which Bedrock uses from version 26.50 ([How external servers work](/docs/proxies/external-servers/#how-players-reach-your-server)).
- Your server has a public IP address, or a hostname that resolves only to public addresses, and the internet can reach it on its port. On a home connection, forward the port on your router to the machine that runs the server.
- For the first invoice, credit on your account pays first. Otherwise you pay by card or PayPal on the page the order lands on ([How the first payment works](/docs/get-started/order-a-service/#how-the-first-payment-works)).

## Order an external server

Open the order page in one of these ways:

- On the [Edge Proxy](https://www.coritan.com/dashboard/proxies/game) page, select **New proxy…**, choose **Minecraft Java** or **Minecraft Bedrock**, then choose **A server elsewhere**. That card shows the plan's starting price. The order page opens set to the edition you chose.
- On [**Order a service**](https://www.coritan.com/dashboard/order), select the **External Server** card under **Edge Proxy**. The order page opens set to Java.

The page has three numbered sections, and the summary under **Your order** sits beside them. On a phone the summary follows the sections, and **Review order** at the bottom of the screen takes you to it.

1. Under **Plan**, the External Server plan is already chosen. Choose the billing cycle with the buttons beside the heading, such as **Monthly**. A longer term names what it saves, such as `Annually · save 25%`.
2. Under **Join address**, type the name that players will type in **Join subdomain**, such as `survival-smp`. The field checks the name as you type, and shows `survival-smp.coritan.gg is available.` when it is free ([Name rules](/docs/proxies/join-addresses/create-a-join-address/#name-rules)).

    To pick a generated name instead, select **Suggest a name**, then select one of the names it offers. Picking one also fills in **Server name** when it is empty.
3. Optionally, enter a **Server name** of up to 100 characters. Without one, the external server takes its subdomain as its name.
4. Under **Your server**, check that the **Edition**, **Java** or **Bedrock**, matches your server. When you change it, the **Port** moves to the new edition's default port, unless you had typed a port of your own.
5. In **Server address**, enter your server's public IP address or hostname, such as `203.0.113.10` or `play.example.com`. In **Port**, enter the port it listens on. When you paste an address with its port, such as `play.example.com:25565`, the page splits it.
6. Leave the options as they are unless your server needs them ([Connection settings](#connection-settings)).
7. Under **Proxy region**, choose the region closest to most of your players. Each card shows the region's name and code, such as `Frankfurt` and `fra · Germany`. The page chooses a region for you when one has an edge available.
8. Check the summary. It lists the plan with its billing cycle, the **Join address** and the address it **Forwards to**, such as `203.0.113.10:25565`, with **Change** beside each to go back to its section. The **Total** shows the price and what is due today, and the line under it says how the first invoice is paid.
9. Select **Connect server** under the summary. While something is missing, the button is greyed out and the line under it names what, such as `Enter a subdomain.`

If we refuse the order, **Could not place the order** appears above the button with the reason, and your choices stay as they were.

Once you place it, the order's own page opens. When its title is **Order placed, payment due**, pay under **Pay invoice** with account credit, a saved card or PayPal account, or a new card ([Pay and follow the order](/docs/get-started/order-a-service/#pay-and-follow-the-order)). To pay later, leave the page and pay the invoice under [Invoices](/docs/billing/invoices/). Coritan sets the external server up once the invoice is paid.

## Connection settings

**Edition**
: **Java** for Minecraft Java Edition, or **Bedrock** for Minecraft Bedrock. The edition decides who can join and on which port ([Editions and ports](/docs/proxies/join-addresses/#editions-and-ports)).

**Server address**
: Your server's public IP address, or a full hostname of up to 253 characters. Coritan refuses private and reserved addresses, its own edges and other customers' join addresses ([Addresses Coritan cannot forward to](/docs/proxies/external-servers/#addresses-coritan-cannot-forward-to)).

**Port**
: The port your server listens on, from `1` to `65535`. It starts at `25565` for Java and `19132` for Bedrock. Players still join on the edge's own port, whatever you enter here.

**PROXY protocol**
: Off by default, and for Java only. When it is on, the edge starts each connection with a PROXY protocol version 2 header that carries the player's address. Turn it on only when your server expects the header, or every player is refused ([Set up your server](#set-up-your-server)).

**RealIP in the handshake**
: Shown for Java while **PROXY protocol** is off. The edge adds the player's address to the server address in the handshake, where a plugin can read it ([What your server receives](/docs/proxies/join-addresses/#what-your-server-receives)). Turn it off when your own proxy in front of the server stops matching its forced hosts. Clearing it on the order page has no effect: a new external server starts with it on, so clear it on the **Connection** tab once the server is set up.

**Geyser on the same port**
: Java only. It marks a Java server that also answers Bedrock players through Geyser on the same address and port, and the edition badge then reads `Java + Geyser`. The edge does not carry Bedrock players to an external server through Geyser, so Bedrock players cannot join it, even with this on.

**Proxy region**
: The region whose edges carry your players ([Regions and edge addresses](/docs/proxies/external-servers/#regions-and-edge-addresses)). The list offers only the regions that have an edge available.

## Change the connection

1. Open the external server from the **Game** tab of [Edge Proxy](https://www.coritan.com/dashboard/proxies/game), and select the **Connection** tab. **Change** on the **Route** card of the **Overview** tab opens it too.
2. Change the **Server name**, the connection settings or the **Proxy region**. The region list shows each region's name and code, such as `Frankfurt (fra)`. When your current region has no edge available, its entry ends in `(no edges available right now)`.
3. Select **Save changes**. The dashboard shows `Settings saved.`

When you change the server address or port, Coritan checks your server at once, and the badge in the header shows the result. After you change only the edition, the badge shows `Not checked` until the next check. A custom domain linked to the join address follows every change. The **Activity** table on the **Billing** tab lists each change as `Config changed`, with `External server settings changed` as its details.

While the plan is suspended, the tab shows `This server is suspended`, and you cannot change the connection until the plan is active again ([Failed payments and suspended services](/docs/billing/failed-payments/#a-service-is-suspended)).

## Test the connection

1. Open the external server's **Overview** tab.
2. On the **Your server** card, select **Test connection**.

When your server answers, the dashboard shows a message such as `Backend answered in 18 ms.`, and the card shows the **Latency**, **Players**, **Version** and **MOTD**. When it does not answer, the dashboard shows the reason, and the card shows `The backend did not answer` with the same reason ([Troubleshooting](#troubleshooting)).

Your account can run 20 tests a minute. **Test connection** is greyed out while the plan is suspended.

## Set up your server

- Allow the **Edge addresses** from the **Your server** card through your server's firewall, on its port. Players' connections arrive from these addresses. You can block every other address on that port, so that players reach the server only through the join address. Check the list again after you change the region.
- Leave `online-mode` in `server.properties` as it is. The edge does not take part in signing players in, so your server checks each player as it always has.
- Keep `prevent-proxy-connections` at `false`, its default, unless **PROXY protocol** is on. The setting compares the address that each player connects from with the one they signed in to Minecraft from. Without PROXY protocol, your server sees the edge's address instead, and refuses every player.
- With **PROXY protocol** on, set your server to expect the header, or it refuses every player:
    - Paper: `proxies.proxy-protocol: true` in `config/paper-global.yml`
    - Velocity: `haproxy-protocol = true` in `velocity.toml`
    - Waterfall: `proxy_protocol: true` on the listener in `config.yml`
- With **RealIP in the handshake** on, install a plugin that reads the player's address from the handshake if you want your server's logs and bans to see it. A server without one ignores the extra text.

The **On your server** card on the **Connection** tab repeats these points.

## Result

Once you pay the first invoice, Coritan creates the join address, such as `survival-smp.coritan.gg`, and checks your server. The order's page follows the setup and updates on its own. Its title becomes **Your order is ready** when the external server is active, and `Open external server` at the top of the page opens it.

The external server's status moves from `pending` to `provisioning`, then to `active`. It appears on the **Game** tab of [Edge Proxy](https://www.coritan.com/dashboard/proxies/game), with a note such as `External · Frankfurt` that names its region. When your server answers the check, the badge shows `Online`, and players can join at the join address.

## Troubleshooting

`Enter a public IP address; private, loopback and reserved ranges cannot be proxied to.`
: The address is private, such as `192.168.1.20`. Enter your server's public address. On a home connection, that is your router's public address, with the port forwarded to the server.

`Enter a public IP address or a full hostname, such as play.example.com.`
: The address has no dot, such as `minecraft`. Enter the full hostname.

`Enter a public hostname; private and reserved names cannot be proxied to.`
: The name ends in a private suffix, such as `.local` or `.lan`. Enter a public hostname or the public IP address.

`The server address has characters that are not valid in a hostname.`
: A hostname has only letters, digits, hyphens and dots. Remove spaces, underscores and any other characters.

`Enter a port between 1 and 65535.`
: The port is out of range. Enter the port your server listens on.

`Choose the region players should connect through.`
: No region is chosen. When **Proxy region** says `No regions are available for this product right now.`, no region has an edge available, so try again later. Otherwise, choose a region.

`That subdomain is taken.`
: We cannot give you the name, and the message under **Join subdomain** says why, such as `Subdomain is already in use`. Choose another name, or select **Suggest a name**.

`Could not resolve play.example.com; check the address`
: The hostname has no address. Check its spelling, or enter your server's IP address.

`play.example.com resolves to a private or reserved address, so we cannot proxy to it`
: At least one of the name's addresses is private. Point the name at your public address, or enter the public IP address.

A message that starts `That address is one of our proxy edges`
: The address belongs to one of Coritan's edges, for example because you entered the IP address that your join address resolves to. Enter the address your server listens on. To forward to a server hosted here, enter that server's join address.

`play.example.com is another customer's server on this network; enter the address of a server you run`
: The name is another customer's join address or custom domain. Enter your own server's address.

`survival-smp.coritan.gg is already a join address in front of a server; enter that server's own address`
: The name is the join address of an external server. Enter the address that server listens on.

`No server on this network answers to lobby.coritan.gg; check the join address, or enter the server's own address`
: The name is under `coritan.gg`, but no join address has it. Check the spelling.

`That region has no proxy edges available right now`
: The region lost its last available edge after the form opened. Choose another region.

The status is `failed` after you paid
: Coritan could not set up the external server. The **Activity** table on the **Billing** tab lists `Provisioning failed` with the reason. It can be one of the address messages above, or `Subdomain 'survival-smp' is already in use on coritan.gg` when someone took the name before setup. [Contact support](/docs/support/conversations/) with the service number.

The badge shows `Offline` with `No Minecraft Java server answered on that address and port`
: Nothing answered at the address and port within 3 seconds. Check that the server is running, that **Port** is the port it listens on, that your router forwards the port, and that your firewall allows the **Edge addresses**. Then select **Test connection**.

`The server answered, but not with a valid status:` and a reason
: Something answered on the port, but it did not answer as a Minecraft Java server. Check the **Port**, and check that the **Edition** is **Java**.

`No Minecraft Bedrock server answered on that address and port`
: Nothing answered as a Bedrock server within 3 seconds. Check that the server is running, the **Port**, your router's port forward and your firewall.

`Something answered, but it is not a Bedrock server`
: Something other than a Bedrock server answers on the port, such as a Java server. Check the **Port**, and check that the **Edition** is **Bedrock**.

The badge shows `Offline` with PROXY protocol on, but players can join
: The check does not send a PROXY protocol header, so a server that requires the header does not answer it ([How Coritan checks your server](/docs/proxies/external-servers/#how-coritan-checks-your-server)). Players are not affected.

Every player is refused
: **PROXY protocol** is on, and your server does not expect the header. Turn off **PROXY protocol** on the **Connection** tab, or set your server to expect it ([Set up your server](#set-up-your-server)).

The badge shows `Online`, but Bedrock players cannot join
: Your server speaks only the older RakNet protocol, which the check accepts. Players on Bedrock 26.50 and newer join over NetherNet, so update the server to a version that accepts NetherNet connections.

Bedrock players cannot join a Java server that runs Geyser
: The edge does not carry Bedrock players to an external server through Geyser, and no setting changes that.

The badge shows `Not checked` after a change
: You changed the edition without changing the address or port, so Coritan cleared the last check. Select **Test connection**, or wait up to 5 minutes for the next check.

**Save changes** is greyed out
: Nothing has changed, the plan is suspended, or the form has a problem. The text beside the button names the problem.

**A server elsewhere** is greyed out
: The card reads `Not available on this account.` Your account cannot order external servers. [Contact support](/docs/support/conversations/) if you expected to.

`No External Server plans yet`
: The External Server plan is not in the catalogue for your account. [Contact support](/docs/support/conversations/) if you expected it.

**Could not load the plans**
: The plans did not load. Select **Try again**, or reload the page.

`Too many requests for this action. Please wait and try again.`
: You ran more than 20 tests in a minute, or changed the connection more than 30 times in 5 minutes. Wait, then try again ([Rate limits](/docs/api/rate-limits/#actions-with-their-own-budget)).

## Related

- [How external servers work](/docs/proxies/external-servers/)
- [Manage an external server's plan](/docs/proxies/external-servers/billing/)
- [Customise the server list entry](/docs/proxies/join-addresses/server-list/)
- [Use your own domain for a join address](/docs/proxies/join-addresses/custom-domain/)
- [Troubleshoot proxies and join addresses](/docs/proxies/troubleshooting/)

## With the API

### Place the order

Find the plan with [`GET /products/`](/docs/api/reference/client/catalog/#op-get-api-v1-products): its `module_name` is `external_server`, and each entry in its `pricing` list is a `pricing_id` you can order. Check the name first with `POST /api/v1/gameproxy/availability` ([Create a join address](/docs/proxies/join-addresses/create-a-join-address/#with-the-api)). Then place the order with [`POST /services/order`](/docs/api/reference/client/services/#op-post-api-v1-services-order), with the connection in `config`:

```bash
curl -X POST https://api.coritan.com/api/v1/services/order \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": 31,
    "pricing_id": 88,
    "idempotency_key": "b7e2c1d4-5f3a-4e8b-9c6d-1a2b3c4d5e6f",
    "config": {
      "subdomain": "survival-smp",
      "display_name": "Survival SMP",
      "mode": "minecraft_java",
      "upstream_host": "203.0.113.10",
      "upstream_port": 25565,
      "proxy_protocol": false,
      "bedrock_bridge": false,
      "location_id": 3
    }
  }'
```

| Key | Values | Default | What it sets |
|---|---|---|---|
| `subdomain` | 3–28 characters that follow the [name rules](/docs/proxies/join-addresses/create-a-join-address/#name-rules) | Required | The join address's name under `coritan.gg`. |
| `display_name` | Up to 100 characters | The order's `hostname`, or else the subdomain | The server's name. |
| `mode` | `minecraft_java` or `minecraft_bedrock` | `minecraft_java` | The edition. |
| `upstream_host` | A public IP address, or a full hostname of up to 253 characters | Required | Your server's address. |
| `upstream_port` | `1`–`65535` | Required | Your server's port. |
| `proxy_protocol` | `true` or `false` | `false` | A PROXY protocol version 2 header on each connection. Java only. |
| `bedrock_bridge` | `true` or `false` | `false` | **Geyser on the same port**. Java only. |
| `location_id` | A region's `id` from `GET /client/external-servers/regions` | The first region | The proxy region. |

The order checks only the form of `config`, and answers `422` with `{"detail": {"errors": [...]}}` when something is missing or malformed, such as `Subdomain is required`, `Server address is required` or `Port must be between 1 and 65535`. An external server takes no add-ons, so an order with `addons` answers `422` with `External Server does not take add-ons. Order each product on its own.` When `requires_payment` is `true`, pay `invoice_id` as [Pay an invoice](/docs/billing/invoices/#with-the-api) shows ([Order a service](/docs/get-started/order-a-service/#with-the-api)).

Coritan checks the name, the address and the region when it sets the server up after payment. When one of those checks fails, the service's status becomes `failed`, and [`GET /services/{service_ref}/events`](/docs/api/reference/client/services/#op-get-api-v1-services-service-ref-events) lists a `provisioning_failed` event with the reason. Once the server is set up, read it as [Read external servers with the API](/docs/proxies/external-servers/#read-external-servers-with-the-api) shows.

### Update the connection

Change the connection with [`PATCH /client/external-servers/{service_id}`](/docs/api/reference/client/external-servers/#op-patch-api-v1-client-external-servers-service-id). Send only the fields you want to change:

```bash
curl -X PATCH https://api.coritan.com/api/v1/client/external-servers/1203 \
  -H "Authorization: Bearer $CORITAN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"upstream_host": "play.example.com", "upstream_port": 25566}'
```

| Field | Values | What it changes |
|---|---|---|
| `display_name` | 1–100 characters | The server's name. |
| `mode` | `minecraft_java` or `minecraft_bedrock` | The edition. When PROXY protocol is on, send `"proxy_protocol": false` with `minecraft_bedrock`. |
| `upstream_host` | A public IP address, or a full hostname of up to 253 characters | Your server's address. |
| `upstream_port` | `1`–`65535` | Your server's port. |
| `proxy_protocol` | `true` or `false` | The PROXY protocol header. Java only. |
| `real_ip` | `true` or `false` | The player's address in the Java handshake while PROXY protocol is off. |
| `bedrock_bridge` | `true` or `false` | **Geyser on the same port**. Coritan keeps it off for Bedrock. |
| `location_id` | A region's `id` | The proxy region. It must have an edge available. |

A field you leave out, or send as `null`, keeps its value, and a body with no fields changes nothing. The call answers with the external server, in the shape [Read external servers with the API](/docs/proxies/external-servers/#read-external-servers-with-the-api) describes. When the address or port changed, the answer's `probe` already holds the new check.

| Status | `detail` | Cause |
|---|---|---|
| `404` | `External server not found` | The external server is not on your account. |
| `409` | `This external server is suspended` | The plan is suspended. |
| `422` | `{"errors": ["That region has no proxy edges available right now"]}` | Coritan refused the change. `errors` holds one message, such as a message from [Troubleshooting](#troubleshooting), `Name is required`, or `This external server has no join address yet` before setup has finished. |
| `422` | A list of fields in `detail` | A value is out of range, such as a port above `65535` or a name longer than 100 characters. |
| `429` | `"error": "rate_limited"` | More than 30 changes to the server in 5 minutes. |

The API also refuses PROXY protocol on a Bedrock server, with `PROXY protocol is not available for Bedrock servers; the proxy speaks RakNet to them and cannot prepend a header`.

### Run a test

Check your server now with [`POST /client/external-servers/{service_id}/test`](/docs/api/reference/client/external-servers/#op-post-api-v1-client-external-servers-service-id-test):

```bash
curl -X POST https://api.coritan.com/api/v1/client/external-servers/1203/test \
  -H "Authorization: Bearer $CORITAN_TOKEN"
```

```json
{
  "probe": {
    "ok": true,
    "latency_ms": 18,
    "players_online": 12,
    "players_max": 100,
    "version_name": "Paper 1.21.8",
    "motd": "Survival SMP",
    "error": null,
    "checked_at": "2026-09-26T10:15:03+00:00",
    "transport": null
  },
  "state": "online"
}
```

`state` is `online` when your server answered, and `offline` when it did not, with the reason in `error`. For Bedrock, `transport` says which protocol answered: `nethernet`, or `raknet` for a server that speaks only RakNet, which players on Bedrock 26.50 and newer cannot join. It is `null` for Java. Coritan keeps the result as the last check, without `transport`.

A server that has no join address yet answers `404` with `This external server has no join address`. More than 20 tests a minute from your account answer `429`.

## API

- `POST /api/v1/services/order`: Order a platform service, and any add-ons bought with it (https://www.coritan.com/docs/api/reference/client/services/#op-post-api-v1-services-order)
- `PATCH /api/v1/client/external-servers/{service_id}`: Change where players are forwarded, how, and through which region (https://www.coritan.com/docs/api/reference/client/external-servers/#op-patch-api-v1-client-external-servers-service-id)
- `POST /api/v1/client/external-servers/{service_id}/test`: Status-ping the backend now and record the answer (https://www.coritan.com/docs/api/reference/client/external-servers/#op-post-api-v1-client-external-servers-service-id-test)
