How to Install Apache Subversion (SVN) on CentOS Stream 9

Updated on June 8, 2022
How to Install Apache Subversion (SVN) on CentOS Stream 9 header image

Introduction

Apache Subversion (SVN) is an open-source, centralized version control system. Software developers use it to store and manage versions of various files, including source code and documentation. This article explains how to set up an Apache Subversion server on a CentOS Stream 9 server instance at Vultr.

Prerequisites

Before moving on, you need to:

1. Set Up DNS Records

If you are hosting the apex domain name example.com at Vultr, set up DNS records as follows to bind example.com, www.example.com, and svn.example.com to the Apache Subversion server's IPv4 address 203.0.113.100:

|table|100| |thead| |tr| |th|20|Type| |th|20|Name| |th|20|Data| |th|20|TTL(seconds)| |th|20|Priority| |tbody| |tr| |td|A| |td| | |td|203.0.113.100| |td|300| |td| | |tr| |td|A| |td|www| |td|203.0.113.100| |td|300| |td| | |tr| |td|A| |td|svn| |td|203.0.113.100| |td|300| |td| | |tr| |td|MX| |td| | |td|example.com| |td|300| |td|10| |tr| |td|NS| |td| | |td|ns1.vultr.com| |td|300| |td| | |tr| |td|NS| |td| | |td|ns2.vultr.com| |td|300| |td| |

To learn more about managing DNS through Vultr, refer to this article: Introduction to Vultr DNS.

If you are hosting the domain name example.com on other platforms, instructions on setting up DNS records may vary.

2. Harden the System

Log in to the Apache Subversion server instance as root with the initial password you found on the Server Details page. Then perform the tasks listed below to harden the system.

Find out if any swap space exists on the system:

# swapon -s

If so, feel free to go to the next task. Otherwise, set up a swap file of 2GB to ease system operations:

# fallocate -l 2g /swap
# chmod 600 /swap
# mkswap /swap
# swapon /swap
# echo '/swap    swap swap defaults 0 0' | tee -a /etc/fstab
# free -m

Change the initial root password to a strong password. For example, if you chose this-strong-password as your password:

# echo 'root:this-strong-password' | chpasswd && history -d -1

Create a sudo user named svnsa with a strong password. another-strong-password, for example.

# useradd -ms /bin/bash svnsa
# echo 'svnsa:another-strong-password' | chpasswd && history -d -1
# echo 'svnsa    ALL=(ALL)   NOPASSWD: ALL' | tee -a /etc/sudoers.d/designated
# chmod 0440 /etc/sudoers.d/designated

Update firewall rules to allow traffic on ports:

  • SSH(22)
  • HTTP(80)
  • HTTPS(443)
  • SVN(3690)

Run the commands below.

# firewall-cmd --zone=public --add-service=ssh --permanent
# firewall-cmd --zone=public --add-service=http --permanent
# firewall-cmd --zone=public --add-service=https --permanent
# firewall-cmd --zone=public --add-port=3690/tcp --permanent
# firewall-cmd --reload
# firewall-cmd --list-services
# firewall-cmd --list-ports

Install the Extra Packages for Enterprise Linux (EPEL) and EPEL-Next repositories:

# dnf config-manager --set-enabled crb
# dnf install epel-release epel-next-release -y

Upgrade the system, and reboot the machine to apply all updates:

# dnf upgrade --refresh -y
# dnf autoremove
# shutdown -r now

After the machine reboots, log in as the sudo user snvsa to continue.

3. Install and Configure Apache

Install Apache and the required Apache modules:

$ sudo dnf install httpd httpd-tools mod_ssl mod_dav_svn -y

Disable the welcome page:

$ sudo sed -i 's/^/#&/g' /etc/httpd/conf.d/welcome.conf

Prevent Apache from exposing files in the document root directory:

$ sudo sed -i "s/Options Indexes FollowSymLinks/Options FollowSymLinks/" /etc/httpd/conf/httpd.conf

Start the Apache service and make it start on boot:

$ sudo systemctl start httpd.service
$ sudo systemctl enable httpd.service

4. Install and Configure Apache Subversion

Install Apache Subversion:

$ sudo dnf install subversion subversion-tools -y
$ svnserve --version

Specify the root directory of SVN repositories:

$ sudo mkdir /srv/svn

Create the first SVN repository named repo001:

$ sudo svnadmin create /srv/svn/repo001
$ sudo chown -R apache:apache /srv/svn/repo001

Create another SVN repository named repo002, if necessary:

$ sudo svnadmin create /srv/svn/repo002
$ sudo chown -R apache:apache /srv/svn/repo002

