Apache Subversion (SVN) on Ubuntu 24.04 on Azure User Guide
Overview
Apache Subversion (SVN) is the enterprise centralised version-control system from the Apache Software Foundation. It keeps a single authoritative repository with a complete, ordered history of every change, and lets teams check out a working copy, commit revisions, branch and tag, and roll back to any earlier state. Because history and access control live on the server rather than in every clone, Subversion remains a natural fit for large binary assets, fine-grained path-based permissions, and organisations that want one governed source of truth.
The cloudimg image serves one repository over HTTPS through Apache httpd and mod_dav_svn at /svn/repo. Access is secured by a self-signed TLS certificate and HTTP Basic Auth, and a dedicated repository user (cloudimg) with a strong password is generated uniquely on first boot. There is no anonymous read or write - every operation requires authentication. Backed by 24/7 cloudimg support.
What is included:
- Apache Subversion 1.14 (Apache-2.0) served over HTTPS by Apache httpd 2.4 +
mod_dav_svn - One FSFS repository at
/srv/svn/repo, created empty and ready to commit - A per-VM repository user
cloudimgwhose password is generated on first boot (no shared default credential) - A per-VM self-signed TLS certificate generated on first boot; swap it for a CA-signed certificate for production
- Mandatory authentication on every path (
Require valid-user) - no anonymous access - An unauthenticated
/healthzendpoint for load-balancer and probe checks - 24/7 cloudimg support
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting point. NSG inbound: allow 22/tcp from your management network for SSH, and 443/tcp from the clients that will access the repository over HTTPS. Port 80/tcp is optional (it serves a landing page and redirects repository requests to HTTPS).
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Apache Subversion 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) and HTTPS (443). Then Review + create -> Create.
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name svn \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
Open inbound 443/tcp (and 22/tcp for SSH) on the VM's network security group.
Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 - Confirm Subversion is installed and serving
Apache serves the repository over HTTPS and listens on :80 (landing + redirect) and :443 (repository). Check the service, the Subversion version, the listeners, and that the repository exists:
systemctl is-active apache2
svn --version --quiet
ss -tln | grep -E ':80 |:443 '
sudo ls -ld /srv/svn/repo

Step 5 - Retrieve your per-VM repository credentials
The repository user is cloudimg; its password is generated uniquely on this VM's first boot and written to a root-only file. Read it over SSH:
sudo cat /root/svn-credentials.txt
The file contains SVN_URL, SVN_USERNAME (cloudimg) and SVN_PASSWORD. These credentials are unique to this VM - nothing is baked into the image.
Step 6 - Confirm access requires authentication (secure by default)
Subversion is served behind mandatory HTTP Basic Auth. An anonymous request and a wrong password are both rejected with 401; only the per-VM password authenticates. The commands below read the real password from the credentials file:
SVN_PASS=$(sudo grep '^SVN_PASSWORD=' /root/svn-credentials.txt | cut -d= -f2-)
curl -ks -o /dev/null -w 'anonymous request : HTTP %{http_code}\n' https://127.0.0.1/svn/repo/
curl -ks -o /dev/null -w 'wrong password : HTTP %{http_code}\n' -u cloudimg:wrong-password https://127.0.0.1/svn/repo/
curl -ks -o /dev/null -w 'per-VM credentials : HTTP %{http_code}\n' -u "cloudimg:$SVN_PASS" https://127.0.0.1/svn/repo/
You will see 401, 401, then 200 - proof that anonymous and wrong-password access are refused and only the per-VM credentials succeed.

Step 7 - Check out the repository and commit a change
The repository is empty and ready to use. From an SSH session on the VM, check it out, add a file, and commit - all over HTTPS with your per-VM credentials. Because the first-boot certificate is self-signed, the commands below trust it explicitly with --trust-server-cert-failures:
SVN_PASS=$(sudo grep '^SVN_PASSWORD=' /root/svn-credentials.txt | cut -d= -f2-)
T="--non-interactive --trust-server-cert-failures=unknown-ca,cn-mismatch,expired,not-yet-valid,other --no-auth-cache"
WORK=$(mktemp -d)
svn checkout $T --username cloudimg --password "$SVN_PASS" https://127.0.0.1/svn/repo "$WORK/repo"
NOTE="release-notes-$(date -u +%Y%m%d-%H%M%S).txt"
echo "First commit from cloudimg" > "$WORK/repo/$NOTE"
svn add $T "$WORK/repo/$NOTE"
svn commit $T --username cloudimg --password "$SVN_PASS" -m "Add $NOTE" "$WORK/repo"
svn log $T --username cloudimg --password "$SVN_PASS" "$WORK/repo"
rm -rf "$WORK"
From a workstation you would instead run svn checkout https://<vm-ip>/svn/repo --username cloudimg and enter the password when prompted, accepting the self-signed certificate the first time.

Step 8 - How the credentials are protected
There is no default password. The cloudimg user's password is generated per VM on first boot, stored bcrypt-hashed in Apache's AuthUserFile, and the plaintext is written only to a root-owned 0600 file - it never ships inside the image:
sudo stat -c 'file: %n perms: %a owner: %U:%G' /root/svn-credentials.txt
sudo stat -c 'file: %n perms: %a owner: %U:%G' /etc/apache2/svn.htpasswd
sudo sed -E 's/(cloudimg:\$2[aby]\$[0-9]{2}\$.{6}).*/\1********************/' /etc/apache2/svn.htpasswd
The credentials file is 0600 root:root, the .htpasswd stores a bcrypt hash (not the plaintext), and only root and the Apache worker can read it.

Step 9 - Add repository users
Each repository user is an entry in Apache's AuthUserFile. Add another user (you will be prompted for their password), then they can check out and commit exactly like cloudimg:
sudo htpasswd -B /etc/apache2/svn.htpasswd alice
sudo systemctl reload apache2
For read-only or per-path permissions, configure mod_authz_svn with an access file (AuthzSVNAccessFile) in the <Location /svn/repo> block of /etc/apache2/sites-available/000-cloudimg-ssl.conf.
Step 10 - Use a CA-signed certificate for production
The first-boot certificate is self-signed, so clients must trust it explicitly. For production, point a DNS name at the VM and install a CA-signed certificate (for example with Certbot), which removes the certificate warning for every client:
sudo apt-get install -y certbot python3-certbot-apache
sudo certbot --apache -d svn.example.com
After Certbot installs the certificate, svn checkout https://svn.example.com/svn/repo works without the --trust-server-cert-failures flag.
Step 11 - Back up the repository
Take a portable dump of the whole repository history at any time. Store the dump off the VM (for example in Azure Blob Storage) as your backup:
sudo svnadmin dump /srv/svn/repo > /tmp/svn-repo-backup.dump
ls -lh /tmp/svn-repo-backup.dump
Restore into a fresh repository with svnadmin load. See the Subversion book for repository administration and hook scripts.
Support
Every cloudimg image comes with 24/7 support. Email support@cloudimg.co.uk or visit cloudimg.co.uk for documentation and assistance.