Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save mt-shihab26/2bc7b27b9b904a4d22053452986d2c5c to your computer and use it in GitHub Desktop.

Select an option

Save mt-shihab26/2bc7b27b9b904a4d22053452986d2c5c to your computer and use it in GitHub Desktop.
WordPress Setup on Ubuntu 24.04 LTS with Nginx and Cloudflare SSL

WordPress Setup on Ubuntu 24.04 LTS with Nginx and Cloudflare SSL

Prerequisites

  • DigitalOcean Ubuntu 24.04 LTS server with root or sudo access
  • Domain name pointed to your server's IP address
  • Cloudflare account with domain added

Step 1: Initial Server Setup

Update the system

sudo apt update && sudo apt upgrade -y

Install essential packages

sudo apt install curl wget unzip software-properties-common -y

Step 2: Remove Apache2 and Install Nginx

Remove Apache2 (if installed)

sudo systemctl stop apache2
sudo systemctl disable apache2
sudo apt purge apache2 apache2-utils apache2-bin apache2-data -y
sudo apt autoremove -y
sudo apt autoclean

Remove Apache2 configuration files

sudo rm -rf /etc/apache2
sudo rm -rf /var/www/html

Install Nginx

sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx

Configure firewall

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

Step 3: Install MySQL

sudo apt install mysql-server -y
sudo systemctl start mysql
sudo systemctl enable mysql

Secure MySQL installation

sudo mysql_secure_installation

Follow the prompts:

  • Set root password: Yes
  • Remove anonymous users: Yes
  • Disallow root login remotely: Yes
  • Remove test database: Yes
  • Reload privilege tables: Yes

Create WordPress database

sudo mysql -u root -p

In MySQL prompt:

CREATE DATABASE wordpress_db;
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'your_strong_password';
GRANT ALL PRIVILEGES ON wordpress_db.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Step 4: Install PHP

sudo apt install php php-fpm php-mysql php-curl php-gd php-intl php-mbstring php-soap php-xml php-xmlrpc php-zip php-cli php-common php-opcache -y

Start PHP-FPM

sudo systemctl start php8.3-fpm
sudo systemctl enable php8.3-fpm

Optimize PHP configuration

sudo vim /etc/php/8.3/fpm/php.ini

Update these settings:

upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 300
max_input_vars = 3000

Restart PHP-FPM:

sudo systemctl restart php8.3-fpm

Step 5: Download and Configure WordPress

Download WordPress

cd /tmp
wget https://wordpress.org/latest.tar.gz
tar -xzf latest.tar.gz

Set up WordPress directory

Replace your-domain.com with your actual domain name:

sudo mkdir -p /var/www/your-domain.com
sudo cp -R wordpress/* /var/www/your-domain.com/
sudo chown -R www-data:www-data /var/www/your-domain.com/
sudo chmod -R 755 /var/www/your-domain.com/

Configure WordPress

cd /var/www/your-domain.com/
sudo cp wp-config-sample.php wp-config.php
sudo vim wp-config.php

Update database settings:

define('DB_NAME', 'wordpress_db');
define('DB_USER', 'wp_user');
define('DB_PASSWORD', 'your_strong_password');
define('DB_HOST', 'localhost');

Add security keys (get from https://api.wordpress.org/secret-key/1.1/salt/):

define('AUTH_KEY',         'your-unique-key');
define('SECURE_AUTH_KEY',  'your-unique-key');
define('LOGGED_IN_KEY',    'your-unique-key');
define('NONCE_KEY',        'your-unique-key');
define('AUTH_SALT',        'your-unique-key');
define('SECURE_AUTH_SALT', 'your-unique-key');
define('LOGGED_IN_SALT',   'your-unique-key');
define('NONCE_SALT',       'your-unique-key');

Step 6: Configure Nginx for WordPress

Create Nginx server block

Replace your-domain.com with your actual domain name:

sudo vim /etc/nginx/sites-available/your-domain.com

Add this configuration:

server {
    listen 80;
    server_name your-domain.com www.your-domain.com;
    root /var/www/your-domain.com;
    index index.php index.html index.htm;

    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_proxied expired no-cache no-store private auth;
    gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # WordPress security
    location ~ /\.ht {
        deny all;
    }

    location = /xmlrpc.php {
        deny all;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # Block access to sensitive files
    location ~* /(?:uploads|files)/.*\.php$ {
        deny all;
    }
}

Enable the site

sudo ln -s /etc/nginx/sites-available/your-domain.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Step 7: Configure Cloudflare SSL

Set Cloudflare SSL Mode

  1. Login to Cloudflare dashboard
  2. Go to your domain → SSL/TLS
  3. Set SSL/TLS encryption mode to "Full (strict)"

Install Cloudflare Origin Certificate

  1. In Cloudflare dashboard, go to SSL/TLS → Origin Server
  2. Click "Create Certificate"
  3. Choose "Let Cloudflare generate a private key and a CSR"
  4. Select RSA 2048-bit key
  5. Set hostname to *.your-domain.com, your-domain.com
  6. Choose certificate validity (15 years recommended)
  7. Click "Create"

Save the certificates on your server

sudo mkdir -p /etc/ssl/cloudflare
sudo vim /etc/ssl/cloudflare/cert.pem

Paste the Origin Certificate content.

sudo vim /etc/ssl/cloudflare/key.pem

Paste the Private Key content.

Set proper permissions

sudo chmod 400 /etc/ssl/cloudflare/key.pem
sudo chmod 444 /etc/ssl/cloudflare/cert.pem
sudo chown root:root /etc/ssl/cloudflare/*

Update Nginx configuration for SSL

sudo vim /etc/nginx/sites-available/your-domain.com

Replace the content with:

server {
    listen 80;
    server_name your-domain.com www.your-domain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name your-domain.com www.your-domain.com;
    root /var/www/your-domain.com;
    index index.php index.html index.htm;

    # SSL Configuration
    ssl_certificate /etc/ssl/cloudflare/cert.pem;
    ssl_certificate_key /etc/ssl/cloudflare/key.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_proxied expired no-cache no-store private auth;
    gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        
        # Add real IP from Cloudflare
        fastcgi_param HTTP_CF_CONNECTING_IP $http_cf_connecting_ip;
    }

    # WordPress security
    location ~ /\.ht {
        deny all;
    }

    location = /xmlrpc.php {
        deny all;
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # Block access to sensitive files
    location ~* /(?:uploads|files)/.*\.php$ {
        deny all;
    }
}

Test and reload Nginx

sudo nginx -t
sudo systemctl reload nginx

Step 8: Configure WordPress for Cloudflare

Add these lines to your wp-config.php file:

sudo vim /var/www/your-domain.com/wp-config.php

Add before "/* That's all, stop editing! */":