Set up a password database file /srv/svn/passwd to store user credentials. For example, the username is user001 for the first user, and the password is pass001.

$ sudo htpasswd -bcm /srv/svn/passwd user001 pass001 && history -d -1
$ sudo chown root:apache /srv/svn/passwd
$ sudo chmod 640 /srv/svn/passwd

If you need more users, create them the same way, but don't use the -c flag, which erases the credential file. For example, to create users user002, user003, and user004, use these commands:

$ sudo htpasswd -bm /srv/svn/passwd user002 pass002 && history -d -1
$ sudo htpasswd -bm /srv/svn/passwd user003 pass003 && history -d -1
$ sudo htpasswd -bm /srv/svn/passwd user004 pass004 && history -d -1

Set up a file /srv/svn/authz to store user permissions:

$ sudo cp /srv/svn/repo001/conf/authz /srv/svn/authz

For this example, assume that:

  • User001 is the administrator who has read and write permissions on all SVN repositories.
  • User002 and user003 are qualified users who have read and write permissions on both repo001 and repo002.
  • User004 is a trainee who has only read permission on repo002.

Open the user permissions file with the Nano editor:

$ sudo nano /srv/svn/authz

Edit the file as follows to grant the permissions mentioned above:

[groups]
admin = user001
user = user002, user003
trainee = user004

[/]
@admin = rw

[repo001:/]
@user = rw

[repo002:/]
@user = rw
@trainee = r

Press Ctrl+O, Enter, and Ctrl+X to save the file and quit.

Forbid anonymous access to both SVN repositories:

$ sudo sed -i "s;# anon-access = read;anon-access = none;" /srv/svn/repo001/conf/svnserve.conf
$ sudo sed -i "s;# anon-access = read;anon-access = none;" /srv/svn/repo002/conf/svnserve.conf

Grant write permission on both SVN repositories to authorized users:

$ sudo sed -i "s;# auth-access = write;auth-access = write;" /srv/svn/repo001/conf/svnserve.conf
$ sudo sed -i "s;# auth-access = write;auth-access = write;" /srv/svn/repo002/conf/svnserve.conf

Specify the password database file for both SVN repositories:

$ sudo sed -i "s;# password-db = passwd;password-db = /srv/svn/passwd;" /srv/svn/repo001/conf/svnserve.conf
$ sudo sed -i "s;# password-db = passwd;password-db = /srv/svn/passwd;" /srv/svn/repo002/conf/svnserve.conf

Specify the user permissions file for both SVN repositories:

$ sudo sed -i "s;# authz-db = authz;authz-db = /srv/svn/authz;" /srv/svn/repo001/conf/svnserve.conf
$ sudo sed -i "s;# authz-db = authz;authz-db = /srv/svn/authz;" /srv/svn/repo002/conf/svnserve.conf

Define permission scope for both SVN repositories:

$ sudo sed -i "s;# realm = My First Repository;realm = /srv/svn/repo001;" /srv/svn/repo001/conf/svnserve.conf
$ sudo sed -i "s;# realm = My First Repository;realm = /srv/svn/repo002;" /srv/svn/repo002/conf/svnserve.conf

Specify the default root directory of all SVN repositories:

$ sudo sed -i "s;/var/svn;/srv/svn;" /etc/sysconfig/svnserve

Disable SELinux:

$ sudo setenforce 0
$ sudo sed -i "s/SELINUX=enforcing/SELINUX=disabled/" /etc/selinux/config

Start the SVN server and make it automatically start on boot:

$ sudo systemctl start svnserve.service
$ sudo systemctl enable svnserve.service

Define an available Apache virtual host:

$ sudo mkdir /etc/httpd/sites-available
$ sudo mkdir /etc/httpd/sites-enabled
$ sudo nano /etc/httpd/sites-available/svn.example.com.conf

Populate the file with:

<VirtualHost *:80>
    ServerName svn.example.com
    DocumentRoot /srv/svn/
    <Location />
        DAV svn
        SVNParentPath /srv/svn/
        AuthType Basic
        AuthName "SVN Repository"
        AuthUserFile /srv/svn/passwd
        Require valid-user
    </Location>
    ErrorLog /var/log/httpd/${HOSTNAME}_error.log
    LogLevel warn
    CustomLog /var/log/httpd/${HOSTNAME}_access.log combined
</VirtualHost>

Press Ctrl+O, Enter, and Ctrl+X to save the file and quit.

Create a symbol link to enable the newly created Apache virtual host:

$ sudo ln -s /etc/httpd/sites-available/svn.example.com.conf /etc/httpd/sites-enabled/svn.example.com.conf

