AddThis Social Bookmark Button

Print
FreeBSD Basics

Setting up a Secure Subversion Server

by Dru Lavigne, author of BSD Hacks
05/12/2005

Recently a client hired a team of web developers to assist his overworked web administrator. They asked me to set up a revision-control system to ensure that no one on the team inadvertently overwrote another member's work and to give the administrator the flexibility of rolling back to any version of a file.

My first thought was Subversion, as it is the revisioning system I used with my editor when writing BSD Hacks A search for subversion in the Ports Collection indicated that there are also several related ports. For example, esvn looked like an excellent match for the client, as this GUI front end works from Unix, Mac OS X, and Windows. That's perfect for a web development team short on Unix skills who would be accessing data stored on a FreeBSD server from non-FreeBSD operating systems.

This week's article demonstrates how to create a secure repository using Subversion. The next installment will show how to train your users to access the repository using a GUI client.

Preparing the System

In my scenario, it was important that only the members of the development team have access to the repository. We also chose to have the repository on a system separate from the actual web server and left it up to the web administrator to copy over files from the repository to the web server as he saw fit.

To accomplish this, start by creating a backup of the existing directory structure you wish to put under revision control, and send it securely to the repository server. In my case, I backed up the www data on the web server to an internal server at 192.168.2.2.

# tar czvf - /usr/local/etc/www/data | ssh dru@192.168.2.2 "cat > www.tar.gz"

Next, on the repository system, create a new group called svn and add to it any existing user accounts that need access to the repository. For example, I added my existing web administrator as I created the group by adding this line to /etc/group:

# vi /etc/group
svn:*:3690:webadmin

Then, create a new user called svn and, if necessary, any missing user accounts that need access to the repository. Make sure each account is a member of the svn group and has a password and a valid shell. I used sysinstall to create user accounts for the new web developers. When I finished, I double-checked the membership of the svn group. It looked something like this:

# grep svn /etc/group
svn:*:3690:webadmin,devel1,devel2

Dealing with umask

Before installing Subversion, take a close look at the existing umask for the svn user. On my FreeBSD system it was:

# su -l svn
% umask
022

In Unix, the umask value determines the default permissions of a newly created directory or file. It does this by defining which permissions to disable. If you remember:

r = 4
w = 2
x = 1

you'll see that this umask doesn't turn off any (0) permissions for the user (svn); it turns off write (2) for the group (svn); and it turns off write (2) for world.

Because the members of the svn group should be able to write to the repository, change that group 2 to a 0. If you don't want nongroup members even to be aware of the existence of the repository, also change the world 2 to a 7.

The easy part is changing the umask for the svn user's shell. If it uses csh:

% vi ~svn/.cshrc

then find the existing umask line and change it to either 002 or 007.

If your svn user has a shell other than csh, make your edit in your chosen shell's configuration file.

Once you've saved your changes to ~svn/.cshrc (or wherever), don't forget to tell the shell:

% source ~svn/.cshrc

Repeat the umask command to verify that your changes have taken place.

Installing Subversion with the correct umask

If you chose a umask of 002, you can compile a wrapper into Subversion when you build it from the ports collection. If you chose a umask of 007 or prefer to install the precompiled version of Subversion, create a wrapper script to ensure that the Subversion binaries use your umask value.

To compile in a wrapper that sets a umask of 002:

# cd /usr/ports/devel/subversion
# make -DWITH_SVNSERVE_WRAPPER install clean

Alternatively, to install the precompiled binary:

# pkg_add -r subversion

Note: before installing by either method, finish reading the article. You may find some additional compile options that interest you.

If you didn't compile in your wrapper, move your existing binary and create your own wrapper script:

# mv /usr/local/bin/svn /usr/local/bin/svn.orig
# vi /usr/local/bin/svn
#!/bin/sh
#wrapper script to set umask to 007 on subversion binaries
umask 007
/usr/local/bin/svn.orig "$@"

Set your umask to either 002 or 007 so that it is the same as the umask for your svn user.

Don't forget to make your wrapper script executable:

# chmod +x /usr/local/bin/svn

Creating the Repository

Now that your environment is set up properly, you're ready to create the repository itself. Log in as the user svn to ensure that both the svn user and the svn group own the files you create in the repository. From /usr/home/svn/, type:

% svnadmin create repository

In this example, I've called my repository repository. You can choose any name that is useful to you.

svnadmin create simply creates the directory infrastructure required by the Subversion tools:

% ls -F repository
README.txt	dav/	format	locks/
conf/		db/	hooks/

Notice that db directory? By default, Subversion uses databases to track changes to the files that you place under revision control. This means that you must import your data into those databases.

At that point, I untarred my backup so that I had some data to import. If you do this, don't restore directly into the ~svn/repository directory. (It's a database, remember?) Instead, I first made a new directory structure:

% pwd
/usr/home/svn

% mkdir www && cd www
% mkdir branches tags trunk
% cd trunk
% tar xzvf /full/path/to/www.tar.gz .
% cd

That made the svn user's home directory look like:

% ls -F ~svn
repository/	www/

Importing the Data

Next, it's time to import the information from ~svn/www/ into the Subversion databases. To do so, use the svn import command:

% svn import www file:///usr/home/svn/repository/www -m "initial import"

