A privacy-focused, end-to-end encrypted WebRTC video calling application designed specifically for local networks, VPN environments, and private infrastructure. Built as a single PHP file with zero external dependencies, this application provides secure peer-to-peer video communication with AES-256 encrypted signaling and DTLS-SRTP media encryption.
Demo: https://xsukax.ct.ws/call
xsukax Local Network Call is a self-hosted, privacy-centric video calling solution that operates entirely within your controlled network environment. Unlike cloud-based services, this application keeps all signaling data within your infrastructure while establishing direct peer-to-peer connections for media streams. The entire application is contained in a single PHP file, making deployment and maintenance remarkably simple.
Primary Use Cases:
- Secure video calls over OpenVPN networks
- Private communication within Tailscale meshes
- Corporate intranet video conferencing
- Home network video calls
- Any scenario requiring zero third-party involvement
The application implements a room-based architecture where a host creates an encrypted room, shares the link and password separately, and guests join by decrypting the connection information using the shared password.
The server never has access to room passwords or the ability to decrypt signaling data. All encryption and decryption occur client-side in the browser, ensuring that even the server administrator cannot intercept or decrypt communication metadata.
graph TD
A[User Password] -->|PBKDF2 100k iterations| B[AES-256 Key]
B --> C[Encrypt Signaling Data]
C --> D[Server Storage]
D --> E[Transfer to Peer]
E -->|Same Password| F[Decrypt Signaling]
F --> G[WebRTC Connection]
G -->|DTLS-SRTP| H[Encrypted Media Stream]
Signaling Encryption:
- AES-256-GCM encryption for all WebRTC signaling data (offers, answers, ICE candidates)
- PBKDF2 key derivation with 100,000 iterations and random salts
- Unique initialization vectors (IV) for each encryption operation
- Authenticated encryption preventing tampering
Media Encryption:
- DTLS-SRTP (Datagram Transport Layer Security - Secure Real-time Transport Protocol) for all audio and video streams
- Direct peer-to-peer connections bypass the server entirely
- Forward secrecy through ephemeral key exchange
Data Minimization:
- No user accounts or authentication required
- No personal information collected or stored
- Room data automatically expires after one hour
- No logging of connection attempts or user activity
Network Privacy:
- Operates entirely within your local network or VPN
- Compatible with OpenVPN, Tailscale, WireGuard, and standard LANs
- No external dependencies or third-party services
- STUN server used only for NAT traversal (no media relay)
Isolation Benefits:
- Complete control over infrastructure
- No data leakage to external services
- Compliance-friendly for regulated industries
- Audit trail stays within your network
- Single-File Deployment: Entire application in one PHP file - no complex setup or dependency management
- Password-Protected Rooms: Cryptographically secure room access control with separate password channel recommendation
- HD Video Quality: Support for SD (640Γ480), HD (1280Γ720), and Full HD (1920Γ1080) resolution options
- Responsive Design: Fully optimized mobile interface with touch controls and safe area support
- Audio/Video Controls: Toggle camera, microphone, self-view, and audio-only mode during calls
- Draggable Preview: Repositionable local video preview that stays out of your way
- Fullscreen Mode: Immersive calling experience on any device
- Auto Room Cleanup: Automatic removal of expired rooms (configurable 1-hour default)
- Zero Database Required: File-based storage using JSON - simplifies backup and reduces attack surface
- Minimal Server Load: Signaling-only server role - media flows peer-to-peer
- Cross-Platform: Works on Windows, macOS, Linux, iOS, Android via modern browsers
- GitHub-Inspired UI: Clean, professional interface familiar to developers
- Progressive Enhancement: Graceful degradation for older browsers
- Network Agnostic: Functions on any IP network - LAN, VPN, or internet
- Easy Deployment: Copy one file to web server and start calling
- Low Maintenance: No database migrations or complex updates
- Portable: Move between servers with a simple file copy
- Self-Contained: No external CDN dependencies for core functionality (only Tailwind CSS)
- Debuggable: Single file makes troubleshooting straightforward
- Web server with PHP 7.4 or higher (Apache, Nginx, Caddy, etc.)
- HTTPS connection (required for WebRTC camera/microphone access)
- Modern web browser with WebRTC support
# Clone the repository
git clone https://github.com/xsukax/xsukax-Local-Network-Call.git
# Navigate to the directory
cd xsukax-Local-Network-CallEnsure your php.ini file has the following settings configured:
# File upload and POST data limits (for signaling data)
post_max_size = 8M
upload_max_filesize = 8M
# Execution time (for long-polling signaling)
max_execution_time = 60
# Memory limit
memory_limit = 128M
# Enable JSON extension (usually enabled by default)
extension=json
# File operations
file_uploads = On
allow_url_fopen = OnOption A: Apache
# Copy to web root
sudo cp index.php /var/www/html/call.php
# Set appropriate permissions
sudo chown www-data:www-data /var/www/html/call.php
sudo chmod 644 /var/www/html/call.php
# Create data directory
sudo mkdir /var/www/html/vpn_call_data
sudo chown www-data:www-data /var/www/html/vpn_call_data
sudo chmod 755 /var/www/html/vpn_call_dataOption B: Nginx
# Copy to web root
sudo cp index.php /usr/share/nginx/html/call.php
# Set appropriate permissions
sudo chown nginx:nginx /usr/share/nginx/html/call.php
sudo chmod 644 /usr/share/nginx/html/call.php
# Ensure PHP-FPM is configured
# Data directory will be auto-created by the applicationOption C: Development Server
# Quick test with PHP built-in server
php -S 0.0.0.0:8080 index.phpWebRTC requires HTTPS for camera and microphone access. For local networks:
Self-Signed Certificate (Development):
# Generate certificate
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout selfsigned.key -out selfsigned.crt
# Configure your web server to use the certificateLet's Encrypt (Production):
# For public domains
sudo certbot --apache -d yourdomain.com
# or
sudo certbot --nginx -d yourdomain.comTailscale HTTPS:
# Tailscale provides automatic HTTPS certificates
tailscale cert yourhostname.tailnet-name.ts.netNavigate to your server's address:
- Local network:
https://192.168.1.100/call.php - OpenVPN:
https://10.8.0.1/call.php - Tailscale:
https://hostname.tailnet.ts.net/call.php
sequenceDiagram
participant Host
participant Server
participant Guest
Host->>Host: Enter strong password (min 6 chars)
Host->>Host: Select video quality
Host->>Server: Request room creation
Server->>Server: Generate unique room ID
Server->>Host: Return room link
Host->>Host: Grant camera/microphone permissions
Host->>Host: Encrypt offer with password (AES-256)
Host->>Server: Send encrypted offer
Host->>Guest: Share room link (separate channel)
Host->>Guest: Share password (different channel!)
Guest->>Server: Access room link
Guest->>Guest: Enter password
Guest->>Guest: Grant camera/microphone permissions
Guest->>Server: Request encrypted offer
Server->>Guest: Return encrypted offer
Guest->>Guest: Decrypt offer with password
Guest->>Guest: Create and encrypt answer
Guest->>Server: Send encrypted answer
Server->>Host: Forward encrypted answer
Host->>Host: Decrypt answer
Note over Host,Guest: Direct P2P connection established (DTLS-SRTP)
Step-by-Step Process:
-
Host Creates Room:
- Open the application in your browser
- Enter a strong password (minimum 6 characters, recommend 12+)
- Select desired video quality (SD, HD, or Full HD)
- Click "π Create Encrypted Room"
- Grant browser permissions for camera and microphone
- Copy the generated room link
-
Secure Password Sharing:
- Send the room link via one channel (email, Slack, etc.)
- Send the password via a different channel (SMS, Signal, phone call)
- This ensures compromise of one channel doesn't expose both pieces
-
Guest Joins:
- Open the room link in a browser
- Enter the password provided by the host
- Grant camera and microphone permissions
- Click "π Decrypt & Join Call"
- Wait for peer-to-peer connection establishment
Call Controls:
graph LR
A[π₯ Toggle Camera] --> B{Video State}
B -->|On| C[Stream Video]
B -->|Off| D[Audio Only]
E[π€ Toggle Mic] --> F{Audio State}
F -->|On| G[Stream Audio]
F -->|Off| H[Muted]
I[ποΈ Hide Self] --> J[Hide Local Preview]
K[π΅ Audio Mode] --> L[Disable Both Videos]
M[βΆ Fullscreen] --> N[Immersive View]
O[π Hangup] --> P[End Call]
Available Controls:
- π₯ Camera Toggle: Turn video on/off (activates audio-only mode when off)
- π€ Microphone Toggle: Mute/unmute audio
- ποΈ Hide Self View: Hide your local video preview while keeping it active for the other person
- π΅ Audio Only Mode: Disable video for both users, reduces bandwidth
- βΆ Fullscreen: Enter fullscreen mode for immersive experience
- π Hangup: End the call and disconnect
Local Video Preview:
- Drag the small preview window to any position on screen
- Automatically stays within screen boundaries
- Hidden in audio-only mode
- Can be manually hidden with the eye icon
The application works seamlessly with various network configurations:
OpenVPN Setup:
# Hosts can access via OpenVPN IP
https://10.8.0.5/call.php
# Ensure web server listens on VPN interface
# Apache: Listen 10.8.0.5:443
# Nginx: listen 10.8.0.5:443 ssl;Tailscale Setup:
# Access via Tailscale hostname
https://myserver.tailnet-name.ts.net/call.php
# Tailscale provides automatic HTTPS and mesh routing
# No additional configuration neededLocal Network:
# Standard LAN access
https://192.168.1.50/call.php
# Ensure firewall allows HTTPS (port 443)
sudo ufw allow 443/tcpConnection Issues:
flowchart TD
A[Connection Failed] --> B{HTTPS Working?}
B -->|No| C[Configure SSL Certificate]
B -->|Yes| D{Same Network?}
D -->|No| E[Check VPN/Tailscale]
D -->|Yes| F{Correct Password?}
F -->|No| G[Verify Password Match]
F -->|Yes| H{Firewall Blocking?}
H -->|Yes| I[Open Required Ports]
H -->|No| J[Check Browser Console]
Common Solutions:
- "Failed to access media devices": Grant camera/microphone permissions in browser
- "Wrong password or corrupted data": Ensure exact password match (case-sensitive)
- Room expired: Rooms auto-delete after 1 hour, create a new one
- No video showing: Check camera is not being used by another application
- Connection stuck: Refresh both browsers and try again
Edit the ROOM_EXPIRY constant in index.php:
// Default: 1 hour (3600 seconds)
define('ROOM_EXPIRY', 3600);
// Change to 30 minutes
define('ROOM_EXPIRY', 1800);
// Change to 4 hours
define('ROOM_EXPIRY', 14400);Change the storage location:
// Default: same directory as index.php
define('DATA_DIR', __DIR__ . '/vpn_call_data');
// Custom path
define('DATA_DIR', '/var/lib/vpn_call_data');Modify the JavaScript constraints in the initializeMedia() function to customize video quality parameters, audio processing, or frame rates.
This project is licensed under the GNU General Public License v3.0.
Contributions, issues, and feature requests are welcome! Feel free to check the issues page.
- Repository: https://github.com/xsukax/xsukax-Local-Network-Call
- WebRTC Documentation: https://webrtc.org/
- OpenVPN: https://openvpn.net/
- Tailscale: https://tailscale.com/
Built with π by xsukax | Secure, Private, Self-Hosted