Google Cloud Cloud SQL Compute Engine

How to install WordPress on Google Cloud with LEMP

Disclosure: This post may contain affiliate links, which means we may receive a commission if you click a link and purchase something that we recommended.

Pinterest LinkedIn Tumblr

In this post, I will help you install WordPress on Google Cloud with Ubuntu 18.04 LTS, Nginx + FastCGI, PHP 7.2, Cloud SQL.

This setup is tested on Google Cloud Platform, it will also work fine on other cloud services and on any VPS or Dedicated servers running Ubuntu.

Prerequisites

  1. Your Compute Engine Instance running.
  2. For setting up Compute Engine, see the Setting up Compute Engine Instance.
  3. For installing Nginx and PHP 7.3, see how to install LEMP in Compute Engine Instance.
  4. Domain name is pointed to your virtual machine.
  5. For setting up Cloud DNS, see the Setting up Google Cloud DNS for your domain.
  6. Google Cloud SQL Setup, see Setup Cloud SQL and connect with Compute Engine.
  7. Connect and access your instance with FileZilla.

Setup your website

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

Replace yourdomainname.com with your original domain name.

home
-- yourdomainname.com
---- logs
---- public

The public directory is your website’s root directory and logs directory for your error logs

Now we create these directories and set correct permissions

You need to SSH into your VM Instance and run these commands

mkdir -p yourdomainname.com/logs yourdomainname.com/public
sudo chmod -R 755 yourdomainname.com

Now create a new Nginx configuration for your website in the sites-available directory

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

Copy and paste the following configuration, ensure that you change the server_name, error_log and root directives to match your domain name. Hit CTRL+X followed by Y to save the changes.

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

    server_name yourdomainname.com www.yourdomainname.com;

    error_log /home/username/yourdomainname.com/logs/error.log;

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

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

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php7.3-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }
}

To enable this newly created website configuration, symlink the file that you just created into the sites-enabled directory.

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

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

sudo nginx -t
sudo service nginx restart

Create SSL certificate and enable HTTP/2

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;
    # redirect http to https www
    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;

    # redirect https non-www to https www
    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;

    error_log /home/username/yourdomainname.com/logs/error.log;

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

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

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php7.3-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;

        add_header Content-Security-Policy "img-src * 'self' data: blob: https:; default-src 'self' https://*.googleapis.com https://*.googletagmanager.com https://*.google-analytics.com https://s.ytimg.com https://www.youtube.com https://www.yourdomainname.com https://*.googleapis.com https://*.gstatic.com https://*.gravatar.com https://*.w.org data: 'unsafe-inline' 'unsafe-eval';" always;
        add_header X-Xss-Protection "1; mode=block" always;
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header Access-Control-Allow-Origin "https://www.yourdomainname.com";
        add_header Referrer-Policy "origin-when-cross-origin" always;
        add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
    }
}

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.

Download WordPress

Now that our server software is configured, we can download and set up WordPress.

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

cd ~/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 ~/yourdomainname.com/public/wordpress/. ~/yourdomainname.com/public

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

sudo rm -r ~/yourdomainname.com/public/wordpress
sudo rm -f ~/yyourdomainname.com/public/latest.tar.gz

Set correct permissions for the root folder. Don’t forget to replace the username with your username and yourdomainname.com with your domain name

sudo chown -R username ~/yourdomainname.com/public

Installing WordPress and setting up Configuration File

Now visit your website in the browser and select the language you would like to use and click continue.

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.

Now you can run the installation.

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.

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

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.

Now your WordPress is installed and ready to use. In the next post, we shall see how to setup Nginx-FastCGI cache for a lightning fast website.

4 Comments

  1. If you by the end of this got a 502 Bad gateway error in the web browser, instead of a wordpress setup page – what do you think went wrong..?

  2. “Open your site’s Nginx configuration file” in the Redirection step – is that the same configuration file as the one edited in the earlier step, or is it a different one?

  3. Thanks for the guide! I struggled with getting it working for some time, but I finally figured out why. Since you have redirected https://yourdomain.com to https://www.yourdomain.com, that becomes a problem somewhere, and I am not sure where the problem is whether it’s in wordpress or the domain/server/browser automatic redirects, but as soon as I reversed that to redirect www. to without www. instead – everything now works perfectly!
    Hope that’s helpful to someone reading this – if your website like mine didn’t load at all – just do like this:
    In the (site-available) nginx config file for your website,
    change the server_name in the first server block to http://www.yourdomain.com instead of just yourdomain.com

    comment out in the first server block
    #root /home/username/yourdomain.com/public/;
    #index index.html index.php;

    And put that instead in the second server block under error_log.

    Then change
    return 301 https://www.yourdomain.com$request_uri;
    to
    return 301 https://yourdomain.com$request_uri;

    Then change the link from http://www.yourdomain.com to just yourdomain.com in the links in the security header settings at the bottom of the document and you’re done – your website now redirects www. to no just yourdomain. This will resolve all “too_many_redirect” issues and the site works beautifully.
    Hope it helps.
    Would be interesting to know though why redirects to www. subdomains are not working in the first place? Guess it doesn’t matter, since the use of www. is not really that prevalent anymore, so I am not sure why it was forced in this tutorial.

Write A Comment

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