Installing and Upgrading Moodle with Docker Compose on Ubuntu 22.04
Note: work in progress
Moodle is probably (there's little agreement among the pundits) the market-leading Free and Open Source Software (FOSS) Learning Management System (LMS). It's pretty much everywhere. Here's how you can set up and maintain your own Moodle instance(s).
Prerequisites
If you would like to host your own (and we certainly encourage it!) using the same approach we use at the OER Foundation here is how you get started:
- Set up a Virtual Private Server (VPS) and configure it to run Ubuntu Linux and Docker Compose.
- Make sure any administrative users can log into the VPS securely via Secure Shell (SSH).
From that point, use the following process.
Installing Moodle on Ubuntu 22.04 with Docker Compose
The process for completing the install involves
-
setting up a domain name (or subdomain) to point at the server so people can easily find the Moodle site,
-
installing all the relevant code via 'Git' on the VPS' file system,
-
configuring the Docker Compose file, defining the set of Docker containers comprising this site's moving parts, and 'pulling' the component containers (to download the current versions of each to our VPS),
-
adding the 'default configuration' for the Dockerised NGINX instance, so it knows how to server Moodle from the adjacent containers,
-
configuring the NGINX webserver running on the VPS to act as a 'reverse proxy' as well as using to generate a Let's Encrypt Secure Sockets Layer (SSL) certificate to encrypt and otherwise secure users' interactions with the Moodle instance, and finally
-
configuring the Moodle instance itself.
Configure a domain name
Configuring a domain name requires us to register a domain with a 'domain registrar' - we use one called Metaname, based here in Christchurch, New Zealand - and using the registrar's browser based configuration system to create a 'zone file' which defines the server to which the domain points. Each registrar is likely to have their own bespoke zone file configuration tools, so consider this to be just one example.
Our convention at the OERF is to allocate a default domain name to each VPS we create. Each one hosts one or more Free and Open Source Software services. Each of those services has its own domain name. Usually we designate "A" and "AAAA" records for the default domain name pointing to the IPv4 and IPv6 addresses given to the VPS by the cloud services provider.
For the purposes of this tutorial, we'll create a site called moodletest.milll.ws which is the moodletest
subdomain of the milll.ws
(Ministry for Education, Sport, and Culture's 'innovative Lifelong Learning Lab', aka MiLLL, in (western) Samoa). We use a "CNAME" to point the subdomain at the VPS' official name, sandbox.milll.ws
, which is how its A and AAAA records identify it (via its IPv4 and IPv6 addresses).
So our "Fully Qualified Domain Name" (FQDN) is moodletest.milll.ws
.
To prepare for the rest of this tutorial, we're going to set a variable for your selected domain name. Do that by typing this at your command prompt. It will set this variable ''for this session'':
FQDN=your domain name
in our case, it'd be
FQDN=moodletest.milll.ws
The following will assuming that this value is set correctly.
Install the Moodle source code
Before we can install the Moodle source code, we have to prepare a sensible place for it to live. We do that by creating suitable directories for both the Docker configurations and the Moodle instance data and configuration as follows:
sudo mkdir -p /home/docker/${FQDN} /home/data/${FQDN}
That creates two directories as you can see. We need to go into the data directory:
cd /home/data/${FQDN}
and in there, we'll execute this git command to download the entire Moodle codebase:
sudo git clone https://github.com/moodle/moodle.git src
When that finishes, go into the source directory:
cd src
Here, we'll have to execute this new command, which we use to declare this a 'safe' git directory, which helps protect us from nefarious parties running git commands in dangerous places if they can get access to our server via some other security vulnerability...
sudo git config --global --add safe.directory /home/data/${FQDN}
Then we can run this comman:
git branch -a
This should give you a list of all the Moodle repository version 'tags'.
In this case, we're going to install a stable (but not the latest) version of Moodle - to do that we tell git what tag we're going to track:
sudo git branch --track MOODLE_310_STABLE origin/MOODLE_310_STABLE
And then, to make sure that our Docker container's nginx webserver can read these files (they need to be owned by the www-data
users, and I (user 'dave') can run git commands without needing to use sudo
. Replace with your own user name here!
sudo chown -R www-data:dave ../src sudo chmod -R g+w ../src ls -l git status git checkout MOODLE_310_STABLE
Configure Docker Compose to host Moodle
The first step to running anything with Docker Compose - which helps you combine a set of Docker containers together into a useful, maintainable service - is to create docker-compose.yml
file. It usually contains the full 'recipe' for the service.
Go to the relevant docker directory and create and edit the file:
cd /home/docker/${FQDN}
sudo nano docker-compose.yml
And copy and past in this content (with FQDN occurrences and [secret password] placeholders to be replaced appropriately, of course):
version: '3' services: mariadb: image: mariadb:10 container_name: db environment: MYSQL_RANDOM_ROOT_PASSWORD: 1 MYSQL_DATABASE: moodle MYSQL_USER: moodle MYSQL_PASSWORD: [secret MariaDB password] volumes: - /home/data/FQDN/mariadb:/var/lib/mysql moodle: image: oeru/moodle:php74-fpm environment: MOODLE_DOMAIN: FQDN MOODLE_DB_HOST: mariadb MYSQL_PORT_3306_TCP: 3306 MOODLE_DB_NAME: moodle MOODLE_DB_USER: moodle MOODLE_DB_PASSWORD: [secret MariaDB password] volumes: - /home/data/FQDN/src:/var/www/html - /home/data/FQDN/data:/var/www/moodledata restart: unless-stopped depends_on: - mariadb cron: image: oeru/moodle-cron:php74-fpm environment: MOODLE_DOMAIN: FQDN MOODLE_DB_HOST: mariadb MYSQL_PORT_3306_TCP: 3306 MOODLE_DB_NAME: moodle MOODLE_DB_USER: moodle MOODLE_DB_PASSWORD: [secret MariaDB password] volumes: - /home/data/FQDN/src:/var/www/html - /home/data/FQDN/data:/var/www/moodledata restart: unless-stopped depends_on: - mariadb nginx: image: nginx depends_on: - moodle ports: - 127.0.0.1:8080:80 volumes: - /home/data/FQDN/nginx:/etc/nginx/conf.d - /home/data/FQDN/src:/var/www/html restart: unless-stopped
And, naturally, save the file.
Note, the last stanza of the docker-compose.yml
file, defining the NGINX component, specifies a port number on the host machine (i.e. 'localhost' or 127.0.0.1) of 8080, which in turn points to port 80 on the NGINX container. If this is the only Docker Compose configuration on your server, then 8080 is probably an avaiable port to use, but if you server has lots of other Docker Compose (or other sorts of services on it) port 8080 might not be available. You can check by running
sudo netstat -punta
If netstat
isn't installed, you can install it via sudo apt install net-tools
.
Running this command will give output that looks something like this:
Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 11199/nginx: master tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN 60021/master tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 59473/sshd: /usr/sb tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 11263/systemd-resol tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN 94497/docker-proxy tcp 0 0 127.0.0.1:6010 0.0.0.0:* LISTEN 13691/sshd: dave@pt tcp 0 0 127.0.0.1:6011 0.0.0.0:* LISTEN 13097/sshd: dave@pt tcp 0 0 147.182.232.12:22 203.118.159.63:39248 ESTABLISHED 13044/sshd: dave [p tcp 0 0 147.182.232.12:22 202.4.38.248:54655 ESTABLISHED 94900/sshd: william tcp 0 0 147.182.232.12:22 202.4.38.248:53108 ESTABLISHED 91961/sshd: sialofi tcp 0 52 147.182.232.12:22 203.118.159.63:39650 ESTABLISHED 13638/sshd: dave [p tcp 0 0 147.182.232.12:22 202.4.38.248:62921 ESTABLISHED 92704/sshd: eleanor tcp6 0 0 :::80 :::* LISTEN 11199/nginx: master tcp6 0 0 :::25 :::* LISTEN 60021/master tcp6 0 0 :::22 :::* LISTEN 59473/sshd: /usr/sb tcp6 0 0 ::1:6010 :::* LISTEN 13691/sshd: dave@pt tcp6 0 0 ::1:6011 :::* LISTEN 13097/sshd: dave@pt udp 0 0 127.0.0.53:53 0.0.0.0:* 11263/systemd-resol
You'll notice that in this case, the 7th line says
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN 94497/docker-proxy
which means that port 8080 is already in use with 127.0.0.1 on the server and trying to start my containers with that port defined would result in a 'port unavailable' error.
Here's a quick one-liner allowing you to check whether any particular port is in use right now (replace '8080' with whatever port number you're checking):
sudo netstat -punta | grep '8080'
if it returns nothing, that port is ''currently'' unused. If it returns a line like
tcp 0 0 127.0.0.1:8080 0.0.0.0:* LISTEN 94497/docker-proxy
it's in use and you'll need to choose another port, e.g. 8081 or 8070 or something else. Ports over 8000 are unlikely to be used by most normal software so should be fair game. You can verify that your selected port is available before launching your containers.
Download your containers from Docker Hub
You should then be able to 'pull' the relevant Docker images (might take a while depending on your server's location and available bandwidth):
sudo docker-compose pull
Once that's done, we need to make sure that our container running NGINX webserver has a valid Moodle-specific configuration.
Configure NGINX container for Moodle
To do that, we're going to create an NGINX default configuration for the Moodle containers by creating and editing the file:
sudo nano /home/data/${FQDN}/nginx/default.conf
copying and pasting in the following content. It shouldn't require any changes.
# This configuration is used by a Docker container running nginx, and is not intended to be # directly connected to the Internet (for that we recommend using SSL on port 443). # You should reverse proxy this container on the Docker host using whatever webserver # you have running there. # server { listen 80 default_server; # default path to Mautic - from the point of view of the docker container root /var/www/html; index index.php index.html index.htm; fastcgi_keep_conn on; # keep alive to the FCGI upstream location / { # First attempt to serve request as file try_files $uri $uri/index.php; # moodle rewrite rules rewrite ^/(.*.php)(/)(.*)$ /$1?file=/$3 last; } # php parsing location ~ ^(.+\.php)(.*)$ { fastcgi_split_path_info ^(.+\.php)(.*)$; fastcgi_index index.php; fastcgi_pass moodle:9000; include /etc/nginx/mime.types; include fastcgi_params; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_buffer_size 128k; fastcgi_buffers 256 4k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; client_max_body_size 100M; } add_header 'Access-Control-Allow-Origin' "*"; }
Once this is in place, you can start up the Docker containers like this (as your own user!):
docker-compose up -d && docker-compose logs -f
which will start the containers (the up -d
) in 'daemon mode', where they continue to run even if you log out of the server, and then show you the logging from the containers (the logs -f
) part. To exit the log view (which will update automatically as more log messages are created), hit the CTRL-C
key combination. If there're any errors from your individual containers, they should visible here.
That's it, your Docker containers should be running. Once you're out of the log view, you can always check on your containers by going into the /home/docker/FQDN
directory and executing:
docker-compose ps
which should show you a list of the currently running containers and their states. Here's an example:
Name Command State Ports -------------------------------------------------------------------------------------------- db docker-entrypoint.sh mariadbd Up 3306/tcp moodletestmilllws_cron_1 /entrypoint.sh /bin/sh -c ... Up 9000/tcp moodletestmilllws_moodle_1 /entrypoint.sh php-fpm Up 9000/tcp moodletestmilllws_nginx_1 /docker-entrypoint.sh ngin ... Up 127.0.0.1:8080->80/tcp
or, to get a bit more info, you can run
docker-compose top
which should show you a bit more information about the different running containers and their active processes. Here's an example:
db UID PID PPID C STIME TTY TIME CMD ----------------------------------------------------------- lxd 12056 12035 0 May23 ? 00:04:06 mariadbd moodletestmilllws_cron_1 UID PID PPID C STIME TTY TIME CMD ------------------------------------------------------------------------------------------------ root 12244 12201 0 May23 ? 00:00:00 /bin/sh -c cron && tail -f /var/log/cron.log root 12651 12244 0 May23 ? 00:00:02 cron root 12652 12244 0 May23 ? 00:00:13 tail -f /var/log/cron.log moodletestmilllws_moodle_1 UID PID PPID C STIME TTY TIME CMD ------------------------------------------------------------------------------------------------------------- root 12250 12173 0 May23 ? 00:00:12 php-fpm: master process (/usr/local/etc/php-fpm.conf) www-data 37755 12250 2 01:46 ? 00:00:00 php-fpm: pool www www-data 37757 12250 1 01:46 ? 00:00:00 php-fpm: pool www www-data 37758 12250 1 01:46 ? 00:00:00 php-fpm: pool www www-data 37759 12250 0 01:46 ? 00:00:00 php-fpm: pool www moodletestmilllws_nginx_1 UID PID PPID C STIME TTY TIME CMD -------------------------------------------------------------------------------------------------- root 13207 13179 0 May23 ? 00:00:00 nginx: master process nginx -g daemon off; systemd+ 13333 13207 0 May23 ? 00:00:01 nginx: worker process systemd+ 13334 13207 0 May23 ? 00:00:00 nginx: worker process
So, now we should have all the relevant containers for your Moodle instance running... Al that's left to do is hook up the reverse proxy configuration creating that last vital link: between your browser's request and the Moodle service (secured by Let's Encrypt)!
Create a secure reverse-proxy configuration
The first step to doing that is to create a reverse proxy configuration:
sudo nano /etc/nginx/sites-available/${FQDN}
Copy and paste the following into the file. Of course, you will want to replace every occurrence of 'FQDN' with your own domain name.
server { # add [IP-Address:]80 in the next line if you want to limit this to a single interface listen 80; listen [::]:80; server_name FQDN; root /var/www/html; # for let's encrypt renewals! include includes/letsencrypt.conf; access_log /var/log/nginx/FQDN_access.log; error_log /var/log/nginx/FQDN_error.log; # redirect all HTTP traffic to HTTPS. location / { return 302 https://$server_name$request_uri; } } # This configuration assumes that there's an nginx container talking to the moodle PHP-fpm container, # and this is a reverse proxy for that Moodle instance. fastcgi_cache_path /etc/nginx/cache levels=1:2 keys_zone=moodle:100m inactive=1d max_size=100m; fastcgi_cache_key "$scheme$request_method$host$request_uri"; server { # add [IP-Address:]443 in the next line if you want to limit this to a single interface listen 443 ssl; listen [::]:443 ssl; ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; # ssl_certificate /etc/letsencrypt/live/FQDN/fullchain.pem; # ssl_certificate_key /etc/letsencrypt/live/FQDN/privkey.pem; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # A strong ssl_dhparam will help secure your server from certain kinds of attacks. # It is commented out unless you've created it (if it's uncommented but doesn't exist # nginx won't start). To create one, see # https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html # note: it can take 5-30 minutes to create one. #ssl_dhparam /etc/ssl/certs/dhparam.pem; #ssl_stapling on; #ssl_stapling_verify on; ssl_session_tickets off; resolver_timeout 5s; keepalive_timeout 20s; server_name FQDN; # for let's encrypt renewals! include includes/letsencrypt.conf; access_log /var/log/nginx/FQDN_access.log; error_log /var/log/nginx/FQDN_error.log; client_max_body_size 100M; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $http_host; } }
Once you've saved that file, we need to make sure NGINX can see the configuration - we do that by creating a 'symbolic link' between our configuration file in the sites-available
directory and the sites-enabled
directory as follows:
sudo ln -sf /etc/nginx/sites-available/${FQDN} /etc/nginx/sites-enabled/
Before we can restart NGINX with this new configuration, we have to make sure that the 'letsencrypt.conf' cited in our configuration file exists. We do that by creating a new directory:
sudo mkdir /etc/nginx/includes
and creating the letsencrypt.conf
file:
sudo nano /etc/nginx/includes/letsencrypt.conf
into which we copy and paste the following:
############################################################################# # Configuration file for Let's Encrypt ACME Challenge location # This file is already included in listen_xxx.conf files. # Do NOT include it separately! ############################################################################# # # This config enables to access /.well-known/acme-challenge/xxxxxxxxxxx # on all our sites (HTTP), including all subdomains. # This is required by ACME Challenge (webroot authentication). # You can check that this location is working by placing ping.txt here: # /var/www/letsencrypt/.well-known/acme-challenge/ping.txt # And pointing your browser to: # http://xxx.domain.tld/.well-known/acme-challenge/ping.txt # # Sources: # https://community.letsencrypt.org/t/howto-easy-cert-generation-and-renewal-with-nginx/3491 # # Rule for legitimate ACME Challenge requests location ^~ /.well-known/acme-challenge/ { default_type "text/plain"; # this can be any directory, but this name keeps it clear root /var/www/letsencrypt; } # Hide /acme-challenge subdirectory and return 404 on all requests. # It is somewhat more secure than letting Nginx return 403. # Ending slash is important! location = /.well-known/acme-challenge/ { return 404; }
In turn, we also have to make sure that the directory stipulated in the letsencrypt.conf file exists - we'll attempt to create the directory, which won't hurt anything if it already exists:
sudo mkdir /var/www/letsencrypt
With that done, we can test NGINX's configuration:
sudo nginx -t
If it's free of errors (there might be a warning related to the snakeoil
''temporary'' certificates we've specified. That's ok - we just specified them so that we can get NGINX restarted in a way that let's us request an SSL certificate from Let's Encrypt!), we can get NGINX to reload its configuration, so that it'll know how to respond to requests for the FQDN domain!
sudo service nginx reload
If that returns without errors, we're in business! It's time to make our Let's Encrypt certificate. Creating one is easy:
sudo letsencrypt certonly --webroot -w /var/www/letsencrypt -d ${FQDN}
In our case, it's:
sudo letsencrypt certonly --webroot -w /var/www/letsencrypt -d moodletest.milll.ws
Running that should trigger output like this:
Saving debug log to /var/log/letsencrypt/letsencrypt.log Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel): webmaster@milll.ws - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Please read the Terms of Service at https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must agree in order to register with the ACME server. Do you agree? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: y - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Would you be willing, once your first certificate is successfully issued, to share your email address with the Electronic Frontier Foundation, a founding partner of the Let's Encrypt project and the non-profit organization that develops Certbot? We'd like to send you email about our work encrypting the web, EFF news, campaigns, and ways to support digital freedom. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: y Account registered. Requesting a certificate for moodletest.milll.ws Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/moodletest.milll.ws/fullchain.pem Key is saved at: /etc/letsencrypt/live/moodletest.milll.ws/privkey.pem This certificate expires on 2022-08-21. These files will be updated when the certificate renews. Certbot has set up a scheduled task to automatically renew this certificate in the background. We were unable to subscribe you the EFF mailing list because your e-mail address appears to be invalid. You can try again later by visiting https://act.eff.org. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - If you like Certbot, please consider supporting our work by: * Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate * Donating to EFF: https://eff.org/donate-le - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
... which means you've successfully received a new certificate! Now you can update your NGINX reverse proxy configuration:
sudo nano /etc/nginx/sites-available/${FQDN}
to change it as follows (again, make sure you've replaced FQDN with your actual domain name!)
# ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; # ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; ssl_certificate /etc/letsencrypt/live/FQDN/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/FQDN/privkey.pem;
Once you've saved the file you can test your NGINX configuration:
sudo nginx -t
and if it doesn't return any errors (nor should it return warnings), you can reload NGINX's config to make your new secure configuration live!
sudo service nginx reload
Installing Moodle
Now that we've filled in all the parts of the tool-chain, your server is ready to receive requests for your Moodle site! You should be able to go to your web browser on your local computer and enter the URL, replacing FQDN with your domain name of course:
https://FQDN
(and entering http://FQDN
should automatically redirect to https://FQDN
- feel free to test it!)
And if all is well, your Docker Compose stack running Moodle should respond by serving you up a page that looks like the attached "Install page" screenshot.
You'll probably notice it looks a bit rough, as, for the moment at least, the Cascading Style Sheets (aka CSS, the code that determines how web content looks) won't be loading correctly. We'll address that shortly.
We need to get through the installation of Moodle first, during which time, the Moodle system creates your config.php
file in the /home/data/${FQDN}/src/
directory. Once that's created, you'll be able to edit the file and make the tweaks to fix this problem.
But first you'll need to proceed with the installation process - you'll be asked to select your language. And then you can click 'next' to continue. You'll be asked to specify your database (pick 'MariaDB' in this case) and then you'll be asked for the database details, as showing in the attached screenshot.
Your host will be db
, your database name and user will both be moodle
(case sensitive!) and you'll have to enter the database password you put into your docker-compose.yml
file.
Then you should get a page showing you that your setup meets Moodle's requirement for installation (see attached screenshot), and finally you'll be asked to proceed with the install. Do so!
The installation will create the relevant database tables in the moodle
database via the MariaDB container, and Moodle will create the aforementioned config.php
file. The next thing to do is edit that file:
sudo nano /home/data/${FQDN}/src/config.php
where you'll tweak the configuration file so that the line
$CFG->wwwroot = 'http://moodletest.milll.ws';
looks like (note the shift from ''http'' to ''https''):
$CFG->wwwroot = 'https://moodletest.milll.ws';
And add this line above the final comment (the lines starting with '//')
$CFG->sslproxy=true;
which informs the Moodle system that it's sitting behind an SSL reverse proxy so it can adjust its behaviour accordingly.
So it should look something like this:
<?php // Moodle configuration fileunset($CFG);global $CFG;$CFG = new stdClass();$CFG->dbtype = 'mariadb';$CFG->dblibrary = 'native';$CFG->dbhost = 'db';$CFG->dbname = 'moodle';$CFG->dbuser = 'moodle';$CFG->dbpass = '[your super-secret db password]';$CFG->prefix = 'mdl_';$CFG->dboptions = array ( 'dbpersist' => 0, 'dbport' => 3306, 'dbsocket' => '', 'dbcollation' => 'utf8mb4_general_ci',);$CFG->wwwroot = 'https://moodletest.milll.ws';$CFG->dataroot = '/var/www/moodledata';$CFG->admin = 'admin';$CFG->directorypermissions = 0777;$CFG->sslproxy=true;require_once(__DIR__ . '/lib/setup.php');// There is no php closing tag in this file,// it is intentional because it prevents trailing whitespace problems!?>
Save your updated config.php file, and return to the installation process - after the next button press, when the Moodle installer page loads, you should suddenly see the interface look all beautiful and tidy as the CSS suddenly loads.
You'll be asked set some properties for your site, like giving it a name, and finally, you'll have to provide the details of an 'admin' user - I recommend creating a default admin user, 'admin', with a very strong password. You'll log in with that admin user (and provide the details to your organisation so that there's a bit of succession planning, if you're not available at some point) just this once, and immediately create a new user for ''yourself'' with your preferred details, which you'll then elevate to 'administrator' privileges, and then do all your administration of the site via your own user.
Once you've successfully completed defining an admin user, you'll end up at the admin 'dashboard', where you can create the personal administrator user for yourself. And then you can log out as 'admin' and log in as yourself... at which point, you're done! Moodle is installed. Hazzah!
Backing up your data
The way we run Docker Compose, all the files we want to preserve are stored on the VPS's own filesystem. The Docker containers only store 'volatile' data. That means we can literally remove the Docker containers at any time, and it won't (under normal circumstances) affect our precious data. The only time it ''might'' is when data, e.g. in the database, is held in system memory rather than being written to disk.
That means that making backups of our data can be achieve simply by copying files on the hard disk - and if we're really interested in preserving that data, we'll send it somewhere else - on a different computer, in a different geographic region, and ideally managed by a different company - to achieve suitable diversity.
MariaDB database dumps
The only element of our stack which isn't amenable to this file copying is the data managed by MariaDB. It is ''not'' generally safe to copy the files of a running database and to expect that restarting the database with those copied files will result in an uncorrupted data set. To safely backup a database, you either have to shut it down (which is disruptive and inelegant) or you have to get it do a database 'dump' while it's running (which it can usually do very quickly, without noticable impact on the performance of the database.
A database 'dump' is a frozen snapshot of the data in a generic form, usually SQL. It allows us to restore the database tables, the data they contain, and the relationships (indices, foreign keys, etc.) between the tables. It usually even lets us take data from an older version of MariaDB and import it into a newer version (which is very handy!).
So we need a method for periodically - and automatically - creating database dumps of our MariaDB Moodle database. Luckily, it's not too hard. I've created this script to do it.
Add new comment