🚀 NGINX WordPress Hosting Guide

Section 19: Hosting an Additional Site - Complete Setup and Hardening Process

📋 Table of Contents

📖 Overview

This comprehensive guide walks you through the process of hosting an additional WordPress site on your NGINX server. The process includes creating site directories, configuring databases, setting up NGINX server blocks, installing WordPress, and implementing security hardening measures.

Complete Workflow

1
Create Site Directories

Set up the directory structure for your new site

2
Create Database

Generate database with random credentials

3
Generate Admin Credentials

Create secure WordPress admin credentials and salts

4
Configure NGINX Server Block

Set up NGINX configuration for the new domain

5
Install WordPress

Download and configure WordPress files

6
Harden Security

Implement PHP pools, permissions, and security measures

7
Configure SSL

Install and configure SSL certificates

8
Optimize Performance

Enable caching and optimize PHP-FPM

🔧 Initial Site Setup

Step 1: Create Bash Scripts Directory

First, navigate to your home directory and create a directory for WordPress bash scripts:

cd
mkdir wp_bash_scripts/
cd wp_bash_scripts/

Step 2: Create Site Directories Script

Create a script to automatically generate site directories:

nano 1.create_wp_directories.sh

Script Contents:

#!/bin/bash # Function to create site directories create_site_directories() { domain=$1 # Check if the directory already exists if [ ! -d "/var/www/$domain" ]; then # Create the directories with appropriate permissions sudo mkdir -p "/var/www/$domain/public_html" sudo mkdir -p "/var/www/$domain/tmp" echo "Site directory for $domain created successfully." else echo "Site directory for $domain already exists." fi } # Main script starts here # Ask for domain name read -p "Enter domain name: " domain_name # Call function to create site directories create_site_directories "$domain_name"

Execute the Script:

chmod +x 1.create_wp_directories.sh
./1.create_wp_directories.sh
📝 Example Usage:

When prompted, enter your domain name (e.g., nginx.help)

The script will create: /var/www/nginx.help/public_html/ and /var/www/nginx.help/tmp/

Verify Directory Creation:

ls -l /var/www/
ls -l /var/www/nginx.help/
ls -l /var/www/nginx.help/public_html/

Step 3: Create Database Script

nano 2.create_wp_database.sh
⚠️ CRITICAL WARNING:

DO NOT USE A PERIOD IN THE DATABASE NAME!

Use an underscore (_) in place of a period when entering the database name.

Example: For domain nginx.help, use database name nginx_help

Script Contents:

#!/bin/bash echo "DO NOT USE A PERIOD IN THE DATABASE NAME" echo "use an underscore in place of a period" echo "What is your domain name?" read domain DB="$domain" # create random database user DBUSER="$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 12 | head -n 1)" # create random password PASSWORD="$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 12 | head -n 1)" # create random database prefix PREFIX="$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 4 | head -n 1)" mysql <

Execute the Script:

chmod +x 2.create_wp_database.sh
./2.create_wp_database.sh
💾 Save Your Credentials:

Immediately save the generated database credentials to a secure text file. You will need these for WordPress installation.

  • Database Name
  • Database User
  • Database Password
  • Table Prefix

Step 4: Generate Admin Credentials and Salts

nano 3.admin_credentials.sh

Script Contents:

#!/bin/bash # Generate and display WordPress admin username and password echo "Randomly Generated 30 Character WordPress Administrative Credentials" echo "" echo "WordPress Admin Username: $(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 30 | head -n 1)" echo "WordPress Admin Password: $(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 30 | head -n 1)" # Fetch WordPress salts wp_salts=$(curl -s https://api.wordpress.org/secret-key/1.1/salt/) # Add WP constants wp_constants=$(cat << 'EOF' /** Allow Direct Updating Without FTP */ define('FS_METHOD', 'direct' ); /** Disable Editing of Themes and Plugins Using the Built In Editor */ define('DISALLOW_FILE_EDIT', 'true' ); /** TURN OFF AUTOMATIC UPDATES */ define('WP_AUTO_UPDATE_CORE', 'false' ); EOF ) # Output the salts and constants echo "" echo "WordPress Salts" echo "" echo "$wp_salts" echo "" echo "Constants to be added to wp-config.php" echo "" echo "$wp_constants"

Execute the Script:

chmod +x 3.admin_credentials.sh
./3.admin_credentials.sh
✅ Best Practice:

Copy all generated credentials (admin username, password, salts, and constants) to your secure text file. You'll need these during WordPress configuration.

Step 5: Create NGINX Server Block

nano 4.nginx_server_block.sh

Script Contents:

#!/bin/bash # Function to create directories and files if they don't exist create_files_and_directories() { # Check if the includes directory exists, if not create it if [ ! -d "/etc/nginx/includes" ]; then sudo mkdir -p /etc/nginx/includes fi # Check if fastcgi_optimize.conf exists, if not create it if [ ! -f "/etc/nginx/includes/fastcgi_optimize.conf" ]; then sudo tee /etc/nginx/includes/fastcgi_optimize.conf > /dev/null < /dev/null < /dev/null <

Execute the Script:

chmod +x 4.nginx_server_block.sh
./4.nginx_server_block.sh
🔴 Important:

When prompted for the domain name in this script, USE THE PERIOD in the domain name (e.g., nginx.help)

The underscore restriction only applies to database names, not domain names.

Test and Reload NGINX:

sudo nginx -t
sudo systemctl reload nginx

Verify Server Block Creation:

cd /etc/nginx/sites-available/
ls -l
cd /etc/nginx/sites-enabled/
ls -l

Test Domain Response:

curl -I http://nginx.help
📊 Expected Behavior:
Scenario Response Explanation
Before NGINX reload Connection reset by peer Domain points to server but no server block is active
After NGINX reload (empty directory) 403 Forbidden Server block is active but document root is empty
After WordPress installation 200 OK WordPress is installed and serving content

📦 WordPress Installation

Step 1: Download WordPress

cd
wget https://wordpress.org/latest.tar.gz
ls

Step 2: Extract WordPress Files

tar xf latest.tar.gz
ls
cd wordpress/
ls

Step 3: Prepare Configuration File

mv wp-config-sample.php wp-config.php
ls

Step 4: Edit wp-config.php

nano wp-config.php

Configuration Changes Required:

Setting What to Change Source
DB_NAME Your database name From database creation script
DB_USER Your database username From database creation script
DB_PASSWORD Your database password From database creation script
Authentication Keys and Salts Replace all 8 salt lines From admin credentials script
$table_prefix Change to random prefix From database creation script
WP Constants Add before "That's all, stop editing!" From admin credentials script
⚙️ WordPress Constants to Add:
/** Allow Direct Updating Without FTP */ define('FS_METHOD', 'direct'); /** Disable Editing of Themes and Plugins Using the Built In Editor */ define('DISALLOW_FILE_EDIT', 'true'); /** TURN OFF AUTOMATIC UPDATES */ define('WP_AUTO_UPDATE_CORE', 'false');

Step 5: Copy Files and Set Ownership

cd
rsync -artv wordpress/ /var/www/nginx.help/public_html/
cd /var/www/nginx.help/
sudo chown -R www-data:www-data public_html/
ls -l
cd public_html/
ls -l

Step 6: Complete Installation via Browser

🌐 Browser Installation:
  1. Open your web browser
  2. Navigate to http://nginx.help (or your domain)
  3. Select your language
  4. Enter site title, admin username (from script), admin password (from script), and admin email
  5. Complete the installation

🔒 WordPress Hardening

PHP Pool Configuration

Create a dedicated PHP-FPM pool for enhanced security and isolation:

Step 1: Create System User

sudo useradd nginx_help_user
sudo usermod -a -G nginx_help_user www-data
sudo usermod -a -G www-data nginx_help_user
sudo usermod -a -G $USER nginx_help_user

Step 2: Create Pool Configuration

cd /etc/php/8.3/fpm/pool.d/
ls
sudo cp www.conf nginx.help.conf
ls
sudo nano nginx.help.conf

Pool Configuration Contents:

; pool name [nginx_help] ; Username and Group user = nginx_help_user group = nginx_help_user ; Path and Unix Socket Filename - unique to this pool listen = /run/php/php8.3-fpm-nginx.help.sock ; Set open file descriptor rlimit. rlimit_files = 15000 ; Set max core size rlimit. rlimit_core = 100 ; PHP POOL CONFIGURATION php_flag[display_errors] = off php_admin_value[error_log] = /var/log/fpm-php.nginx_help.log php_admin_flag[log_errors] = on

