Still running Subversion in 2026? You’re not alone. Plenty of enterprises, regulated industries, and legacy codebases depend on SVN for centralized version control where Git’s distributed model is overkill or a compliance headache. Apache Subversion 1.14 (the current LTS branch) is stable, well-supported, and does the job it was built for.
This guide covers a full SVN server setup with Apache mod_dav_svn on Rocky Linux 10 and Ubuntu 24.04, including repository creation, HTTP basic authentication, path-based authorization, SELinux configuration, firewall rules, and SSL/TLS with Let’s Encrypt. There is also a practical SVN command cheat sheet at the end for daily operations.
Last verified: March 2026 | Tested on Rocky Linux 10.1, Ubuntu 24.04 LTS
Prerequisites
- A server running Rocky Linux 10, AlmaLinux 10, RHEL 10, or Ubuntu 24.04 LTS
- Root or sudo access
- Minimum 1 GB RAM, 1 vCPU (SVN is lightweight)
- Ports 80/tcp and 443/tcp open for HTTP/HTTPS access
- A domain or subdomain pointed to your server (for SSL)
- Tested with: Subversion 1.14.5 (Rocky 10), Subversion 1.14.3 (Ubuntu 24.04)
Install Apache Subversion on Rocky Linux 10 / AlmaLinux 10
Subversion and the Apache DAV module are available directly from the AppStream repository. No extra repos needed.
Update the system first:
sudo dnf update -y
Install Subversion, the Apache HTTP server, and the mod_dav_svn module:
sudo dnf install -y subversion mod_dav_svn httpd httpd-tools
Confirm the installed versions:
svn --version --quiet
httpd -v | head -1
You should see Subversion 1.14.5 and Apache 2.4.63:
1.14.5
Server version: Apache/2.4.63 (Rocky Linux)
Install Apache Subversion on Ubuntu 24.04
On Ubuntu, the SVN Apache module is packaged separately as libapache2-mod-svn.
Update package lists and install:
sudo apt update
sudo apt install -y subversion libapache2-mod-svn apache2-utils
Enable the required Apache modules:
sudo a2enmod dav dav_svn authz_svn
Verify the installation:
svn --version --quiet
apache2 -v | head -1
Expected output on Ubuntu 24.04:
1.14.3
Server version: Apache/2.4.58 (Ubuntu)
Create an SVN Repository
Create the parent directory for all SVN repositories and your first project repository. The SVNParentPath directive (configured later) lets Apache serve multiple repos from a single location.
sudo mkdir -p /var/www/svn /etc/svn
sudo svnadmin create /var/www/svn/myproject
Set ownership to the Apache user. On RHEL/Rocky this is apache, on Ubuntu it is www-data:
# Rocky / AlmaLinux / RHEL
sudo chown -R apache:apache /var/www/svn
# Ubuntu / Debian
sudo chown -R www-data:www-data /var/www/svn
Verify the repository was created successfully:
sudo svnadmin info /var/www/svn/myproject
The output confirms the repository format and filesystem type:
Path: /var/www/svn/myproject
UUID: a7546642-23ea-4d67-a3bd-4e3ad692926e
Revisions: 0
Repository Format: 5
Compatible With Version: 1.10.0
Repository Capability: mergeinfo
Filesystem Type: fsfs
Filesystem Format: 8
FSFS Sharded: yes
FSFS Shard Size: 1000
FSFS Shards Packed: 0/0
FSFS Logical Addressing: yes
Configure Apache with mod_dav_svn
The mod_dav_svn module serves SVN repositories over HTTP(S) through Apache. Create the configuration file for your OS.
Rocky / AlmaLinux / RHEL
Create the Apache SVN configuration file:
sudo vi /etc/httpd/conf.d/subversion.conf
Add the following configuration:
<Location /svn>
DAV svn
SVNParentPath /var/www/svn
AuthType Basic
AuthName "SVN Repository"
AuthUserFile /etc/svn/svn-auth
AuthzSVNAccessFile /etc/svn/svn-authz
Require valid-user
</Location>
Ubuntu / Debian
On Ubuntu, the DAV SVN module ships with a default config file. Replace its contents:
sudo vi /etc/apache2/mods-available/dav_svn.conf
Add the same Location block:
<Location /svn>
DAV svn
SVNParentPath /var/www/svn
AuthType Basic
AuthName "SVN Repository"
AuthUserFile /etc/svn/svn-auth
AuthzSVNAccessFile /etc/svn/svn-authz
Require valid-user
</Location>
The key directives here: SVNParentPath serves every repository under /var/www/svn automatically, AuthUserFile points to the htpasswd credentials, and AuthzSVNAccessFile enables per-path access control.
Create SVN Users with htpasswd
SVN over Apache uses HTTP Basic authentication. Create the password file and add your first user with the -c flag (creates the file):
sudo htpasswd -c /etc/svn/svn-auth admin
You will be prompted to enter and confirm a password. To add more users, omit the -c flag so the existing file is not overwritten:
sudo htpasswd /etc/svn/svn-auth developer
sudo htpasswd /etc/svn/svn-auth designer
Lock down the password file permissions so only Apache can read it:
# Rocky / AlmaLinux / RHEL
sudo chown root:apache /etc/svn/svn-auth
sudo chmod 640 /etc/svn/svn-auth
# Ubuntu / Debian
sudo chown root:www-data /etc/svn/svn-auth
sudo chmod 640 /etc/svn/svn-auth
Set Up Path-Based Authorization
The AuthzSVNAccessFile directive referenced in the Apache config points to a file that controls who can read or write specific paths within each repository. This is one of SVN’s advantages over basic filesystem permissions.
Create the authorization file:
sudo vi /etc/svn/svn-authz
Add group definitions and per-path rules:
[groups]
admins = admin
developers = developer, designer
[myproject:/]
@admins = rw
@developers = rw
[myproject:/releases]
@admins = rw
@developers = r
[myproject:/config]
@admins = rw
* =
In this example, admins have full read-write access everywhere. Developers can read and write to most paths but only read from /releases. The /config path is restricted to admins only, with * = denying everyone else. You can add more repositories by creating additional [reponame:/path] sections.
Configure SELinux for SVN (Rocky / AlmaLinux / RHEL)
Rocky Linux 10 runs SELinux in enforcing mode by default. Apache needs the correct security contexts to read and write SVN repository files. Without these, you will get “403 Forbidden” errors when accessing the repository.
Set the SELinux file context so Apache can write to the SVN directory:
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/svn(/.*)?"
sudo restorecon -Rv /var/www/svn
The restorecon command applies the new context to all existing files. You should see output confirming each file was relabeled:
Relabeled /var/www/svn from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:httpd_sys_rw_content_t:s0
Relabeled /var/www/svn/myproject from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:httpd_sys_rw_content_t:s0
Relabeled /var/www/svn/myproject/db from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:httpd_sys_rw_content_t:s0
...
Enable the httpd_unified boolean so Apache can access all its content directories uniformly:
sudo setsebool -P httpd_unified 1
Verify there are no SELinux denials after the configuration:
sudo ausearch -m avc -ts recent
A clean output (<no matches>) means SELinux is happy with the configuration. If you see AVC denials later after accessing the repository, check what is being denied with ausearch and adjust the context or booleans accordingly.
Configure the Firewall
Open HTTP and HTTPS ports so clients can reach the SVN server.
Firewalld (Rocky / AlmaLinux / RHEL)
If firewalld is configured on your server, open the required ports:
sudo firewall-cmd --add-service=http --permanent
sudo firewall-cmd --add-service=https --permanent
sudo firewall-cmd --reload
Confirm the services are listed:
sudo firewall-cmd --list-services
UFW (Ubuntu / Debian)
On Ubuntu, allow Apache through UFW:
sudo ufw allow "Apache Full"
sudo ufw enable
sudo ufw status
Start Apache and Verify SVN Access
Enable and start the Apache service:
# Rocky / AlmaLinux / RHEL
sudo systemctl enable --now httpd
sudo systemctl status httpd
# Ubuntu / Debian
sudo systemctl enable --now apache2
sudo systemctl restart apache2
sudo systemctl status apache2
Test SVN access from the command line on the server itself:
curl -u admin http://localhost/svn/myproject/
After entering the password, you should see the repository HTML listing:
<html><head><title>myproject - Revision 0: /</title></head>
<body>
<h2>myproject - Revision 0: /</h2>
<ul>
</ul>
</body></html>
From a remote machine, open http://your-server-ip/svn/myproject in a web browser. You will be prompted for credentials before seeing the repository browser.
Secure SVN with SSL/TLS (Let’s Encrypt)
Running SVN over plain HTTP sends credentials in base64 encoding, which is trivially decoded. For any production use, you must enable HTTPS. Here we use Let’s Encrypt for a free SSL certificate.
Install Certbot
# Rocky / AlmaLinux / RHEL
sudo dnf install -y certbot python3-certbot-apache mod_ssl
# Ubuntu / Debian
sudo apt install -y certbot python3-certbot-apache
Obtain and Install the Certificate
Replace svn.example.com with your actual domain. Certbot will automatically configure Apache for SSL:
sudo certbot --apache -d svn.example.com --non-interactive --agree-tos -m [email protected]
Certbot creates the SSL virtual host configuration and sets up automatic HTTP to HTTPS redirection. Verify the certificate renewal works:
sudo certbot renew --dry-run
After SSL is configured, access your repository at https://svn.example.com/svn/myproject. All SVN client connections should also use the HTTPS URL going forward.
SVN Client Operations
With the server running, here are the essential client-side operations. Install the SVN client on your workstation if you have not already (dnf install subversion or apt install subversion).
Checkout a Repository
svn checkout https://svn.example.com/svn/myproject --username admin
This creates a local working copy. You will be prompted for the password on first access, and SVN caches the credentials for subsequent operations:
Checked out revision 0.
Add Files and Commit
cd myproject
echo "Project README" > README.txt
mkdir src
echo '#!/bin/bash' > src/build.sh
svn add README.txt src
svn commit -m "Initial project structure"
SVN confirms each added file and the resulting revision number:
Adding README.txt
Adding src
Adding src/build.sh
Transmitting file data ..done
Committing transaction...
Committed revision 1.
View Repository Info and Log
svn info
Shows the working copy metadata:
Path: .
Working Copy Root Path: /home/user/myproject
URL: https://svn.example.com/svn/myproject
Relative URL: ^/
Repository Root: https://svn.example.com/svn/myproject
Repository UUID: a7546642-23ea-4d67-a3bd-4e3ad692926e
Revision: 1
Node Kind: directory
Last Changed Author: admin
Last Changed Rev: 1
Last Changed Date: 2026-03-24 11:14:18 +0000 (Tue, 24 Mar 2026)
View the commit history:
svn log
The log shows all revisions with author, date, and commit message:
------------------------------------------------------------------------
r1 | admin | 2026-03-24 11:14:18 +0000 (Tue, 24 Mar 2026) | 1 line
Initial project structure
------------------------------------------------------------------------
Create Additional Repositories
Because we used SVNParentPath, adding a new repository is just two commands. No Apache restart needed:
sudo svnadmin create /var/www/svn/another-project
Set the correct ownership for your OS:
# Rocky / AlmaLinux / RHEL
sudo chown -R apache:apache /var/www/svn/another-project
# Ubuntu / Debian
sudo chown -R www-data:www-data /var/www/svn/another-project
On RHEL-based systems, also apply the SELinux context:
sudo restorecon -Rv /var/www/svn/another-project
Add authorization rules in /etc/svn/svn-authz for the new repository, then access it at https://svn.example.com/svn/another-project.
SVN Command Cheat Sheet
This reference table covers the commands you will use most often when working with Subversion repositories.
| Command | Description | Example |
|---|---|---|
svn checkout URL | Create a local working copy from a remote repository | svn checkout https://svn.example.com/svn/myproject |
svn update | Pull latest changes from the server into your working copy | svn update |
svn add FILE | Schedule a new file or directory for addition | svn add src/main.py |
svn delete FILE | Schedule a file for deletion on next commit | svn delete old-config.ini |
svn commit -m "msg" | Send local changes to the server | svn commit -m "Add login module" |
svn status | Show modified, added, or deleted files in working copy | svn status |
svn diff | Show line-by-line differences in modified files | svn diff src/main.py |
svn log | Show commit history | svn log -l 10 (last 10 commits) |
svn info | Display working copy or repository metadata | svn info https://svn.example.com/svn/myproject |
svn revert FILE | Undo local changes (restore to last committed version) | svn revert src/main.py |
svn copy SRC DST | Create a branch or tag (server-side copy) | svn copy ^/trunk ^/branches/feature-x -m "Branch" |
svn merge SRC | Merge changes from another branch into working copy | svn merge ^/branches/feature-x |
svn switch URL | Switch working copy to a different branch or tag | svn switch ^/branches/feature-x |
svn export URL | Export a clean copy without .svn metadata | svn export ^/trunk /tmp/release |
svn blame FILE | Show per-line author and revision information | svn blame src/main.py |
svn propset | Set a property on a file or directory | svn propset svn:ignore "*.log" . |
svn cleanup | Clean up a broken working copy (remove locks) | svn cleanup |
svn list URL | List directory contents in a repository | svn list https://svn.example.com/svn/myproject |
svnadmin create PATH | Create a new repository (server-side) | svnadmin create /var/www/svn/newrepo |
svnadmin dump REPO | Export full repository for backup or migration | svnadmin dump /var/www/svn/myproject > backup.dump |
svnadmin load REPO | Restore a repository from a dump file | svnadmin load /var/www/svn/myproject < backup.dump |
svnadmin hotcopy | Create a safe backup of a live repository | svnadmin hotcopy /var/www/svn/myproject /backup/myproject |
SVN Repository Backup and Restore
Regular backups are essential. SVN provides two approaches: dump files (portable, can be loaded into different SVN versions) and hotcopy (fast, byte-for-byte clone).
Dump and Load (Portable Backup)
svnadmin dump /var/www/svn/myproject > /backup/myproject-$(date +%Y%m%d).dump
To restore into a fresh repository:
sudo svnadmin create /var/www/svn/myproject-restored
sudo svnadmin load /var/www/svn/myproject-restored < /backup/myproject-20260324.dump
Hotcopy (Fast Clone)
For quick backups on the same server, hotcopy is faster because it copies the repository at the filesystem level:
sudo svnadmin hotcopy /var/www/svn/myproject /backup/myproject-hotcopy
Automate daily backups with a cron job. This example runs at 2 AM and keeps 7 days of dumps:
echo "0 2 * * * root svnadmin dump /var/www/svn/myproject | gzip > /backup/myproject-\$(date +\%Y\%m\%d).dump.gz && find /backup -name 'myproject-*.dump.gz' -mtime +7 -delete" | sudo tee /etc/cron.d/svn-backup
OS-Specific Differences
This comparison table summarizes the key differences between setting up SVN on RHEL-based and Debian-based systems. Keep this handy when following the steps above.
| Item | Rocky / AlmaLinux / RHEL 10 | Ubuntu 24.04 / Debian |
|---|---|---|
| SVN version in repos | 1.14.5 | 1.14.3 |
| SVN package | subversion | subversion |
| Apache DAV module | mod_dav_svn | libapache2-mod-svn |
| Apache config path | /etc/httpd/conf.d/subversion.conf | /etc/apache2/mods-available/dav_svn.conf |
| Apache user | apache | www-data |
| Service name | httpd | apache2 |
| Enable modules | Loaded automatically via config | a2enmod dav dav_svn authz_svn |
| Firewall | firewall-cmd | ufw |
| SELinux/AppArmor | SELinux context + boolean required | No action needed (AppArmor has no default Apache profile) |
| Install certbot | dnf install certbot python3-certbot-apache mod_ssl | apt install certbot python3-certbot-apache |
Troubleshooting Common Issues
Error: “403 Forbidden” when accessing /svn/
This almost always means SELinux is blocking Apache from reading the repository files on RHEL-based systems. Verify the SELinux context is correct:
ls -lZ /var/www/svn/
Every file should show httpd_sys_rw_content_t. If it shows default_t or httpd_sys_content_t (read-only), run restorecon -Rv /var/www/svn and make sure you set the httpd_sys_rw_content_t context, not httpd_sys_content_t. Check the audit log with ausearch -m avc -ts recent for details.
Error: “500 Internal Server Error” on repository access
Check the Apache error log for specifics:
# Rocky / RHEL
sudo tail -20 /var/log/httpd/error_log
# Ubuntu
sudo tail -20 /var/log/apache2/error.log
Common causes: the repository path in SVNParentPath does not match the actual directory, or the Apache user does not own the repository files. Fix ownership with chown -R apache:apache /var/www/svn (or www-data:www-data on Ubuntu).
Error: “Could not open the requested SVN filesystem”
This means the repository directory exists but was not created with svnadmin create. A plain mkdir does not create a valid SVN repository. Remove the directory and recreate it properly with svnadmin create /var/www/svn/reponame.
Error: “Authorization failed” with correct password
If the password is correct but access is still denied, the issue is in the svn-authz file. Check that the username in the authz file matches exactly (case-sensitive) what is in the htpasswd file. Also verify the repository name in the authz section header matches the actual repository directory name under /var/www/svn/.
SVN commits fail with “txn-current-lock: Permission denied”
The Apache user cannot write to the repository. This happens when new files are created with wrong ownership after a manual operation. Fix it:
# Rocky / AlmaLinux / RHEL
sudo chown -R apache:apache /var/www/svn/myproject
# Ubuntu / Debian
sudo chown -R www-data:www-data /var/www/svn/myproject
On RHEL-based systems, also re-apply the SELinux context: sudo restorecon -Rv /var/www/svn/myproject.
Frequently Asked Questions
Is SVN still maintained in 2026?
Yes. Apache Subversion 1.14 is the current LTS branch. The latest release is 1.14.5 (December 2024), which included a security fix for CVE-2024-46901. The project receives bugfix and security updates, though no major feature releases are planned.
Should I use SVN or Git?
Git is the standard for most software projects today. SVN still makes sense for large binary assets (game studios, hardware design), strict centralized access control requirements (regulated industries), or legacy codebases where migration cost outweighs the benefit. If you are starting a new project with no constraints, use Git.
What port does SVN use?
When served through Apache (mod_dav_svn), SVN uses standard HTTP/HTTPS ports: 80/tcp and 443/tcp. The standalone svnserve daemon uses port 3690/tcp, but the Apache method is recommended for production because it provides SSL, authentication integration, and fine-grained path authorization.
How do I migrate from SVN to Git?
Use git svn clone to convert an SVN repository to Git while preserving full history. For large repositories, the svn2git tool provides better control over author mapping and branch conversion. Plan for a transition period where both systems are available.
Wrapping Up
You now have a fully functional Apache Subversion server with HTTP authentication, path-based authorization, and SSL encryption. The setup works identically across Rocky Linux 10, AlmaLinux 10, RHEL 10, and Ubuntu 24.04, with the only differences being package names, Apache user accounts, and SELinux requirements on RHEL-based systems.
For production environments, consider integrating LDAP authentication instead of htpasswd for centralized user management, setting up automated backups with the cron job shown above, and monitoring Apache access logs for unauthorized access attempts. If your team is evaluating alternatives, GitLab CE offers a modern web-based Git platform with built-in CI/CD.
Hi Josphat,
This is the second Linux tutorial I’ve used for you and your instructions is spot on. Thanks for this. Trying to get back into programming and building my resources to accomplish this.