Install Moodle on Google Cloud with Ubuntu 18.04, Nginx and Cloud SQL.
Prerequisites
- Your Compute Engine Instance running.
- For setting up Compute Engine, see the Setting up Compute Engine Instance.
- For installing Nginx and PHP, see how to install LEMP in Compute Engine Instance.
- Domain name is pointed to your virtual machine.
- For setting 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.
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
Install Intl PHP Extension
Moodle requires Intl PHP extension. So if you didn’t install this before, you can install it now.
sudo apt install php7.2-intl
Download Moodle LMS
Make sure you have completed the prerequisites to set up your server in Google Cloud.
Access SSH in your Compute Engine Instance and navigate to your root directory and run the following command to download Moodle.
cd ~/yourdomainname.com/public
curl -LO https://download.moodle.org/stable36/moodle-3.6.2.tgz
sudo tar xzvf moodle-3.6.2.tgz
sudo cp -a ~/yourdomainname.com/public/moodle/. ~/yourdomainname.com/public
sudo rm -r ~/yourdomainname.com/public/moodle
sudo rm -r ~/yourdomainname.com/public/moodle-3.6.2.tgz
Set up Permissions and Install File
sudo chown -R username ~/yourdomainname.com/public
NGINX configuration for Moodle LMS
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;
error_log /home/username/yourdomainname.com/logs/error.log;
root /home/username/yourdomainname.com/public/;
index index.php;
rewrite ^/(.*.php)(/)(.*)$ /$1?file=/$3 last;
location / {
try_files $uri $uri/ /index.php?$args;
}
location /dataroot/ {
internal;
alias /home/username/yourdomainname.com/public/moodledata/;
}
location ~ .php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_pass unix:/run/php/php7.2-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;
error_log /home/username/yourdomainname.com/logs/error.log;
root /home/username/yourdomainname.com/public/;
index 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.yourdomainname.com;
# SSL code
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.php;
rewrite ^/(.*.php)(/)(.*)$ /$1?file=/$3 last;
location / {
try_files $uri $uri/ /index.php?$args;
}
location /dataroot/ {
internal;
alias /home/username/yourdomainname.com/public/moodledata/;
}
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 ~ .php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_pass unix:/run/php/php7.2-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://.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";
}
location ~* .(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
location ~* .(?:css|js)$ {
expires 7d;
add_header Cache-Control "no-cache, public, must-revalidate, proxy-revalidate";
}
location ~* .(?:eot|woff|woff2|ttf|svg|otf) {
expires 30d;
add_header Cache-Control "public";
types {font/opentype otf;}
types {application/vnd.ms-fontobject eot;}
types {font/truetype ttf;}
types {application/font-woff woff;}
types {font/x-woff woff2;}
}
}
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.
Setup Cloud SQL for Moodle LMS
Make sure you have created Cloud SQL and connected to Compute Engine VM Instance as documented in the 6th point of prerequisites.
Once your Cloud SQL is setup you can proceed to install Moodle.
Install Moodle
Now visit your domain name in your browser, you will be taken to the installation process to complete your Moodle installation.

Choose your preferred language and click Next.
Make sure your Data directory is the path given in the Nginx configuration.

Once everything is okay click Next.
In the Choose database driver section select Improved MySQL (native/mysqli).

Click Next.
In the admin configuration enter your admin username and password and proceed with the installation.

Once the installation is completed you will be redirected to your Moodle Dashboard.

Congratulations! Now Moodle Learning Management System is installed successfully on Google Cloud with Ubuntu 18.04, PHP 7.2, Nginx and Cloud SQL.
6 Comments
Hello there! This is my 1st comment here so I just wanted to give a quick shout out and tell you I really enjoy reading your blog posts.
Can you suggest any other blogs/websites/forums that go over
the same subjects? Appreciate it!
It’s amazing to visit this website and reading the views of all friends concerning this article,
while I am also keen of getting knowledge.
Hi there to every single one, it’s really pleasant for me to pay a quick visit
this web site, it consists of important Information.
One hint:
“`
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://.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;
“`
if instructors added embedded material to courses, you can have hadr times with these settings. you can disable it when embedding is impossible but be careful!
Hi Gokhan,
Which file should be edited to configure the Content-Security?
Update on my previous comment.
The file to be edited is the nginx config file for your domain !/home/user/sites-available/yourdomain and edit the line in there.
Add the awesome fonts if you will be installing moodle 3.9 and above otherwise some fonts will not work.