Private
Public Access
1
0
Files
websitebox/docs/SECURITY.md
constantprojects a440026701 Initial commit: complete WebsiteBox project
Docker-based self-hosted WordPress deployment system with:
- Four-container stack (nginx, wordpress/php-fpm, mariadb, certbot)
- Automatic SSL via Let's Encrypt with self-signed fallback
- First-boot WordPress setup via WP-CLI (GeneratePress + child theme, plugins)
- Interactive setup wizard and one-line install script
- Backup, update, healthcheck, and SSL renewal scripts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 15:24:23 -07:00

3.3 KiB

Security Practices

Container Security

  • All containers use minimal Alpine-based images where possible
  • MariaDB is not exposed to the host network — it communicates only with WordPress on the internal Docker network
  • Only ports 80 (HTTP) and 443 (HTTPS) are exposed to the host
  • No containers run in privileged mode
  • The Docker socket is never mounted into any container
  • All containers use restart: unless-stopped (not always)

SSL/TLS

  • Let's Encrypt certificates are acquired automatically on first boot
  • Certificates are renewed automatically every 12 hours (per Let's Encrypt recommendation)
  • TLS 1.2+ only (TLS 1.0 and 1.1 are disabled)
  • Strong cipher suites with forward secrecy
  • HSTS header with a 2-year max-age
  • OCSP stapling enabled
  • SSL session tickets disabled for forward secrecy

WordPress Hardening

  • DISALLOW_FILE_EDIT: The theme and plugin file editor in wp-admin is disabled. This prevents an attacker with admin access from injecting code via the editor. Note: this does NOT block plugin/theme updates via the admin GUI — those still work normally.
  • XML-RPC disabled: The XML-RPC endpoint is disabled both at the application level (via mu-plugin) and at the nginx level (returns 403). XML-RPC is a common attack vector for brute-force and DDoS amplification.
  • Non-standard table prefix: Tables use wbox_ instead of the default wp_, which mitigates automated SQL injection attacks targeting default table names.
  • Strong passwords: Database passwords and WordPress salts are auto-generated using cryptographic randomness (openssl rand). Admin passwords must be at least 12 characters.
  • Post revisions limited: WordPress stores a maximum of 10 revisions per post to limit database growth.
  • Minor auto-updates: WordPress core security patches are applied automatically.

Nginx Security

  • Rate limiting: wp-login.php is rate-limited to 1 request/second with a burst of 3, mitigating brute-force login attempts.
  • Security headers: HSTS, X-Content-Type-Options, X-Frame-Options (SAMEORIGIN), X-XSS-Protection, Referrer-Policy.
  • PHP upload restrictions: Blocked in uploads/ directory at nginx level.
  • Hidden files blocked: Dotfiles (.htaccess, .git, etc.) return 403.

Wordfence

Wordfence is pre-installed and provides:

  • Application-level web application firewall (WAF)
  • Brute-force login protection
  • Malware scanning
  • Real-time threat intelligence

Note: Wordfence's .htaccess-based WAF rules do not apply to nginx. The nginx rate limiting and Wordfence's application-level firewall provide equivalent protection.

Secrets Management

  • All secrets are stored in .env with permissions set to 600 (owner read/write only)
  • The .env file is gitignored and never committed to the repository
  • Auto-generated admin passwords are stored temporarily in .credentials — users are instructed to delete this file after recording the password
  • WordPress salts are generated uniquely per installation

Network Architecture

Internet → :80/:443 → nginx → wordpress (FastCGI :9000) → db (:3306 internal only)
                          ↕
                       certbot (ACME challenges)

Only nginx is reachable from the internet. All other services communicate on the internal Docker network (websitebox_internal).