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>
This commit is contained in:
63
docs/SECURITY.md
Normal file
63
docs/SECURITY.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# 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`).
|
||||
Reference in New Issue
Block a user