Skip to main content
Proper security configuration is critical for protecting your Pterodactyl Panel installation. This guide covers SSL/TLS, proxy configuration, session security, and other security-related settings.

SSL/TLS Configuration

Application URL

Always use HTTPS in production:
.env
APP_URL=https://panel.example.com
Critical: Using HTTP in production exposes user credentials and session cookies to interception.

Force HTTPS

The Panel automatically enforces HTTPS when APP_URL uses https://. Ensure your web server (Nginx/Apache) is configured to redirect HTTP to HTTPS.
server {
    listen 80;
    server_name panel.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name panel.example.com;
    
    ssl_certificate /etc/letsencrypt/live/panel.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/panel.example.com/privkey.pem;
    ssl_session_cache shared:SSL:10m;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256";
    ssl_prefer_server_ciphers on;
    
    # ... rest of configuration
}

Trusted Proxies

What are Trusted Proxies?

When the Panel runs behind a reverse proxy (Cloudflare, load balancer, etc.), the Panel sees the proxy’s IP address instead of the client’s. Configuring trusted proxies allows the Panel to read the real client IP from proxy headers.

Configuration

.env
TRUSTED_PROXIES=*
TRUSTED_PROXIES
string
Comma-separated list of trusted proxy IP addresses or CIDR ranges.Special values:
  • * - Trust the directly connected proxy only
  • ** - Trust all proxies in the chain
  • 192.168.1.1,10.0.0.0/8 - Specific IPs or CIDR ranges

Common Configurations

# Trust Cloudflare's IP ranges
TRUSTED_PROXIES=173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/13,104.24.0.0/14,172.64.0.0/13,131.0.72.0/22
Security Risk: Only set TRUSTED_PROXIES=** if you fully control all proxies in the chain. Malicious proxies can spoof client IPs.

Verifying Proxy Configuration

Check if the Panel sees the correct client IP:
php artisan tinker
request()->ip()
// Should return your actual IP, not the proxy's IP

Session Security

Session Configuration

.env
SESSION_DRIVER=redis
SESSION_LIFETIME=720
SESSION_ENCRYPT=true
SESSION_SECURE_COOKIE=true
SESSION_HTTP_ONLY=true
SESSION_SAME_SITE=lax
SESSION_DRIVER
string
default:"redis"
Session storage driver. Use redis or database in production, never file.
SESSION_LIFETIME
integer
default:"720"
Session lifetime in minutes (12 hours by default).
SESSION_ENCRYPT
boolean
default:"true"
Encrypt session data before storage.
Always keep this enabled in production.
Only send session cookies over HTTPS. Auto-detected from APP_URL if not set.
Must be enabled when using HTTPS, or users will be logged out.
SESSION_HTTP_ONLY
boolean
default:"true"
Prevent JavaScript from accessing session cookies.
Never disable! This protects against XSS attacks stealing session cookies.
SESSION_SAME_SITE
string
default:"lax"
SameSite cookie attribute. Options:
  • lax - Balanced security (recommended)
  • strict - Maximum security, may break some workflows
  • none - Allow cross-site requests (requires secure flag)
.env
SESSION_COOKIE=pterodactyl_session
SESSION_DOMAIN=
SESSION_PATH=/
Session cookie name. Auto-generated from APP_NAME if not set.
SESSION_DOMAIN
string
Cookie domain. Leave empty to use the current domain.
Set to .example.com (with leading dot) to share sessions across subdomains.
SESSION_PATH
string
default:"/"
Cookie path. Usually should remain /.

Encryption Key Management

Application Key

.env
APP_KEY=base64:YOUR_ENCRYPTION_KEY_HERE
The APP_KEY is used to encrypt:
  • Session data
  • Cookies
  • Database encrypted fields
  • Signed URLs
Never share or commit your APP_KEY to version control!Changing this key will:
  • Log out all users
  • Invalidate all encrypted data
  • Break password reset tokens

Generating a New Key

php artisan key:generate --force

Key Rotation

To rotate the encryption key without breaking existing data:
  1. Add the current key to APP_PREVIOUS_KEYS:
    .env
    APP_PREVIOUS_KEYS=base64:OLD_KEY_HERE
    
  2. Generate a new key:
    php artisan key:generate --force
    
  3. Laravel will attempt to decrypt data with old keys if the current key fails.

Debug Mode

