Install WordPress with Nginx Reverse Proxy to Apache with Ubuntu 18.04 on Google Cloud Platform with PHP 7.3, Nginx, Apache, Let’s Encrypt SSL, Cloud SQL (MySQL 5.7).

We already have covered how to install and set up WordPress with Nginx and with Apache. In this guide you are going to learn how to set up WordPress with the two most popular web servers Nginx and Apache.

By this approach you will get the the benefits of Apache and Nginx for fast loading websites.

Prerequisites

  1. Your Compute Engine Instance running.
  2. For setting up Compute Engine, see the Setting up Compute Engine Instance.
  3. Initial Server Setup on Google Cloud.
  4. Set up Cloud DNS, see the Setting up Google Cloud DNS for your domain.
  5. Google Cloud SQL Setup, see Setup Cloud SQL and connect with Compute Engine.

Install Nginx and Apache

Once you have your VM instance up and running and the server setup is completed, you can proceed to install Nginx and Apache.

sudo apt install nginx
sudo apt install apache

Now both Apache and Nginx will listen on port 80, so either one of the server refuses to start. So, you need to configure Apache to listen on different port.

Configure Apache on Different Port

Now you can configure Apache to listen on port 8081. To configure this you need to change the port value in ports.conf

sudo nano /etc/apache2/ports.conf

Change port to 8081. So, you will have the port look like this

Listen 8081

Hit Ctrl + X followed by Y and Enter to save and exit the file.

Setup your website

Your website will be located in the html directory and have the following structure.

Replace yourdomainname.com with your original domain name.

/var/www/html
 -- yourdomainname.com
 ---- public

The public directory is your website’s root directory. Go ahead and create those directories.

sudo mkdir -p /var/www/html/yourdomainname.com/public

Set up Apache Virtual Host

Once Apache listens on port 8081, you can proceed to setup your Apache virtual host.

Remove the default virtual host first.

sudo a2dissite 000-default

Create new configuration.

sudo nano /etc/apache2/sites-available/yourdomainname.conf

Paste the below Virtual Host configuration in your file.

<VirtualHost *:8081>
    ServerName yourdomainname.com

    DocumentRoot /var/www/html/yourdomainname.com/public

    <Directory />
        Options FollowSymLinks
        AllowOverride None
    </Directory>

    <Directory /var/www/html/yourdomainname.com/public>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All
        Order allow,deny
        allow from all
        Require all granted
    </Directory>
</VirtualHost>

Hit Ctrl + X followed by Y and Enter to save and exit the file.

Enable the new configuration.

sudo a2ensite yourdomainname

Replace your yourdomainname with the name of the file you created above.

Enable Apache rewrite mode.

sudo a2enmod rewrite

Restart Apache.

sudo systemctl restart apache2

Configure Nginx

If you have firewall enabled, make sure the HTTP and HTTPS ports are allowed.

 sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'

Next, open the Nginx configuration file, which can be found at /etc/nginx/nginx.conf

sudo nano /etc/nginx/nginx.conf

The worker_processes directive is the amount of CPU cores your instance. In my case, this is 1.

Uncomment the multi_accept directive and set it to on.

Lower the keepalive_timeout directive to 15.

For security reasons, you should uncomment the server_tokens directive and ensure it is set to off.

Add the new client_max_body_size directive below the server_tokens and set the value to 64m.

Uncomment the gzip_proxied directive and set it to any, uncomment the gzip_comp_level directive and set it to the value of 2 and finally uncomment the gzip_types directive.

Now you need to add a catch-all block to the Nginx configuration.