Step 3: Create Log File

sudo touch /var/log/fpm-php.nginx_help.log
sudo chown nginx_help_user:www-data /var/log/fpm-php.nginx_help.log
sudo chmod 660 /var/log/fpm-php.nginx_help.log

Step 4: Update NGINX Configuration

sudo nano /etc/nginx/sites-available/nginx.help.conf

Modify the PHP processing location block:

location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm-nginx.help.sock; include /etc/nginx/includes/fastcgi_optimize.conf; }

Step 5: Test and Reload Services

sudo nginx -t
sudo systemctl reload nginx
sudo systemctl reload php8.3-fpm

Ownership and Permissions

Standard Permissions (For Updates):

cd /var/www/nginx.help/
sudo chown -R nginx_help_user:nginx_help_user public_html/ tmp/
sudo chmod 770 public_html/
sudo chmod 770 tmp/
sudo find /var/www/nginx.help/public_html/ -type d -exec chmod 770 {} \;
sudo find /var/www/nginx.help/public_html/ -type f -exec chmod 660 {} \;
ls -l

Hardened Permissions (Production):

sudo find /var/www/nginx.help/public_html/ -type d -exec chmod 550 {} \;
sudo find /var/www/nginx.help/public_html/ -type f -exec chmod 440 {} \;
sudo find /var/www/nginx.help/public_html/wp-content/ -type d -exec chmod 770 {} \;
sudo find /var/www/nginx.help/public_html/wp-content/ -type f -exec chmod 660 {} \;
🔐 Permission Explanation:
Permission Directories Files Purpose
Standard 770 660 Allows WordPress to update themes/plugins
Hardened (Core) 550 440 Prevents modifications to core files
Hardened (wp-content) 770 660 Allows uploads and plugin functionality

PHP Function Restrictions

Add to the pool configuration file to disable dangerous PHP functions:

sudo nano /etc/php/8.3/fpm/pool.d/nginx.help.conf
; DISABLED FUNCTIONS php_admin_value[disable_functions] = shell_exec, opcache_get_configuration, opcache_get_status, disk_total_space, diskfreespace, dl, exec, passthru, pclose, pcntl_alarm, pcntl_exec, pcntl_fork, pcntl_get_last_error, pcntl_getpriority, pcntl_setpriority, pcntl_signal, pcntl_signal_dispatch, pcntl_sigprocmask, pcntl_sigtimedwait, pcntl_sigwaitinfo, pcntl_strerror, pcntl_waitpid, pcntl_wait, pcntl_wexitstatus, pcntl_wifcontinued, pcntl_wifexited, pcntl_wifsignaled, pcntl_wifstopped, pcntl_wstopsig, pcntl_wtermsig, popen, posix_getpwuid, posix_kill, posix_mkfifo, posix_setpgid, posix_setsid, posix_setuid, posix_uname, proc_close, proc_get_status, proc_nice, proc_open, proc_terminate, show_source, system
sudo systemctl reload php8.3-fpm

Open Base Directory Restrictions

Restrict PHP to access only necessary directories:

sudo nano /etc/php/8.3/fpm/pool.d/nginx.help.conf
php_admin_value[upload_tmp_dir] = /var/www/nginx.help/tmp/ php_admin_value[sys_temp_dir] = /var/www/nginx.help/tmp/ php_admin_value[open_basedir] = /var/www/nginx.help/public_html/:/var/www/nginx.help/tmp/

Database Privilege Restrictions

Step 1: Check Current Credentials

sudo grep DB_NAME /var/www/nginx.help/public_html/wp-config.php
sudo grep DB_USER /var/www/nginx.help/public_html/wp-config.php

Step 2: Restrict Database Privileges

mysql
REVOKE ALL PRIVILEGES ON database_name.* FROM 'username'@'localhost'; GRANT SELECT, INSERT, UPDATE, DELETE ON database_name.* TO 'username'@'localhost'; FLUSH PRIVILEGES; EXIT;
⚠️ Database Security:

Revoking CREATE, DROP, and ALTER privileges prevents attackers from modifying database structure, even if they compromise the WordPress installation.

🔐 SSL Certificate Configuration

Step 1: Obtain SSL Certificate

sudo certbot certonly --webroot -w /var/www/nginx.help/public_html/ -d nginx.help -d www.nginx.help

