Server setup

1 — Prerequisites

# Go 1.24+
sudo apt install golang-go

# FFmpeg dependencies (for screen capture / encode)
sudo apt install libavcodec-dev libavformat-dev libswscale-dev \
                 libavdevice-dev libavfilter-dev pkg-config

# PipeWire (Linux capture backend)
sudo apt install libpipewire-0.3-dev

2 — Build FFmpeg (first time, ~15 min)

./scripts/build-ffmpeg.sh --prefix /opt/ntkvdi/ffmpeg
export PKG_CONFIG_PATH=/opt/ntkvdi/ffmpeg/lib/pkgconfig:$PKG_CONFIG_PATH

3 — Build and run server

make server

# Dev / testing (mock mode — no real NTK required)
NTV_MOCK_NTK=true ./bin/ntkVDI-server

# Production
NTV_QUIC_ADDR=0.0.0.0:7443 \
NTV_MAX_SESSIONS=100 \
NTV_TARGET_LATENCY_MS=50 \
./bin/ntkVDI-server

1 — Prerequisites

# Homebrew
brew install go pkg-config

# FFmpeg dependencies
brew install ffmpeg nasm yasm

2 — Build FFmpeg

./scripts/build-ffmpeg.sh --prefix /opt/ntkvdi/ffmpeg
export PKG_CONFIG_PATH=/opt/ntkvdi/ffmpeg/lib/pkgconfig:$PKG_CONFIG_PATH

3 — Build and run server

make server

# Dev mode (ScreenCaptureKit — requires macOS 13+)
NTV_MOCK_NTK=true ./bin/ntkVDI-server

# Grant screen recording permission when prompted

1 — Prerequisites

# Install Go 1.24+ from https://go.dev/dl/
# Install MSYS2 for CGo (https://www.msys2.org/)

# In MSYS2 MINGW64 shell:
pacman -S mingw-w64-x86_64-go mingw-w64-x86_64-pkg-config \
          mingw-w64-x86_64-ffmpeg

2 — Build and run server

# In MSYS2 MINGW64:
make server
# Output: bin/ntkVDI-server.exe

# Dev mode (DXGI capture — Windows 8+)
NTV_MOCK_NTK=true .\bin\ntkVDI-server.exe

# Run as Administrator for DXGI Desktop Duplication

Flutter client setup

  1. 01
    Install Flutter SDK (3.x+) from flutter.dev and Dart SDK.
  2. 02
    Build the native Go FFI bridge first — the Flutter client depends on it.
  3. 03
    Build the client:
make client
# Builds client/native/ Go bridge, then Flutter app
# Output: client/build/
  1. 04
    Connect: enter host:7443 in the client. On first connect the server auto-generates a self-signed TLS certificate.
  2. 05
    In mock mode (NTV_MOCK_NTK=true), any credentials are accepted. For production, configure the NTK access point with real Kyber/Dilithium keys.

Environment variables

All configuration is via environment variables. No config files. The server validates required vars at startup and fails fast with a clear error.

Variable Default Notes
NTV_MOCK_NTK false Set true for all local dev / tests. Real NTK (Kyber/Dilithium) is skipped.
NTV_QUIC_ADDR 0.0.0.0:7443 QUIC listen address. Ensure UDP 7443 is open in firewall.
NTV_ENCODER_PRESET ultrafast x264 encode preset. Trade CPU for quality: ultrafast → medium → slow.
NTV_TARGET_LATENCY_MS 50 p95 target for adaptive quality manager. RTT above this triggers quality reduction.
NTV_MAX_SESSIONS 100 Concurrent session cap (server-wide). Returns error on exceed.
NTV_MAX_SESSIONS_PER_USER 3 Per-authenticated-user session cap.
NTV_SESSION_TIMEOUT_SEC 28800 Idle timeout before graceful SESSION_CLOSE (8 hours default).
NTV_DISPLAY_INDEX 0 0-based display index for capture. Multi-monitor: set 1, 2, etc.
NTV_KEEPALIVE_INTERVAL_S 30 Control stream KEEPALIVE send interval (seconds).
NTV_KEEPALIVE_TIMEOUT_S 60 Disconnect threshold when KEEPALIVE replies go stale.

QUIC stream layout

Stream ID Direction Purpose
0 Bidirectional Control — auth handshake, keepalive, RTT feedback, session close
2 Server → Client H.264 video frames
4 Server → Client Audio (stub, reserved)
6 Bidirectional Input events — mouse, keyboard from client to server

Control Frame Format (8-byte header)

[version:1][msgType:1][flags:2][payloadLen:4] + payload

protocolVersion = 1

Run the test suite

All tests (lint + unit + integration + Flutter)

NTV_MOCK_NTK=true make test

Go unit tests only (race detector + coverage)

make test-server
# go test -race -count=1 -timeout 120s ./server/... ./pkg/...

Single test

go test -run TestControlFrame_RoundTrip ./server/internal/quic/
Important

Always pass NTV_MOCK_NTK=true in tests

Real NTK (Kyber-1024/Dilithium5) is not wired in the test environment. Tests fail without mock mode. Coverage gate: 80% enforced by scripts/test-all.sh.