Find the line with include /etc/nginx/sites-enabled/*;

Below this line add the following

server { 
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444;
}

In order for Nginx to correctly serve PHP you also need to ensure the fastcgi_param SCRIPT_FILENAME directive is set, otherwise, you will receive a blank white screen when accessing any PHP scripts. So open fastcgi_params file by issuing this command

sudo nano /etc/nginx/fastcgi_params

Add the following at the end of the file

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

That’s all, this is the basic Nginx configuration, hit CTRL+X followed by Y to save the changes.

Now you can remove the default server blocks from Nginx.

sudo rm /etc/nginx/sites-available/default
sudo rm /etc/nginx/sites-enabled/default

Hit CTRL+X followed by Y to save the changes and then test the Nginx configuration and restart Nginx.

Set up Nginx as Reverse Proxy

Once you have Nginx configured, you can setup reverse proxy by creating new server blocks.

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

Paste the below configurations in the file.

 server {
    listen [::]:80;
    listen 80;

    server_name www.yourdomainname.com;

    root /var/www/html/yourdomainname.com/public;
    index index.php;

    location / {
        try_files $uri @apache;
    }

    location ~ ^/\.user\.ini {
        deny all;
    }

    location ~*  \.(svg|svgz)$ {
        types {}
        default_type image/svg+xml;
    }

    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    location @apache {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:8081;
    }

    location ~[^?]*/$ {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:8081;
    }

    location ~ \.php$ {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:8081;
    }

    location ~/\. {
        deny all;
        access_log off;
        log_not_found off;
    }
}

Hit Ctrl + X followed by Y and Enter to save and exit the file.

Enable the configuration.

sudo ln -s /etc/nginx/sites-available/yourdomainname.conf /etc/nginx/sites-enabled/yourdomainname.conf

Check the configuration and restart Nginx.

sudo nginx -t
sudo service nginx restart

Now Nginx is placed before Apache as a reverse proxy.

Install and configure PHP

sudo apt install php7.2 libapache2-mod-php php7.2-common php7.2-mysql php7.2-xml php7.2-xmlrpc php7.2-curl php7.2-gd php7.2-imagick php7.2-cli php7.2-dev php7.2-imap php7.2-mbstring php7.2-opcache php7.2-soap php7.2-zip php7.2-redis php7.2-intl unzip -y

Modify PHP configurations by editing the php.ini file.

sudo nano /etc/php/7.3/apache2/php.ini

Hit F6 for search inside the editor and update the following values

upload_max_filesize = 32M 
post_max_size = 48M
memory_limit = 256M
max_execution_time = 600
max_input_vars = 3000
max_input_time = 1000

Hit CTRL+X and Y to save the configuration and check if the configuration is correct and restart Apache.

sudo service apache2 restart

Download WordPress

Now that your server software is configured, you can download and set up WordPress.

It is always recommended to get the latest version of WordPress from their website.

cd /var/www/html/yourdomainname.com/public
curl -LO https://wordpress.org/latest.tar.gz

This command will download the latest version and it needs to be extracted.

tar xzvf latest.tar.gz

Now, you can copy the entire contents of the directory into our document root.

sudo cp -a /var/www/html/yourdomainname.com/public/wordpress/. /var/www/html/yourdomainname.com/public

Next cleanup your root directory by deleting the wordpress folder and the downloaded tar file.

sudo rm -r /var/www/html/yourdomainname.com/public/wordpress
sudo rm -f /var/www/html/yourdomainname.com/public/latest.tar.gz

Set correct permissions for the your website directory

sudo chown -R www-data:www-data /var/www/html/yourdomainname.com/public
sudo chmod -R 755 /var/www/html/yourdomainname.com/public

Install Free Let’s Encrypt SSL Certificate

HTTPS
HTTPS is a protocol for secure communication between a server (instance) and a client (web browser). Due to the introduction of Let’s Encrypt, which provides free SSL certificates, HTTPS are adopted by everyone and also provides trust to your audiences.

HTTP/2
HTTP/2 is the latest version of the HTTP protocol and can provide a significant improvement to the load time of your sites. There really is no reason not to enable HTTP/2, the only requirement is that the site must use HTTPS.

sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx

Now we have installed Certbot by Let’s Encrypt for Ubuntu 18.04, run this command to receive your certificates.

sudo certbot --nginx certonly

Enter your email and agree to the terms and conditions, then you will receive the list of domains you need to generate SSL certificate.

To select all domains simply hit Enter

The Certbot client will automatically generate the new certificate for your domain. Now we need to update the Nginx config.

Redirect HTTP Traffic to HTTPS with www in Nginx

