feat: v2.0.0 production-ready release with Redis, OPcache and Nginx optimizations
This commit is contained in:
579
playbooks/lemp-wordpress-ultimate.yml
Normal file
579
playbooks/lemp-wordpress-ultimate.yml
Normal file
@@ -0,0 +1,579 @@
|
||||
---
|
||||
# Ultimate LEMP WordPress installation with Redis, OPcache and Nginx Optimization
|
||||
- name: Install Ultimate LEMP stack with WordPress, Redis, OPcache and Nginx Performance (Ubuntu/Debian)
|
||||
hosts: all
|
||||
become: yes
|
||||
|
||||
pre_tasks:
|
||||
- name: Gather OS facts
|
||||
setup:
|
||||
gather_subset:
|
||||
- '!all'
|
||||
- '!min'
|
||||
- 'distribution'
|
||||
- 'distribution_version'
|
||||
- 'os_family'
|
||||
|
||||
- name: Load Debian family variables
|
||||
include_vars: "../vars/debian-family.yml"
|
||||
|
||||
- name: Debug OS information
|
||||
debug:
|
||||
msg: |
|
||||
OS Family: {{ ansible_os_family }}
|
||||
Distribution: {{ ansible_distribution }}
|
||||
Version: {{ ansible_distribution_version }}
|
||||
Supported: Ubuntu/Debian family systems
|
||||
|
||||
- name: Verify supported OS
|
||||
fail:
|
||||
msg: "This playbook only supports Ubuntu/Debian systems. Detected: {{ ansible_os_family }}"
|
||||
when: ansible_os_family != "Debian"
|
||||
|
||||
# Environment Detection and Configuration
|
||||
- name: Detect if running in Docker
|
||||
stat:
|
||||
path: /.dockerenv
|
||||
register: docker_env
|
||||
tags: always
|
||||
|
||||
- name: Check for deployment_environment override
|
||||
set_fact:
|
||||
environment_override: "{{ deployment_environment is defined }}"
|
||||
tags: always
|
||||
|
||||
- name: Set deployment environment (auto-detect or override)
|
||||
set_fact:
|
||||
deployment_environment: "{{ deployment_environment | default('docker' if docker_env.stat.exists else 'bare_metal') }}"
|
||||
tags: always
|
||||
|
||||
- name: Set WordPress site URL with smart defaults
|
||||
set_fact:
|
||||
wp_site_url: "{{ wp_site_url | default(_auto_wp_url) }}"
|
||||
vars:
|
||||
_auto_wp_url: "{{ 'http://localhost:8080' if (deployment_environment == 'docker') else 'http://' + (ansible_default_ipv4.address | default('localhost')) }}"
|
||||
tags: always
|
||||
|
||||
- name: Debug deployment configuration
|
||||
debug:
|
||||
msg: |
|
||||
Environment: {{ deployment_environment }} ({{ 'overridden' if environment_override else 'auto-detected' }})
|
||||
WordPress URL: {{ wp_site_url }}
|
||||
Docker detected: {{ docker_env.stat.exists }}
|
||||
tags: always
|
||||
|
||||
vars:
|
||||
# WordPress Configuration
|
||||
wordpress_path: "{{ web_root }}"
|
||||
wordpress_url: "http://{{ ansible_default_ipv4.address | default('localhost') }}"
|
||||
|
||||
# Database Configuration (use inventory variables or these defaults)
|
||||
default_mysql_root_password: "{{ mysql_root_password | default('secure_root_password_123') }}"
|
||||
default_wordpress_db_name: "{{ wordpress_db_name | default('wordpress_db') }}"
|
||||
default_wordpress_db_user: "{{ wordpress_db_user | default('wordpress_user') }}"
|
||||
default_wordpress_db_password: "{{ wordpress_db_password | default('secure_wp_password_123') }}"
|
||||
|
||||
# WordPress Admin (use inventory variables directly)
|
||||
# These variables come from inventory/production.yml
|
||||
# wp_admin_user, wp_admin_password, wp_admin_email, wp_site_title
|
||||
|
||||
tasks:
|
||||
# Package Installation
|
||||
- name: Update package cache
|
||||
apt:
|
||||
update_cache: yes
|
||||
cache_valid_time: 3600
|
||||
tags: packages
|
||||
|
||||
- name: Install all required packages
|
||||
package:
|
||||
name: "{{ packages }}"
|
||||
state: present
|
||||
tags: packages
|
||||
|
||||
# Service Management
|
||||
- name: Start and enable Nginx
|
||||
service:
|
||||
name: "{{ nginx_service }}"
|
||||
state: started
|
||||
enabled: yes
|
||||
tags: nginx
|
||||
|
||||
- name: Start and enable MySQL/MariaDB
|
||||
service:
|
||||
name: "{{ mysql_service }}"
|
||||
state: started
|
||||
enabled: yes
|
||||
tags: mysql
|
||||
|
||||
- name: Start and enable PHP-FPM
|
||||
service:
|
||||
name: "{{ php_fpm_service }}"
|
||||
state: started
|
||||
enabled: yes
|
||||
tags: php
|
||||
|
||||
# Firewall Configuration
|
||||
- name: Configure firewall (UFW)
|
||||
ufw:
|
||||
rule: allow
|
||||
port: "{{ item }}"
|
||||
proto: tcp
|
||||
loop:
|
||||
- "22"
|
||||
- "80"
|
||||
- "443"
|
||||
tags: firewall
|
||||
|
||||
# MySQL Security (Ubuntu 24.04 fix for auth_socket)
|
||||
- name: Set MySQL root password (using auth_socket first)
|
||||
mysql_user:
|
||||
name: root
|
||||
password: "{{ mysql_root_password }}"
|
||||
plugin: mysql_native_password
|
||||
login_unix_socket: /var/run/mysqld/mysqld.sock
|
||||
state: present
|
||||
become: true
|
||||
tags: mysql
|
||||
|
||||
- name: Create MySQL configuration for root
|
||||
template:
|
||||
src: ../templates/my.cnf.j2
|
||||
dest: /root/.my.cnf
|
||||
mode: '0600'
|
||||
tags: mysql
|
||||
|
||||
- name: Remove anonymous MySQL users
|
||||
mysql_user:
|
||||
name: ""
|
||||
host_all: yes
|
||||
state: absent
|
||||
tags: mysql
|
||||
|
||||
- name: Remove MySQL test database
|
||||
mysql_db:
|
||||
name: test
|
||||
state: absent
|
||||
tags: mysql
|
||||
|
||||
# WordPress Database Setup
|
||||
- name: Create WordPress database
|
||||
mysql_db:
|
||||
name: "{{ wordpress_db_name }}"
|
||||
state: present
|
||||
tags: mysql
|
||||
|
||||
- name: Create WordPress database user
|
||||
mysql_user:
|
||||
name: "{{ wordpress_db_user }}"
|
||||
password: "{{ wordpress_db_password }}"
|
||||
priv: "{{ wordpress_db_name }}.*:ALL"
|
||||
host: localhost
|
||||
state: present
|
||||
tags: mysql
|
||||
|
||||
# WordPress Installation
|
||||
- name: Create web root directory
|
||||
file:
|
||||
path: "{{ wordpress_path }}"
|
||||
state: directory
|
||||
owner: www-data
|
||||
group: www-data
|
||||
mode: '0755'
|
||||
tags: wordpress
|
||||
|
||||
- name: Remove default nginx index file
|
||||
file:
|
||||
path: "{{ wordpress_path }}/index.nginx-debian.html"
|
||||
state: absent
|
||||
tags: wordpress
|
||||
|
||||
- name: Download WordPress
|
||||
get_url:
|
||||
url: https://wordpress.org/latest.tar.gz
|
||||
dest: /tmp/wordpress.tar.gz
|
||||
mode: '0644'
|
||||
tags: wordpress
|
||||
|
||||
- name: Extract WordPress
|
||||
unarchive:
|
||||
src: /tmp/wordpress.tar.gz
|
||||
dest: /tmp/
|
||||
remote_src: yes
|
||||
tags: wordpress
|
||||
|
||||
- name: Copy WordPress files
|
||||
command: "cp -r /tmp/wordpress/. {{ wordpress_path }}/"
|
||||
args:
|
||||
creates: "{{ wordpress_path }}/wp-config-sample.php"
|
||||
tags: wordpress
|
||||
|
||||
- name: Set WordPress file permissions
|
||||
file:
|
||||
path: "{{ wordpress_path }}"
|
||||
owner: "{{ nginx_user }}"
|
||||
group: "{{ nginx_user }}"
|
||||
recurse: yes
|
||||
tags: wordpress
|
||||
|
||||
# SSL Configuration (optional)
|
||||
- name: Generate self-signed SSL certificate (if SSL enabled but no cert provided)
|
||||
command: >
|
||||
openssl req -x509 -nodes -days 365 -newkey rsa:2048
|
||||
-keyout {{ ssl_cert_key_path | default('/etc/ssl/private/nginx-selfsigned.key') }}
|
||||
-out {{ ssl_cert_path | default('/etc/ssl/certs/nginx-selfsigned.crt') }}
|
||||
-subj "/C=DE/ST=State/L=City/O=Organization/OU=OrgUnit/CN={{ domain_name }}"
|
||||
when:
|
||||
- ssl_enabled | default(false)
|
||||
- not (ssl_cert_path is defined and ssl_cert_key_path is defined)
|
||||
tags: ssl
|
||||
|
||||
# Nginx Configuration
|
||||
- name: Create Nginx configuration for WordPress
|
||||
template:
|
||||
src: ../templates/{% if ssl_enabled | default(false) %}wordpress-ssl.nginx.j2{% else %}wordpress.nginx.j2{% endif %}
|
||||
dest: "{{ nginx_sites_available }}/wordpress"
|
||||
backup: yes
|
||||
notify: restart nginx
|
||||
tags: nginx
|
||||
|
||||
- name: Enable WordPress site
|
||||
file:
|
||||
src: "{{ nginx_sites_available }}/wordpress"
|
||||
dest: "{{ nginx_sites_enabled }}/wordpress"
|
||||
state: link
|
||||
notify: restart nginx
|
||||
tags: nginx
|
||||
|
||||
- name: Remove default Nginx site
|
||||
file:
|
||||
path: "{{ nginx_sites_enabled }}/default"
|
||||
state: absent
|
||||
notify: restart nginx
|
||||
tags: nginx
|
||||
|
||||
# PHP Configuration
|
||||
- name: Configure PHP-FPM pool
|
||||
template:
|
||||
src: ../templates/www.conf.j2
|
||||
dest: "{{ php_fpm_pool_path }}/www.conf"
|
||||
backup: yes
|
||||
notify: restart php-fpm
|
||||
tags: php
|
||||
|
||||
- name: Configure PHP settings
|
||||
lineinfile:
|
||||
path: "{{ php_cli_config_path }}/php.ini"
|
||||
regexp: "{{ item.regexp }}"
|
||||
line: "{{ item.line }}"
|
||||
backup: yes
|
||||
loop:
|
||||
- { regexp: '^upload_max_filesize', line: 'upload_max_filesize = 64M' }
|
||||
- { regexp: '^post_max_size', line: 'post_max_size = 64M' }
|
||||
- { regexp: '^memory_limit', line: 'memory_limit = 256M' }
|
||||
- { regexp: '^max_execution_time', line: 'max_execution_time = 300' }
|
||||
- { regexp: '^disable_functions', line: 'disable_functions = ' }
|
||||
notify: restart php-fpm
|
||||
tags: php
|
||||
|
||||
# WordPress Configuration
|
||||
- name: Configure WordPress
|
||||
template:
|
||||
src: ../templates/wp-config.php.j2
|
||||
dest: "{{ wordpress_path }}/wp-config.php"
|
||||
owner: www-data
|
||||
group: www-data
|
||||
mode: '0600'
|
||||
tags: wordpress
|
||||
|
||||
# WP-CLI Installation
|
||||
- name: Download WP-CLI
|
||||
get_url:
|
||||
url: https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
|
||||
dest: /usr/local/bin/wp
|
||||
mode: '0755'
|
||||
tags: wp-cli
|
||||
|
||||
- name: Verify WP-CLI installation
|
||||
command: wp --info
|
||||
environment:
|
||||
HOME: "{{ wordpress_path }}"
|
||||
register: wp_cli_info
|
||||
tags: wp-cli
|
||||
|
||||
- name: Display WP-CLI info
|
||||
debug:
|
||||
var: wp_cli_info.stdout_lines
|
||||
tags: wp-cli
|
||||
|
||||
# WordPress Core Installation
|
||||
- name: Install WordPress Core
|
||||
command: >
|
||||
wp core install
|
||||
--url="{{ wp_site_url }}"
|
||||
--title="{{ wp_site_title }}"
|
||||
--admin_user="{{ wp_admin_user }}"
|
||||
--admin_password="{{ wp_admin_password }}"
|
||||
--admin_email="{{ wp_admin_email }}"
|
||||
--path="{{ wordpress_path }}"
|
||||
--allow-root
|
||||
environment:
|
||||
HOME: "{{ wordpress_path }}"
|
||||
tags: wp-install
|
||||
|
||||
- name: Set WordPress file ownership after installation
|
||||
file:
|
||||
path: "{{ wordpress_path }}"
|
||||
owner: "{{ nginx_user }}"
|
||||
group: "{{ nginx_user }}"
|
||||
recurse: yes
|
||||
tags: wp-install
|
||||
|
||||
- name: Display WordPress installation success
|
||||
debug:
|
||||
msg: |
|
||||
WordPress installation completed!
|
||||
URL: {{ wp_site_url }}
|
||||
Admin User: {{ wp_admin_user }}
|
||||
Admin Password: {{ wp_admin_password }}
|
||||
Admin Email: {{ wp_admin_email }}
|
||||
tags: wp-install
|
||||
|
||||
# =============================
|
||||
# REDIS CACHE (ULTIMATE FEATURE)
|
||||
# =============================
|
||||
- name: Install Redis server
|
||||
package:
|
||||
name: redis-server
|
||||
state: present
|
||||
when: enable_redis | default(false)
|
||||
tags: redis
|
||||
|
||||
- name: Start and enable Redis
|
||||
service:
|
||||
name: redis-server
|
||||
state: started
|
||||
enabled: yes
|
||||
when: enable_redis | default(false)
|
||||
tags: redis
|
||||
|
||||
- name: Configure Redis for WordPress
|
||||
lineinfile:
|
||||
path: /etc/redis/redis.conf
|
||||
regexp: "{{ item.regexp }}"
|
||||
line: "{{ item.line }}"
|
||||
backup: yes
|
||||
loop:
|
||||
- { regexp: '^# maxmemory', line: 'maxmemory 128mb' }
|
||||
- { regexp: '^# maxmemory-policy', line: 'maxmemory-policy allkeys-lru' }
|
||||
- { regexp: '^save 900 1', line: 'save 900 1' }
|
||||
when: enable_redis | default(false)
|
||||
notify: restart redis
|
||||
tags: redis
|
||||
|
||||
- name: Install Redis Object Cache plugin
|
||||
command: >
|
||||
wp plugin install redis-cache --activate
|
||||
--path="{{ wordpress_path }}"
|
||||
--allow-root
|
||||
environment:
|
||||
HOME: "{{ wordpress_path }}"
|
||||
when: enable_redis | default(false)
|
||||
tags: redis
|
||||
|
||||
- name: Enable Redis object cache
|
||||
command: >
|
||||
wp redis enable
|
||||
--path="{{ wordpress_path }}"
|
||||
--allow-root
|
||||
environment:
|
||||
HOME: "{{ wordpress_path }}"
|
||||
when: enable_redis | default(false)
|
||||
ignore_errors: yes
|
||||
tags: redis
|
||||
|
||||
- name: Display Redis status
|
||||
debug:
|
||||
msg: "Redis caching {{ 'ENABLED' if enable_redis | default(false) else 'DISABLED' }}"
|
||||
tags: redis
|
||||
|
||||
# =============================
|
||||
# OPCACHE OPTIMIZATION (ULTIMATE FEATURE)
|
||||
# =============================
|
||||
- name: Configure OPcache for WordPress
|
||||
lineinfile:
|
||||
path: "{{ php_cli_config_path }}/php.ini"
|
||||
regexp: "{{ item.regexp }}"
|
||||
line: "{{ item.line }}"
|
||||
backup: yes
|
||||
loop:
|
||||
- { regexp: '^;?opcache.enable=', line: 'opcache.enable=1' }
|
||||
- { regexp: '^;?opcache.memory_consumption=', line: 'opcache.memory_consumption=128' }
|
||||
- { regexp: '^;?opcache.interned_strings_buffer=', line: 'opcache.interned_strings_buffer=8' }
|
||||
- { regexp: '^;?opcache.max_accelerated_files=', line: 'opcache.max_accelerated_files=4000' }
|
||||
- { regexp: '^;?opcache.revalidate_freq=', line: 'opcache.revalidate_freq=2' }
|
||||
- { regexp: '^;?opcache.fast_shutdown=', line: 'opcache.fast_shutdown=1' }
|
||||
when: enable_opcache | default(false)
|
||||
notify: restart php-fpm
|
||||
tags: opcache
|
||||
|
||||
- name: Configure OPcache for PHP-FPM
|
||||
lineinfile:
|
||||
path: "/etc/php/{{ php_version }}/fpm/php.ini"
|
||||
regexp: "{{ item.regexp }}"
|
||||
line: "{{ item.line }}"
|
||||
backup: yes
|
||||
loop:
|
||||
- { regexp: '^;?opcache.enable=', line: 'opcache.enable=1' }
|
||||
- { regexp: '^;?opcache.memory_consumption=', line: 'opcache.memory_consumption=128' }
|
||||
- { regexp: '^;?opcache.interned_strings_buffer=', line: 'opcache.interned_strings_buffer=8' }
|
||||
- { regexp: '^;?opcache.max_accelerated_files=', line: 'opcache.max_accelerated_files=4000' }
|
||||
- { regexp: '^;?opcache.revalidate_freq=', line: 'opcache.revalidate_freq=2' }
|
||||
- { regexp: '^;?opcache.fast_shutdown=', line: 'opcache.fast_shutdown=1' }
|
||||
when: enable_opcache | default(false)
|
||||
notify: restart php-fpm
|
||||
tags: opcache
|
||||
|
||||
- name: Display OPcache status
|
||||
debug:
|
||||
msg: "OPcache optimization {{ 'ENABLED' if enable_opcache | default(false) else 'DISABLED' }}"
|
||||
tags: opcache
|
||||
|
||||
# =============================
|
||||
# NGINX PERFORMANCE OPTIMIZATION (ULTIMATE FEATURE)
|
||||
# =============================
|
||||
- name: Backup original nginx.conf
|
||||
copy:
|
||||
src: /etc/nginx/nginx.conf
|
||||
dest: /etc/nginx/nginx.conf.backup
|
||||
remote_src: yes
|
||||
when: enable_nginx_optimization | default(false)
|
||||
tags: nginx-optimization
|
||||
|
||||
# Clean up any existing ansible-managed blocks first
|
||||
- name: Remove existing ansible-managed blocks from nginx.conf
|
||||
blockinfile:
|
||||
path: /etc/nginx/nginx.conf
|
||||
marker: "# {mark} ANSIBLE MANAGED BLOCK - Ultimate Performance"
|
||||
state: absent
|
||||
when: enable_nginx_optimization | default(false)
|
||||
tags: nginx-optimization
|
||||
|
||||
- name: Remove duplicate worker directives from wrong blocks
|
||||
lineinfile:
|
||||
path: /etc/nginx/nginx.conf
|
||||
regexp: "{{ item }}"
|
||||
state: absent
|
||||
loop:
|
||||
- '^\s*worker_processes\s+auto;.*# Added by Ansible'
|
||||
- '^\s*worker_rlimit_nofile\s+65535;.*# Added by Ansible'
|
||||
when: enable_nginx_optimization | default(false)
|
||||
tags: nginx-optimization
|
||||
|
||||
# Configure Worker settings in main block (before events)
|
||||
- name: Configure Nginx worker settings in main block (before events)
|
||||
lineinfile:
|
||||
path: /etc/nginx/nginx.conf
|
||||
regexp: "{{ item.regexp }}"
|
||||
line: "{{ item.line }}"
|
||||
insertbefore: "events {"
|
||||
backup: yes
|
||||
loop:
|
||||
- { regexp: '^worker_processes', line: 'worker_processes auto;' }
|
||||
- { regexp: '^worker_rlimit_nofile', line: 'worker_rlimit_nofile 65535;' }
|
||||
when: enable_nginx_optimization | default(false)
|
||||
notify: restart nginx
|
||||
tags: nginx-optimization
|
||||
|
||||
- name: Configure Nginx events block
|
||||
lineinfile:
|
||||
path: /etc/nginx/nginx.conf
|
||||
regexp: '^(\s*)worker_connections.*'
|
||||
line: '\1worker_connections 2048;'
|
||||
backrefs: yes
|
||||
backup: yes
|
||||
when: enable_nginx_optimization | default(false)
|
||||
notify: restart nginx
|
||||
tags: nginx-optimization
|
||||
|
||||
# Configure HTTP block optimizations (only unique directives)
|
||||
- name: Configure optimized Nginx HTTP configuration
|
||||
blockinfile:
|
||||
path: /etc/nginx/nginx.conf
|
||||
marker: "# {mark} ANSIBLE MANAGED BLOCK - HTTP Performance"
|
||||
insertafter: "http {"
|
||||
block: |
|
||||
# Ultimate Performance optimizations (unique directives only)
|
||||
keepalive_requests 1000;
|
||||
|
||||
# Enhanced Gzip compression
|
||||
gzip_vary on;
|
||||
gzip_min_length 1000;
|
||||
gzip_comp_level 6;
|
||||
gzip_types
|
||||
text/plain
|
||||
text/css
|
||||
text/xml
|
||||
text/javascript
|
||||
application/javascript
|
||||
application/json
|
||||
application/xml+rss
|
||||
application/atom+xml
|
||||
image/svg+xml;
|
||||
|
||||
# Buffer sizes
|
||||
client_body_buffer_size 128k;
|
||||
client_max_body_size 64m;
|
||||
client_header_buffer_size 1k;
|
||||
large_client_header_buffers 4 4k;
|
||||
|
||||
# Timeouts
|
||||
client_body_timeout 12;
|
||||
client_header_timeout 12;
|
||||
send_timeout 10;
|
||||
|
||||
# Cache for file handles
|
||||
open_file_cache max=200000 inactive=20s;
|
||||
open_file_cache_valid 30s;
|
||||
open_file_cache_min_uses 2;
|
||||
open_file_cache_errors on;
|
||||
backup: yes
|
||||
when: enable_nginx_optimization | default(false)
|
||||
notify: restart nginx
|
||||
tags: nginx-optimization
|
||||
|
||||
- name: Create Nginx cache directory
|
||||
file:
|
||||
path: /var/cache/nginx/fastcgi
|
||||
state: directory
|
||||
owner: www-data
|
||||
group: www-data
|
||||
mode: '0755'
|
||||
when: enable_nginx_optimization | default(false)
|
||||
tags: nginx-optimization
|
||||
|
||||
- name: Display Nginx optimization status
|
||||
debug:
|
||||
msg: "Nginx performance optimization {{ 'ENABLED' if enable_nginx_optimization | default(false) else 'DISABLED' }}"
|
||||
tags: nginx-optimization
|
||||
|
||||
handlers:
|
||||
- name: restart nginx
|
||||
service:
|
||||
name: "{{ nginx_service }}"
|
||||
state: restarted
|
||||
|
||||
- name: restart php-fpm
|
||||
service:
|
||||
name: "{{ php_fpm_service }}"
|
||||
state: restarted
|
||||
|
||||
- name: restart mysql
|
||||
service:
|
||||
name: "{{ mysql_service }}"
|
||||
state: restarted
|
||||
|
||||
- name: restart redis
|
||||
service:
|
||||
name: redis-server
|
||||
state: restarted
|
||||
Reference in New Issue
Block a user