> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/LizardByte/Sunshine/llms.txt
> Use this file to discover all available pages before exploring further.

# Security Best Practices

> Secure your Sunshine deployment with authentication, network security, and encryption

## Overview

Proper security configuration is essential for production Sunshine deployments. This guide covers authentication, network security, firewall configuration, and encryption setup.

<Warning>
  Sunshine is designed for trusted networks. Exposing Sunshine directly to the internet without proper security measures can compromise your system.
</Warning>

## 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:

<Steps>
  ### Step 1: Access Web UI

  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.

  <Info>
    The certificate is automatically generated on first run and stored in `credentials/cacert.pem`.
  </Info>

  ### Step 3: Create Admin Account

  Create a username and strong password.

  <Warning>
    Store these credentials securely. If lost, you'll need to reset them via command line.
  </Warning>
</Steps>

#### Reset Credentials

If you forget your credentials:

<CodeGroup>
  ```bash Standard Installation theme={null}
  sunshine --creds <new-username> <new-password>
  ```

  ```bash AppImage theme={null}
  ./sunshine.AppImage --creds <new-username> <new-password>
  ```

  ```bash Flatpak theme={null}
  flatpak run --command=sunshine dev.lizardbyte.app.Sunshine --creds <new-username> <new-password>
  ```

  ```bash Docker theme={null}
  docker-compose exec sunshine sunshine --creds <new-username> <new-password>
  ```
</CodeGroup>

### Client Pairing Authentication

Moonlight clients must pair with Sunshine using a PIN.

<Steps>
  ### Step 1: Initiate Pairing

  In Moonlight, add your Sunshine server manually or via auto-discovery.

  ### Step 2: Enter PIN

  When prompted:

  1. Log into the Sunshine web UI
  2. Navigate to "PIN" in the navbar
  3. Enter the PIN shown in Moonlight
  4. Provide a name for the device
  5. Click "Pair"

  ### Step 3: Verify Pairing

  Check "Clients" section in web UI to see paired devices.
</Steps>

### Unpair Clients

Remove compromised or unused clients:

<CodeGroup>
  ```bash Web UI theme={null}
  1. Navigate to Configuration → Clients
  2. Click "Unpair" next to the client
  3. Confirm removal
  ```

  ```bash API theme={null}
  curl -X POST https://localhost:47990/api/clients/unpair \
    -u admin:password \
    -H "Content-Type: application/json" \
    -d '{"client_id": "<client-uuid>"}'
  ```
</CodeGroup>

## Network Security

### Web UI Access Control

Restrict web UI access by origin:

```conf sunshine.conf theme={null}
# 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                        |
| ----- | ------------------ | ------------------------------- |
| `pc`  | Localhost only     | Single-user desktop             |
| `lan` | Local network only | Home network                    |
| `wan` | Any IP address     | Public server (not recommended) |

### Bind Address

Restrict which network interface Sunshine listens on:

<CodeGroup>
  ```conf Specific Interface theme={null}
  # Bind to specific IP
  bind_address = 192.168.1.100
  ```

  ```conf Localhost Only theme={null}
  # Only accept local connections
  bind_address = 127.0.0.1
  ```

  ```conf All Interfaces (Default) theme={null}
  # Bind to all interfaces (0.0.0.0)
  # Leave empty or comment out
  # bind_address =
  ```
</CodeGroup>

### Port Configuration

Change default ports to reduce attack surface:

```conf sunshine.conf theme={null}
# 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:

```conf sunshine.conf theme={null}
# IPv4 only (default)
address_family = ipv4

# IPv4 and IPv6
address_family = both
```

<Info>
  Using IPv4 only reduces attack surface but limits IPv6 clients.
</Info>

## Firewall Configuration

### Linux (iptables)

#### Allow Sunshine Ports

```bash theme={null}
# 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

```bash theme={null}
# 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

```bash theme={null}
sudo nano /etc/firewalld/services/sunshine.xml
```

```xml sunshine.xml theme={null}
<?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

```bash theme={null}
# 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)