Open your site’s Nginx configuration file add replace everything with the following. Replacing the file path with the one you received when obtaining the SSL certificate. The ssl_certificate directive should point to your fullchain.pem file, and the ssl_certificate_key directive should point to your privkey.pem file.

server {
    listen [::]:80;
    listen 80;

    server_name yourdomainname.com www.yourdomainname.com;

    return 301 https://www.yourdomainname.com$request_uri;
}

server {
    listen [::]:443 ssl http2;
    listen 443 ssl http2;

    server_name yourdomainname.com;

    ssl_certificate /etc/letsencrypt/live/yourdomainname.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomainname.com/privkey.pem;

    root /home/username/yourdomainname.com/public/;
    index index.html index.php;

    return 301 https://www.yourdomainname.com$request_uri;
}

server {
    listen [::]:443 ssl http2;
    listen 443 ssl http2;

    server_name www.yyourdomainname.com;

    ssl_certificate /etc/letsencrypt/live/yourdomainname.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomainname.com/privkey.pem;

    root /var/www/html/yourdomainname.com/public;
    index index.php;

    location / {
        try_files $uri @apache;
    }

    location ~ ^/\.user\.ini {
        deny all;
    }

    location ~*  \.(svg|svgz)$ {
        types {}
        default_type image/svg+xml;
    }

    location = /favicon.ico {
        log_not_found off;
        access_log off;
    }

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    location @apache {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:8081;
    }

    location ~[^?]*/$ {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:8081;
    }

    location ~ \.php$ {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:8081;
    }

    location ~/\. {
        deny all;
        access_log off;
        log_not_found off;
    }
}

The http2 value is all that is needed to enable the HTTP/2 protocol.

Now you have enabled SSL Hardening, created a Content Security Policy, X-XSS-Protection, Clickjacking, MIME Sniffing, Referrer Policy, Access Control Allow Origin.

These are some Nginx security tweaks by closing all areas of attacks.

Hit CTRL+X followed by Y to save the changes.

Check your configuration and restart Nginx for the changes to take effect.

sudo nginx -t
sudo service nginx restart

Renewing SSL Certificate

Certificates provided by Let’s Encrypt are valid for 90 days only, so you need to renew them often. Now you set up a cronjob to check for the certificate which is due to expire in next 30 days and renew it automatically.

sudo crontab -e

Add this line at the end of the file

0 0,12 * * * certbot renew >/dev/null 2>&1

Hit CTRL+X followed by Y to save the changes.

This cronjob will attempt to check for renewing the certificate twice daily.

Configure WordPress for Reverse Proxy

Now you need to configure WordPress for Reverse proxy to use HTTPS by adding the lines in the wp-config.php

If you leave these out, you will end up in the endless redirect loop.

sudo nano ~/yourdomainname.com/public/wp-config.php

Add these line to the top of the file below <?php

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

Now, you’re ready to force all your traffic to use HTTPS.

Setup WordPress Filesystem

Once the Installation is complete we need to set the method that WordPress should use to write to the filesystem. Since we’ve given the web server permission to write where it needs to, we can explicitly set the filesystem method to “direct”. Failure to set this with our current settings would result in WordPress prompting for FTP credentials when we perform some actions like WordPress update, plugin updates, file upload, etc. This setting can be added below the database connection settings in the configuration file.

Find the line define('DB_PASSWORD', 'password'); and paste the following line below it.

define('FS_METHOD', 'direct');

Hit Ctrl+X and Y to save your configuration file.

Install WordPress

Now you can do the famous 5 minute WordPress installation.

You will be prompted to enter your database, user, password, and hostname.

Enter the database name we created in Cloud SQL and the user assigned with the database with the password. Finally, enter the IP address of Cloud SQL as the hostname.

Conclusion

Now you have installed WordPress with Nginx as a reverse proxy to Apache and installed SSL certificate and connected to Cloud SQL.

Now you have a high performance WordPress installation with the benefits of Apache and Nginx.

Write A Comment

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Like this post...

Signup for FREE Cloudbooklet Newsletter
SUBSCRIBE
close-link
Please help us get 1000 likes in Facebook. Thank You!
LIKE NOW

Stay Connected!

Get latest tutorials on Google Cloud and Open Source topics
SUBSCRIBE
close-link