Tc
Applications Azure

TCExam on Ubuntu 24.04 on Azure User Guide

| Product: TCExam on Ubuntu 24.04 LTS on Azure

Overview

TCExam is an open source platform for computer based assessment (CBA): you author a question bank organised into modules, subjects and questions, assemble tests, exams and quizzes, deliver them to candidates through a public test taking area, and review the results, reporting and statistics with PDF export. The cloudimg image ships TCExam 17.2.4 served by nginx and PHP 8.3 FPM on a hardened, fully patched Ubuntu 24.04 LTS base, together with a bundled local MariaDB server so the appliance is complete and useful on its own. TCExam is reachable over both HTTP on port 80 and HTTPS on port 443 (a self signed certificate generated per VM). The bundled MariaDB listens only on the loopback interface (127.0.0.1:3306). A unique administrator password is generated on the first boot of every VM. Backed by 24/7 cloudimg support.

What is included:

  • TCExam 17.2.4 served by nginx and PHP 8.3 FPM, managed by systemd
  • A bundled MariaDB server holding the TCExam database, already installed and ready
  • A ready to use TCExam with a small example question bank and a Sample Quiz test, waiting for your own content
  • A per VM administrator password generated on first boot and recorded in a root only file
  • No shipped default login: the default admin / 1234 account is rotated to a unique per VM secret, and no known or blank credential authenticates
  • No installer or setup wizard reachable on the network: the installer directory is removed from the image
  • nginx hardening that denies direct web access to the configuration, shared library, backup, cache and vendor directories
  • A per VM self signed TLS certificate on port 443, and a per VM random security salt for CSRF and result access tokens
  • MariaDB bound to 127.0.0.1 only, never exposed to the network
  • nginx.service, php8.3-fpm.service and mariadb.service as enabled systemd units
  • An unauthenticated /healthz endpoint for Azure Load Balancer health probes
  • 24/7 cloudimg support

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting point; size up for larger candidate pools or busier exam windows. NSG inbound: allow 22/tcp from your management network and 80/tcp and 443/tcp for the exam site. The image serves both HTTP and HTTPS (with a per VM self signed certificate); for production, put your own domain and a CA signed certificate in front. The bundled MariaDB is never exposed: it listens on 127.0.0.1 only, so port 3306 stays off the network.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for TCExam by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22), HTTP (80) and HTTPS (443). Then Review + create then Create.

Step 2 - Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name tcexam \
  --image <marketplace-image-urn> \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

Then open the exam site ports:

az vm open-port --resource-group <your-rg> --name tcexam --port 80 --priority 900
az vm open-port --resource-group <your-rg> --name tcexam --port 443 --priority 901

Step 3 - Confirm the services are running

SSH in as azureuser and confirm nginx, PHP FPM and MariaDB are all active. Note that MariaDB listens only on 127.0.0.1:3306 while nginx serves TCExam on ports 80 and 443.

systemctl is-active nginx php8.3-fpm mariadb
ss -tlnp | grep -E ':80 |:443 |:3306 ' | sed 's/  */ /g'

The nginx, php8.3-fpm and mariadb services active, with nginx on ports 80 and 443 and MariaDB bound to loopback 127.0.0.1:3306

Step 4 - Retrieve the per VM administrator password

Every VM generates its own TCExam administrator password on first boot and writes it, along with the login user and the admin area URL, to a root only credentials file. Read it with sudo:

sudo cat /root/tcexam-credentials.txt

The per VM TCExam credentials file, showing the admin login user, the generated password and the admin area URL

You sign in to the admin area as user admin with the TCEXAM_ADMIN_PASSWORD from this file. On the box itself you can also run sudo mariadb to reach the database directly over the local socket without a password.

Step 5 - Sign in to the admin area

Browse to http://<vm-public-ip>/admin/code/ (or https://<vm-public-ip>/admin/code/, accepting the self signed certificate). You land on the TCExam administration sign in page. Enter username admin and the password from Step 4.

The TCExam administration sign in page showing the username and password fields

Once signed in you land on the TCExam admin dashboard, where the top navigation gives you Users, Questions, Tests, Results and the other management areas.

