# Windows (no Docker)

Source: https://docs.gryt.chat/docs/host/windows

Run a Gryt server on Windows without Docker — just extract and start

The Windows self-hosted bundle lets you run a Gryt server on any Windows machine without Docker.
Everything is included in a single zip: the signaling server, SFU media server, and image worker.

<Callout type="info">
This is ideal for LAN parties, local teams, or anyone who wants a simple server on a Windows PC.
For production deployments on a VPS or cloud server, see the [Docker Compose guide](https://docs.gryt.chat/docs/host/docker-compose).
</Callout>

## Prerequisites

- **Windows 10 or later** (x64)
- **[Node.js](https://nodejs.org/) 22.13 or later** — download the LTS installer from [nodejs.org](https://nodejs.org/)

Verify Node.js is installed, and that it's new enough:

```bash
node --version
```

<Callout type="warn">
  Gryt used to run on Node.js 20. It now uses the SQLite support built into
  Node rather than a compiled module, and that's only available from **22.13**
  onwards — 22.12 isn't enough. If you're upgrading an existing server, update
  Node.js before you start it, or it will refuse to start and tell you why.
</Callout>

## Setup

<Steps>
<Step>
### Download the bundle

Download the latest `gryt-server-windows-x64-v*.zip` from the
[GitHub releases page](https://github.com/Gryt-chat/server/releases).

Extract it to a folder of your choice (e.g. `C:\Gryt`).

</Step>
<Step>
### Configure

Open `config.env` in a text editor and customize:

```bash
# Give your server a name
SERVER_NAME=My Gryt Server

# Port for the signaling server (API + WebSocket)
PORT=5000

# Port for the SFU (voice/video media)
SFU_PORT=5005
SFU_WS_HOST=ws://127.0.0.1:5005
SFU_PUBLIC_HOST=127.0.0.1:5005

# STUN servers for automatic NAT traversal (voice/video)
STUN_SERVERS=stun:stun.l.google.com:19302,stun:stun1.l.google.com:19302
```

For LAN-only use, the defaults work out of the box. If you want users to connect over the internet,
set `SFU_PUBLIC_HOST` and `EXTERNAL_HOST` to your public IP or domain:

```bash
EXTERNAL_HOST=http://your-public-ip:5000
SFU_PUBLIC_HOST=your-public-ip:5005
SFU_WS_HOST=ws://your-public-ip:5005
```

See the [Configuration](https://docs.gryt.chat/docs/host/configuration) page for all available options.

</Step>
<Step>
### Start the server

Double-click **`start.bat`** or run it from a terminal.

```
Starting Gryt Image Worker...
Starting Gryt SFU...
Starting Gryt Server...
```

Older versions did a one-time native module build on first launch. That step is
gone — there's nothing left to compile, so the server starts straight away.

</Step>
<Step>
### Connect

Connect to your server using the [Gryt desktop app](https://github.com/Gryt-chat/gryt/releases) or
the hosted web client at [app.gryt.chat](https://app.gryt.chat).

Enter your server address: `localhost:5000` (same machine) or `your-ip:5000` (from another device on the network).

The **first user** to join becomes the **owner/admin**. After that, the server is **invite-only** —
create invite links in **Server settings → Invites**.

</Step>
</Steps>

## Firewall

If other devices need to connect, allow these ports through Windows Firewall:

| Port | Protocol | Service |
|------|----------|---------|
| `5000` | TCP | Signaling server (API + WebSocket) |
| `5005` | TCP | SFU WebSocket |
| `3478` | UDP | WebRTC media, `ICE_UDP_MUX_PORT` |

To open a port: **Windows Security → Firewall → Advanced settings → Inbound Rules → New Rule → Port**.

<Callout type="info">
For remote users, STUN is enabled by default and will automatically discover your public IP and attempt
NAT hole-punching. On most home routers this means voice/video works without manual port forwarding.
If remote users still can't connect to voice, forward the ports above in your router and set
`SFU_PUBLIC_HOST` to your public IP in `config.env`.
</Callout>

## Configuration reference

All settings are in `config.env`. Key options:

| Variable | Default | Description |
|----------|---------|-------------|
| `SERVER_NAME` | `My Gryt Server` | Display name shown to users |
| `PORT` | `5000` | Signaling server port |
| `SFU_PORT` | `5005` | SFU media server port |
| `SFU_WS_HOST` | `ws://127.0.0.1:5005` | SFU WebSocket URL (used by the server internally) |
| `SFU_PUBLIC_HOST` | `127.0.0.1:5005` | SFU address given to clients |
| `DATA_DIR` | `./data` | Where SQLite database and file uploads are stored |
| `STORAGE_BACKEND` | `filesystem` | File storage mode (`filesystem` for self-hosted) |
| `JWT_SECRET` | *(auto-generated)* | Session token secret — set a strong value for production |

## Stopping the server

Close the terminal window, or press `Ctrl+C` in the terminal where `start.bat` is running.

To kill background processes from a previous run that didn't shut down cleanly:

```bash
taskkill /IM gryt_sfu.exe /F
taskkill /IM node.exe /F
```

## Data and backups

All server data is stored in the `data/` directory:

- `data/gryt.db` — SQLite database (users, channels, messages, settings)
- `data/uploads/` — uploaded files and images

To back up your server, copy the entire `data/` directory.

## Troubleshooting

**"node" isn't recognized**
Node.js isn't installed or not on your PATH. Download it from [nodejs.org](https://nodejs.org/) and restart your terminal.

**"Your Node.js is too old" / `No such built-in module: node:sqlite`**
Gryt needs Node.js 22.13 or later. Install the current LTS from
[nodejs.org](https://nodejs.org/), close the terminal so the new version is
picked up, and run `start.bat` again. If you see the raw `node:sqlite` message
rather than Gryt's own, you're on an older release of the server as well —
upgrading Node.js still fixes it.

**Antivirus blocks `gryt_sfu.exe`**
Some antivirus software flags unsigned executables. Add an exception for the Gryt server folder.

**Port already in use**
Another process is using port 5000 or 5005. Either close that process or change the ports in `config.env`.

**Voice not working (remote users)**
The server uses STUN to automatically discover your public IP and punch through most home NATs — in many
cases voice will work for remote users without manual port forwarding. If it still doesn't connect,
open TCP 5005 and the UDP media port in your firewall and forward them in your router, then set
`SFU_PUBLIC_HOST` to your public IP.

**Can't connect from another device on the network**
Check Windows Firewall allows inbound connections on port 5000. Try connecting with `your-local-ip:5000` (find your IP with `ipconfig`).
