Skip to main content

Security Overview

Running a public Pokemon Showdown server requires careful attention to security. This guide covers essential security practices to protect your server and users.
Security is an ongoing process. Regularly update your server, monitor logs, and stay informed about new security threats.

Production Checklist

Before running your server in production, verify these critical security settings:
1

Disable Development Features

Ensure development-only features are disabled:
config/config.js
exports.noguestsecurity = false;  // MUST be false
exports.nothrottle = false;       // MUST be false
exports.noipchecks = false;       // MUST be false
NEVER enable noguestsecurity in production. It allows anyone to impersonate any user without authentication.
2

Restrict Console Access

Limit developer console access to localhost only:
config/config.js
exports.consoleips = ['127.0.0.1'];
Or disable it entirely:
config/config.js
exports.consoleips = [];
3

Review Backdoor Setting

Decide whether to allow Pokemon Showdown system operators access:
config/config.js
exports.backdoor = false;  // Set to false if you don't trust PS operators
The backdoor allows Pokemon Showdown developers to help with technical support but gives them full admin access.
4

Enable Crash Guard

Configure error handling and alerting:
config/config.js
exports.crashguard = true;
Consider setting up email alerts:
config/config.js
exports.crashguardemail = {
  options: {
    host: 'mail.example.com',
    port: 465,
    secure: true,
    auth: {
      user: '[email protected]',
      pass: 'secure-password'
    }
  },
  from: '[email protected]',
  to: '[email protected]',
  subject: 'Pokemon Showdown Crash Alert'
};

Network Security

HTTPS/SSL Configuration

Always use HTTPS in production to encrypt traffic:
config/config.js
exports.ssl = {
  port: 443,
  options: {
    key: './config/ssl/privkey.pem',
    cert: './config/ssl/fullchain.pem',
  },
};
The Pokemon Showdown client requires port 443 for SSL connections. Use Let’s Encrypt for free SSL certificates.

Let’s Encrypt Setup

1

Install Certbot

sudo apt-get update
sudo apt-get install certbot
2

Obtain Certificate

sudo certbot certonly --standalone -d yourdomain.com
3

Configure Auto-Renewal

