Replace dual linear/R-tree registry with atomic live slabs, free-list tombstones, and O(1) UpdatePosition via session VisBox atomics. Drop tidwall/rtree. Add real-world hub benches. HANDOFF.md tasks the next agent with gnet fixed-worker I/O plus position write coalescing (delete after reading).
openfsd
openfsd is an open-source multiplayer flight simulation server implementing the modern VATSIM FSD protocol. It connects pilots and air traffic controllers in a shared virtual environment.
About
Flight Sim Daemon (colloquially known as FSD) is the software/protocol responsible for connecting home flight simulator clients to a single, shared multiplayer world on hobbyist networks such as VATSIM and IVAO. FSD was originally written in the late 90's by Marty Bochane for SATCO, later to be forked and taken closed-source by VATSIM in 2001. As of May 2025, FSD is still used to facilitate over 140,000 active members connecting their flight simulators to the network.
Features
- Multiplayer flight simulation with VATSIM protocol compatibility
- Web-based management for users, settings, and connections
- SQLite for persistent storage (single file; easy backups)
- Single binary — FSD and web share one process and one database; enable services with CLI flags
Package layout
cmd/openfsd/ # Binary entrypoint (FSD + web; image CMD is /openfsd)
pkg/protocol/ # Pure wire format (parse/marshal; no I/O)
pkg/fsdclient/ # Mock/real FSD client for e2e and tools
internal/server/ # TCP accept, login, handlers, service HTTP
internal/session/ # Per-connection state + outbound send worker
internal/postoffice/ # Callsign registry + geospatial index
internal/geo/ # Pure haversine / bounding box
internal/auth/ # JWT + VATSIM client auth
internal/metar/ # METAR worker pool (injectable HTTP)
internal/db/ # Shared repositories + migrations
internal/web/ # Gin MPA + /api/v1
Build and run
go build -o openfsd ./cmd/openfsd
./openfsd # both FSD and web (default)
./openfsd -fsd # FSD only (:6809 + service HTTP :13618)
./openfsd -web # web only (:8000)
| Flag | Effect |
|---|---|
| (none) | Both services |
-fsd |
FSD only |
-web |
Web only |
-fsd -web |
Both (same as default) |
Environment
| Variable | Default | Notes |
|---|---|---|
DATABASE_SOURCE_NAME |
:memory: |
SQLite path or :memory:; shared by both services |
DATABASE_DRIVER |
sqlite |
Compatibility only; must be sqlite or unset (Postgres removed) |
DATABASE_AUTO_MIGRATE |
true |
FSD applies migrations on startup |
FSD_LISTEN_ADDRS |
:6809 |
FSD TCP listen address(es) |
SERVICE_HTTP_LISTEN_ADDR |
:13618 |
Internal FSD admin HTTP |
FSD_HTTP_SERVICE_ADDRESS |
http://127.0.0.1:13618 |
Web → FSD service HTTP |
LISTEN_ADDR |
:8000 |
Web UI + /api/v1 |
LOG_DEBUG |
(unset) | Set true for debug logging |
Colocated mode (default) uses the shared DB and in-process service HTTP. For -web against a remote FSD, set FSD_HTTP_SERVICE_ADDRESS.
Quick start (Docker)
Preferred for operators. See the Deployment Wiki (source: wiki/).
Images: ghcr.io/renorris/openfsd (:latest, :dev, sha-*) published by CI on every push to main and dev.
Upgrading from PostgreSQL? openfsd is SQLite-only. Use openfsd-migrate-to-sqlite and follow Migrating from PostgreSQL.
git clone https://github.com/renorris/openfsd.git
cd openfsd
docker compose up -d # pull/build single image; both services
# or: docker compose up -d --build
- Open
http://localhost:8000 - Log in with the default admin credentials (printed in container logs on first startup)
- Configure Server — see the Configuration wiki
- Connect a client — Client Connection Wiki
Service selection
# Both (default CMD)
docker run --rm -p 6809:6809 -p 8000:8000 ghcr.io/renorris/openfsd:latest
# FSD only
docker run --rm -p 6809:6809 ghcr.io/renorris/openfsd:latest /openfsd -fsd
# Web only (remote FSD)
docker run --rm -p 8000:8000 \
-e FSD_HTTP_SERVICE_ADDRESS=http://fsd-host:13618 \
ghcr.io/renorris/openfsd:latest /openfsd -web
Local smoke
docker compose up -d --build
curl -fsS -o /dev/null -w "%{http_code}\n" http://localhost:8000/login
nc -z localhost 6809 && echo "fsd:6809 open"
docker compose down
Tests
go test -race ./...
bash scripts/check-coverage.sh 80 # overall ≥80%; pure-pkg floors (see AGENTS.md)
go test -bench=. -benchmem ./internal/postoffice/ ./pkg/protocol/
go test -tags=stress -count=1 -timeout=120s ./internal/server/ -run TestStress -v
E2E: internal/server/e2e_test.go via pkg/fsdclient + StartTestServer. Stress is optional (CI schedule / workflow_dispatch).
API
/api/v1 covers auth, users, config, and FSD connections. See internal/web.
Protocol docs
Unofficial reverse-engineered FSD protocol docs live under docs/:
pip install mkdocs
mkdocs serve