Skip to main content

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:
1
Step 1: Access Web UI
2
Navigate to https://localhost:47990 (or your server IP).
3
Step 2: Accept Self-Signed Certificate
4
Your browser will warn about the self-signed certificate. This is expected.
5
The certificate is automatically generated on first run and stored in credentials/cacert.pem.
6
Step 3: Create Admin Account
7
Create a username and strong password.
8
Store these credentials securely. If lost, you’ll need to reset them via command line.

Reset Credentials

If you forget your credentials:
sunshine --creds <new-username> <new-password>

Client Pairing Authentication

Moonlight clients must pair with Sunshine using a PIN.
1
Step 1: Initiate Pairing
2
In Moonlight, add your Sunshine server manually or via auto-discovery.
3
Step 2: Enter PIN
4
When prompted:
5
  • 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”
  • 6
    Step 3: Verify Pairing
    7
    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:
    sunshine.conf
    # 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
    
    ValueDescriptionUse Case
    pcLocalhost onlySingle-user desktop
    lanLocal network onlyHome network
    wanAny IP addressPublic server (not recommended)

    Bind Address

    Restrict which network interface Sunshine listens on:
    # Bind to specific IP
    bind_address = 192.168.1.100
    

    Port Configuration

    Change default ports to reduce attack surface:
    sunshine.conf
    # 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:
    sunshine.conf
    # 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
    
    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

    # 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

    sunshine.conf
    # No encryption (default)
    lan_encryption_mode = 0
    
    # Optional encryption (client decides)
    lan_encryption_mode = 1
    
    # Mandatory encryption
    lan_encryption_mode = 2
    
    ModeBehaviorPerformanceSecurity
    0Never encryptBestLowest
    1Encrypt if client supportsGoodMedium
    2Always encrypt (reject unencrypted)LowerHighest
    Encryption reduces streaming performance, especially on lower-end hardware.

    WAN Encryption

    sunshine.conf
    # 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:
    OSLocation
    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:
    1
    Step 1: Generate Certificate
    2
    # 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
    
    3
    Step 2: Configure Sunshine
    4
    # Custom certificate paths
    pkey = /path/to/cakey.pem
    cert = /path/to/cacert.pem
    
    5
    Step 3: Restart Sunshine
    6
    # 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

    sunshine.conf
    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

    1
    Step 1: Install WireGuard
    2
    sudo apt install wireguard
    
    3
    Step 2: Generate Keys
    4
    wg genkey | tee privatekey | wg pubkey > publickey
    
    5
    Step 3: Configure Server
    6
    [Interface]
    Address = 10.0.0.1/24
    ListenPort = 51820
    PrivateKey = <server-private-key>
    
    [Peer]
    PublicKey = <client-public-key>
    AllowedIPs = 10.0.0.2/32
    
    7
    Step 4: Start VPN
    8
    sudo wg-quick up wg0
    sudo systemctl enable wg-quick@wg0
    
    Access Sunshine via VPN IP: https://10.0.0.1:47990

    Security Checklist

    1
    Step 1: Authentication
    2
  • Strong web UI password configured
  • PIN required for client pairing
  • Unused clients unpaired
  • 3
    Step 2: Network Security
    4
  • Web UI access restricted to LAN (origin_web_ui_allowed = lan)
  • Firewall rules configured
  • Non-default ports configured (optional)
  • Bind address restricted (optional)
  • 5
    Step 3: Encryption
    6
  • LAN encryption enabled if on untrusted network
  • WAN encryption enabled (default)
  • HTTPS enabled for web UI (automatic)
  • Custom certificates configured (optional)
  • 7
    Step 4: System Security
    8
  • Sunshine running as non-root user
  • System packages up to date
  • Firewall enabled and configured
  • VPN configured for remote access (optional)
  • 9
    Step 5: Monitoring
    10
  • Logs reviewed regularly
  • Paired clients audited
  • Failed authentication attempts monitored
  • Security Best Practices

    1. Never expose Sunshine directly to the internet - Use a VPN for remote access
    2. Use strong, unique passwords - Store credentials in a password manager
    3. Enable encryption - Especially for WAN streaming
    4. Keep Sunshine updated - Apply security patches promptly
    5. Audit paired clients regularly - Remove unused devices
    6. Restrict web UI access - Use origin_web_ui_allowed = lan
    7. Use firewall rules - Allow only necessary ports
    8. Monitor logs - Watch for suspicious activity
    9. Use system service - Run with minimal privileges
    10. Backup credentials - Store certificates securely

    Build docs developers (and LLMs) love