Stud.IP Learning Management on Ubuntu 24.04 on Azure User Guide
Overview
This guide covers the deployment and configuration of Stud.IP on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. Stud.IP is a mature open source platform for learning management and campus management, run in production by hundreds of universities and colleges across Germany and Europe and published at studip.de. It brings the whole life of a course online: lecturers create courses and seminars, students enrol and build a personal timetable, and each course gets its own space for documents, a forum, a wiki, a participant list, a schedule and announcements.
The image installs Stud.IP 6.1.2, nginx and PHP 8.3 FPM to serve it, and MariaDB 10.11 from Ubuntu 24.04 to hold every piece of platform data, and wires all of it together. Unattended security upgrades are configured to keep the server patched on your running VM.
One appliance, three services. nginx and php8.3-fpm serve the platform on port 80, and mariadb holds every user, course, enrolment, document record, forum post and calendar entry. MariaDB is bound to 127.0.0.1:3306 and PHP FPM listens on a Unix socket, so neither is ever exposed to the network. Port 80 is the only reachable surface.
A deployment done properly. The document root is the application's public/ directory and nothing above it. The application source, the command line tools, the database dumps and above all config/config_local.inc.php — which holds this VM's database password — live outside any URL the web server can address. On top of that, only Stud.IP's own front controllers are permitted to execute PHP, so a file placed anywhere else in the web root is refused rather than run, and the browser setup wizard is removed from the image entirely.
Security by design — the well known root@studip/testing default is closed. Stud.IP normally ships a super administrator with the username root@studip and the password testing. This image ships with no schema, no administrator account and no database password at all. On the very first boot of every VM a one shot service imports the schema, generates a unique database password, and then rotates the seeded administrator to a unique per instance password — proving through the real login form that the new password signs in and that testing, a blank password and other common guesses do not, before writing /root/studip-credentials.txt (mode 0600, root only).
The platform cannot serve an unprovisioned instance. nginx and php8.3-fpm are each gated on a bootstrap marker that first boot writes only after the schema is imported and the administrator rotated. Until that marker exists systemd skips those units entirely, so there is no window in which the transient root@studip/testing default is reachable on any network. The units are still enabled, so the platform comes straight back after a reboot.
What is included:
-
Stud.IP 6.1.2 served by nginx and PHP 8.3 FPM, with the
public/directory as the only web root -
MariaDB 10.11 (
mariadb.service) holding all platform data, bound to loopback -
A background cronjob worker running every minute as a systemd timer, so notifications and scheduled tasks are handled out of the box
-
Courses and seminars with open or application based enrolment; per course documents, forums, wikis, participant lists, schedules and news; a personal desktop, calendar, messaging and activity stream; Courseware for online lessons; evaluations; room booking; a full role and permission system; and LDAP/Shibboleth single sign on
-
A per instance database password and a rotated administrator password generated on first boot and documented in
/root/studip-credentials.txt(0600)
Prerequisites
-
An Azure subscription with permission to create resources
-
An SSH key pair (
ssh-keygen -t rsa -b 4096if you need one) -
Basic familiarity with the Azure Portal or the Azure CLI
Step 1: Deploy from the Azure Portal
-
Search the Azure Marketplace for Stud.IP Learning Management on Ubuntu 24.04 LTS by cloudimg and select Create.
-
Choose your subscription and resource group, a region, and the recommended size Standard_B2s (2 vCPU, 4 GB).
-
Set the administrator username to
azureuserand provide your SSH public key. -
On the Networking tab, allow inbound port 80 (HTTP) and port 22 (SSH).
-
Review and create. When the VM is running, note its public IP address.
Step 2: Deploy from the Azure CLI
RG="studip-prod"; LOCATION="eastus"; VM_NAME="studip"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/studip-ubuntu-24-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az vm create \
--resource-group "$RG" --name "$VM_NAME" \
--image "$GALLERY_IMAGE_ID" \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values "$SSH_KEY" \
--public-ip-sku Standard
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 80 --priority 1001
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 22 --priority 1002
Step 3: First boot and your credentials
On first boot the image imports the Stud.IP schema, generates this VM's database password, rotates the root@studip administrator to a unique password, opens the bootstrap gate, starts the web server, verifies the new credentials work and root@studip/testing is rejected, and writes /root/studip-credentials.txt. This completes within a minute or two. SSH in as azureuser and read the details:
sudo cat /root/studip-credentials.txt
The file is mode 0600 and owned by root, so only a privileged user can read it. It contains the platform URL, the administrator username (root@studip) and password, and the database name, user and password.
Step 4: Confirm the appliance is running
All three services should report active. ss confirms the platform is on port 80 while MariaDB is bound to loopback only, and the response headers carry no server version banner.
systemctl is-active mariadb.service php8.3-fpm.service nginx.service
php -r 'echo "PHP ".PHP_VERSION."\n";'
sudo mysql -N -e "SELECT CONCAT('MariaDB ', VERSION())"
nginx -v
ss -tlnp | grep -E ':(80|3306) ' | sed 's/users:.*//' | sort
curl -sI http://127.0.0.1/dispatch.php/login | head -3

Step 5: Sign in to your platform
Browse to http://<your-server-ip>/ and sign in with the username root@studip and the password from your credentials file.

Step 6: Accept the terms and reach your desktop
On the very first sign in Stud.IP asks you to accept its terms of use, then drops you on your personal desktop — the hub with your courses, your schedule, messages, announcements and quick links to every tool. This is proof the whole stack is working end to end: the web server, PHP and the database are all answering.