Update the main Apache configuration file to run the newly created Apache virtual host:

$ echo 'IncludeOptional /etc/httpd/sites-enabled/*.conf' | sudo tee -a /etc/httpd/conf/httpd.conf

Restart the Apache service:

$ sudo systemctl restart httpd.service

Point your favorite web browser to http://svn.example.com/repo001, and input the username user001 and the password pass001 to log in as the administrator. The system will prompt the repository name and the revision number as follows:

repo001 - Revision 0: /

Return to the terminal program and input the commands listed below to add the required directories. Input credentials of the sudo user svnsa and the SVN administrator user001 when prompted.

$ mkdir -p /tmp/repository/repo-template/{trunk,branches,tags}
$ svn import -m 'Initial Import' /tmp/repository/repo-template/ http://127.0.0.1/repo001
Authentication realm: <http://127.0.0.1:80> SVN Repository
Password for 'svnsa': ****************

Authentication realm: <http://127.0.0.1:80> SVN Repository
Username: user001
Password for 'user001': *******
...
Store password unencrypted (yes/no)? yes

Refresh the repo001 web page in the web browser to view the changes:

repo001 - Revision 1: /
branches/
tags/
trunk/

Create folder structure for repo002 in the same fashion:

$ svn import -m 'Initial Import' /tmp/repository/repo-template/ http://127.0.0.1/repo002

Visit the repo002 page http://svn.example.com/repo002 to view the changes:

repo002 - Revision 1: /
branches/
tags/
trunk/

5. Enable HTTPS Access

To enable HTTPS access to Apache Subversion in a production environment, you need to deploy an effective TLS certificate in the system. A practical choice is a free Let's Encrypt TLS certificate.

Install snapd:

$ sudo dnf install snapd -y
$ sudo systemctl enable --now snapd.socket
$ sudo ln -s /var/lib/snapd/snap /snap

Restart the server instance to load all updates:

$ sudo shutdown -r now

After the system gets up and running again, log in as the same sudo user svnsa to move on.

Upgrade to the latest version of snap:

$ sudo snap install core && sudo snap refresh core

Remove any legacy Certbot-Auto and Certbot packages installed from other channels to avoid conflicts:

$ sudo dnf remove certbot
$ sudo sed -i '/certbot-auto/d' /etc/crontab
$ sudo rm /usr/local/bin/certbot-auto
$ sudo rm -rf /opt/eff.org

Use snap to install Certbot:

$ sudo snap install --classic certbot
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

Use Certbot to get a Let's Encrypt TLS certificate for selected domain names:

$ sudo systemctl stop httpd.service
$ sudo certbot certonly --standalone --email admin@example.com --agree-tos --no-eff-email -d svn.example.com -d www.example.com -d example.com
...
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/svn.example.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/svn.example.com/privkey.pem
...

Test if certificate renewals are in the schedule:

$ sudo certbot renew --dry-run
$ sudo systemctl list-timers | grep snap.certbot.renew.service

Use the Nano editor to open the Apache virtual host configuration file:

$ sudo nano /etc/httpd/sites-available/svn.example.com.conf

Update the file as follows:

<VirtualHost *:80>
ServerName svn.example.com
DocumentRoot /srv/svn/
Redirect permanent / https://svn.example.com/
</VirtualHost>
<VirtualHost *:443>
ServerName svn.example.com
DocumentRoot /srv/svn/
SSLEngine on
SSLProtocol all -SSLv2
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
SSLCertificateFile /etc/letsencrypt/live/svn.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/svn.example.com/privkey.pem
ErrorLog /var/log/httpd/${HOSTNAME}_error.log
LogLevel warn
CustomLog /var/log/httpd/${HOSTNAME}_access.log combined
<Location />
DAV svn
SVNParentPath /srv/svn/
AuthType Basic
AuthName "SVN Repository"
AuthUserFile /srv/svn/passwd
Require valid-user
</Location>
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
    SSLOptions +StdEnvVars
</Files>
SetEnvIf User-Agent ".*MSIE.*" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0
CustomLog /var/log/httpd/${HOSTNAME}_ssl_request_log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>

Press Ctrl+O, Enter, and Ctrl+X to save the file and quit.

Restart the Apache service to load the updated configuration:

$ sudo systemctl start httpd.service

Point your favorite web browser to http://svn.example.com/repo001 again to confirm the automatic redirect from HTTP to HTTPS.

Next Steps

You can use an SVN client such as TortoiseSVN for Windows to access the online SVN repositories and commit data. See the Apache Subversion homepage for more information.