// Cloudflare support
if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
    $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
}

// Force SSL
define('FORCE_SSL_ADMIN', true);
if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false) {
    $_SERVER['HTTPS'] = 'on';
}

// WordPress URLs
define('WP_HOME','https://your-domain.com');
define('WP_SITEURL','https://your-domain.com');

Step 9: Complete WordPress Installation

  1. Visit https://your-domain.com in your browser
  2. Follow the WordPress installation wizard
  3. Create admin account and complete setup

Step 10: Install WordPress Security Plugin (Optional but Recommended)

Install Wordfence Security or Sucuri Security plugin for additional protection through the WordPress admin dashboard:

  1. Visit https://your-domain.com/wp-admin
  2. Go to Plugins → Add New
  3. Search for "Wordfence Security"
  4. Install and activate the plugin
  5. Configure security settings as needed

Additional recommended plugins:

  • Yoast SEO: Search engine optimization
  • W3 Total Cache: Performance optimization
  • UpdraftPlus: Backup solution
  • Two Factor: Two-factor authentication

Step 11: Enable Cloudflare Features

In your Cloudflare dashboard:

  1. SpeedOptimization:

    • Enable Auto Minify (CSS, JavaScript, HTML)
    • Enable Brotli compression
  2. CachingConfiguration:

    • Set Browser Cache TTL to "1 month"
    • Enable "Always Online"
  3. SecuritySettings:

    • Set Security Level to "Medium"
    • Enable "Challenge Passage"

Performance Optimization

Install Redis (Optional)

sudo apt install redis-server -y
sudo systemctl start redis
sudo systemctl enable redis

Install PHP Redis extension

sudo apt install php-redis -y
sudo systemctl restart php8.3-fpm

Maintenance Commands

Update WordPress core (via admin dashboard)

  • Visit https://your-domain.com/wp-admin
  • Go to Dashboard → Updates
  • Update WordPress core and plugins as needed

Backup database

sudo mysqldump -u root -p wordpress_db > wordpress_backup_$(date +%Y%m%d).sql

Set proper file permissions

sudo find /var/www/your-domain.com/ -type d -exec chmod 755 {} \;
sudo find /var/www/your-domain.com/ -type f -exec chmod 644 {} \;
sudo chown -R www-data:www-data /var/www/your-domain.com/

Troubleshooting

Check service status

sudo systemctl status nginx
sudo systemctl status mysql
sudo systemctl status php8.3-fpm

View logs

sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/php8.3-fpm.log

Test SSL certificate

openssl s_client -connect your-domain.com:443 -servername your-domain.com

Common Issues

502 Bad Gateway Error

  • Check if PHP-FPM is running: sudo systemctl status php8.3-fpm
  • Verify socket path in Nginx config matches PHP-FPM socket
  • Check Nginx error logs: sudo tail -f /var/log/nginx/error.log

Database Connection Error

  • Verify database credentials in wp-config.php
  • Test database connection: mysql -u wp_user -p wordpress_db
  • Check MySQL service: sudo systemctl status mysql

Security Checklist

  • ✅ Strong database passwords
  • ✅ WordPress security keys configured
  • ✅ File permissions set correctly
  • ✅ SSL/TLS encryption enabled
  • ✅ Security headers configured
  • ✅ Xmlrpc.php blocked
  • ✅ Directory browsing disabled
  • ✅ PHP file execution in uploads blocked

Important Notes

  1. Replace placeholders: Change your-domain.com, your_strong_password, etc. with your actual values
  2. DNS settings: Make sure your domain's DNS is pointing to Cloudflare's nameservers
  3. Cloudflare settings: The "Full (strict)" SSL mode ensures end-to-end encryption
  4. Backup strategy: Set up automated backups for both files and database

Your WordPress site should now be running securely with Nginx and Cloudflare SSL protection!

Contributing

Found an issue or want to improve this guide? Feel free to open an issue or submit a pull request.

License

This guide is provided as-is under the MIT License. Use at your own risk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment