How to Install Apache Subversion (SVN) on CentOS Stream 9
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:
- Deploy a CentOS Stream 9 server instance at Vultr. Assuming this server instance has an example IPv4 address 203.0.113.100.
- Prepare a domain name svn.example.com for accessing the Apache Subversion version control system.
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.