> ## Documentation Index
> Fetch the complete documentation index at: https://docs.freestylevoice.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-hosting

> Run the Freestyle server standalone with Docker.

The Freestyle server can run independently of the Electron app as a standalone Docker container. This is useful for headless setups, shared team servers, or integrating Freestyle's API into other tools.

The image is published to GitHub Container Registry at `ghcr.io/freestyle-voice/freestyle-server`.

## Quick start

```bash theme={null}
docker run -d \
  --name freestyle \
  -p 4649:4649 \
  -v freestyle-data:/data \
  ghcr.io/freestyle-voice/freestyle-server
```

The server is now available at `http://localhost:4649`. Verify with:

```bash theme={null}
curl http://localhost:4649/api/health
# {"status":"ok","name":"freestyle"}
```

## Docker Compose

```yaml theme={null}
services:
  freestyle:
    image: ghcr.io/freestyle-voice/freestyle-server
    ports:
      - "4649:4649"
    volumes:
      - freestyle-data:/data
    restart: unless-stopped

volumes:
  freestyle-data:
```

## Environment variables

The Docker image sets `FREESTYLE_DB_PATH`, `HOST`, `PORT`, and `FREESTYLE_ENV` for you. `FREESTYLE_DB_PATH` is required — the server refuses to start without it (the image defaults it to `/data/freestyle.db`).

| Variable            | Default                         | Description                                                                                 |
| ------------------- | ------------------------------- | ------------------------------------------------------------------------------------------- |
| `FREESTYLE_DB_PATH` | `/data/freestyle.db` (in image) | Path to the SQLite database file. Required. The `/data` volume persists it across restarts. |
| `PORT`              | `4649`                          | Port to listen on.                                                                          |
| `HOST`              | `0.0.0.0`                       | Interface to bind to.                                                                       |
| `FREESTYLE_ENV`     | `production`                    | App environment flag.                                                                       |
| `DO_NOT_TRACK`      | *(none)*                        | Set to `1` to disable all telemetry.                                                        |

## Persistent data

The SQLite database stores all your settings, dictionary, vocabulary, formats, and transcription history. Mount a volume at `/data` to persist it:

```bash theme={null}
-v freestyle-data:/data
```

If no volume is mounted, data is lost when the container is removed.

## Health check

The container has a built-in health check that pings `GET /api/health` every 30 seconds. Docker reports the container as `healthy` when the endpoint responds.

```bash theme={null}
docker inspect --format='{{.State.Health.Status}}' freestyle
# healthy
```

## Security

<Warning>
  The server has **no built-in authentication**. It's designed to run on loopback (as the desktop app's embedded backend) or on a trusted private network. Don't expose it directly to the public internet.
</Warning>

The only access control the server enforces is a trusted-origin check: state-changing requests (anything other than `GET`/`HEAD`/`OPTIONS`) and WebSocket upgrades are rejected with `403` unless they come from a trusted origin (`localhost`, `127.0.0.1`, or the app's own `app://` origin) or omit the `Origin` header. This blocks cross-origin browser attacks, but it is **not** a substitute for authentication — a plain `curl` with no `Origin` header is treated as trusted.

If you need to reach the server from other machines, put it behind a reverse proxy (nginx, Caddy, Traefik) or a tunnel that adds authentication and TLS, and keep the container bound to a private interface.

## Connecting the desktop app

You can point the Electron app at a remote Freestyle server instead of using its embedded one. This is useful for sharing settings, dictionary, and vocabulary across machines.

<Note>
  Remote server support is an advanced configuration. The desktop app is designed to work out of the box with its embedded server.
</Note>

## Plugins

Plugins work the same way in the standalone server. Install them with the API:

```bash theme={null}
curl -X POST http://localhost:4649/api/plugins/install \
  -H "Content-Type: application/json" \
  -d '{"npmName": "@freestyle-voice/profanity-filter"}'
```