svn import is one of many svn commands available to users. Type svn help to see the names of all the available commands. If you insert one of those commands between svn and help, as in svn import help, you'll receive help on the syntax for that specified command.

After svn import, specify the name of the directory containing the data to import (www). Your data doesn't have to be in the same directory; simply specify the full path to the data, but ensure that your svn user has permission to access the data you wish to import. Note: once you've successfully imported your data, you don't have to keep an original copy on disk. In my case, I issued the command rm -Rf www.

Next, notice the syntax I used when specifying the full path to the repository. Subversion supports multiple URL schemas or "repository access" RA modules. Verify which schemas your svn supports with:

% svn --version
svn, version 1.1.3 (r12730)
   compiled Mar 20 2005, 11:04:16

Copyright (C) 2000-2004 CollabNet.
Subversion is open source software, see http://subversion.tigris.org/
This product includes software developed by CollabNet (http://www.Collab.Net/).

The following repository access (RA) modules are available:

* ra_dav : Module for accessing a repository via WebDAV (DeltaV) protocol.
  - handles 'http' schema
  - handles 'https' schema
* ra_local : Module for accessing a repository on local disk.
  - handles 'file' schema
* ra_svn : Module for accessing a repository using the svn network protocol.
  - handles svn schema

Because I wished to access the repository on the local disk, I used the file:/// schema. I also appended www at the very end of the URL, as I wish that particular part of the repository to be available by that name. Yes, you can import multiple directory structures into the same Subversion repository, so give each one a name that is easy for you and your users to remember.

Finally, I used the -m message switch to append the comment "initial import" to the repository log. If I hadn't included this switch, svn would have opened the log for me in the user's default editor (vi) and asked me to add a comment before continuing.

This is a very important point. The whole reason to install a revision control system is to allow multiple users to modify files, possibly even simultaneously. It's up to each user to log clearly which changes they made to which files. It's your job to make your users aware of the importance of adding useful comments whenever an svn command prompts them to do so.

Deciding Upon a URL Schema

Congratulations! You now have a working repository. Now's the best time to take a closer look at the various URL schemas and choose the access method that best suits your needs.

Chapter 6 of the freely available e-book Version Control with Subversion gives details about the possible configurations. You can choose to install the book when you compile the FreeBSD port by adding -DWITH_BOOK to your make command.

If all of your users log in to the system either locally or through ssh, use the file:/// schema. Because users are "local" to the repository, this scenario doesn't open a TCP/IP port to listen for Subversion connections. However, it does require an active shell account for each user and assumes that your users are comfortable logging in to a Unix server. As with any shell account, your security depends upon your users choosing good passwords and you setting up repository permissions and group memberships correctly. Having users ssh to the system does ensure that they have encrypted sessions.

Another possibility is to integrate Subversion into an existing Apache server. By default, the FreeBSD port of Subversion compiles in SSL support, meaning your users can have the ability to access your repository securely from their browsers using the https:// schema. However, if you're running Apache 2.x instead of Apache 1.x, remember to pass the -DWITH_MOD_DAV_SVN option to make when you compile your FreeBSD port.

If you're considering giving browser access to your users, read carefully through the Apache httpd configuration section of the Subversion book first. You'll have to go through a fair bit of configuration; fortunately, the documentation is complete.

A third approach is to use svnserve to listen for network connections. The book suggests running this process either through inetd or as a stand-alone daemon. Both of these approaches allow either anonymous access or access once the system has authorized a user using CRAM-MD5. Clients connect to svnserve using the svn:// schema.

Anonymous access wasn't appropriate in my scenario, so I followed the configuration options for CRAM-MD5. However, I quickly discovered that CRAM-MD5 wasn't on my FreeBSD system. When a Google search failed to find a technique for integrating CRAM-MD5 with my Subversion binary, I decided to try the last option.

This was to invoke svnserve in tunnel mode, which allows user authentication through the normal SSH mechanism as well as any restrictions you have placed in your /etc/ssh/sshd_config file. For example, I could use the AllowUsers keyword to control which users can authenticate to the system. Note that this schema uses svn+ssh://.

The appeal of this method is that I could use an existing authentication scheme without forcing the user to actually be "on" the repository system. However, this network connection is unencrypted; the use of SSH is only to authenticate. If your data is sensitive, either have your users use file:// after sshing in or use https:// after you've properly configured Apache.

If you decide to use the svnserve server and you compiled in the wrapper, it created a binary called svnserve.bin. Users won't be able to access the repository until:

# cp /usr/local/bin/svnserve.bin /usr/local/bin/svnserve

That's it for this installment. In the next column, I'll show how to start accessing the repository as a client.

Dru Lavigne is a network and systems administrator, IT instructor, author and international speaker. She has over a decade of experience administering and teaching Netware, Microsoft, Cisco, Checkpoint, SCO, Solaris, Linux, and BSD systems. A prolific author, she pens the popular FreeBSD Basics column for O'Reilly and is author of BSD Hacks and The Best of FreeBSD Basics.

Version Control with Subversion

Related Reading

Version Control with Subversion
By Ben Collins-Sussman, Brian W. Fitzpatrick, C. Michael Pilato

Return to the BSD DevCenter

Return to O'Reilly SysAdmin