Install WordPress with Nginx Reverse Proxy to Apache on Ubuntu 18.04 -Google Cloud
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.
Support
- You can hire me on Fiverr for $5 for professional Google Cloud services and WordPress website development
- Support me with $1 on Patreon to create more tutorials on Google Cloud and Wordpress
Prerequisites
- Your Compute Engine Instance running.
- For setting up Compute Engine, see the Setting up Compute Engine Instance.
- Initial Server Setup on Google Cloud.
- Set up Cloud DNS, see the Setting up Google Cloud DNS for your domain.
- 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 8080
. To configure this you need to change the port value in ports.conf
sudo nano /etc/apache2/ports.conf
Change port to 8080. So, you will have the port look like this
Listen 8080
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 8080, 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 *:8080>
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 '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:8080;
}
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:8080;
}
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:8080;
}
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:8080;
}
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:8080;
}
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:8080;
}
location ~/\. {
deny all;
access_log off;
log_not_found off;
}
}
The http2
value is all that is needed to enable the HTTP/2 protocol.
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.
Originally published at https://www.cloudbooklet.com on May 31, 2019.