Apache Subversion (SVN) is a centralized version control system still widely used in enterprise environments, government agencies, and organizations with legacy repositories. Unlike distributed systems like Git, SVN uses a single central repository – which makes it simpler for teams that need strict access control and linear version history. Apache Subversion handles binary files efficiently and supports partial checkouts, making it a practical choice for large repositories with mixed content types.
This guide covers installing and configuring an SVN server on Ubuntu 24.04 and Debian 13. We set up both the native svnserve daemon and Apache-based WebDAV access, configure user authentication and path-based authorization, and cover backup procedures.
Prerequisites
- A server running Ubuntu 24.04 LTS or Debian 13
- Root or sudo access
- At least 1GB RAM and 10GB disk space (more for large repositories)
- Ports 3690 (svnserve), 80/443 (Apache WebDAV) open if using a firewall
- A domain name pointed to the server (optional, for Apache WebDAV access)
Step 1: Install Subversion on Ubuntu 24.04 / Debian 13
Subversion is available in the default repositories for both Ubuntu and Debian. Update the package index and install the subversion package.
sudo apt update
sudo apt install -y subversion
Confirm the installation by checking the SVN version:
svn --version
The output shows the installed Subversion version and the supported repository access methods:
svn, version 1.14.x (r...)
compiled ...
The following repository access (RA) modules are available:
* ra_svn : Module for accessing a repository using the svn network protocol.
* ra_local : Module for accessing a repository on local disk.
* ra_serf : Module for accessing a repository via WebDAV protocol using serf.
Step 2: Create an SVN Repository
Create a directory to hold your SVN repositories and initialize the first one. We use /srv/svn as the base path – a clean, standard location for service data.
sudo mkdir -p /srv/svn
sudo svnadmin create /srv/svn/myproject
Verify the repository was created successfully by listing its contents:
ls -la /srv/svn/myproject/
You should see the standard SVN repository structure including conf, db, hooks, and locks directories:
total 24
drwxr-xr-x 6 root root 4096 ... .
drwxr-xr-x 3 root root 4096 ... ..
drwxr-xr-x 2 root root 4096 ... conf
drwxr-sr-x 6 root root 4096 ... db
-r--r--r-- 1 root root 2 ... format
drwxr-xr-x 2 root root 4096 ... hooks
drwxr-xr-x 2 root root 4096 ... locks
-rw-r--r-- 1 root root 229 ... README.txt
Step 3: Configure svnserve (Native SVN Protocol)
The svnserve daemon provides fast repository access over the svn:// protocol on port 3690. Configuration involves three files inside the repository’s conf directory.
Configure svnserve.conf
Open the main svnserve configuration file:
sudo vi /srv/svn/myproject/conf/svnserve.conf
Uncomment and set the following values in the [general] section:
[general]
# Anonymous users get read-only access; authenticated users get full read/write
anon-access = read
auth-access = write
# Path to the password file (relative to the conf directory)
password-db = passwd
# Path to the authorization file for path-based access control
authz-db = authz
# Realm name displayed to users during authentication
realm = My Project Repository
If you want to disable anonymous access entirely, set anon-access = none instead.
Configure the Password File
Open the password file to add SVN users:
sudo vi /srv/svn/myproject/conf/passwd
Add users in the format username = password under the [users] section:
[users]
developer1 = SecurePass123
developer2 = AnotherPass456
deployer = DeployPass789
These passwords are stored in plain text. For production, use SASL authentication or Apache with mod_dav_svn for encrypted password handling.
Configure the Authorization File
Open the authz file for path-based access control:
sudo vi /srv/svn/myproject/conf/authz
Define groups and set permissions per directory path:
[groups]
developers = developer1, developer2
deployers = deployer
# Root of the repository - developers get read/write, deployers read-only
[/]
@developers = rw
@deployers = r
# Only deployers can write to the releases directory
[/releases]
@deployers = rw
@developers = r
Step 4: Run svnserve as a Systemd Service
Running svnserve as a systemd service ensures it starts automatically on boot and can be managed with standard systemctl commands. Create a dedicated system user first for security.
sudo useradd -r -s /usr/sbin/nologin svn
sudo chown -R svn:svn /srv/svn
Create the systemd unit file:
sudo vi /etc/systemd/system/svnserve.service
Add the following service configuration:
[Unit]
Description=Subversion SVN Server
After=network.target
[Service]
Type=simple
User=svn
Group=svn
ExecStart=/usr/bin/svnserve -d --foreground -r /srv/svn
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
The -r /srv/svn flag sets the root directory so clients connect using svn://hostname/myproject instead of the full path. Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable --now svnserve
Verify the service is running:
sudo systemctl status svnserve
The output should show active (running) status:
● svnserve.service - Subversion SVN Server
Loaded: loaded (/etc/systemd/system/svnserve.service; enabled; preset: enabled)
Active: active (running) since ...
Main PID: ...
Tasks: 1 (limit: ...)
Memory: ...
CPU: ...
CGroup: /system.slice/svnserve.service
└─... /usr/bin/svnserve -d --foreground -r /srv/svn
Confirm svnserve is listening on port 3690:
ss -tlnp | grep 3690
You should see svnserve bound to port 3690 on all interfaces:
LISTEN 0 128 0.0.0.0:3690 0.0.0.0:* users:(("svnserve",pid=...,fd=3))
Step 5: Configure Apache with mod_dav_svn for Web Access
Apache with mod_dav_svn provides HTTP/HTTPS access to SVN repositories. This is the recommended approach for production since it supports SSL encryption, integrates with LDAP/AD authentication, and works through corporate firewalls that block non-HTTP ports.
Install Apache and the SVN WebDAV module:
sudo apt install -y apache2 libapache2-mod-svn
Enable the required Apache modules:
sudo a2enmod dav dav_svn authz_svn
Create an Apache password file for SVN users using htpasswd:
sudo apt install -y apache2-utils
sudo htpasswd -cm /etc/apache2/dav_svn.passwd developer1
sudo htpasswd -m /etc/apache2/dav_svn.passwd developer2
The -c flag creates the file (use only for the first user). Each command prompts for a password. Now create the Apache virtual host configuration:
sudo vi /etc/apache2/sites-available/svn.conf
Add the following configuration to serve SVN repositories over HTTP:
<VirtualHost *:80>
ServerName svn.example.com
<Location /svn>
DAV svn
SVNParentPath /srv/svn
# Authentication
AuthType Basic
AuthName "SVN Repository"
AuthUserFile /etc/apache2/dav_svn.passwd
Require valid-user
# Path-based authorization
AuthzSVNAccessFile /srv/svn/myproject/conf/authz
</Location>
ErrorLog ${APACHE_LOG_DIR}/svn_error.log
CustomLog ${APACHE_LOG_DIR}/svn_access.log combined
</VirtualHost>
Set the correct ownership so Apache can access the repository:
sudo chown -R www-data:www-data /srv/svn
Enable the site and restart Apache:
sudo a2ensite svn.conf
sudo a2dissite 000-default.conf
sudo systemctl restart apache2
Verify Apache is running with the SVN module loaded:
sudo systemctl status apache2
sudo apachectl -M | grep svn
The module check should confirm dav_svn_module is loaded:
dav_svn_module (shared)
You can now access the repository at http://svn.example.com/svn/myproject using a web browser or SVN client. For production use, add SSL with Let’s Encrypt to encrypt credentials in transit.
Note: If you plan to use only Apache-based access (not svnserve), stop the svnserve service to avoid ownership conflicts:
sudo systemctl stop svnserve
sudo systemctl disable svnserve
Step 6: Configure Firewall for SVN Access
Open the required ports depending on which access method you configured. For firewalld on Debian/Ubuntu, use the following rules.
If using UFW (default on Ubuntu):
sudo ufw allow 3690/tcp comment "SVN svnserve"
sudo ufw allow 80/tcp comment "HTTP"
sudo ufw allow 443/tcp comment "HTTPS"
sudo ufw reload
If using firewalld:
sudo firewall-cmd --permanent --add-port=3690/tcp
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
Verify the firewall rules are active:
sudo ufw status
You should see the SVN port listed as allowed:
To Action From
-- ------ ----
3690/tcp ALLOW Anywhere
80/tcp ALLOW Anywhere
443/tcp ALLOW Anywhere
Step 7: Checkout and Commit to SVN Repository
With the server running, test the workflow from a client machine. Install the subversion package on the client if it is not already present.
Checkout the Repository
For svnserve access (port 3690):
svn co svn://192.168.1.10/myproject ~/myproject
For Apache WebDAV access:
svn co http://svn.example.com/svn/myproject ~/myproject
Add Files and Commit
Create a standard SVN directory structure and commit it:
cd ~/myproject
mkdir trunk branches tags
svn add trunk branches tags
svn commit -m "Create standard SVN directory structure"
A successful commit shows the new revision number:
Adding branches
Adding tags
Adding trunk
Committed revision 1.
Add a file to the trunk and commit:
echo "# My Project" > trunk/README.md
svn add trunk/README.md
svn commit -m "Add project README"
Check the repository log to verify the commit history:
svn log svn://192.168.1.10/myproject
The log output shows each revision with the author, date, and commit message:
------------------------------------------------------------------------
r2 | developer1 | 2026-03-22 ... | 1 line
Add project README
------------------------------------------------------------------------
r1 | developer1 | 2026-03-22 ... | 1 line
Create standard SVN directory structure
------------------------------------------------------------------------
Step 8: User Access Control with the authz File
SVN’s authz file provides granular path-based access control. This is one of SVN’s strengths over simpler setups – you can restrict who reads or writes specific directories within a repository.
Open the authz file:
sudo vi /srv/svn/myproject/conf/authz
Here is a more detailed example for a team with multiple roles:
[groups]
admins = admin1
developers = dev1, dev2, dev3
qa = tester1, tester2
readonly = auditor1
# Repository root - admins get full access
[/]
@admins = rw
* =
# Trunk - developers can write, QA can read
[/trunk]
@developers = rw
@qa = r
# Branches - developers and QA can write their own branches
[/branches]
@developers = rw
@qa = rw
# Tags - only admins can create tags (releases)
[/tags]
@admins = rw
@developers = r
@qa = r
# Read-only users can see everything but not change anything
[/]
@readonly = r
Key authorization rules to understand:
rwgrants read and write accessrgrants read-only access- An empty value (
* =) denies all access - More specific path rules override parent path rules
- Group names are prefixed with
@
Changes to the authz file take effect immediately – no service restart is needed. For the SVN Book reference, the authz format supports per-repository sections when using SVNParentPath with Apache.
Step 9: Backup SVN Repository
Regular backups are critical for any version control system. SVN provides two backup methods – svnadmin dump for portable archives and svnadmin hotcopy for fast full copies.
Full Dump Backup
The dump format creates a portable archive that can be loaded into any SVN server:
sudo svnadmin dump /srv/svn/myproject > /backup/svn/myproject-$(date +%Y%m%d).dump
To restore from a dump file, create a new repository and load the dump:
sudo svnadmin create /srv/svn/myproject-restored
sudo svnadmin load /srv/svn/myproject-restored < /backup/svn/myproject-20260322.dump
Hot Copy Backup
For faster backups, hotcopy creates an exact copy of the repository while it is running:
sudo svnadmin hotcopy /srv/svn/myproject /backup/svn/myproject-hotcopy
Automated Backup Script
Create a backup script and schedule it with cron for daily automated backups:
sudo vi /usr/local/bin/svn-backup.sh
Add the following backup script:
#!/bin/bash
BACKUP_DIR="/backup/svn"
REPO_DIR="/srv/svn"
DATE=$(date +%Y%m%d)
RETENTION=30
mkdir -p "$BACKUP_DIR"
for repo in "$REPO_DIR"/*/; do
repo_name=$(basename "$repo")
svnadmin dump "$repo" | gzip > "$BACKUP_DIR/${repo_name}-${DATE}.dump.gz"
done
# Remove backups older than retention period
find "$BACKUP_DIR" -name "*.dump.gz" -mtime +$RETENTION -delete
echo "SVN backup completed: $(date)"
Make the script executable and add it to cron:
sudo chmod +x /usr/local/bin/svn-backup.sh
sudo mkdir -p /backup/svn
Add a cron job to run the backup daily at 2 AM:
echo "0 2 * * * root /usr/local/bin/svn-backup.sh >> /var/log/svn-backup.log 2>&1" | sudo tee /etc/cron.d/svn-backup
Conclusion
You now have a working SVN server on Ubuntu 24.04 or Debian 13 with both svnserve (native protocol) and Apache WebDAV access configured. The setup includes user authentication, path-based authorization, firewall rules, and automated backups.
For production hardening, enable SSL/TLS on Apache with Let's Encrypt, integrate authentication with LDAP or Active Directory, set up repository backup replication to offsite storage, and monitor disk usage as repositories grow. If you manage Docker containers alongside SVN, consider running svnserve in a container for easier deployment across environments.
Thanks for the tutorial. However, I encountered a problemusing svn import.
The solution was the same – to remove the line
Alias /svn /var/lib/svn
in the dav_svn.conf file (using Debian 10).