.env
APP_DEBUG=false
APP_DEBUG
boolean
default:"false"
Enable detailed error messages and stack traces.
Critical Security Risk! Debug mode exposes:
  • Environment variables (including passwords)
  • Database queries
  • File paths
  • Application internals
NEVER enable in production!

Safe Error Reporting

For production error tracking, use error monitoring services:
.env
APP_DEBUG=false
APP_REPORT_ALL_EXCEPTIONS=false
LOG_LEVEL=error

Password Security

The Panel uses bcrypt for password hashing. No additional configuration needed.

Password Requirements

Password requirements are enforced at the application level:
  • Minimum 8 characters
  • No maximum length
  • No character requirements (allowing passphrases)

Two-Factor Authentication

Encourage users to enable 2FA:
  1. User account → Security → Two-Factor Authentication
  2. Scan QR code with authenticator app
  3. Enter verification code
Consider making 2FA mandatory for administrator accounts.

Security Headers

Configure security headers in your web server:
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "same-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'self';" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

Header Explanations

Prevents browsers from MIME-sniffing responses away from the declared content-type.X-Content-Type-Options: nosniff
Prevents clickjacking attacks by controlling whether the page can be embedded in frames.X-Frame-Options: SAMEORIGIN - Allow framing only from the same origin.
Enables browser’s XSS filtering (legacy, but still useful for older browsers).X-XSS-Protection: 1; mode=block
Controls how much referrer information is included with requests.Referrer-Policy: same-origin - Only send referrer for same-origin requests.
Controls which resources the browser is allowed to load, preventing XSS and injection attacks.
The Panel requires unsafe-inline and unsafe-eval for JavaScript functionality.
Forces browsers to only use HTTPS connections.Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Only enable HSTS after verifying HTTPS works correctly. Once enabled, browsers will refuse HTTP connections for the specified duration.

Firewall Configuration

Required Ports

Only expose necessary ports to the internet:
PortProtocolPurposePublic Access
80HTTPRedirect to HTTPSYes
443HTTPSPanel web interfaceYes
3306TCPMySQL/MariaDBNo
6379TCPRedisNo
Never expose database or Redis ports to the public internet!

UFW Firewall

# Allow HTTP and HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Deny database ports from external access
sudo ufw deny 3306/tcp
sudo ufw deny 6379/tcp

# Enable firewall
sudo ufw enable

File Permissions

Proper file permissions prevent unauthorized access:
# Set ownership
chown -R www-data:www-data /var/www/pterodactyl

# Set directory permissions
find /var/www/pterodactyl -type d -exec chmod 755 {} \;

# Set file permissions
find /var/www/pterodactyl -type f -exec chmod 644 {} \;

# Make storage and cache writable
chmod -R 770 /var/www/pterodactyl/storage
chmod -R 770 /var/www/pterodactyl/bootstrap/cache
Never set permissions to 777 or run the Panel as root!

Security Checklist

1

Use HTTPS

Configure SSL/TLS with a valid certificate (Let’s Encrypt recommended).
2

Disable Debug Mode

Set APP_DEBUG=false in production.
3

Secure Environment File

Set .env permissions to 600 and never commit to version control.
chmod 600 /var/www/pterodactyl/.env
4

Configure Trusted Proxies

Set TRUSTED_PROXIES if behind a reverse proxy or CDN.
5

Enable Session Security

Verify SESSION_ENCRYPT, SESSION_SECURE_COOKIE, and SESSION_HTTP_ONLY are enabled.
6

Secure Database Access

Use strong passwords and restrict access to localhost or private network.
7

Secure Redis

Set REDIS_PASSWORD and bind to localhost.
8

Configure Firewall

Only expose ports 80 and 443 to the public internet.
9

Set File Permissions

Follow the principle of least privilege for file permissions.
10

Enable 2FA

Enable two-factor authentication for all administrator accounts.
11

Regular Updates

Keep the Panel, PHP, and system packages up to date.
12

Monitor Logs

Regularly review logs for suspicious activity:
tail -f /var/www/pterodactyl/storage/logs/laravel-*.log

Additional Resources

Let's Encrypt SSL

Free SSL/TLS certificates with automatic renewal.

Mozilla SSL Config

Generate secure SSL configurations for your web server.

Security Headers

Test your site’s security headers.

SSL Labs Test

Test your SSL/TLS configuration.

Build docs developers (and LLMs) love