Step 2: Create SSL Configuration File

sudo nano /etc/nginx/ssl/ssl_certs_nginx.help.conf

SSL Configuration Contents:

ssl_certificate /etc/letsencrypt/live/nginx.help/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/nginx.help/privkey.pem; # SSL STAPLING ssl_trusted_certificate /etc/letsencrypt/live/nginx.help/chain.pem;

Step 3: Update NGINX Server Block for HTTPS

sudo nano /etc/nginx/sites-available/nginx.help.conf

Updated Server Block Configuration:

server { listen 80; server_name nginx.help www.nginx.help; # Redirect HTTP to HTTPS return 301 https://nginx.help$request_uri; } server { listen 443 ssl; http2 on; listen 443 quic; http3 on; server_name nginx.help www.nginx.help; root /var/www/nginx.help/public_html; index index.php; # Include SSL certificates include /etc/nginx/ssl/ssl_certs_nginx.help.conf; include /etc/nginx/ssl/ssl_all_sites.conf; location / { try_files $uri $uri/ /index.php$is_args$args; } # Include HTTP security headers include /etc/nginx/includes/http_headers.conf; # Include WordPress security directives include /etc/nginx/includes/wp_security.conf; location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_param HTTP_HOST $host; fastcgi_pass unix:/run/php/php8.3-fpm-nginx.help.sock; include /etc/nginx/includes/fastcgi_optimize.conf; } include /etc/nginx/includes/browser_caching.conf; access_log /var/log/nginx/access_nginx.help.log combined buffer=256k flush=60m; error_log /var/log/nginx/error_nginx.help.log; }

Step 4: Test and Reload

sudo nginx -t
sudo systemctl reload nginx

Step 5: Verify Redirects

curl -I http://nginx.help
curl -I http://www.nginx.help
curl -I https://www.nginx.help
curl -I https://nginx.help
✅ SSL Testing Resources:

Rate Limiting Configuration

cd /etc/nginx/includes/
sudo cp rate_limiting_example.com.conf rate_limiting_nginx.help.conf
sudo nano rate_limiting_nginx.help.conf

Rate Limiting Contents:

location = /wp-login.php { limit_req zone=wp burst=20 nodelay; limit_req_status 444; include snippets/fastcgi-php.conf; fastcgi_param HTTP_HOST $host; fastcgi_pass unix:/run/php/php8.3-fpm-nginx.help.sock; include /etc/nginx/includes/fastcgi_optimize.conf; } location = /xmlrpc.php { limit_req zone=wp burst=20 nodelay; limit_req_status 444; include snippets/fastcgi-php.conf; fastcgi_param HTTP_HOST $host; fastcgi_pass unix:/run/php/php8.3-fpm-nginx.help.sock; include /etc/nginx/includes/fastcgi_optimize.conf; }

Include in server block:

# Rate Limiting Include include /etc/nginx/includes/rate_limiting_nginx.help.conf;

⚡ Performance Optimization

WordPress Core Optimizations

1. Disable Post Revisions

Add to wp-config.php:

define('WP_POST_REVISIONS', 'false');

2. Increase Memory Limit

Edit PHP pool configuration:

sudo nano /etc/php/8.3/fpm/pool.d/nginx.help.conf
php_admin_value[memory_limit] = 256M

Add to wp-config.php:

/** MEMORY LIMIT */ define('WP_MEMORY_LIMIT', '256M');

3. Disable WP-Cron

Add to wp-config.php:

/** DISABLE WP-CRON */ define('DISABLE_WP_CRON', true);

Set up system cron:

crontab -e
*/15 * * * * wget -q -O - https://nginx.help/wp-cron.php?doing_wp_cron >/dev/null 2>&1

OPcache Configuration

sudo nano /etc/php/8.3/fpm/pool.d/nginx.help.conf

Development Server Configuration:

; OPCACHE CONFIGURATION - DEVELOPMENT SERVER php_admin_value[opcache.memory_consumption] = 256 php_admin_value[opcache.interned_strings_buffer] = 32 php_admin_value[opcache.max_accelerated_files] = 20000 php_admin_flag[opcache.validate_timestamps] = 1 php_admin_value[opcache.revalidate_freq] = 2 php_admin_flag[opcache.validate_permission] = 1

Production Server Configuration:

; OPCACHE CONFIGURATION - PRODUCTION SERVER php_admin_value[opcache.memory_consumption] = 256 php_admin_value[opcache.interned_strings_buffer] = 32 php_admin_value[opcache.max_accelerated_files] = 20000 php_admin_flag[opcache.validate_timestamps] = 0 php_admin_flag[opcache.validate_permission] = 1
📊 OPcache Setting Explanation:
Setting Purpose Dev vs Prod
memory_consumption Amount of memory for OPcache Same (256MB)
interned_strings_buffer Memory for string interning Same (32MB)
max_accelerated_files Maximum cached files Same (20000)
validate_timestamps Check file modifications Dev: 1 (check), Prod: 0 (don't check)
revalidate_freq Seconds between timestamp checks Dev: 2 seconds, Prod: N/A

FastCGI Caching

Step 1: Configure nginx.conf

sudo nano /etc/nginx/nginx.conf
### FASTCGI CACHING # fastcgi_cache_path directive - PATH & NAME must be unique for each site fastcgi_cache_path /var/run/nginx_help levels=1:2 keys_zone=NGINXHELP:100m inactive=60m; fastcgi_cache_path /var/run/site2 levels=1:2 keys_zone=SITE2:100m inactive=60m; # Applied to all sites fastcgi_cache_key "$scheme$request_method$host$request_uri"; fastcgi_cache_use_stale error timeout invalid_header http_500; fastcgi_ignore_headers Cache-Control Expires Set-Cookie;

Step 2: Update Server Block

sudo nano /etc/nginx/sites-available/nginx.help.conf

Add to PHP location block:

location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_param HTTP_HOST $host; fastcgi_pass unix:/run/php/php8.3-fpm-nginx.help.sock; include /etc/nginx/includes/fastcgi_optimize.conf; # FastCGI caching directives fastcgi_cache_bypass $skip_cache; fastcgi_no_cache $skip_cache; fastcgi_cache NGINXHELP; fastcgi_cache_valid 60m; } # Include cache exclusions include /etc/nginx/includes/fastcgi_cache_excludes.conf; add_header X-FastCGI-Cache $upstream_cache_status; # Cache purge location location ~ /purge(/.*) { fastcgi_cache_purge NGINXHELP "$scheme$request_method$host$1"; }

Permission Management Scripts

Loosen Permissions Script (For Updates)

cd ~/wp_bash_scripts/
nano 5.loosen_permissions.sh
#!/bin/bash # List directory contents of /var/www for reference sudo ls -l /var/www # Prompt for the domain name read -p "Enter the domain name: " domain_name # Check if the domain directory exists if [ ! -d "/var/www/$domain_name/public_html/" ]; then echo "Error: Domain directory /var/www/$domain_name/public_html/ does not exist." exit 1 fi # Set permissions with confirmation echo "Setting permissions for /var/www/$domain_name/public_html/..." # Grant read, write, and execute permissions to owner and group - directories sudo find "/var/www/$domain_name/public_html/" -type d -exec chmod 770 {} \; # Grant read and write permissions to owner and group - files sudo find "/var/www/$domain_name/public_html/" -type f -exec chmod 660 {} \; echo "Permissions set to allow WordPress updates using the dashboard!"

Tighten Permissions Script (For Production)

nano 6.tighten_permissions.sh
#!/bin/bash # List directory contents of /var/www for reference sudo ls -l /var/www # Prompt for the domain name read -p "Enter the domain name: " domain_name # Check if the domain directory exists if [ ! -d "/var/www/$domain_name/public_html/" ]; then echo "Error: Domain directory /var/www/$domain_name/public_html/ does not exist." exit 1 fi # Set permissions with confirmation echo "Setting permissions for /var/www/$domain_name/public_html/..." # Grant read and execute permissions to the owner and group only sudo find "/var/www/$domain_name/public_html/" -type d -exec chmod 550 {} \; # Grant read permissions to the owner and group only sudo find "/var/www/$domain_name/public_html/" -type f -exec chmod 440 {} \; # Grant read, write and execute permissions to owner and group - wp-content/ sudo find "/var/www/$domain_name/public_html/wp-content" -type d -exec chmod 770 {} \; # Grant read, write to owner and group - wp-content/ sudo find "/var/www/$domain_name/public_html/wp-content/" -type f -exec chmod 660 {} \; echo "Permissions hardened, no write permissions on core WordPress files and directories!"

Make Scripts Executable:

chmod +x 5.loosen_permissions.sh
chmod +x 6.tighten_permissions.sh

Monitoring Scripts

PHP-FPM Pool Memory Usage

nano pool_list_usage.sh
#!/bin/bash # Extract pool names pools=$(grep -E '^\s*user\s*=' /etc/php/8.3/fpm/pool.d/*.conf | awk -F= '{print $2}' | xargs | tr ' ' '\n' | sort -u) # Display memory used by each pool for pool in $pools; do memory_used=$(ps -C php-fpm --user "$pool" -o rss= | awk '{ sum += $1; count++ } END { if (count > 0) printf ("%d%s\n", sum/NR/1024,"M") }') echo -e "Pool: $pool\nMemory Used: $memory_used\n" done

OPcache File Count Checker

nano opcache_files.sh
#!/bin/bash echo "" echo "Checking for and displaying the opcache.max_accelerated_files directive value in each sites PHP pool file" echo "" POOL_DIR="/etc/php/8.3/fpm/pool.d/" for file in "$POOL_DIR"*.conf; do filename=$(basename "$file") if grep -q "^[^#;]*opcache.max_accelerated_files" "$file"; then value=$(grep "^[^#;]*opcache.max_accelerated_files" "$file" | awk -F'=' '{print $2}' | tr -d ' ') echo "File: $filename - opcache.max_accelerated_files: $value" else echo "File: $filename - opcache.max_accelerated_files directive not found" fi done echo "" echo "Listing sites and number of PHP files in each site, compare to the value set in the pool file" echo "" WWW_DIR="/var/www/" for domain_dir in "$WWW_DIR"*/ ; do if [ "$domain_dir" == "/var/www/html/" ]; then continue fi domain_name=$(basename "$domain_dir") public_html_dir="$domain_dir/public_html/" if [ -d "$public_html_dir" ]; then php_file_count=$(find "$public_html_dir" -type f -name "*.php" | wc -l) echo "Domain: $domain_name - PHP files: $php_file_count" else echo "Domain: $domain_name - public_html directory not found" fi done echo ""

Make Monitoring Scripts Executable:

chmod +x pool_list_usage.sh
chmod +x opcache_files.sh

📋 Quick Reference Checklist

Initial Setup Checklist

Step Task Status
1 Create site directories
2 Create database (use underscore, not period!)
3 Generate admin credentials and salts
4 Create NGINX server block
5 Test and reload NGINX
6 Download and extract WordPress
7 Configure wp-config.php
8 Copy files and set ownership
9 Complete browser installation

Security Hardening Checklist

Step Task Status
1 Create dedicated system user
2 Create PHP-FPM pool configuration
3 Create PHP error log file
4 Update NGINX to use new PHP socket
5 Set file ownership and permissions
6 Disable dangerous PHP functions
7 Configure open_basedir restrictions
8 Restrict database privileges
9 Obtain and configure SSL certificates
10 Enable rate limiting
11 Test SSL configuration

Optimization Checklist

Step Task Status
1 Disable post revisions
2 Increase WordPress memory limit
3 Disable WP-Cron
4 Set up system cron job
5 Configure OPcache
6 Enable FastCGI caching
7 Create permission management scripts
8 Create monitoring scripts

⚠️ Important Notes and Best Practices

Database Naming Convention

NEVER use a period (.) in database names!

MySQL does not support periods in database names. Always use underscores (_) instead.

Example: nginx.helpnginx_help

Save All Credentials

Immediately save all generated credentials in a secure location:

  • Database name, username, and password
  • Database table prefix
  • WordPress admin username and password
  • WordPress salts

Permission Management

Always use the appropriate permissions based on your needs:

  • Standard (770/660): When you need to update WordPress, themes, or plugins via the dashboard
  • Hardened (550/440 for core, 770/660 for wp-content): For maximum security in production

Use the provided scripts to easily switch between permission levels.

Testing Recommendations

Always test your configuration after changes:

  • Test NGINX configuration: sudo nginx -t
  • Test SSL: Use SSL Labs and HTTP/3 Check tools
  • Test redirects: Use curl to verify all redirect paths
  • Monitor logs: Check error logs regularly