```bash theme={null}
# 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

<CodeGroup>
  ```powershell Add Rules (PowerShell) theme={null}
  # 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"
  ```

  ```batch Add Rules (Batch Script) theme={null}
  @echo off
  set PROGRAM="C:\Program Files\Sunshine\sunshine.exe"

  netsh advfirewall firewall add rule name="Sunshine" dir=in action=allow protocol=tcp program=%PROGRAM% enable=yes
  netsh advfirewall firewall add rule name="Sunshine" dir=in action=allow protocol=udp program=%PROGRAM% enable=yes
  ```

  ```powershell Remove Rules theme={null}
  Remove-NetFirewallRule -DisplayName "Sunshine TCP"
  Remove-NetFirewallRule -DisplayName "Sunshine UDP"
  ```
</CodeGroup>

#### Restrict to Private Network

```powershell theme={null}
# 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

```conf sunshine.conf theme={null}
# 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  |

<Warning>
  Encryption reduces streaming performance, especially on lower-end hardware.
</Warning>

#### WAN Encryption

```conf sunshine.conf theme={null}
# No encryption (not recommended)
wan_encryption_mode = 0

# Optional encryption (default)
wan_encryption_mode = 1

# Mandatory encryption
wan_encryption_mode = 2
```

<Info>
  WAN encryption is enabled by default (`wan_encryption_mode = 1`).
</Info>

### 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:

<Steps>
  ### Step 1: Generate Certificate

  ```bash theme={null}
  # 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
  ```

  ### Step 2: Configure Sunshine

  ```conf sunshine.conf theme={null}
  # Custom certificate paths
  pkey = /path/to/cakey.pem
  cert = /path/to/cacert.pem
  ```

  ### Step 3: Restart Sunshine

  ```bash theme={null}
  # Linux (systemd)
  systemctl --user restart sunshine.service

  # Docker
  docker-compose restart

  # Windows
  Restart-Service Sunshine
  ```
</Steps>

#### Use Let's Encrypt Certificate

For production deployments with a domain:

```bash theme={null}
# 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
```

<Warning>
  Not all Moonlight clients support ECDSA keys. Use RSA-2048 for best compatibility.
</Warning>

## Reverse Proxy

For advanced deployments, use a reverse proxy:

### NGINX Configuration

```nginx sunshine.conf theme={null}
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;
}
```

<Warning>
  Reverse proxies only work for the web UI. Streaming traffic must go directly to Sunshine.
</Warning>

## VPN Configuration

For secure remote access, use a VPN:

### WireGuard

<Steps>
  ### Step 1: Install WireGuard

  ```bash theme={null}
  sudo apt install wireguard
  ```

  ### Step 2: Generate Keys

  ```bash theme={null}
  wg genkey | tee privatekey | wg pubkey > publickey
  ```

  ### Step 3: Configure Server

  ```conf /etc/wireguard/wg0.conf theme={null}
  [Interface]
  Address = 10.0.0.1/24
  ListenPort = 51820
  PrivateKey = <server-private-key>

  [Peer]
  PublicKey = <client-public-key>
  AllowedIPs = 10.0.0.2/32
  ```

  ### Step 4: Start VPN

  ```bash theme={null}
  sudo wg-quick up wg0
  sudo systemctl enable wg-quick@wg0
  ```
</Steps>

Access Sunshine via VPN IP: `https://10.0.0.1:47990`

## Security Checklist

<Steps>
  ### Step 1: Authentication

  * [ ] Strong web UI password configured
  * [ ] PIN required for client pairing
  * [ ] Unused clients unpaired

  ### Step 2: Network Security

  * [ ] Web UI access restricted to LAN (`origin_web_ui_allowed = lan`)
  * [ ] Firewall rules configured
  * [ ] Non-default ports configured (optional)
  * [ ] Bind address restricted (optional)

  ### Step 3: Encryption

  * [ ] LAN encryption enabled if on untrusted network
  * [ ] WAN encryption enabled (default)
  * [ ] HTTPS enabled for web UI (automatic)
  * [ ] Custom certificates configured (optional)

  ### Step 4: System Security

  * [ ] Sunshine running as non-root user
  * [ ] System packages up to date
  * [ ] Firewall enabled and configured
  * [ ] VPN configured for remote access (optional)

  ### Step 5: Monitoring

  * [ ] Logs reviewed regularly
  * [ ] Paired clients audited
  * [ ] Failed authentication attempts monitored
</Steps>

## 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

## Related Resources

* [Sunshine Configuration Reference](/configuration/general)
* [API Documentation](/api/overview)
* [Network Configuration](/configuration/network)
* [OpenSSL Documentation](https://www.openssl.org/docs/)
* [Let's Encrypt](https://letsencrypt.org/)
* [WireGuard](https://www.wireguard.com/)
