# Hosting from the app

Source: https://docs.gryt.chat/docs/host/from-the-app

The desktop client ships with a server in it. Run one, or several, without a terminal.

The Gryt desktop app has a full server inside it. Not a demo mode or a cut-down
build — the same signalling server, SFU and image worker that a Docker
deployment runs. Open the app, create a server, and people on your network can
join it.

If you ever ran a Minecraft server off your own machine so your friends could
join, this is that. Download, host, play. On a LAN it really is that simple:
[discovery](https://docs.gryt.chat/docs/host/multi-server) does what Hamachi used to.

From outside your network you still open a port. For people on the desktop app
that's all you need: forward the ports, hand out your IP, and skip domains and
certificates entirely. See [No domain, just an IP](https://docs.gryt.chat/docs/host/no-domain).

A [Cloudflare Tunnel](https://docs.gryt.chat/docs/host/cloudflare-tunnel) is for letting people
join from a browser, which needs a real hostname and certificate. A tunnel
covers the HTTPS and WebSocket side only. WebRTC media is UDP and a tunnel
can't carry it, so the SFU still needs its UDP port reachable directly.

## Creating one

1. Click the **+** in the server rail
2. Choose **Create my own**
3. Give it a name — the icon is generated from it as you type
4. Take the port it offers, or set your own
5. **Create**

It starts and you're in it. There's no second step.

The port is prefilled with one that's genuinely free, checked against every
interface the server will bind. If you need a particular port — one your router
already forwards, or one your firewall rules already name — type it and the
field tells you whether anything else is on it.

The number is settled here. The server keeps the ports it's given and doesn't
go looking for new ones later, so if your router already forwards something,
type that.

**Discoverable on LAN** decides whether anyone else running Gryt on the same
network sees it appear on its own. Leave it on for a LAN party.

## Ports to open

Three, and the app tells you which. **Settings → My servers → Open these
ports** lists them under the server with the numbers it actually picked, and is
also where you change them. They're typically:

| Port | Protocol | What it is |
|------|----------|------------|
| `5000` | TCP | The server itself. Chat, logins, joining |
| `5005` | TCP | Voice signalling |
| `3478` | UDP | The voice and video themselves |

Open them on the machine's own firewall if anyone is joining from another
computer at all, and forward them on your router as well if anyone is joining
from outside your network.

Voice doesn't travel over the same connection as the chat, and it's UDP
rather than TCP. With that port shut, people join, the member list fills up,
messages send, and nobody can hear anybody.

The numbers aren't always those three. If something already holds one when the
server is created, the app takes the next one up — `5006` rather than `5005` —
and that becomes the server's port. So read the panel rather than assuming the
table.

<Callout type="warn" title="Windows: the SFU asks separately">
  Voice runs in its own executable, `gryt_sfu.exe`, so Windows Firewall prompts
  for it separately from Gryt itself — and clicking **Allow** on that prompt
  usually ticks **Private networks** only. A VPN adapter like Radmin, Hamachi
  or ZeroTier is normally classified as a **Public** network, so friends
  connecting over one are blocked by a rule you thought you had already
  answered. Check both boxes, or add an inbound rule for UDP 3478 by hand under
  **Windows Security → Firewall → Advanced settings → Inbound Rules**.
</Callout>

## When a port is taken

The server refuses to start and says which port, rather than quietly moving to
a free one.

That's deliberate, and it used to work the other way. A server that moves itself
is fine on the machine it runs on and quietly broken for everyone else. Say you
forwarded `5000` on your router. Something claims `5000` one morning, the app
moves to `5001`, and the server comes back up looking perfectly healthy while
nobody outside can reach it. With the media port it's worse: chat keeps working
and only voice goes quiet. Neither shows up anywhere in the app.

So when something else has the port, you get told, and you pick:

- Close whatever took it, and start the server again
- Or open **Open these ports** and give the server a different number

The fields are editable while the server is stopped. Changing one rewrites the
server's `config.env`, including the addresses derived from it, so nothing is
left pointing at the old number. It doesn't touch your router.

## More than one

You can host several. Each server is genuinely separate — its own messages, its
own members, its own invites, its own database — and they cost far less than
running two of anything else:

- **The SFU is shared.** One media process serves every server you host, because
  voice rooms are namespaced per server. Hosting a second server doesn't mean a
  second SFU.
- **The image worker isn't.** Each server gets one, because a worker reads
  exactly one database.

So server number two costs a server process and an image worker, not another
stack.

<Callout type="info">
  Give each one a different name. A server identifies itself to the SFU using
  its name, its port and its instance id — two servers that produce the same
  identity will fight over voice rooms, and the second one's voice won't
  start.
</Callout>

## Managing them

**Settings → My servers** lists everything you host. Each one shows:

- **Running / Stopped**, and Start or Stop
- Both addresses — `127.0.0.1:<port>` for this machine, and the LAN address to
  give somebody else
- **Start automatically with app**, per server
- **Advertised addresses**, which is where voice is told how to reach you
- **Open these ports**, the three numbers and the fields to change them
- **Server logs**, which don't fetch anything until you open them
- **Open**, which puts it in your server rail
- **Delete**

Delete is exactly as final as it sounds. It stops the server, removes its
database, its uploads and its identity key, and asks you to type the server's
name first. There's no second copy anywhere.

<Callout type="warn">
  Deleting a server destroys the key it identifies itself with. Everyone who
  joined pinned that key, so a replacement with the same name and port is a
  *different* server to them — they will be turned away rather than let back in.
</Callout>

## Where things live

Each server gets its own directory under your app data folder:

```
<userData>/gryt-servers/<server-id>/
├── config.env      generated at creation — ports, secret, identity tiers
└── data/
    ├── gryt.db     messages, members, roles, invites
    └── uploads/    files and images
```

`<userData>` is `~/Library/Application Support/gryt-chat` on macOS,
`%APPDATA%/gryt-chat` on Windows, and `~/.config/gryt-chat` on Linux.

Back up a server by copying its directory while it's stopped.

## What it doesn't do

Hosting from the app is a real server, but it's running on a desktop machine,
so the limits are the machine's:

- It's reachable while the app is open and the machine is awake. Closing Gryt
  stops the servers it's hosting.
- Anyone outside your network needs a route in. A
  [tunnel](https://docs.gryt.chat/docs/host/cloudflare-tunnel) covers signalling; the SFU's UDP
  port still has to be forwarded directly.
- Only one hosted server can advertise itself over mDNS on Linux at a time. All
  of them still work by address.

For something that should stay up without a person nearby, run it with
[Docker Compose](https://docs.gryt.chat/docs/host/docker-compose) instead — the same server,
pointed at a disk that isn't your laptop.
