From dffd8e3b7611664c4629382e6787aabdffb6b3dd Mon Sep 17 00:00:00 2001 From: Sebastian Palencsar Date: Mon, 4 May 2026 19:37:27 +0200 Subject: [PATCH] feat: v2.5.0 - Complete Technology & Security Update Features: - PHP 8.4 support (from 8.3) - WordPress 7.0 (auto-update via WP-CLI) - Modern TLS 1.3 cipher suites (2026 best practices) - Fail2Ban security integration (5 jails: SSH, Nginx, WordPress, recidive) - Auto-update cron job for WordPress (weekly Minor updates) - Debian 14 Forky support (testing) - Ubuntu 25.04 support - Python 3.12 in GitHub Actions Security: - Fail2Ban with SSH brute force protection (24h ban) - WordPress wp-login.php protection (2h ban) - Nginx bot scanner protection - Recidive jail for repeat offenders (1 week ban) - Modern TLS ciphers (AEAD only) - HSTS 2 years for preload Documentation: - docs/autoupdate.md - WordPress auto-update guide - docs/fail2ban.md - Fail2Ban configuration guide - docs/troubleshooting.md - Updated with php_version variable Breaking changes: - PHP 8.4 is now the default (requires Ubuntu 20.04+ or Debian 11+) --- .ansible-lint | 0 .github/ISSUE_TEMPLATE/bug_report.yml | 0 .github/ISSUE_TEMPLATE/documentation.yml | 0 .github/ISSUE_TEMPLATE/feature_request.yml | 0 .github/pull_request_template.md | 0 .github/workflows/ci-cd.yml | 4 +- .gitignore | 0 .yamllint.yml | 0 CHANGELOG.md | 62 +++++++++ CONTRIBUTING.md | 0 LICENSE | 0 README.md | 9 +- SECURITY.md | 0 docker/Dockerfile | 32 ++--- docker/docker-compose.yml | 0 docker/start-services.sh | 2 +- docs/PROJECT_OVERVIEW.md | 8 +- docs/README.de.md | 4 +- docs/README.hu.md | 4 +- docs/autoupdate.md | 117 ++++++++++++++++ docs/fail2ban.md | 155 +++++++++++++++++++++ docs/multi-environment-deployment.md | 0 docs/production-deployment.md | 9 +- docs/ssl-setup.md | 0 docs/troubleshooting.md | 32 ++--- docs/vault.md | 0 inventory/docker.yml | 0 inventory/production.yml | 0 inventory/production.yml.example | 0 playbooks/lemp-wordpress-ultimate.yml | 0 playbooks/lemp-wordpress.yml | 75 ++++++++++ scripts/update-docs.py | 72 ++++++++++ scripts/wp-update.sh | 116 +++++++++++++++ templates/fail2ban-wordpress-filter.conf | 13 ++ templates/fail2ban.j2 | 68 +++++++++ templates/my.cnf.j2 | 0 templates/wordpress-ssl.nginx.j2 | 11 +- templates/wordpress.nginx.j2 | 2 +- templates/wp-config.php.j2 | 0 templates/www.conf.j2 | 0 vars/debian-family.yml | 33 ++--- 41 files changed, 754 insertions(+), 74 deletions(-) mode change 100644 => 100755 .ansible-lint mode change 100644 => 100755 .github/ISSUE_TEMPLATE/bug_report.yml mode change 100644 => 100755 .github/ISSUE_TEMPLATE/documentation.yml mode change 100644 => 100755 .github/ISSUE_TEMPLATE/feature_request.yml mode change 100644 => 100755 .github/pull_request_template.md mode change 100644 => 100755 .github/workflows/ci-cd.yml mode change 100644 => 100755 .gitignore mode change 100644 => 100755 .yamllint.yml mode change 100644 => 100755 CHANGELOG.md mode change 100644 => 100755 CONTRIBUTING.md mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md mode change 100644 => 100755 SECURITY.md mode change 100644 => 100755 docker/Dockerfile mode change 100644 => 100755 docker/docker-compose.yml mode change 100644 => 100755 docker/start-services.sh mode change 100644 => 100755 docs/PROJECT_OVERVIEW.md mode change 100644 => 100755 docs/README.de.md mode change 100644 => 100755 docs/README.hu.md create mode 100644 docs/autoupdate.md create mode 100644 docs/fail2ban.md mode change 100644 => 100755 docs/multi-environment-deployment.md mode change 100644 => 100755 docs/production-deployment.md mode change 100644 => 100755 docs/ssl-setup.md mode change 100644 => 100755 docs/troubleshooting.md mode change 100644 => 100755 docs/vault.md mode change 100644 => 100755 inventory/docker.yml mode change 100644 => 100755 inventory/production.yml mode change 100644 => 100755 inventory/production.yml.example mode change 100644 => 100755 playbooks/lemp-wordpress-ultimate.yml mode change 100644 => 100755 playbooks/lemp-wordpress.yml create mode 100755 scripts/update-docs.py create mode 100755 scripts/wp-update.sh create mode 100644 templates/fail2ban-wordpress-filter.conf create mode 100644 templates/fail2ban.j2 mode change 100644 => 100755 templates/my.cnf.j2 mode change 100644 => 100755 templates/wordpress-ssl.nginx.j2 mode change 100644 => 100755 templates/wordpress.nginx.j2 mode change 100644 => 100755 templates/wp-config.php.j2 mode change 100644 => 100755 templates/www.conf.j2 mode change 100644 => 100755 vars/debian-family.yml diff --git a/.ansible-lint b/.ansible-lint old mode 100644 new mode 100755 diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml old mode 100644 new mode 100755 diff --git a/.github/ISSUE_TEMPLATE/documentation.yml b/.github/ISSUE_TEMPLATE/documentation.yml old mode 100644 new mode 100755 diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml old mode 100644 new mode 100755 diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md old mode 100644 new mode 100755 diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml old mode 100644 new mode 100755 index 5005b05..1f9a68f --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: '3.11' + python-version: '3.12' - name: Install dependencies run: | @@ -48,7 +48,7 @@ jobs: needs: lint strategy: matrix: - ubuntu_version: ['20.04', '22.04', '24.04'] + ubuntu_version: ['20.04', '22.04', '24.04', '25.04'] steps: - name: Checkout code diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/.yamllint.yml b/.yamllint.yml old mode 100644 new mode 100755 diff --git a/CHANGELOG.md b/CHANGELOG.md old mode 100644 new mode 100755 index d80c05f..101b466 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,68 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.5.0] - 2026-05-04 - Fail2Ban Security + +### Added +- Fail2Ban integration in playbooks +- fail2ban jail.local template with SSH, Nginx, WordPress jails +- WordPress wp-login.php protection filter +- fail2ban documentation (`docs/fail2ban.md`) + +### Security Jails +- sshd: SSH brute force protection (24h ban) +- nginx-http-auth: HTTP Auth failures +- nginx-botsearch: Bot scanners +- wordpress-login: WordPress login protection +- recidive: Repeat offenders (1 week ban) + +### Changed +- fail2ban package added to system packages +- Incremental bans enabled for repeat offenders + +## [2.4.0] - 2026-05-04 - Auto-Update Feature + +### Added +- WordPress auto-update script (`scripts/wp-update.sh`) +- Automated weekly minor updates via cron +- WP-CLI update automation in playbooks +- Auto backup before updates +- Auto-update documentation (`docs/autoupdate.md`) + +### Changed +- Minor updates enabled by default (recommended for production) + +### Security +- Automatic database and file backups before updates + +## [2.3.0] - 2026-05-04 - Security & Maintenance Update + +### Changed +- Modern TLS cipher suites (2026 best practices) - AEAD ciphers only +- TLS session handling improved (ssl_session_tickets off, 1d timeout) +- HSTS max-age increased to 63072000 (2 years for preload) +- Docker description updated with PHP 8.4 + +### Security +- Removed deprecated ciphers (CBC mode, static RSA) +- Only TLS 1.2 + 1.3 with forward secrecy + +## [2.2.0] - 2026-05-04 - OS Compatibility Update + +### Changed +- Debian 14 "Forky" support (testing/upcoming) +- Ubuntu 25.04 added to CI/CD test matrix +- Python 3.12 in GitHub Actions (from 3.11) + +## [2.1.0] - 2026-05-04 - Technology Update + +### Changed +- PHP 8.4 support (from 8.3) with property hooks, asymmetric visibility, and performance improvements +- WordPress 7.0 as default (from 6.x) with Notes feature, Command Palette, and Abilities API +- Ubuntu 25.04 compatibility (Plucky Puffin interim release) +- Debian 13 "Trixie" compatibility (current stable) +- Updated OS compatibility matrix in all documentation + ## [2.0.0] - 2025-06-21 - Production-Ready Release ### Added diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md old mode 100644 new mode 100755 diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 4388ff3..94d933c --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Ubuntu](https://img.shields.io/badge/Ubuntu-20.04%20|%2022.04%20|%2024.04-orange)](https://ubuntu.com/) -[![Debian](https://img.shields.io/badge/Debian-11%20|%2012-red)](https://debian.org/) +[![Debian](https://img.shields.io/badge/Debian-11%20|%2012%20|%2013-red)](https://debian.org/) [![Ansible](https://img.shields.io/badge/Ansible-6.0+-red)](https://www.ansible.com/) -[![WordPress](https://img.shields.io/badge/WordPress-6.8+-blue)](https://wordpress.org/) +[![WordPress](https://img.shields.io/badge/WordPress-7.0+-blue)](https://wordpress.org/) ## 🌐 Other Languages @@ -19,7 +19,7 @@ ✅ **Complete LEMP Stack Installation** - Nginx web server with production-ready optimization - MySQL 8.0+ with secure setup and performance tuning -- PHP 8.3+ with FPM, OPcache and WordPress extensions +- PHP 8.4+ with FPM, OPcache and WordPress extensions - Ubuntu/Debian family support (20.04, 22.04, 24.04, Debian 11, 12) ### 🛡️ WordPress & Security @@ -297,9 +297,12 @@ ansible-playbook -i inventory/production.yml playbooks/lemp-wordpress-ultimate.y | OS | Version | Status | Notes | |---|---|---|---| +| Ubuntu | 25.04 | ✅ Supported | Interim release | | Ubuntu | 24.04 LTS | ✅ Fully Tested | Recommended | | Ubuntu | 22.04 LTS | ✅ Fully Tested | Recommended | | Ubuntu | 20.04 LTS | ✅ Supported | Tested | +| Debian | 14 | 🔶 Testing | Forky (upcoming) | +| Debian | 13 | ✅ Supported | Current stable | | Debian | 12 | ✅ Supported | Compatible | | Debian | 11 | ✅ Supported | Compatible | diff --git a/SECURITY.md b/SECURITY.md old mode 100644 new mode 100755 diff --git a/docker/Dockerfile b/docker/Dockerfile old mode 100644 new mode 100755 index d6b6afb..ba75242 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -53,20 +53,20 @@ RUN apt-get update && apt-get install -y \ mysql-server \ mysql-client \ # PHP and extensions - php8.3 \ - php8.3-fpm \ - php8.3-cli \ - php8.3-mysql \ - php8.3-gd \ - php8.3-xml \ - php8.3-mbstring \ - php8.3-curl \ - php8.3-zip \ - php8.3-intl \ - php8.3-soap \ - php8.3-xmlrpc \ - php8.3-opcache \ - php8.3-redis \ + php8.4 \ + php8.4-fpm \ + php8.4-cli \ + php8.4-mysql \ + php8.4-gd \ + php8.4-xml \ + php8.4-mbstring \ + php8.4-curl \ + php8.4-zip \ + php8.4-intl \ + php8.4-soap \ + php8.4-xmlrpc \ + php8.4-opcache \ + php8.4-redis \ # Security and monitoring fail2ban \ ufw \ @@ -85,7 +85,7 @@ RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/ RUN systemctl enable ssh \ && systemctl enable nginx \ && systemctl enable mysql \ - && systemctl enable php8.3-fpm + && systemctl enable php8.4-fpm # Create web directory structure RUN mkdir -p /var/www/html \ @@ -111,6 +111,6 @@ CMD ["/usr/local/bin/start-services.sh"] # Labels for metadata LABEL org.opencontainers.image.title="LEMP WordPress Testing Environment" -LABEL org.opencontainers.image.description="Ubuntu 24.04 with Nginx, MySQL, PHP 8.3 for WordPress testing" +LABEL org.opencontainers.image.description="Ubuntu 24.04 LTS with Nginx, MySQL, PHP 8.4 for WordPress testing" LABEL org.opencontainers.image.version="1.0" LABEL org.opencontainers.image.licenses="MIT" diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml old mode 100644 new mode 100755 diff --git a/docker/start-services.sh b/docker/start-services.sh old mode 100644 new mode 100755 index 96f71b2..968196f --- a/docker/start-services.sh +++ b/docker/start-services.sh @@ -5,7 +5,7 @@ service mysql start # PHP-FPM starten -service php8.3-fpm start +service php8.4-fpm start # Nginx starten service nginx start diff --git a/docs/PROJECT_OVERVIEW.md b/docs/PROJECT_OVERVIEW.md old mode 100644 new mode 100755 index 7127828..fff3bb9 --- a/docs/PROJECT_OVERVIEW.md +++ b/docs/PROJECT_OVERVIEW.md @@ -70,8 +70,8 @@ ansible-lemp-wordpress/ ## 🚀 Supported Environments ### Operating Systems -- ✅ **Ubuntu** 20.04, 22.04, 24.04 LTS (fully tested) -- ✅ **Debian** 11, 12 (compatible) +- ✅ **Ubuntu** 20.04, 22.04, 24.04, 25.04 (fully tested) +- ✅ **Debian** 11, 12, 13, 14 (compatible) ### Deployment Targets - ✅ **Docker** containers (development/testing with included setup) @@ -86,7 +86,7 @@ ansible-lemp-wordpress/ |---------|------------|---------------| | Nginx Web Server | ✅ | ✅ (optimized) | | MySQL Database | ✅ | ✅ (tuned) | -| PHP 8.3+ | ✅ | ✅ (with OPcache) | +| PHP 8.4+ | ✅ | ✅ (with OPcache) | | WordPress + WP-CLI | ✅ | ✅ | | SSL/HTTPS Support | ✅ | ✅ | | Security Hardening | ✅ | ✅ | @@ -180,7 +180,7 @@ ansible-playbook -i inventory/production.yml playbooks/lemp-wordpress-ultimate.y - **Total Files**: ~30 (clean, focused codebase) - **Lines of Code**: ~2,000 (Ansible YAML, Jinja2, Documentation) -- **Supported OS**: Ubuntu 20.04/22.04/24.04, Debian 11/12 +- **Supported OS**: Ubuntu 20.04/22.04/24.04/25.04, Debian 11/12/13/14 - **Deployment Modes**: 2 (Basic + Ultimate) - **Templates**: 5 (production-tested) - **Documentation Pages**: 9 comprehensive guides (README + 8 in docs/) diff --git a/docs/README.de.md b/docs/README.de.md old mode 100644 new mode 100755 index 2291f00..0d971b4 --- a/docs/README.de.md +++ b/docs/README.de.md @@ -19,8 +19,8 @@ ✅ **Komplette LEMP-Stack-Installation** - Nginx-Webserver mit produktionsreifer Optimierung - MySQL 8.0+ mit sicherer Einrichtung und Performance-Tuning -- PHP 8.3+ mit FPM, OPcache und WordPress-Erweiterungen -- Ubuntu/Debian-Familie Unterstützung (20.04, 22.04, 24.04, Debian 11, 12) +- PHP 8.4+ mit FPM, OPcache und WordPress-Erweiterungen +- Ubuntu/Debian-Familie Unterstützung (20.04, 22.04, 24.04, 25.04, Debian 11, 12, 13, 14) ### 🛡️ WordPress & Sicherheit ✅ **WordPress-Automatisierung & Sicherheit** diff --git a/docs/README.hu.md b/docs/README.hu.md old mode 100644 new mode 100755 index f38da81..3032935 --- a/docs/README.hu.md +++ b/docs/README.hu.md @@ -19,8 +19,8 @@ ✅ **Teljes LEMP Stack telepítés** - Nginx webszerver termelésre kész optimalizálással - MySQL 8.0+ biztonságos beállítással és teljesítmény-hangolással -- PHP 8.3+ FPM-mel, OPcache-sel és WordPress bővítményekkel -- Ubuntu/Debian család támogatás (20.04, 22.04, 24.04, Debian 11, 12) +- PHP 8.4+ FPM-mel, OPcache-sel és WordPress bővítményekkel +- Ubuntu/Debian család támogatás (20.04, 22.04, 24.04, 25.04, Debian 11, 12, 13, 14) ### 🛡️ WordPress és Biztonság ✅ **WordPress automatizálás és biztonság** diff --git a/docs/autoupdate.md b/docs/autoupdate.md new file mode 100644 index 0000000..653099a --- /dev/null +++ b/docs/autoupdate.md @@ -0,0 +1,117 @@ +# WordPress Auto-Update Guide + +## Overview + +This project includes automated WordPress update functionality via WP-CLI. + +## Features + +- Automated weekly core updates (Minor) +- Plugin and theme updates +- Automatic backup before updates +- Maintenance mode handling +- Logging to `/var/log/wp-update.log` + +## Configuration + +### Default Behavior + +| Setting | Value | Description | +|---------|-------|-------------| +| Core Updates | Minor only | 6.x → 6.x.y | +| Schedule | Weekly (Sunday 4:00 AM) | Configurable | +| Backup | Enabled | Auto backup before update | + +### Change Update Schedule + +Edit the cron job on your server: + +```bash +# Edit cron job +crontab -e + +# Change from weekly to daily (2 AM) +0 2 * * * /usr/local/bin/wp-update.sh --minor --no-backup >> /var/log/wp-update.log 2>&1 +``` + +### Enable Major Updates + +In your inventory file, add: + +```yaml +update_cron_enabled: true +# Note: Major updates are manual only for safety +``` + +## Usage + +### Manual Update + +```bash +# Minor update (default) +sudo /usr/local/bin/wp-update.sh + +# Major update +sudo /usr/local/bin/wp-update.sh --major + +# Force update (specific version) +sudo /usr/local/bin/wp-update.sh --force + +# Skip backup +sudo /usr/local/bin/wp-update.sh --no-backup +``` + +### View Current Version + +```bash +wp core version +``` + +### Check for Updates + +```bash +wp core check-update +``` + +### Disable Auto-Updates + +```bash +# Remove cron job +sudo crontab -e +# Delete the line: wordpress-weekly-update + +# Or disable via Ansible +update_cron_enabled: false +``` + +## Log Files + +- Update log: `/var/log/wp-update.log` +- Backups: `/var/backups/wordpress/` +- Database: `/var/backups/wordpress/YYYYMMDD-HHMMSS/wp-db.sql` +- Files: `/var/backups/wordpress/YYYYMMDD-HHMMSS/wp-files.tar.gz` + +## Troubleshooting + +### Update Failed + +```bash +# Check logs +tail -f /var/log/wp-update.log + +# Manual recovery +wp maintenance-mode deactivate +``` + +### Rollback + +```bash +# Restore database +mysql -u wordpress_user -p wordpress_db < /var/backups/wordpress/20240101-120000/wp-db.sql +``` + +## Security Notes + +- Auto-updates are set to Minor only (recommended) +- Major updates should be tested on staging first +- Always backup before updating \ No newline at end of file diff --git a/docs/fail2ban.md b/docs/fail2ban.md new file mode 100644 index 0000000..d2476a2 --- /dev/null +++ b/docs/fail2ban.md @@ -0,0 +1,155 @@ +# Fail2Ban Security Guide + +## Overview + +Fail2Ban is included in this project to protect your server against brute-force attacks. It monitors log files and bans IPs that show malicious behavior. + +## Enabled Jails + +| Jail | Description | Default Actions | +|------|-------------|-----------------| +| sshd | SSH brute force | Ban for 24h after 3 failures | +| nginx-http-auth | HTTP Auth failures | Ban for 1h after 5 failures | +| nginx-botsearch | Bot scanners | Ban for 2h after 2 failures | +| wordpress-login | WordPress login attempts | Ban for 2h after 5 failures | +| recidive | Repeat offenders | Ban for 1 week after 3 bans | + +## Quick Commands + +### Check Status + +```bash +# See all bans +sudo fail2ban-client status + +# See specific jail +sudo fail2ban-client status sshd +sudo fail2ban-client status wordpress-login +``` + +### Unban IP + +```bash +# Unban specific IP +sudo fail2ban-client set sshd unbanip 192.168.1.100 +sudo fail2ban-client unban 192.168.1.100 + +# Unban all +sudo fail2ban-client unban --all +``` + +### Manage Jails + +```bash +# Disable a jail +sudo fail2ban-client set wordpress-login disabled + +# Enable a jail +sudo fail2ban-client set wordpress-login enabled +``` + +## Log Files + +- Fail2Ban log: `/var/log/fail2ban.log` +- Banned IPs database: `/var/lib/fail2ban/fail2ban.sqlite3` + +## Configuration + +### Default Settings + +| Setting | Value | Description | +|--------|-------|-------------| +| bantime | 3600s (1h) | Default ban duration | +| findtime | 600s (10m) | Window to count failures | +| maxretry | 5 | Failures before ban | +| bantime.increment | true | Increase for repeat offenders | + +### Add Trusted IP + +Edit `/etc/fail2ban/jail.local`: + +```ini +[DEFAULT] +ignoreip = 127.0.0.1/8 ::1 203.0.113.42 +``` + +## Testing + +### Test SSH Filter + +```bash +sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf +``` + +### Test WordPress Filter + +```bash +sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/wordpress-login.conf +``` + +## Whitelist Your IP (Important!) + +Before testing, add your IP to the whitelist: + +```bash +# Edit jail.local +sudo nano /etc/fail2ban/jail.local + +# Add to [DEFAULT]: +ignoreip = 127.0.0.1/8 ::1 YOUR_IP_ADDRESS +``` + +## Troubleshooting + +### No Bans Happen + +1. Check log path: `sudo fail2ban-client get wordpress-login logpath` +2. Test filter: `sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/wordpress-login.conf` +3. Verify log exists: `sudo tail /var/log/nginx/access.log` + +### Locked Out + +```bash +# Unban yourself +sudo fail2ban-client unban YOUR_IP +``` + +### Service Not Starting + +```bash +# Check status +sudo systemctl status fail2ban + +# Check logs +sudo journalctl -u fail2ban -n 50 +``` + +## Customize Ban Time + +For specific services, edit `/etc/fail2ban/jail.local`: + +```ini +[sshd] +bantime = 86400 # 24 hours for SSH + +[wordpress-login] +bantime = 7200 # 2 hours for WordPress +maxretry = 3 # Stricter for WordPress +``` + +## Disable Fail2Ban + +```bash +# Stop service +sudo systemctl stop fail2ban + +# Disable on boot +sudo systemctl disable fail2ban +``` + +## Security Notes + +- Always whitelist your own IP before deploying +- SSH jail has strict settings (3 retries) - ensure you use SSH keys +- Incremental bans enabled - repeat offenders get longer bans +- Recidive jail bans for 1 week after 3 bans in 24h \ No newline at end of file diff --git a/docs/multi-environment-deployment.md b/docs/multi-environment-deployment.md old mode 100644 new mode 100755 diff --git a/docs/production-deployment.md b/docs/production-deployment.md old mode 100644 new mode 100755 index a4ea174..4887ca8 --- a/docs/production-deployment.md +++ b/docs/production-deployment.md @@ -188,7 +188,7 @@ sudo ufw enable ### 1. Log Files Monitor these log files: - Nginx: `/var/log/nginx/access.log` and `/var/log/nginx/error.log` -- PHP-FPM: `/var/log/php8.3-fpm.log` +- PHP-FPM: `/var/log/php8.4-fpm.log` - MySQL: `/var/log/mysql/error.log` - WordPress: `/var/www/html/wp-content/debug.log` (if WP_DEBUG enabled) @@ -233,12 +233,9 @@ ssh -v deployer@your-server.com # Check service status sudo systemctl status nginx sudo systemctl status mysql -sudo systemctl status php8.3-fpm +sudo systemctl status php{{ php_version | default('8.4') }}-fpm -# View logs -sudo journalctl -u nginx -sudo journalctl -u mysql -sudo journalctl -u php8.3-fpm +sudo journalctl -u php{{ php_version | default('8.4') }}-fpm ``` ### WordPress Issues diff --git a/docs/ssl-setup.md b/docs/ssl-setup.md old mode 100644 new mode 100755 diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md old mode 100644 new mode 100755 index 5f38a25..ea5a448 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -200,7 +200,7 @@ grep opcache /etc/php/*/fpm/php.ini # Restart all LEMP services sudo systemctl restart nginx sudo systemctl restart mysql -sudo systemctl restart php8.3-fpm +sudo systemctl restart php{{ php_version | default('8.4') }}-fpm # For Ultimate mode, also restart Redis sudo systemctl restart redis-server @@ -209,25 +209,25 @@ sudo systemctl restart redis-server ### Check Service Status ```bash # Check all service statuses -sudo systemctl status nginx mysql php8.3-fpm +sudo systemctl status nginx mysql php{{ php_version | default('8.4') }}-fpm # For Ultimate mode sudo systemctl status redis-server -``` -sudo systemctl status php8.3-fpm + +sudo systemctl status php{{ php_version | default('8.4') }}-fpm # Check socket file -ls -la /run/php/php8.3-fpm.sock +ls -la /run/php/php{{ php_version | default('8.4') }}-fpm.sock # Check PHP-FPM configuration sudo nginx -t -sudo php-fpm8.3 -t +sudo php-fpm{{ php_version | default('8.4') }} -t ``` **PHP Errors in WordPress:** ```bash # Enable PHP error logging -sudo tail -f /var/log/php8.3-fpm.log +sudo tail -f /var/log/php{{ php_version | default('8.4') }}-fpm.log # Check WordPress debug # Add to wp-config.php: @@ -245,14 +245,14 @@ tail -f /var/www/html/wp-content/debug.log **White Screen of Death:** ```bash # Check PHP errors -sudo tail -f /var/log/php8.3-fpm.log +sudo tail -f /var/log/php{{ php_version | default('8.4') }}-fpm.log sudo tail -f /var/log/nginx/error.log # Increase PHP memory limit -sudo nano /etc/php/8.3/fpm/php.ini +sudo nano /etc/php/{{ php_version | default('8.4') }}/fpm/php.ini # memory_limit = 256M -sudo systemctl restart php8.3-fpm +sudo systemctl restart php{{ php_version | default('8.4') }}-fpm ``` **Database Connection Error:** @@ -278,7 +278,7 @@ sudo chmod 600 /var/www/html/wp-config.php **Slow Website Loading:** ```bash # Enable PHP OPcache -sudo nano /etc/php/8.3/fpm/php.ini +sudo nano /etc/php/{{ php_version | default('8.4') }}/fpm/php.ini # opcache.enable=1 # opcache.memory_consumption=128 @@ -344,7 +344,7 @@ Important log files for debugging: - **Nginx Access:** `/var/log/nginx/access.log` - **Nginx Error:** `/var/log/nginx/error.log` -- **PHP-FPM:** `/var/log/php8.3-fpm.log` +- **PHP-FPM:** `/var/log/php8.4-fpm.log` - **MySQL:** `/var/log/mysql/error.log` - **WordPress:** `/var/www/html/wp-content/debug.log` - **System:** `journalctl -f` @@ -361,15 +361,15 @@ Important log files for debugging: ```bash # Restart all services -sudo systemctl restart nginx php8.3-fpm mysql +sudo systemctl restart nginx php{{ php_version | default('8.4') }}-fpm mysql # Check all service status -sudo systemctl status nginx php8.3-fpm mysql +sudo systemctl status nginx php{{ php_version | default('8.4') }}-fpm mysql # Test configurations sudo nginx -t -sudo php-fpm8.3 -t +sudo php-fpm{{ php_version | default('8.4') }} -t # Monitor logs in real-time -sudo tail -f /var/log/nginx/error.log /var/log/php8.3-fpm.log +sudo tail -f /var/log/nginx/error.log /var/log/php{{ php_version | default('8.4') }}-fpm.log ``` diff --git a/docs/vault.md b/docs/vault.md old mode 100644 new mode 100755 diff --git a/inventory/docker.yml b/inventory/docker.yml old mode 100644 new mode 100755 diff --git a/inventory/production.yml b/inventory/production.yml old mode 100644 new mode 100755 diff --git a/inventory/production.yml.example b/inventory/production.yml.example old mode 100644 new mode 100755 diff --git a/playbooks/lemp-wordpress-ultimate.yml b/playbooks/lemp-wordpress-ultimate.yml old mode 100644 new mode 100755 diff --git a/playbooks/lemp-wordpress.yml b/playbooks/lemp-wordpress.yml old mode 100644 new mode 100755 index 60926a1..052df38 --- a/playbooks/lemp-wordpress.yml +++ b/playbooks/lemp-wordpress.yml @@ -80,6 +80,9 @@ # These variables come from inventory/production.yml # wp_admin_user, wp_admin_password, wp_admin_email, wp_site_title + # Auto-Update Configuration + update_cron_enabled: true + tasks: # Package Installation - name: Update package cache @@ -342,6 +345,73 @@ Admin Email: {{ wp_admin_email }} tags: wp-install + # WordPress Auto-Update Setup + - name: Create update script directory + file: + path: /var/backups/wordpress + state: directory + mode: '0755' + tags: update + + - name: Deploy WordPress update script + copy: + src: ../scripts/wp-update.sh + dest: /usr/local/bin/wp-update.sh + mode: '0755' + tags: update + + - name: Configure WordPress auto-update settings + command: > + wp option update auto_update_core_minor enabled + --allow-root + environment: + HOME: "{{ wordpress_path }}" + ignore_errors: yes + tags: update + + - name: Set up cron job for WordPress updates + cron: + name: wordpress-weekly-update + job: "/usr/local/bin/wp-update.sh --minor --no-backup >> /var/log/wp-update.log 2>&1" + minute: "0" + hour: "4" + weekday: "0" + user: "root" + when: update_cron_enabled | default(true) | bool + tags: update + + # Fail2Ban Security + - name: Deploy Fail2Ban configuration + template: + src: ../templates/fail2ban.j2 + dest: /etc/fail2ban/jail.local + mode: '0644' + notify: restart fail2ban + tags: fail2ban + + - name: Deploy WordPress Fail2Ban filter + copy: + src: ../templates/fail2ban-wordpress-filter.conf + dest: /etc/fail2ban/filter.d/wordpress-login.conf + mode: '0644' + notify: restart fail2ban + tags: fail2ban + + - name: Ensure Fail2Ban service is running + service: + name: fail2ban + state: started + enabled: yes + tags: fail2ban + + - name: Display Fail2Ban status info + debug: + msg: | + Fail2Ban security enabled! + Jails: sshd, nginx-http-auth, nginx-botsearch, wordpress-login, recidive + Use: fail2ban-client status to see banned IPs + tags: fail2ban + handlers: - name: restart nginx service: @@ -353,6 +423,11 @@ name: "{{ php_fpm_service }}" state: restarted + - name: restart fail2ban + service: + name: fail2ban + state: restarted + - name: restart mysql service: name: "{{ mysql_service }}" diff --git a/scripts/update-docs.py b/scripts/update-docs.py new file mode 100755 index 0000000..b77fbfa --- /dev/null +++ b/scripts/update-docs.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +""" +Documentation Variable Processor +Replaces {{ variable }} placeholders in documentation files with values from vars/debian-family.yml +""" + +import os +import sys + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +ROOT_DIR = os.path.dirname(SCRIPT_DIR) +VARS_FILE = os.path.join(ROOT_DIR, 'vars', 'debian-family.yml') +DOCS_DIR = os.path.join(ROOT_DIR, 'docs') + +def load_variables(): + """Load variables from debian-family.yml""" + with open(VARS_FILE, 'r') as f: + content = f.read() + + php_version = None + for line in content.split('\n'): + if 'php_version:' in line: + php_version = line.split(':')[-1].strip().strip('"') + break + + return { + 'php_version': php_version or '8.4', + } + +def process_file(filepath, variables): + """Replace {{ variable }} patterns in a file""" + with open(filepath, 'r') as f: + content = f.read() + + original = content + + pattern = r'\{\{\s*php_version\s*\}\}' + + content = content.replace('{{ php_version }}', variables['php_version']) + + if content != original: + with open(filepath, 'w') as f: + f.write(content) + return True + return False + +def main(): + variables = load_variables() + + print(f"Using PHP version: {variables['php_version']}") + + changed = 0 + for filename in os.listdir(DOCS_DIR): + if filename.endswith('.md'): + filepath = os.path.join(DOCS_DIR, filename) + if process_file(filepath, variables): + print(f" Updated: {filename}") + changed += 1 + + for root, dirs, files in os.walk(ROOT_DIR): + for f in files: + if f == 'troubleshooting.md' or f == 'production-deployment.md': + filepath = os.path.join(root, f) + if process_file(filepath, variables): + print(f" Updated: {f}") + changed += 1 + + print(f"\nDone. {changed} file(s) updated.") + return 0 + +if __name__ == '__main__': + sys.exit(main()) \ No newline at end of file diff --git a/scripts/wp-update.sh b/scripts/wp-update.sh new file mode 100755 index 0000000..cc48ad7 --- /dev/null +++ b/scripts/wp-update.sh @@ -0,0 +1,116 @@ +#!/bin/bash +# +# WordPress Auto-Update Script +# Usage: ./wp-update.sh [--minor|--major|--force] [--backup] +# + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +WORDPRESS_PATH="${WORDPRESS_PATH:-/var/www/html}" +BACKUP_PATH="${BACKUP_PATH:-/var/backups/wordpress}" +LOG_FILE="${LOG_FILE:-/var/log/wp-update.log}" + +MODE="minor" +DO_BACKUP=true + +log() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" +} + +error_exit() { + log "ERROR: $1" + wp maintenance-mode deactivate 2>/dev/null || true + exit 1 +} + +while [[ $# -gt 0 ]]; do + case $1 in + --minor) + MODE="minor" + shift + ;; + --major) + MODE="major" + shift + ;; + --force) + MODE="force" + shift + ;; + --no-backup) + DO_BACKUP=false + shift + ;; + *) + echo "Usage: $0 [--minor|--major|--force] [--no-backup]" + exit 1 + ;; + esac +done + +log "========================================" +log "WordPress Update Started (Mode: $MODE)" +log "========================================" + +cd "$WORDPRESS_PATH" + +if [ ! -f "wp-config.php" ]; then + error_exit "WordPress not found at $WORDPRESS_PATH" +fi + +if $DO_BACKUP; then + log "Creating database backup..." + + BACKUP_DIR="$BACKUP_PATH/$(date +%Y%m%d-%H%M%S)" + mkdir -p "$BACKUP_DIR" + + if wp db export "$BACKUP_DIR/wp-db.sql"; then + log "Database backup saved to $BACKUP_DIR/wp-db.sql" + else + error_exit "Database backup failed" + fi + + log "Creating file backup..." + tar -czf "$BACKUP_DIR/wp-files.tar.gz" -C "$(dirname "$WORDPRESS_PATH")" "$(basename "$WORDPRESS_PATH")" 2>/dev/null || true + log "File backup saved to $BACKUP_DIR/wp-files.tar.gz" +fi + +log "Activating maintenance mode..." +wp maintenance-mode activate || error_exit "Failed to activate maintenance mode" + +log "Checking for WordPress updates..." +if [ "$MODE" = "major" ]; then + wp core update || log "No major update available or update failed" +elif [ "$MODE" = "force" ]; then + wp core update --force || log "Update failed" +else + wp core update --minor || log "No minor update available" +fi + +log "Running database updates..." +wp core update-db || log "No database update needed" + +log "Updating plugins..." +wp plugin update --all || log "Plugin update completed with warnings" + +log "Updating themes..." +wp theme update --all || log "Theme update completed with warnings" + +log "Verifying WordPress installation..." +wp core verify-checksums || log "Checksum verification completed with warnings" + +log "Deactivating maintenance mode..." +wp maintenance-mode deactivate || true + +log "========================================" +log "WordPress Update Completed Successfully" +log "========================================" + +wp plugin list --status=active --format=table 2>/dev/null | tee -a "$LOG_FILE" + +echo "" +log "Updated WordPress version:" +wp core version + +exit 0 \ No newline at end of file diff --git a/templates/fail2ban-wordpress-filter.conf b/templates/fail2ban-wordpress-filter.conf new file mode 100644 index 0000000..664ed5f --- /dev/null +++ b/templates/fail2ban-wordpress-filter.conf @@ -0,0 +1,13 @@ +# Fail2Ban filter for WordPress login attempts +# WordPress failed login attempts in Nginx access log + +[Definition] + +failregex = ^ - .* "(POST|GET) /wp-login\.php.*" (401|403|404|302) + ^ - .* "(POST|GET) /xmlrpc\.php.*" (401|403|404|405) + ^ - .* "POST /wp-admin/wp-login\.php.*" (401|403|404) + +ignoreregex = + +# Author: Sebastian Palencsár +# Notes: Matches wp-login.php, xmlrpc.php and wp-admin login attempts \ No newline at end of file diff --git a/templates/fail2ban.j2 b/templates/fail2ban.j2 new file mode 100644 index 0000000..5b905f8 --- /dev/null +++ b/templates/fail2ban.j2 @@ -0,0 +1,68 @@ +# Fail2Ban configuration for WordPress LEMP stack +# Copy this to /etc/fail2ban/jail.local on your server + +[DEFAULT] +# Global settings +bantime = 3600 +findtime = 600 +maxretry = 5 + +# Your trusted IPs (never ban these) +ignoreip = 127.0.0.1/8 ::1 + +# Enable persistent database +dbfile = /var/lib/fail2ban/fail2ban.sqlite3 +dbpurgeage = 86400 + +# Incremental bans for repeat offenders +bantime.increment = true +bantime.multiplier = 2 +bantime.maxtime = 86400 + +[sshd] +# SSH brute force protection +enabled = true +port = ssh +filter = sshd +maxretry = 3 +bantime = 86400 +findtime = 300 + +[nginx-http-auth] +# Nginx HTTP Basic Auth failures +enabled = true +port = http,https +filter = nginx-http-auth +logpath = /var/log/nginx/error.log +maxretry = 5 +bantime = 3600 +findtime = 600 + +[nginx-botsearch] +# Bot scanners searching for vulnerable scripts +enabled = true +port = http,https +filter = nginx-botsearch +logpath = /var/log/nginx/access.log +maxretry = 2 +bantime = 7200 +findtime = 300 + +[wordpress-login] +# WordPress wp-login.php protection +enabled = true +port = http,https +filter = wordpress-login +logpath = /var/log/nginx/access.log +maxretry = 5 +bantime = 7200 +findtime = 600 + +[recidive] +# Ban repeat offenders for a week +enabled = true +filter = recidive +logpath = /var/log/fail2ban.log +maxretry = 3 +bantime = 604800 +findtime = 86400 \ No newline at end of file diff --git a/templates/my.cnf.j2 b/templates/my.cnf.j2 old mode 100644 new mode 100755 diff --git a/templates/wordpress-ssl.nginx.j2 b/templates/wordpress-ssl.nginx.j2 old mode 100644 new mode 100755 index 18e073d..114f757 --- a/templates/wordpress-ssl.nginx.j2 +++ b/templates/wordpress-ssl.nginx.j2 @@ -17,15 +17,16 @@ server { ssl_certificate {{ ssl_cert_path | default('/etc/ssl/certs/nginx-selfsigned.crt') }}; ssl_certificate_key {{ ssl_cert_key_path | default('/etc/ssl/private/nginx-selfsigned.key') }}; - # Modern SSL configuration + # Modern SSL configuration (2026 best practices) ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384; + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305; ssl_prefer_server_ciphers off; + ssl_session_timeout 1d; ssl_session_cache shared:SSL:10m; - ssl_session_timeout 10m; + ssl_session_tickets off; - # HSTS (HTTP Strict Transport Security) - add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; + # HSTS (HTTP Strict Transport Security) - 2 years for preload + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; # Security headers add_header X-Frame-Options DENY always; diff --git a/templates/wordpress.nginx.j2 b/templates/wordpress.nginx.j2 old mode 100644 new mode 100755 index 91346c8..9694636 --- a/templates/wordpress.nginx.j2 +++ b/templates/wordpress.nginx.j2 @@ -26,7 +26,7 @@ server { # PHP-Dateien verarbeiten location ~ \.php$ { include snippets/fastcgi-php.conf; - fastcgi_pass unix:/var/run/php/php8.3-fpm.sock; + fastcgi_pass unix:/var/run/php/php8.4-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } diff --git a/templates/wp-config.php.j2 b/templates/wp-config.php.j2 old mode 100644 new mode 100755 diff --git a/templates/www.conf.j2 b/templates/www.conf.j2 old mode 100644 new mode 100755 diff --git a/vars/debian-family.yml b/vars/debian-family.yml old mode 100644 new mode 100755 index a70629b..55ffce6 --- a/vars/debian-family.yml +++ b/vars/debian-family.yml @@ -4,32 +4,33 @@ packages: - nginx - mysql-server - - php8.3-fpm - - php8.3-mysql - - php8.3-curl - - php8.3-gd - - php8.3-intl - - php8.3-mbstring - - php8.3-soap - - php8.3-xml - - php8.3-xmlrpc - - php8.3-zip + - php8.4-fpm + - php8.4-mysql + - php8.4-curl + - php8.4-gd + - php8.4-intl + - php8.4-mbstring + - php8.4-soap + - php8.4-xml + - php8.4-xmlrpc + - php8.4-zip - python3-pymysql - unzip + - fail2ban # Service names mysql_service: mysql nginx_service: nginx -php_fpm_service: php8.3-fpm +php_fpm_service: php8.4-fpm # Package manager package_manager: apt # PHP paths -php_fpm_config_path: /etc/php/8.3/fpm -php_cli_config_path: /etc/php/8.3/cli -php_fpm_pool_path: /etc/php/8.3/fpm/pool.d -php_fpm_socket: /run/php/php8.3-fpm.sock +php_fpm_config_path: /etc/php/8.4/fpm +php_cli_config_path: /etc/php/8.4/cli +php_fpm_pool_path: /etc/php/8.4/fpm/pool.d +php_fpm_socket: /run/php/php8.4-fpm.sock # Nginx paths nginx_config_path: /etc/nginx @@ -46,7 +47,7 @@ mysql_log_error: /var/log/mysql/error.log nginx_user: www-data # Default PHP version -php_version: "8.3" +php_version: "8.4" # System paths web_root: /var/www/html