Overview
Proper security configuration is essential for production Sunshine deployments. This guide covers authentication, network security, firewall configuration, and encryption setup.
Sunshine is designed for trusted networks. Exposing Sunshine directly to the internet without proper security measures can compromise your system.
Authentication
Web UI Authentication
Sunshine requires authentication for the web UI and configuration access.
Initial Setup
On first launch, Sunshine prompts you to create credentials:
Navigate to https://localhost:47990 (or your server IP).
Step 2: Accept Self-Signed Certificate
Your browser will warn about the self-signed certificate. This is expected.
The certificate is automatically generated on first run and stored in credentials/cacert.pem.
Step 3: Create Admin Account
Create a username and strong password.
Store these credentials securely. If lost, you’ll need to reset them via command line.
Reset Credentials
If you forget your credentials:
Standard Installation
AppImage
Flatpak
Docker
sunshine --creds < new-usernam e > < new-passwor d >
Client Pairing Authentication
Moonlight clients must pair with Sunshine using a PIN.
In Moonlight, add your Sunshine server manually or via auto-discovery.
Log into the Sunshine web UI
Navigate to “PIN” in the navbar
Enter the PIN shown in Moonlight
Provide a name for the device
Click “Pair”
Check “Clients” section in web UI to see paired devices.
Unpair Clients
Remove compromised or unused clients:
1. Navigate to Configuration → Clients
2. Click "Unpair" next to the client
3. Confirm removal
Network Security
Web UI Access Control
Restrict web UI access by origin:
# Only allow localhost
origin_web_ui_allowed = pc
# Allow LAN devices (default)
origin_web_ui_allowed = lan
# Allow anyone (not recommended)
origin_web_ui_allowed = wan
Value Description Use Case pcLocalhost only Single-user desktop lanLocal network only Home network wanAny IP address Public server (not recommended)
Bind Address
Restrict which network interface Sunshine listens on:
Specific Interface
Localhost Only
All Interfaces (Default)
# Bind to specific IP
bind_address = 192.168.1.100
Port Configuration
Change default ports to reduce attack surface:
# Default port family starts at 47989
port = 47989
# Custom port (offsets all related ports)
port = 50000
Port offsets:
Base port: 47989 (configurable)
Web UI: Base + 21 (48010)
TCP streaming: Base - 5 to Base + 1 (47984-47990)
UDP streaming: Base + 9 to Base + 11 (47998-48000)
Address Family
Control IPv4/IPv6 usage:
# IPv4 only (default)
address_family = ipv4
# IPv4 and IPv6
address_family = both
Using IPv4 only reduces attack surface but limits IPv6 clients.
Firewall Configuration
Linux (iptables)
Allow Sunshine Ports
# TCP ports for streaming and web UI
sudo iptables -A INPUT -p tcp --match multiport --dports 47984:47990,48010 -j ACCEPT
# UDP ports for streaming
sudo iptables -A INPUT -p udp --dport 47998:48000 -j ACCEPT
# Save rules
sudo iptables-save | sudo tee /etc/iptables/rules.v4
Restrict to LAN Only
# Allow only from local network (192.168.1.0/24)
sudo iptables -A INPUT -p tcp -s 192.168.1.0/24 --match multiport --dports 47984:47990,48010 -j ACCEPT
sudo iptables -A INPUT -p udp -s 192.168.1.0/24 --dport 47998:48000 -j ACCEPT
# Drop all other traffic to these ports
sudo iptables -A INPUT -p tcp --match multiport --dports 47984:47990,48010 -j DROP
sudo iptables -A INPUT -p udp --dport 47998:48000 -j DROP
Linux (firewalld)
Create Service Definition
sudo nano /etc/firewalld/services/sunshine.xml
<? xml version = "1.0" encoding = "utf-8" ?>
< service >
< short > Sunshine </ short >
< description > Sunshine Game Streaming </ description >
< port protocol = "tcp" port = "47984-47990" />
< port protocol = "tcp" port = "48010" />
< port protocol = "udp" port = "47998-48000" />
</ service >
Apply Rules
# Reload firewalld to recognize new service
sudo firewall-cmd --reload
# Add service to default zone
sudo firewall-cmd --permanent --add-service=sunshine
# Or add to specific zone
sudo firewall-cmd --permanent --zone=home --add-service=sunshine
# Apply changes
sudo firewall-cmd --reload
# Verify
sudo firewall-cmd --list-services
Linux (UFW)
# Allow Sunshine ports
sudo ufw allow 47984:47990/tcp comment 'Sunshine TCP'
sudo ufw allow 47998:48000/udp comment 'Sunshine UDP'
sudo ufw allow 48010/tcp comment 'Sunshine Web UI'
# Restrict to LAN only (optional)
sudo ufw allow from 192.168.1.0/24 to any port 47984:47990 proto tcp
sudo ufw allow from 192.168.1.0/24 to any port 47998:48000 proto udp
sudo ufw allow from 192.168.1.0/24 to any port 48010 proto tcp
# Enable firewall
sudo ufw enable
# Check status
sudo ufw status
Windows Firewall
Using Installer
The Windows installer automatically creates firewall rules.
Manual Configuration
Add Rules (PowerShell)
Add Rules (Batch Script)
Remove Rules
# TCP Rule
New-NetFirewallRule - DisplayName "Sunshine TCP" `
- Direction Inbound `
- Protocol TCP `
- LocalPort 47984 - 47990 , 48010 `
- Action Allow `
- Program "C:\Program Files\Sunshine\sunshine.exe"
# UDP Rule
New-NetFirewallRule - DisplayName "Sunshine UDP" `
- Direction Inbound `
- Protocol UDP `
- LocalPort 47998 - 48000 `
- Action Allow `
- Program "C:\Program Files\Sunshine\sunshine.exe"
Restrict to Private Network
# Allow only on Private network profile
New-NetFirewallRule - DisplayName "Sunshine TCP" `
- Direction Inbound `
- Protocol TCP `
- LocalPort 47984 - 47990 , 48010 `
- Action Allow `
- Profile Private `
- Program "C:\Program Files\Sunshine\sunshine.exe"
Encryption
Stream Encryption
Sunshine supports encryption for both LAN and WAN streaming.
LAN Encryption
# No encryption (default)
lan_encryption_mode = 0
# Optional encryption (client decides)
lan_encryption_mode = 1
# Mandatory encryption
lan_encryption_mode = 2
Mode Behavior Performance Security 0 Never encrypt Best Lowest 1 Encrypt if client supports Good Medium 2 Always encrypt (reject unencrypted) Lower Highest
Encryption reduces streaming performance, especially on lower-end hardware.
WAN Encryption
# No encryption (not recommended)
wan_encryption_mode = 0
# Optional encryption (default)
wan_encryption_mode = 1
# Mandatory encryption
wan_encryption_mode = 2
WAN encryption is enabled by default (wan_encryption_mode = 1).
HTTPS/TLS for Web UI
Sunshine automatically generates self-signed certificates for HTTPS.
Default Certificates
Certificates are stored in:
OS Location Linux ~/.config/sunshine/credentials/Windows %ProgramFiles%\Sunshine\config\credentials\macOS ~/.config/sunshine/credentials/Docker /config/credentials/
Files:
cakey.pem - Private key (RSA-2048)
cacert.pem - Certificate
Custom Certificates
Replace default certificates with your own:
Step 1: Generate Certificate
# Generate RSA-2048 private key
openssl genrsa -out cakey.pem 2048
# Generate self-signed certificate
openssl req -new -x509 -key cakey.pem -out cacert.pem -days 3650
# Custom certificate paths
pkey = /path/to/cakey.pem
cert = /path/to/cacert.pem
# Linux (systemd)
systemctl --user restart sunshine.service
# Docker
docker-compose restart
# Windows
Restart-Service Sunshine
Use Let’s Encrypt Certificate
For production deployments with a domain:
# Obtain certificate via certbot
sudo certbot certonly --standalone -d sunshine.yourdomain.com
# Link certificates
sudo ln -s /etc/letsencrypt/live/sunshine.yourdomain.com/privkey.pem /path/to/sunshine/credentials/cakey.pem
sudo ln -s /etc/letsencrypt/live/sunshine.yourdomain.com/fullchain.pem /path/to/sunshine/credentials/cacert.pem
Not all Moonlight clients support ECDSA keys. Use RSA-2048 for best compatibility.
Reverse Proxy
For advanced deployments, use a reverse proxy:
NGINX Configuration
upstream sunshine {
server 127.0.0.1:47990;
}
server {
listen 443 ssl http2;
server_name sunshine.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/sunshine.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sunshine.yourdomain.com/privkey.pem;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Web UI
location / {
proxy_pass https://sunshine;
proxy_ssl_verify off ;
proxy_set_header Host $ host ;
proxy_set_header X-Real-IP $ remote_addr ;
proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for ;
proxy_set_header X-Forwarded-Proto $ scheme ;
}
# Streaming ports (pass through)
location /stream {
proxy_pass https://sunshine;
proxy_http_version 1.1 ;
proxy_set_header Upgrade $ http_upgrade ;
proxy_set_header Connection "upgrade" ;
}
}
# Redirect HTTP to HTTPS
server {
listen 80 ;
server_name sunshine.yourdomain.com;
return 301 https://$ server_name $ request_uri ;
}
Reverse proxies only work for the web UI. Streaming traffic must go directly to Sunshine.
VPN Configuration
For secure remote access, use a VPN:
WireGuard
Step 1: Install WireGuard
sudo apt install wireguard
wg genkey | tee privatekey | wg pubkey > publickey
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <server-private-key>
[Peer]
PublicKey = <client-public-key>
AllowedIPs = 10.0.0.2/32
sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0
Access Sunshine via VPN IP: https://10.0.0.1:47990
Security Checklist
Security Best Practices
Never expose Sunshine directly to the internet - Use a VPN for remote access
Use strong, unique passwords - Store credentials in a password manager
Enable encryption - Especially for WAN streaming
Keep Sunshine updated - Apply security patches promptly
Audit paired clients regularly - Remove unused devices
Restrict web UI access - Use origin_web_ui_allowed = lan
Use firewall rules - Allow only necessary ports
Monitor logs - Watch for suspicious activity
Use system service - Run with minimal privileges
Backup credentials - Store certificates securely