
Many teams still rely on Apache Subversion for centralized version control, especially in regulated enterprise environments where atomic commits and path-level access control matter more than Git’s distributed model. Setting up a fresh SVN server on modern Ubuntu can feel confusing because documentation mixes old package names, unclear permission models, and Apache HTTP Server assumptions that don’t apply to every use case. This guide walks you through how to install Apache Subversion on Ubuntu 26.04 LTS with real-world sysadmin experience, covering APT installation, repository creation, Apache WebDAV configuration, user authentication with htpasswd, firewall rules, and a verified first commit. By the end, you will have a fully working SVN server served over HTTP with secured access and tested functionality.
Prerequisites
Before you begin the installation, make sure your environment meets these requirements:
- Operating system: Ubuntu 26.04 LTS server (bare metal, VM, or cloud VPS) [web:7665]
- User account: A non-root user with
sudoprivileges - Minimum hardware: 1 vCPU, 1 GB RAM, 10 GB disk for a small team repository [web:7657]
- Network access: SSH access to your server and outbound internet access for APT
- Open ports: TCP 80 (HTTP) or 443 (HTTPS) for Apache WebDAV access
- Basic knowledge: Comfortable with the Linux terminal and editing text files
- Hostname or IP: Static IP address or a hostname pointed at your server’s public IP
You need sudo privileges because installing packages, creating system users, configuring Apache, and managing services all require elevated permissions. Running these commands as root directly is a security anti-pattern that exposes your system to unnecessary risk.
What Is Apache Subversion (SVN)?
Apache Subversion (SVN) is a centralized version control system managed by the Apache Software Foundation. Unlike Git, which gives every developer a full copy of the repository history, SVN maintains a single authoritative server where all commits are stored. Developers check out working copies, make changes locally, and commit back to the central server.
Key concepts you need to understand before starting:
- Repository: The central database that stores all file versions and revision history
- Working copy: A local directory containing checked-out files that you edit before committing
- Revision: A numbered snapshot of the entire repository after each commit
- Trunk/branches/tags: Standard directory structure for main development, feature branches, and releases
- svnadmin: Command-line tool for creating and administering repositories
- svnserve: Lightweight standalone SVN server daemon (not used in this HTTP-based guide)
- libapache2-mod-svn: Apache module that enables WebDAV-based SVN access [web:7665]
Ubuntu 26.04 LTS ships Subversion version 1.14.x from the Universe component. The “Apache” in the package name refers to the Apache Software Foundation, not the Apache HTTP Server itself. You can run SVN locally with svnserve without ever touching Apache, but this guide uses Apache with WebDAV because it provides better authentication, logging, and HTTPS support out of the box [web:7651][web:7665].
Step 1: Update Your System Package Index
sudo apt update && sudo apt upgrade -y
What this command does:
sudo apt updaterefreshes the local package metadata cache from Ubuntu’s repositoriessudo apt upgrade -yinstalls all available security updates and bug fixes automatically
Why you must do this:
Running apt update ensures APT has the latest package versions available. Without this step, APT might install an outdated or mismatched Subversion version that has known security vulnerabilities. Running apt upgrade before adding new software follows basic security hygiene by closing known exploits before your system becomes more complex [web:7656][web:7665].
Expected output:
Get:1 http://us.archive.ubuntu.com/ubuntu noble InRelease [256 kB]
...
Fetched 123 MB in 45s (2,734 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
12 packages can be upgraded. Run 'apt list --upgradable' to see them.
Reading package lists... Done
Building dependency tree... Done
Building dependency tree... Done
Reading state information... Done
The following packages will be upgraded:
libssl3 ubuntu-pro-client ...
12 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Important note: Subversion lives in Ubuntu’s Universe component. If apt install subversion returns “Unable to locate package,” enable Universe first:
sudo add-apt-repository universe
sudo apt update
Step 2: Install Apache Subversion and Required Packages
sudo apt install -y subversion apache2 libapache2-mod-svn apache2-utils
What each package does:
subversion: Installs the core SVN client binaries (svn,svnadmin,svnlook,svnserve,svnversion) and libraries [web:7665]apache2: Installs the Apache HTTP Server, which acts as the network layer for WebDAV-based SVN access [web:7656]libapache2-mod-svn: Installs the Apache module that translates WebDAV HTTP requests into SVN repository operations. Without this module, Apache has no understanding of SVN’s internal database format [web:7664]apache2-utils: Installs utility tools includinghtpasswd, which creates and manages Basic Auth user credentials for SVN access [web:7656]
Why install all packages together:
APT resolves shared dependencies in a single transaction. Installing packages separately risks version mismatches between apache2, libapache2-mod-svn, and the core Subversion client, which can cause runtime errors when the modules try to communicate.
Expected output:
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
apache2-bin apache2-data apache2-utils libapr1 libaprutil1 ...
The following NEW packages will be installed:
apache2 apache2-utils libapache2-mod-svn subversion
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
...
Setting up subversion (1.14.5-1ubuntu1) ...
Setting up libapache2-mod-svn (1.14.5-1ubuntu1) ...
Setting up apache2 (2.4.58-1ubuntu8) ...
Processing triggers for apache2 (2.4.58-1ubuntu8) ...
Step 3: Verify the Installation
command -v svn svnadmin svnlook svnserve svnversion
svn --version --quiet
apache2 -v
What these commands do:
command -v ...checks whether each SVN binary exists in your system PATH and returns its full pathsvn --version --quietoutputs only the Subversion version number without extra metadataapache2 -vdisplays the Apache HTTP Server version
Why verify before proceeding:
Confirming binary availability and version strings catches failed installations before you waste time creating directories, writing configuration files, or setting permissions that will later fail. This is a quick health check that prevents frustration later in the tutorial.
Expected output on Ubuntu 26.04:
/usr/bin/svn
/usr/bin/svnadmin
/usr/bin/svnlook
/usr/bin/svnserve
/usr/bin/svnversion
1.14.5 (r1918546)
Server version: Apache/2.4.58 (Ubuntu)
If svn is not found, check that Universe is enabled and re-run sudo apt update && sudo apt install -y subversion.
Step 4: Create a Dedicated System User and Repository Directory
sudo addgroup --system svn
sudo adduser --system --ingroup svn --home /srv/svn --shell /usr/sbin/nologin svn
sudo mkdir -p /srv/svn
What each command does:
addgroup --system svn: Creates a system group namedsvnwith a UID below 1000adduser --system --ingroup svn ... svn: Creates a system user namedsvn, assigns it to thesvngroup, sets its home directory to/srv/svn, and prevents interactive loginmkdir -p /srv/svn: Creates the parent directory for all SVN repositories
Why create a dedicated system user:
Running SVN-managed directories under the default www-data user alone creates a single point of failure. If Apache is compromised, the attacker gains direct access to all repository data. A dedicated svn system account isolates repository data from the web process and follows the principle of least privilege [web:7657].
Why use /usr/sbin/nologin:
This shell prevents the svn account from logging in interactively via SSH or console. The account exists only for file ownership and group permissions, not for human login.
Why use /srv/svn:
The /srv/ directory is the Filesystem Hierarchy Standard (FHS) location for service-specific data. Keeping repositories here separates them from the web root (/var/www/) and avoids accidental exposure through web directory browsing. It also clearly signals to other administrators that this directory contains active service data [web:7657].
Why use --system:
System accounts get UIDs below 1000, which signals to admin tooling and monitoring systems that these are service accounts, not regular human user accounts. This distinction helps with security auditing and automated access control.
Step 5: Create the SVN Repository with svnadmin
sudo svnadmin create /srv/svn/project
sudo chown -R svn:svn /srv/svn
sudo chmod -R 770 /srv/svn
sudo usermod -aG svn www-data
sudo systemctl restart apache2
What each command does:
svnadmin create /srv/svn/project: Initializes a new FSFS-format repository at the specified path. The command createsdb/,hooks/,locks/, andformatfiles inside the directory [web:7657][web:7660]chown -R svn:svn /srv/svn: Recursively changes ownership of all repository files to thesvnuser and groupchmod -R 770 /srv/svn: Sets read, write, and execute permissions for owner and group onlyusermod -aG svn www-data: Adds the Apache userwww-datato thesvngroup without removing existing group membershipssystemctl restart apache2: Reloads Apache to pick up any service-level changes
Why svnadmin create is necessary:
This command initializes a new Berkeley DB or FSFS-format repository. It does NOT create a Git-style bare clone. The resulting directory structure is specific to SVN’s internal database format and cannot be used without this initialization step.
Why chown -R svn:svn:
Repository files must be owned by the service account so that Apache (running as www-data) can read and write them through the shared group. If the repository is owned by root, Apache will fail with “Permission denied” errors during commit operations [web:7665].
Why chmod 770 and not 777:
Mode 777 gives world-writable permissions, which is a critical security vulnerability. Anyone on the system could modify or delete repository data. Mode 770 restricts access to the owner (svn) and group members only (including www-data), following the principle of least privilege [web:7658].
Why add www-data to the svn group:
Apache processes run as the www-data user. Group membership grants Apache write access to the repository without changing file ownership or using insecure permissions like 777 [web:7657].
Expected output:
[sudo] password for youruser:
usermod: no changes
The “no changes” message is normal if www-data is already in the group.
Step 6: Configure Apache WebDAV for SVN Access
Create a new Apache configuration file:
sudo nano /etc/apache2/conf-available/svn.conf
Paste this configuration into the file:
<Location /svn>
DAV svn
SVNParentPath /srv/svn
AuthType Basic
AuthName "SVN Repository"
AuthUserFile /etc/svn-auth-file
Require valid-user
</Location>
Save the file and exit the editor (Ctrl+O, Enter, Ctrl+X in nano).
Then enable the configuration and required modules:
sudo a2enconf svn
sudo a2enmod dav_svn
sudo systemctl reload apache2
What each Apache directive does:
<Location /svn>: Defines the URL path where SVN will be accessible. Users will access repositories athttp://YOUR_IP/svn/repo-nameDAV svn: Activates themod_dav_svnhandler, telling Apache to process WebDAV requests at this path as SVN operations [web:7657]SVNParentPath /srv/svn: Specifies the parent directory containing all SVN repositories. This allows multiple repositories under one directory (e.g.,/srv/svn/project,/srv/svn/legacy)AuthType Basic: Enables HTTP Basic Authentication for this locationAuthName "SVN Repository": Sets the authentication realm name shown in the login promptAuthUserFile /etc/svn-auth-file: Points to the file containing username and password credentialsRequire valid-user: Denies access to all users who are not in the password file
Why use SVNParentPath instead of SVNPath:
SVNParentPath allows multiple repositories under one directory, making it easier to scale. SVNPath points to a single repository only. Use SVNParentPath unless you have a specific reason to serve exactly one repository [web:7659].
Why create a dedicated conf file instead of editing dav_svn.conf directly:
Using conf-available and a2enconf follows Debian/Ubuntu’s modular Apache configuration pattern. Editing module config files directly mixes concerns and makes upgrades risky. Modular configuration also makes it easier to disable SVN access by running a2disconf svn without touching core module files [web:7664].
Why store the auth file at /etc/svn-auth-file:
Storing the password file outside the web root (in /etc/) prevents accidental exposure if directory browsing is misconfigured. A file under /var/www/ could be downloadable through a web browser if Apache is misconfigured.
Step 7: Create SVN Users with htpasswd
Create the first user (this creates the password file):
sudo htpasswd -c /etc/svn-auth-file admin
Add additional users (omit -c to avoid overwriting):
sudo htpasswd /etc/svn-auth-file developer1
sudo htpasswd /etc/svn-auth-file developer2
What htpasswd does:
The htpasswd command creates and manages a flat file containing usernames and cryptographically hashed passwords for HTTP Basic Authentication.
Why the -c flag is dangerous on second use:
Using -c again silently overwrites the entire password file, deleting all existing users. This is one of the most common admin mistakes when adding new SVN users. Always omit -c after creating the initial file [web:7659].
Why use htpasswd instead of system users:
htpasswd manages a separate credential store scoped only to SVN. This decouples SVN access from system login. Revoking SVN access by removing a user from the password file does not affect OS accounts, and vice versa [web:7659].
Expected output:
New password:
Retype new password:
Adding password for user admin
Verify the file was created:
ls -l /etc/svn-auth-file
Expected output:
-rw-r--r-- 1 root root 123 May 29 18:45 /etc/svn-auth-file
Step 8: Configure UFW Firewall
sudo ufw allow 'Apache'
sudo ufw allow 22/tcp
sudo ufw enable
sudo ufw status
What each command does:
ufw allow 'Apache': Opens ports 80 (HTTP) and 443 (HTTPS) using Ubuntu’s named Apache profileufw allow 22/tcp: Explicitly allows SSH traffic on port 22ufw enable: Activates the firewall with current rulesufw status: Displays the active firewall rules
Why enable the firewall:
Default Ubuntu 26.04 cloud images may have UFW inactive. Without it, all ports are reachable from the internet, exposing your server to automated scanning and brute-force attacks [web:7657].
Why allow port 22 BEFORE enabling UFW:
If you enable UFW without first allowing SSH, you will lock yourself out of the server during the same session. Always allow port 22 before running ufw enable [web:7657].
Why use the named Apache profile:
The named profile opens both port 80 and 443 automatically, reducing manual effort if you add HTTPS later with Let’s Encrypt. Custom port rules require you to remember exact port numbers.
Expected output:
Rules added (name: Apache)
Rules added
Firewall is active and enabled on system startup
Status: active
To Action From
-- ------ ----
Apache ALLOW Anywhere
22/tcp ALLOW Anywhere
Apache (v6) ALLOW Anywhere (v6)
22/tcp (v6) ALLOW Anywhere (v6)
Step 9: Verify Access in a Web Browser
Open your browser and navigate to:
http://<SERVER_IP>/svn/project/
Replace <SERVER_IP> with your server’s actual public IP address.
Why test in a browser first:
A browser test confirms the entire stack is working (Apache, mod_dav_svn, authentication, permissions) before introducing SVN client behavior as a variable. If the browser works but the client fails, you know the problem is on the client side, not the server [web:7657].
Expected result:
You should see a Basic Auth prompt asking for username and password. After entering admin and the password you set, you should see a Subversion index page showing repository revision and path information.
Troubleshooting browser errors:
- 403 Forbidden: Re-check
www-datagroup membership andchmod 770on/srv/svn - 500 Internal Server Error: Inspect Apache error log at
/var/log/apache2/error.log - Connection refused: Verify Apache is running with
sudo systemctl status apache2
Step 10: Make Your First SVN Commit
On your local development machine (not the server), run:
svn checkout http://<SERVER_IP>/svn/project --username admin
cd project
echo "Initial file" > README.txt
svn add README.txt
svn commit -m "Initial commit"
What each command does:
svn checkout: Creates a working copy connected to the repository URL on your local machinecd project: Changes into the checked-out working copy directoryecho "Initial file" > README.txt: Creates a test file with sample contentsvn add README.txt: Stages the file for inclusion in the next commitsvn commit -m "Initial commit": Pushes the staged changes to the repository with a commit message
Why svn checkout before svn add:
SVN requires a working copy connected to a repository URL before tracking file changes. Unlike Git, you cannot initialize a repository locally and push later. The checkout operation establishes the connection between your local files and the central server [web:7665].
Why use the -m flag for commit messages:
Commit messages are stored permanently in the repository log. Empty or meaningless messages degrade long-term maintainability. The -m flag lets you write a proper message without opening an editor.
Expected output:
A README.txt
Committed revision 1.
Verify the commit was recorded:
svn log
Expected output:
------------------------------------------------------------------------
r1 | admin | 2026-05-29 18:50:12 +0700 (Thu, 29 May 2026) | 1 line
Initial commit
------------------------------------------------------------------------
Troubleshooting Common Errors
Error 1: Unable to locate package subversion
Cause: Ubuntu’s Universe component is not enabled. Subversion is not in the main repository.
Solution:
sudo add-apt-repository universe
sudo apt update
sudo apt install -y subversion
This registers Universe with APT and refreshes the package cache [web:7665].
Error 2: 403 Forbidden When Accessing /svn/project/
Cause: The Apache user www-data lacks group access to /srv/svn.
Solution:
sudo usermod -aG svn www-data
sudo systemctl restart apache2
sudo chmod -R 770 /srv/svn
Verify www-data is in the svn group:
groups www-data
Expected output includes svn in the list [web:7657].
Error 3: Permission denied on Repository Path
Cause: Repository was created with sudo and owned by root instead of svn.
Solution:
sudo chown -R svn:svn /srv/svn
sudo chmod -R 770 /srv/svn
Always create repositories as the svn user or fix ownership immediately after creation [web:7665].
Error 4: 500 Internal Server Error in Browser
Cause: mod_dav_svn is not loaded or Apache configuration has a syntax error.
Solution:
Check Apache configuration syntax:
sudo apache2ctl configtest
Expected output: Syntax OK
Check Apache error log:
sudo tail -f /var/log/apache2/error.log
Ensure mod_dav_svn is enabled:
sudo a2enmod dav_svn
sudo systemctl reload apache2
Inspect the log for specific error messages after reloading [web:7664].
Error 5: All Users Wiped from htpasswd File
Cause: Accidentally used -c flag when adding a new user, which overwrote the entire file.
Solution:
There is no recovery. You must recreate all users without the -c flag:
sudo htpasswd -c /etc/svn-auth-file newadmin
sudo htpasswd /etc/svn-auth-file developer1
Always omit -c for additional users [web:7659].
Post-Installation Best Practices
Enable HTTPS with Let’s Encrypt
Basic Auth over plain HTTP transmits passwords in base64 encoding, which is readable on any network sniff. Use Certbot to add a Let’s Encrypt SSL certificate:
sudo apt install -y certbot python3-certbot-apache
sudo certbot --apache -d yourdomain.com
This automatically configures HTTPS and redirects HTTP to HTTPS [web:7657].
Schedule Daily Backups with svnadmin hotcopy
SVN stores every revision permanently, so repositories grow over time. Use svnadmin hotcopy to create live, consistent backups without taking the server offline:
sudo svnadmin hotcopy /srv/svn/project /bak/project-$(date +%F)
Add this to cron for daily backups:
0 2 * * * svnadmin hotcopy /srv/svn/project /bak/project-$(date +\%F)
This is safe for cron jobs because it does not lock the repository [web:7657].
Add Path-Based Authorization
For team environments, use mod_authz_svn to segment access by path. Create an /etc/svn-authz file:
[groups]
dev-team = admin, developer1
ops-team = admin, developer2
[/project]
@dev-team = rw
@ops-team = r
[/legacy]
@ops-team = rw
* =
This prevents developer1 from accessing /legacy while allowing admin everywhere.
Monitor Disk Usage
SVN repositories grow with every commit. On a constrained VPS, running out of disk space causes write failures silently. Check disk usage regularly:
df -h /srv/svn
du -sh /srv/svn/*
[su_box title=”VPS Manage Service Offer” style=”bubbles” box_color=”#000000″ radius=”10″]If you don’t have time to do all of this stuff, or if this is not your area of expertise, we offer a service to do “VPS Manage Service Offer”, starting from $10 (Paypal payment). Please contact us to get the best deal![/su_box]