Create a renewal hook script:
deploy-ssl.sh
#!/bin/bash
cp /etc/letsencrypt/live/yourdomain.com/privkey.pem ~/Pokemon-Showdown/config/ssl/
cp /etc/letsencrypt/live/yourdomain.com/fullchain.pem ~/Pokemon-Showdown/config/ssl/
chown showdown:showdown ~/Pokemon-Showdown/config/ssl/*.pem
chmod 600 ~/Pokemon-Showdown/config/ssl/*.pem
Add to certbot renewal:
sudo certbot renew --deploy-hook /path/to/deploy-ssl.sh

Reverse Proxy

Consider using a reverse proxy like nginx for additional security:
nginx.conf
upstream showdown {
    server 127.0.0.1:8000;
}

server {
    listen 443 ssl http2;
    server_name yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/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;

    location / {
        proxy_pass http://showdown;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
If using a reverse proxy, configure trusted proxy IPs:
config/config.js
exports.proxyip = ['127.0.0.1'];

Firewall Configuration

Use a firewall to restrict access:
ufw
# Allow SSH
sudo ufw allow 22/tcp

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

# Allow your Pokemon Showdown port (if not using reverse proxy)
sudo ufw allow 8000/tcp

# Enable firewall
sudo ufw enable

Access Control

Administrator Privileges

Minimal Admins

Only grant Administrator (~) rank to the server owner and highly trusted individuals.

Console Restriction

Never give console permission to anyone except the server owner. Console allows arbitrary code execution.

Regular Audits

Periodically review config/usergroups.csv and remove inactive admins.

Secure Credentials

Ensure all admin accounts use strong, unique passwords.

Permission Hierarchy

Follow the principle of least privilege:
  1. Administrators (~) - Server owner only
  2. Moderators (@) - Highly trusted, experienced staff
  3. Drivers (%) - Active, trustworthy moderators
  4. Voice (+) - Trusted community members
  5. Regular users - Everyone else

Console Access

The developer console is the most dangerous feature:
config/config.js
// Best practice: localhost only
exports.consoleips = ['127.0.0.1'];

// Alternative: disable entirely
exports.consoleips = [];

// NEVER do this in production:
exports.consoleips = ['0.0.0.0/0'];  // ❌ UNSAFE
Console access allows execution of arbitrary JavaScript code with full system privileges. A compromised console account can:
  • Read/write any file
  • Access the database
  • Execute system commands
  • Steal user data

User Security

Anti-Abuse Features

Enable security features to combat abuse:
config/config.js
// Restrict link sharing to autoconfirmed users
exports.restrictLinks = true;

// Monitor users with multiple punishments
exports.monitorminpunishments = 3;
exports.punishmentautolock = true;

// Enable name filtering
exports.disablebasicnamefilter = false;

// Enable all throttles and checks
exports.nothrottle = false;
exports.noipchecks = false;

Rate Limiting

Throttles prevent abuse and DoS attacks:
  • Rename throttling (prevent rapid name changes)
  • Chat message throttling (prevent spam)
  • Challenge throttling (prevent harassment)
  • Ladder search throttling (prevent abuse)
Never disable throttles (nothrottle = true) in production. They’re essential for preventing abuse.

IP-Based Protection

IP checking helps identify alt accounts and ban evaders:
config/config.js
exports.noipchecks = false;  // Keep enabled
Features enabled by IP checking:
  • Alt account detection
  • Ban evasion prevention
  • Shared IP identification
  • Connection limiting

Data Protection

Sensitive Files

Protect sensitive configuration files:
chmod 600 config/config.js
chmod 600 config/usergroups.csv
chmod 600 config/punishments.tsv
chmod 600 config/ssl/*.pem
Never commit sensitive files to version control:
.gitignore
config/config.js
config/usergroups.csv
config/punishments.tsv
config/ssl/
config/*.tsv
logs/
*.log

Logging

Enable comprehensive logging for security auditing:
config/config.js
exports.logchat = true;
exports.logchallenges = true;
Log files to monitor:
  • logs/chat/ - Chat room logs
  • logs/modlog/ - Moderation actions
  • logs/repl/ - Console usage
  • Punishment files
Regularly review logs for suspicious activity. Archive old logs and implement log rotation.

Database Security

Pokemon Showdown stores data in TSV files:
# Restrict access to data files
chmod 700 config/
chmod 600 config/*.tsv

# Regular backups
tar -czf backup-$(date +%Y%m%d).tar.gz config/ logs/
Backup schedule recommendation:
  • Daily: User groups and punishments
  • Weekly: Full server backup
  • Monthly: Archive backups off-site

Server Hardening

System Updates

Keep your system and dependencies updated:
# System updates (Ubuntu/Debian)
sudo apt-get update
sudo apt-get upgrade

# Node.js updates
npm install -g n
n latest

# Pokemon Showdown updates
cd pokemon-showdown
git pull
npm install
./pokemon-showdown
Set up automated security updates for your operating system.

Process Management

Use a process manager to automatically restart crashed servers:
# Install PM2
npm install -g pm2

# Start server with PM2
pm2 start pokemon-showdown --name showdown

# Configure auto-restart
pm2 startup
pm2 save
Example PM2 ecosystem file:
ecosystem.config.js
module.exports = {
  apps: [{
    name: 'showdown',
    script: './pokemon-showdown',
    watch: false,
    max_memory_restart: '1G',
    env: {
      NODE_ENV: 'production'
    },
    error_file: './logs/pm2-error.log',
    out_file: './logs/pm2-out.log',
    time: true
  }]
};

Dedicated User

Run Pokemon Showdown as a dedicated non-root user:
# Create dedicated user
sudo useradd -m -s /bin/bash showdown
sudo passwd showdown

# Transfer ownership
sudo chown -R showdown:showdown /home/showdown/pokemon-showdown

# Switch to user
sudo su - showdown
Never run Pokemon Showdown as root. A compromised server could lead to full system compromise.

Monitoring

Server Monitoring

Monitor server health and performance:
# Check server status
pm2 status
pm2 monit

# View logs
pm2 logs showdown

# Resource usage
top
htop

Security Monitoring

Watch for suspicious activity:
  1. Failed login attempts - Monitor authentication failures
  2. Unusual IP patterns - Track connections from suspicious IPs
  3. Privilege escalation - Log all rank changes
  4. Console usage - Audit all console commands
  5. Punishment patterns - Identify serial offenders

Automated Alerts

Set up alerts for critical events:
config/config.js
exports.crashguardemail = {
  // Email configuration for crash alerts
};
Consider external monitoring services:
  • UptimeRobot - Server availability monitoring
  • Sentry - Error tracking and reporting
  • LogRocket - User session replay

Incident Response

Security Breach Protocol

If your server is compromised:
1

Immediate Lockdown

/lockdown - Stop all new battles
Shut down the server once battles complete.
2

Assess Damage

  • Review console logs
  • Check moderation logs
  • Verify user data integrity
  • Identify compromised accounts
3

Reset Credentials

  • Change all admin passwords
  • Regenerate SSL certificates if needed
  • Review and update config/usergroups.csv
  • Reset any compromised accounts
4

Patch Vulnerability

  • Update to latest Pokemon Showdown version
  • Apply security patches
  • Review configuration for weaknesses
  • Implement additional security measures
5

Restore Service

  • Verify all security measures in place
  • Restore from clean backup if necessary
  • Restart server
  • Monitor closely for further issues
6

Post-Incident Review

  • Document what happened
  • Identify root cause
  • Implement preventive measures
  • Communicate with users if data was compromised

Security Best Practices Summary

Defense in Depth

Use multiple security layers: firewall, SSL, authentication, rate limiting

Least Privilege

Give users and processes only the minimum permissions needed

Regular Updates

Keep all software updated with latest security patches

Monitor Everything

Enable logging and monitoring for all security-relevant events

Backup Regularly

Maintain regular backups and test restoration procedures

Security Audits

Periodically review security settings and access logs

Additional Resources

Report Security Issues

If you discover a security vulnerability in Pokemon Showdown itself, report it to the development team at:[email protected]Do not disclose vulnerabilities publicly until they have been patched.

Next Steps

Configuration

Review all configuration options

Administration

Learn user management and moderation

Build docs developers (and LLMs) love