The TCExam admin dashboard after signing in, showing the top navigation for Users, Questions, Tests and Results

Step 6 - Build your question bank and tests

TCExam organises content as Modules that contain Subjects, and each subject holds Questions with their answers (single choice, multiple choice, ordering and free text). The image ships a small example: an Example Module with a General Knowledge subject of three questions, and a Sample Quiz test drawn from it. Open Tests to edit or create tests, set the duration, scoring and how questions are drawn from subjects, then schedule and assign them to candidates.

The TCExam test editor showing the seeded Sample Quiz test and its settings

Step 7 - Deliver exams to candidates

Candidates take their assigned tests through the public area at http://<vm-public-ip>/public/code/. They sign in, work through the questions in a clean, mobile friendly interface, and submit; you then review each attempt, the scores and the statistics from the admin Results area, exporting reports to PDF where needed.

The TCExam public test taking area where candidates sign in to take their assigned exams

Step 8 - No known or default credentials

TCExam ships upstream with a default admin / 1234 account. The cloudimg image rotates that account to a unique per VM secret on first boot, removes the installer directory entirely, and generates a per VM random security salt. You can prove no known credential authenticates with the built in round-trip check, which confirms the per VM administrator signs in through TCExam's own login form while the default 1234 and common weak guesses are all rejected:

sudo mariadb --protocol=socket -uroot -N -e "SELECT CONCAT(user_name,'  (level ',user_level,' administrator)') FROM tcexam.tce_users WHERE user_name='admin'"
sudo bash /usr/local/sbin/tcexam-cred-roundtrip.sh

The admin account present in the TCExam users table, and the round-trip check confirming the per VM admin authenticates via the TCExam login form while the default 1234 and weak guesses are rejected

Step 9 - Verify the stack and where your data lives

Confirm the TCExam version, the health endpoint, and that MariaDB is bound to loopback only. All of your TCExam data (users, question banks, tests, results) lives in the bundled MariaDB, whose data directory is on the VM disk and rides with the image:

cat /var/www/tcexam/VERSION
curl -sI http://127.0.0.1/healthz | head -1
ss -tlnH 'sport = :3306' | sed 's/  */ /g'

The TCExam version, the healthz endpoint returning 200, and MariaDB listening only on 127.0.0.1:3306

Adding your own domain and TLS

The image serves HTTP on port 80 and HTTPS on port 443 with a per VM self signed certificate. For production you should set your own address and a CA signed certificate. TCExam builds its links from the base URL configured on first boot; you can front the appliance with your domain and terminate TLS at Azure Application Gateway, an nginx or Caddy reverse proxy, or a managed load balancer with a certificate for your domain (the appliance honours the X-Forwarded-Proto header). Re-point the base URL by editing K_PATH_HOST in /var/www/tcexam/shared/config/tce_paths.php if you move to a fixed hostname.

Security notes

  • The image serves HTTP on port 80 and HTTPS on port 443 (self signed). For anything beyond a trusted network, put it behind your own TLS terminating reverse proxy or Azure Application Gateway with a certificate for your domain.
  • The bundled MariaDB listens on 127.0.0.1 only and is never reachable from the network. Administer it through TCExam or over SSH.
  • The administrator password is unique per VM and no known or blank credential authenticates. The default admin / 1234 is rotated away on first boot. Keep /root/tcexam-credentials.txt protected and change the password from within TCExam if you share access.
  • The installer and setup wizard directory is removed from the image, so no unauthenticated install flow is reachable.
  • nginx denies direct web access to the configuration, shared code, backup, cache, vendor and installer directories, and to dotfiles.
  • Restrict inbound 80/tcp and 443/tcp in your NSG to the networks that need the exam site.

Trademark

TCExam and its logo are trademarks of Tecnick.com LTD. This image is an independent packaging of the free AGPL licensed TCExam by cloudimg and is not affiliated with, sponsored by, or endorsed by Tecnick.com LTD.

Support

This image is maintained by cloudimg with 24/7 support. If you need help deploying or operating TCExam on Azure, contact us at cloudimg.co.uk.