Apache Subversion (SVN) on AWS User Guide
Overview
This image runs Apache Subversion (SVN) 1.14, the Apache Software Foundation's enterprise centralised version-control system. Subversion keeps a single authoritative repository that stores every version of your files and directories, with atomic commits, branching and tagging, and a complete, queryable history.
The repository is served over HTTPS on port 443 by the Apache HTTP Server with the mod_dav_svn WebDAV module and mod_authz_svn. A fresh empty FSFS repository is provisioned at /srv/svn/repo on a dedicated EBS data volume mounted at /srv/svn, separate from the operating system disk and independently resizable. The repository is owned by the Apache service account so commits are written safely.
Access is authenticated by default. All repository operations require the repository credentials over HTTP Basic Auth, backed by a bcrypt password file - there is no anonymous read or write. An unauthenticated static health endpoint answers at /healthz for load-balancer and uptime checks, and plain HTTP on port 80 serves a landing page and redirects repository clients to HTTPS.
Subversion has no built-in shared password. This image generates one per instance: a one-shot first-boot service creates a unique repository password of 24 characters on every instance, generates a per-instance self-signed TLS certificate, writes the bcrypt-hashed password into the Apache authentication file, and records the plaintext in /root/svn-credentials.txt with mode 0600. The first-boot service proves the authentication gate and a full commit round-trip before it reports ready. No shared or default credentials or certificates ship in the image.
Prerequisites
Before you deploy this image you need:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups, and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group allowing inbound port 22 from your management network, and ports 80 and 443 from the clients that will use the repository
- An SSH client on your workstation, and the Subversion command-line client (
svn) where you intend to work with the repository
Launching from the AWS Marketplace
- Open the product page in AWS Marketplace and choose Continue to Subscribe
- Accept the terms, then choose Continue to Configuration
- Select the software version and the Region you want to deploy into, then choose Continue to Launch
- Choose Launch through EC2 for full control of networking and storage
- Pick an instance type.
m5.largeis the recommended minimum; scale up as your repository size and commit concurrency grow - Select your VPC, subnet and key pair
- Attach a security group that allows inbound TCP 22 from your management network, and TCP 80 and 443 from the clients that will check out and commit
- Launch, and wait for the instance to reach the 2/2 checks passed state
Launching with the AWS CLI
Substitute your own AMI id, key pair, security group and subnet:
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <your-key-pair> \
--security-group-ids <your-sg-id> \
--subnet-id <your-subnet-id> \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=subversion}]'
Connecting to your instance
Connect over SSH on port 22 as the default login user for the operating system variant you launched:
| OS variant | SSH login user |
|---|---|
| Ubuntu 24.04 LTS | ubuntu |
ssh -i /path/to/your-key.pem ubuntu@<public-ip>
First boot takes a few moments to generate the repository password and the TLS certificate. If the credentials file still shows the placeholder text, wait a few seconds and read it again.
Retrieving the repository credentials
The per instance repository password is written to a root-only file on first boot:
sudo cat /root/svn-credentials.txt
The file contains the repository URL, the username cloudimg and the generated password:
# Apache Subversion (SVN) - generated on first boot by svn-firstboot.service
# These credentials are unique to this instance. Store them somewhere safe.
SVN_URL=https://<this-instance-public-ip>/svn/repo
SVN_USERNAME=cloudimg
SVN_PASSWORD=<generated-on-first-boot>
Load the password into a shell variable rather than printing it, so it never lands in your shell history or terminal scrollback. The commands in the rest of this guide use $PW:
PW=$(grep '^SVN_PASSWORD=' /root/svn-credentials.txt | cut -d= -f2-)
if [ -n "$PW" ]; then echo "repository password loaded (${#PW} characters)"; else echo "not yet generated"; fi
repository password loaded (24 characters)
Confirm the file is readable only by root:
stat -c '%a %U:%G' /root/svn-credentials.txt
600 root:root
Verifying the repository is running
Confirm the Apache service is active and serving the repository, and that Subversion is installed:
systemctl is-active apache2.service
svn --version --quiet
active
1.14.3
Both listeners are up - HTTPS on 443 for the repository and HTTP on 80 for the landing page and redirect:
ss -tln | grep -E ':80 |:443 '
LISTEN 0 511 *:443 *:*
LISTEN 0 511 *:80 *:*
The unauthenticated health endpoint answers 200 for load-balancer and uptime checks:
curl -ks -o /dev/null -w 'healthz HTTP %{http_code}\n' https://127.0.0.1/healthz
healthz HTTP 200
The repository store lives on its own data disk, mounted at /srv/svn:
df -h /srv/svn | tail -1
/dev/nvme1n1 40G 208K 38G 1% /srv/svn
The authentication gate
The repository requires authentication for every operation. An unauthenticated request, or one with the wrong password, is rejected with 401:
curl -ks -o /dev/null -w 'unauthenticated: 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:definitely-wrong-pw https://127.0.0.1/svn/repo/
unauthenticated: HTTP 401
wrong password: HTTP 401
The correct per-instance password authenticates, and svn info returns the repository metadata:
PW=$(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'
svn info $T --username cloudimg --password "$PW" https://127.0.0.1/svn/repo | grep -E 'Repository Root|Repository UUID|Revision'
Repository Root: https://127.0.0.1/svn/repo
Repository UUID: 5bdb054c-fc2a-448e-9c5b-2bc0bf0f18b1
Revision: 0
Checking out and committing
Prove the repository round-trips a real commit. This checks out a working copy, adds a file, commits it, and reads it back from the log. It uses $PW so the password is never echoed:
PW=$(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'
WD=$(mktemp -d)
svn co $T --username cloudimg --password "$PW" https://127.0.0.1/svn/repo "$WD/wc" | tail -1
printf 'hello from svn %s\n' "$(date -u +%s)" > "$WD/wc/hello-$(date -u +%s).txt"
svn add $T "$WD/wc"/hello-*.txt | head -1
svn ci $T --username cloudimg --password "$PW" -m 'guide commit round-trip' "$WD/wc" | tail -1
svn log $T --username cloudimg --password "$PW" https://127.0.0.1/svn/repo | head -3
rm -rf "$WD"
Checked out revision 0.
A /tmp/tmp.XXXX/wc/hello-1753178951.txt
Committed revision 1.
------------------------------------------------------------------------
r1 | cloudimg | 2026-07-22 10:09:11 +0000 (Wed, 22 Jul 2026) | 1 line
Every access above was authenticated; there is no anonymous path to the repository.
Using the repository from your workstation
From any machine that can reach the instance on port 443, check out the repository with the standard Subversion client. Replace <public-ip> with your instance's public IP or DNS name, and use the username cloudimg and the password from the credentials file:
svn checkout https://<public-ip>/svn/repo my-working-copy --username cloudimg
On first connection the client will prompt you to accept the per-instance self-signed certificate. From then on you work with the repository exactly as with any Subversion server:
cd my-working-copy
echo "release notes" > NOTES.txt
svn add NOTES.txt
svn commit -m "add release notes"
svn update
svn log
The same URL serves both checkout and commit. Point your CI jobs and existing Subversion tooling at it.
Replacing the self-signed certificate
The image ships with a per-instance self-signed certificate so the repository is encrypted from the very first boot. For production, replace it with a certificate from your own certificate authority or a public CA so that clients validate it without a trust exception.
The certificate and key are referenced by the HTTPS virtual host at /etc/apache2/sites-available/000-cloudimg-ssl.conf:
SSLCertificateFile /etc/ssl/cloudimg/cloudimg.crt
SSLCertificateKeyFile /etc/ssl/cloudimg/cloudimg.key
Install your certificate and private key over those two files (or point the directives at new paths), keep the key readable only by root, then reload Apache:
sudo install -m 0644 your-fullchain.crt /etc/ssl/cloudimg/cloudimg.crt
sudo install -m 0600 your-private.key /etc/ssl/cloudimg/cloudimg.key
sudo apachectl configtest
sudo systemctl reload apache2
If you use a public DNS name for the repository, issue the certificate for that name and give it to your clients as the repository host.
Backup and maintenance
The repository is a standard FSFS Subversion repository under /srv/svn/repo. Take a consistent, portable dump of the full history with svnadmin dump, which is safe to run against a live repository:
sudo svnadmin dump /srv/svn/repo | gzip > svn-repo-$(date -u +%Y%m%d).svndump.gz
Restore into a fresh repository with svnadmin load. Because the repository lives on its own EBS volume mounted at /srv/svn, you can also snapshot that volume from the EC2 console or CLI for block-level backups, and grow it independently of the operating system disk as your history expands.
Keep the operating system patched with the distribution's normal update mechanism, and monitor the service with:
systemctl status apache2.service --no-pager | head -3
● apache2.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/apache2.service; enabled; preset: enabled)
Active: active (running)
Support
This image is published and supported by cloudimg. If you need help with deployment, repository layout and access control, replacing the TLS certificate, integrating clients and CI, storage sizing, backup or upgrade planning, contact cloudimg support at support@cloudimg.co.uk. Technical support is available 24/7 by email and chat.
Apache, Apache Subversion and the Apache feather logo are trademarks of the Apache Software Foundation. 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.