SvaraRTC Self Hosted Telehealth Starter Kit
Provide a ready to deploy, privacy first, HIPAA ready video consultation solution that:
-
Runs 100% on the customer’s infrastructure
-
Uses Flutter for cross-platform doctor/patient apps
-
Ships with Docker stack for backend (SFU + signaling + TURN)
-
Is extensible for other industries with minimal code changes
Core Architecture
Backend (Docker)
-
SFU Layer: Mediasoup or LiveKit server for scalable video routing
-
Signaling API: Node.js (Express) or Go service for room lifecycle
-
TURN/STUN Server: Coturn, for NAT traversal
-
Recording Service (Optional): FFmpeg-based mixer container
-
Storage: Local disk or S3-compatible bucket (customer chooses)
Frontend (Flutter)
-
Doctor app
-
Patient app
-
Shared RoomKit UI components
Security
-
JWT-based room access tokens
-
TLS by default
-
Optional E2EE for video/audio
-
Self-hosted storage (no external cloud unless configured)
Features
Patient Flow
-
Receives appointment link/code
-
Enters waiting room
-
Doctor admits them
-
Video call starts (optional recording)
-
Post-call notes & prescription upload
Doctor Flow
-
Logs in via secure credentials
-
Sees list of scheduled appointments
-
Joins call & controls admission
-
Can share screen/images
-
Ends call → patient is disconnected
Shared Features
-
Mute/unmute audio & video
-
Chat for text-based communication
-
Secure file exchange
-
Auto bandwidth adaptation (simulcast)
-
Local or cloud recording (customer’s storage)
UI Kit Components (Flutter)
Common Widgets
-
WaitingRoomScreen() -
VideoCallScreen()with grid/active speaker modes -
ParticipantTile()(with mute/video indicators) -
ChatPanel()with file send -
DeviceSelector()(camera/mic switch) -
ConsentDialog()(pre-call legal agreement)
Compliance Helpers
Common Widgets
-
WaitingRoomScreen() -
VideoCallScreen()with grid/active speaker modes -
ParticipantTile()(with mute/video indicators) -
ChatPanel()with file send -
DeviceSelector()(camera/mic switch) -
ConsentDialog()(pre-call legal agreement)
version: "3.8"
services:
sfu:
image: yourorg/mediasoup-sfu:latest
container_name: sfu
restart: always
ports:
– “4000:4000” # signaling to SFU
– “50000-50050:50000-50050/udp” # RTP/RTCP
environment:
– NODE_ENV=production
– LISTEN_IP=0.0.0.0
– ANNOUNCED_IP=${PUBLIC_IP}
networks:
– rtcnet
signaling:
image: yourorg/svarartc-signaling:latest
container_name: signaling
restart: always
ports:
– “3000:3000” # API + WebSocket
environment:
– JWT_SECRET=${JWT_SECRET}
– SFU_URL=sfu:4000
– STORAGE_PATH=/storage
volumes:
– storage-data:/storage
networks:
– rtcnet
turn:
image: instrumentisto/coturn
container_name: turn
restart: always
ports:
– “3478:3478/udp”
– “3478:3478/tcp”
– “5349:5349/tcp”
environment:
– TURN_REALM=telehealth.local
– TURN_USER=${TURN_USER}
– TURN_PASSWORD=${TURN_PASSWORD}
networks:
– rtcnet
recorder:
image: yourorg/svarartc-recorder:latest
container_name: recorder
restart: always
volumes:
– storage-data:/storage
depends_on:
– sfu
environment:
– SFU_URL=sfu:4000
– OUTPUT_PATH=/storage/recordings
networks:
– rtcnet
storage:
image: minio/minio
container_name: storage
command: server /data
ports:
– “9000:9000”
– “9001:9001”
environment:
– MINIO_ROOT_USER=${MINIO_USER}
– MINIO_ROOT_PASSWORD=${MINIO_PASSWORD}
volumes:
– storage-data:/data
networks:
– rtcnet
networks:
rtcnet:
driver: bridge
volumes:
storage-data:
