Perl programmer for hire: download my resume (PDF).
John Bokma MexIT
freelance Perl programmer

Subversion with Apache and SSL on Ubuntu

Friday, June 24, 2011 | 0 comments

In the afternoon I installed Subversion on my Dell Vostro running Lucid Lynx. Yesterday I had done a fresh install of Ubuntu Lucid Lynx 10.04.02 LTS and in order to be able to do some work I really had to restore the SVN repositories I keep my work in and make them accessible again.

Installing the Apache web server

Since I had been using the Apache web server to access SVN repositories via https on the previous installation of Ubuntu on my development computer without any issues I had decided to use this setup again.

From that ealier installation I recalled that just installing the apache2 package as follows:

sudo apt-get install apache2

would install apache2-mpm-worker and that if I would install PHP later, in my case to be able to use MediaWiki, it would be replaced by apache2-mpm-prefork. So in order to keep things simple I installed the Apache web server version 2.2.14 by installing PHP version 5.5.3.2 as follows:

sudo apt-get install php5

which installs apache2-mpm-prefork.

If you like me get the following warning during the above installation of PHP:

apache2: Could not reliably determine the server's fully 
qualified domain name, using 127.0.1.1 for ServerName

don't worry. Open /etc/apache2/httpd.conf in, for example vi -- make sure to use sudo -- and add the following line to this file, replacing ecce with the hostname of your computer:

ServerName ecce

I also enabled hostname look ups so I would get actual hostnames instead of numerical IP addresses in the log files Apache generates by adding the following line to httpd.conf as well:

HostnameLookups On

The next time you restart the Apache web server the "Could no reliably determine ..." warning should no longer be given.

Installing Subversion

Once the Apache web server has been installed it's time to install Subversion, mod_dav_svn; the module that makes serving Subversion repositories through the Apache HTTP server possible, and mod_authz_svn; the module that handles path-based authorization. The latter two are in the same package, libapache2-svn.

sudo apt-get install subversion
sudo apt-get install libapache2-svn

Don't restart Apache yet since SSL hasn't been configured and enabled yet.

Intermezzo: my SVN repository layout

I use a hierarchy of directories to organize the repositories on my computer in /home/svn which I created by invoking sudo mkdir /home/svn not by adding a user svn. I check out the repositories under a directory Amber in my home directory following the same hierarchy. The name Amber is a reference to Castle Amber, the name I used up until a few years ago for my company. Currently I am self-employed as a Perl programmer under my own name which according to my bookkeeper is less of a hassle.

An excerpt of the hierarchy I currently use is given below:

.
`--admin
|  `--invoices
|  `--notes
|  `--quotes
|  `--seo-reports
|  `--support
`--customers
|  `--joe-customer-1
|  |  `--project-1
|  |  `--project-2
:  :
`--in-house
|  `--documents
:  :  :
|  |  `--ubuntu
|  `--projects
|  |  `--ambercam
|  |  `--anti-spam
:  :  :
|  |  `--backup-tools
:  :  :
|  |  `--perl-modules
|  |  `--perl-snippets
:  :
|  `--sites
|  |  `--castleamber.com
|  |  `--johnbokma.com
:  :

The complete tree I used to create the above excerpt was generated using the following find magic on the command line:


find . -maxdepth 3 -name .svn -prune -o -type d -print \
| sort \
| sed -e 's,[^/]*/\([^/]*\)$,`--\1,' -e 's,[^/]*/,|  ,g'

The -name .svn -prune part skips descending into .svn directories. The -type d limits the output to directories only and -maxdepth 3 limits the depth of the tree to 3 levels. The sort sorts the nodes and leaves of the tree and the sed command provides the tree structure. Note that the colons in the output were manually added by me to denote removed parts.

Configuring and enabling SSL

First, an SSL virtual host is needed so Subversion can connect to this. Since I named my computer ecce I created a file ssl-ecce in the directory /etc/apache2/sites-available. The skeleton of this file looks as follows:

<VirtualHost *:443>
    ServerAdmin webmaster@ecce

    # SSL related
    SSLEngine on
    SSLCertificateFile /etc/apache2/ssl/apache.pem
    SSLProtocol all
    SSLCipherSuite HIGH:MEDIUM

    # See: /usr/share/doc/apache2.2-common/README.Debian.gz
    SetEnvIf User-Agent ".*MSIE.*" \
             nokeepalive ssl-unclean-shutdown \
             downgrade-1.0 force-response-1.0

    # Enable Basic Authorization
    <Directory />
        AuthType Basic
        AuthName "Subversion Repository"
        AuthUserFile /etc/apache2/ssl-ecce-svn.passwd
	Require valid-user
	SSLRequireSSL	
    </Directory>

    # Add Location directives here

    # Logging related
    LogLevel warn
    ErrorLog /var/log/apache2/ssl-ecce-error.log
    CustomLog /var/log/apache2/ssl-ecce-access.log combined
    CustomLog /var/log/apache2/ssl-ecce-svn-action.log \
	"%h %u %t %{SVN-ACTION}e" env=SVN-ACTION
<VirtualHost>

Make sure you replace ecce with the hostname of your own computer (five times).

Note that this is a skeleton. You have to add a Location directive for each directory that can hold one or more repositories as will be explained below.

Also note that the last CustomLog directive; it logs Subversion actions to its own, more readable, log file.

Second, a self-signed SSL certificate has to be created. For this I issued the following two commands, the first creates the directory for storing the certificate and the second one generates the actual certificate:

sudo mkdir /etc/apache2/ssl
sudo /usr/sbin/make-ssl-cert /usr/share/ssl-cert/ssleay.cnf \
     /etc/apache2/ssl/apache.pem

The latter asks for a host name. Enter the name of your computer, in my case ecce

Third, since I use basic authorization, see the virtual host skeleton above, I had to create a file with my username and (a one-way hash of) my password, which I did as follows:

sudo htpasswd -c -m /etc/apache2/ssl-ecce-svn.passwd john

If you want to add more users, remember that the -c option is only required if the passwd file doesn't exists yet. And again make sure to replace ecce in the filename with the host name of your computer.

Finally, enable the SSL module, enable the newly created site, and restart the Apache web server as follows:

sudo a2enmod ssl
sudo a2ensite ssl-ecce
sudo /etc/init.d/apache2 restart

First time usage

When you access the repository via svn or a browser you will get a warning about the self-signed certificate since it's not issued by a trusted authority. Accept the certificate permanently to stop this warning from showing up again.

An example of the output you can expect the first time you check out a repository follows below. Notice how, as expected, the password is asked for user 'john'.

svn co https://ecce/customers/fred/blue-widgets/trunk blue-widgets
Error validating server certificate for 'https://ecce:443':
 - The certificate is not issued by a trusted authority. Use the
   fingerprint to validate the certificate manually!
Certificate information:
 - Hostname: ecce
 - Valid: from Fri, 24 Jun 2011 19:28:19 GMT until Mon, 21 Jun 2021 19:28:19 GMT
 - Issuer: ecce
 - Fingerprint: **:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**
(R)eject, accept (t)emporarily or accept (p)ermanently? p
Authentication realm: <https://ecce:443> Subversion Repository
Password for 'john': 

Subversion recipes

Below follow four Subversion recipes to get you started.

Adding a directory for new repositories

Each time I get a new customer, for example Fred, I create a new directory to contain the repositories for each project of the customer as follows:

sudo mkdir /home/svn/customers/fred

Next, I add the following to ssl-ecce:

<Location /customers/fred>
    DAV svn
    SVNParentPath /home/svn/customers/fred
</Location>

and reload the Apache web server as follows:

sudo /etc/init.d/apache2 reload

Creating a Subversion repository

If a customer of mine, say Fred, has a project, say "Blue Widgets" I create a repository for this customer's project as follows:

sudo svnadmin create /home/svn/customers/fred/blue-widgets
sudo chown -R www-data: /home/svn/customers/fred/blue-widgets

followed by an initial import and check-out of the trunk:

cd ~/Amber/customers/fred
mkdir -p blue-widgets/{trunk,tags,branches}
svn import blue-widgets \
    https://ecce/customers/fred/blue-widgets -m 'initial import'
rm -ri blue-widgets
svn co https://ecce/customers/fred/blue-widgets/trunk \
    blue-widgets

Creating a backup of a repository

I create a backup of a repository as follows. Again I use the fictitious customer Fred and his "Blue Widgets" projects as an example.

svnadmin -q dump /home/svn/customers/fred/blue-widgets \
       | gzip -c9 customers-fred-blue-widgets.gz

The repository dump is compressed using gzip.

Restoring a backup of a repository

The backup created in the previous section can be restored as follows:

sudo mkdir -p /home/svn/customers/fred/blue-widgets
sudo svnadmin create /home/svn/customers/fred/blue-widgets

gzip -cd customers-fred-blue-widgets.gz \
   | sudo svnadmin load /home/svn/customers/fred/blue-widgets

sudo chown -R www-data: /home/svn/customers/fred/blue-widgets

Note that you have to add the Location directive to the ssl virtual host section as well if this hasn't been added yet, see "Adding a directory for new repositories".

Subversion related

Also today

Please post a comment | read 0 comments | RSS feed