Installing Subversion

In the following example I'm using Subversion (SVN) through WebDAV via an Apache web server running on Ubuntu Linux 18.

Installation

For installing Ubuntu Linux 18 see the Installing Ubuntu 18 tutorial.

As SVN is shipped with Ubuntu the installation is pretty easy:

root@machine~# apt-get install subversion libapache2-mod-svn apache2

This installs Subversion, the module for the Apache web server as well as the Apache web server itself.

Configuration

Next we create the directories for our SVN repository:

root@machine~# mkdir -p /var/local/svn
root@machine~# svnadmin create --fs-type fsfs /var/local/svn
root@machine~# chown -R www-data:www-data /var/local/svn

Now we have to activate the SVN support in the Apache web server:

(Should already be the case)

root@machine~# a2enmod dav_svn
root@machine~# ln -s /etc/apache2/mods-available/authz_svn.load /etc/apache2/mods-enabled/authz_svn.load

(If you want to have LDAP support)

root@machine~# ln -s /etc/apache2/mods-available/ldap.load /etc/apache2/mods-enabled/ldap.load
root@machine~# ln -s /etc/apache2/mods-available/authnz_ldap.load /etc/apache2/mods-enabled/authnz_ldap.load

(In any case)

root@machine~# nano /etc/apache2/mods-enabled/dav_svn.conf

Jump to the end of the file (the file should just consist of comments). If you want authentication via a password file:

<Location /svn>
  DAV svn

  SVNPath /var/local/svn

  AuthType Basic
  AuthName "Subversion Repository"

  # --- Authentication by htpasswd file ---
  AuthUserFile /etc/apache2/dav_svn.passwd

  # --- LimitExcept allows read-only access for everyone ---
  <LimitExcept GET PROFFIND OPTIONS REPORT>
    Require valid-user
  </LimitExcept>
</Location>

Location specifies the folder at which the SVN will be accessible through the web server. Let's say the system's IP is 192.168.1.2 the URL in this case would be:

Now we create the password file (instead of "john.doe" fill in the name of the user). -c creates a new file, -m forces MD5 encryption of the password.

root@machine~# htpasswd -cm /etc/apache2/dav_svn.passwd john.doe
New password:
Re-type new password:
Adding password for user john.doe

Okay, now we restart the Apache web server:

root@machine~# service apache2 restart

Now we can test if the SVN works as expected. In our case we type the following URL into a web browser:

http://192.168.1.2/svn

You should get access without the need of an user:

svn - Revision 0: /

Powered by Apache Subversion version 1.9.7 (r1800392).

If you don't want read-only access for everyone just comment out the <LimitExcept> tags like this:

root@machine~# nano /etc/apache2/mods-enabled/dav_svn.conf
<Location /svn>
  [...]
  # --- LimitExcept allows read-only access for everyone ---
  #<LimitExcept GET PROFFIND OPTIONS REPORT>
    Require valid-user
  #</LimitExcept>
</Location>

Restart the web server:

root@machine~# service apache2 restart

Try to access the URL again:
Now you should get an authentication dialogue by your web browser. If you cancel it, you'll get an Unauthorized page. If you enter your user and password you defined in the password file, you should get access.

LDAP authentication

The following I've tested on Ubuntu 16 as well as on Ubuntu 18. I also tested it with OpenLDAP as well as Microsoft Active Directory.

If you want to have LDAP authentication (e.g. via Microsoft Active Directory), you'll need to activate the LDAP and LDAP authentication modules like mentioned earlier in the Configuration section.
I also have a tutorial about how to install an OpenLDAP service / directory.

In addition the configuration must be changed:

root@machine~# nano /etc/apache2/mods-enabled/dav_svn.conf
<Location /svn>
  DAV svn

  SVNPath /var/local/svn

  AuthType Basic
  AuthName "Subversion Repository"

  # --- Authentication by LDAP ---
  #AuthLDAPAuthoritative on
  AuthBasicProvider ldap
  AuthLDAPBindDN "cn=svn-admin,ou=Service Accounts,dc=mydomain,dc=com"
  AuthLDAPBindPassword "password"
  # --- Filter by group - only group members are allowed to access the repository ---
  AuthLDAPURL "ldap://192.168.1.3:389/ou=Users,dc=mydomain,dc=com?sAMAAccount?sub?(&(objectClass=*)(memberOf=cn=Development,ou=Security Groups,ou=Users,dc=mydomain,dc=com))"

  # --- LimitExcept allows read-only access for everyone ---
  <LimitExcept GET PROFFIND OPTIONS REPORT>
    Require valid-user
  </LimitExcept>
</Location>

In this case svn-admin is an account in the service account group having the password password. The Active Directory is running on 192.168.1.3 and LDAP via port 389 is activated. The log-in name is the sAMAccount field content (which is the Windows log-in name). All members (or more precisely: all objects) of the security group Development should have access.

In case of a generic LDAP server / an OpenLDAP server the AuthLDAPURL may look like this:

ldap://[IP-ADDRESS]:[PORT]/[BASE-DN]?uid?sub?(objectClass=inetOrgPerson)

In case of a Microsoft Active Directory the AuthLDAPURL may look like this:

ldap://[IP-ADDRESS]:[PORT]/[BASE-DN]?sAMAccountName?sub?(objectClass=user)

If you want to add a group membership as a requirement in a Microsoft Active Directory environment, you can do so by changing the last part:

(&(objectClass=user)(memberOf=[GROUP-DN]))

where [GROUP-DN] is the DN of the required group.

Restart the web server:

root@machine~# service apache2 restart

Commit only with comment

Every commit into the repository should at least have a comment. Therefore we set-up a so called hook (those hooks also can be used for other things like triggering a build):

root@machine~# cp /var/local/svn/hooks/pre-commit.tmpl /var/local/svn/hooks/pre-commit
root@machine~# chown www-data:www-data /var/local/svn/hooks/pre-commit
root@machine~# nano /var/local/svn/hooks/pre-commit

The following lines have to be modified / added:

# script aims to execute.
# For similar reasons, you should also add a trailing @ to URLs which
# are passed to SVN commands accepting URLs with peg revisions.
#
# Here is an example hook script, for a Unix /bin/sh interpreter.
# For more examples and pre-written hooks, see those in
# /usr/share/subversion/hook-scripts, and in the repository at
# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and
# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/


REPOS="$1"
TXN="$2"

# Make sure that the log message contains some text.
SVNLOOK=/usr/bin/svnlook
#$SVNLOOK log -t "$TXN" "$REPOS" | \
#   grep "[a-zA-Z0-9]" > /dev/null || exit 1
$SVNLOOK log -t "$TXN" "$REPOS" | \
   grep "[a-zA-Z0-9]" > /dev/null

# Check that a commit comment is available.
GREP_STATUS=$?
if [ GREP_STATUS -ne 0 ]
then
    echo "Your commit has been blocked because you didn't give any log message" >&2
    echo "Please write a log message describing the purpose of your changed and" >&2
    echo "then try committing again. --- Thank you" >&2
    exit 1
fi

# Exit on all errors.
#set -e

# Check that the author of this commit has the rights to perform
# the commit on the files and directories being modified.
#"$REPOS"/hooks/commit-access-control.pl "$REPOS" $TXN \
#  "$REPOS"/hooks/commit-access-control.cfg

# All checks passed, so allow the commit.
exit 0

Restart the web server:

root@machine~# service apache2 restart

Make SVN properties modifiable

If you want to make the SVN properties editable (e.g. during the migration from another source control management to SVN), you can do it the following way:

root@machine~# cp /var/local/svn/hooks/pre-revprop-change.tmpl /var/local/svn/hooks/pre-revprop-change
root@machine~# chown www-data:www-data /var/local/svn/hooks/pre-revprop-change
root@machine~# nano /var/local/svn/hooks/pre-revprop-change
REPOS="$1"
REV="$2"
USER="$3"
PROPNAME="$4"
ACTION="$5"

if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi
if [ "$ACTION" = "A" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi
if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:date" ]; then exit 0; fi
if [ "$ACTION" = "A" -a "$PROPNAME" = "svn:date" ]; then exit 0; fi
if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:author" ]; then exit 0; fi
if [ "$ACTION" = "A" -a "$PROPNAME" = "svn:author" ]; then exit 0; fi

echo "Changing revision properties other than svn:log is prohibited (repos $REPOS; rev $REV; user $USER; propName: $PROPNAME; action $ACTION)" >&2
exit 1

Sources