Step 7: Change the administrator password
Open the avatar menu (top right) and go to Settings → Password to set your own password. The administrator account is the one Stud.IP calls a root user: it can reach the whole Admin area. You can also change any user's password from the command line:
cd /usr/local/studip
printf '<new-password>\n<new-password>\n' | sudo -u www-data php cli/studip user:password root@studip
Step 8: Administer the platform
The Admin area (the cog in the top navigation) is where an institution is configured: create and manage user accounts and roles, create institutes and course categories, manage the semesters and the course catalogue, configure the available tools and global settings, and moderate content. From here you build out your campus.

Step 9: Create your first course
From Admin → Courses → New course (or the + in the top bar as a lecturer), give the course a name, pick a semester and a course type, and create it. Each course opens with its own set of tools — participants, documents and folders, a forum, a wiki, a schedule and news — that you enable per course. Enrol participants directly or open the course for self enrolment with an optional access code.
Step 10: The background cronjob worker
Stud.IP runs scheduled work — notification digests, cleanup tasks and more — through a cronjob worker. The image ships it as a systemd timer that fires every minute, so there is nothing to configure. Confirm it is active:
systemctl is-active studip-cron.timer
systemctl list-timers studip-cron.timer --all --no-pager
Step 11: Configure mail so notifications and password reset work
A fresh appliance relies on the local mail transport. To send mail through your own SMTP server, set the mail options in config/config_local.inc.php. The relevant keys are $MAIL_TRANSPORT, $MAIL_HOST, $MAIL_PORT, $MAIL_USER and $MAIL_PASSWORD; add them for your provider at <your-domain> and clear the cache. See the Stud.IP administration documentation for the full mail configuration reference.
Step 12: Use your own domain and add TLS
Point an A record at your VM's public IP. Stud.IP builds absolute URLs from the request Host header, so no configuration change is needed for the new hostname. Then install a certificate with Certbot:
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d studip.<your-domain> --redirect --agree-tos -m you@<your-domain>
Certbot edits the nginx site in place and reloads it. Renewal is handled automatically by the packaged timer.
Step 13: How the security model works
nginx and php8.3-fpm are each gated on the bootstrap marker /var/lib/cloudimg/studip-bootstrap-ready, which first boot creates only after the schema is imported, the per instance database password written and the root@studip account rotated. Until then systemd skips those units, so the transient root@studip/testing default is never reachable. Both units are still enabled, so the platform returns after a reboot.
grep -H ConditionPathExists /etc/systemd/system/{nginx,php8.3-fpm}.service.d/cloudimg-bootstrap-gate.conf
systemctl is-enabled mariadb.service php8.3-fpm.service nginx.service studip-firstboot.service studip-cron.timer

The web root is the Stud.IP public/ directory and nothing above it. config/config_local.inc.php (this VM's database password) lives above the web root, and the secret configuration and the command line tools are never reachable over HTTP. Only the named front controllers execute PHP, so the removed setup wizard and any other .php are refused.
grep -E '^\s+root ' /etc/nginx/sites-available/studip
for p in /config/config_local.inc.php /config/config.inc.php /install.php /cli/studip; do
printf '%-32s HTTP %s\n' "$p" "$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1$p)"
done

The per instance database password is unique to this VM, and the real login form rejects root@studip/testing and every other common guess. Exactly one administrator account exists on a fresh instance.
sudo bash /usr/local/sbin/studip-cred-roundtrip.sh

Step 14: Back up your platform
Everything Stud.IP stores — users, courses, enrolments, documents, forums and settings — lives in the studip MariaDB database. Take a consistent dump at any time:
sudo mysqldump --single-transaction studip > <backup-dir>/studip-$(date +%F).sql
Restore into an empty database with mysql studip < your-dump.sql. Keep the dump somewhere off the VM (Azure Blob Storage, for example), together with the contents of /usr/local/studip/data if you store uploaded documents on the VM.
Step 15: Keeping Stud.IP up to date
The OS receives unattended security updates automatically. To move to a newer Stud.IP release, back up the database and the data/ tree first, deploy the new release tree, run sudo -u www-data php cli/studip migrate to apply the database migrations, and clear the cache. Always test on a copy first. See the Stud.IP UPDATE.md for the release specific steps.
Troubleshooting
-
The platform returns nothing right after boot. First boot takes a minute or two to import the schema and rotate the credentials.
systemctl status studip-firstboot.serviceshows its progress;nginxandphp8.3-fpmonly start once it finishes. -
root@studip/testingdoes not work. That is by design — the default is closed on first boot. Use the per instance password fromsudo cat /root/studip-credentials.txt. -
A page shows a database error. Confirm MariaDB is running (
systemctl status mariadb) and thatconfig/config_local.inc.phpholds the per instance password (it is written on first boot). -
Notifications or scheduled tasks are not running. Check the cronjob worker timer:
systemctl list-timers studip-cron.timer --allandjournalctl -u studip-cron.service. -
Mail is not delivered. Configure your SMTP server in
config/config_local.inc.php(Step 11) and clear the cache.
Support
cloudimg provides 24/7 technical support for this Stud.IP image by email (support@cloudimg.co.uk) and live chat, with a one hour average response time for critical issues. We help with domain and TLS setup, user and course management, enrolment and roles, LDAP and Shibboleth single sign on, Courseware, plugins and the API, mail delivery, the background cronjob worker, MariaDB backup and restore, performance tuning and version upgrades.
Stud.IP is free software licensed under the GNU General Public License version 2. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.