Sunday, 5 December 2010

Comprehensive guide to SVN+trac install on Ubuntu 10.04

Software Change Management (SCM) is fundamental for all professional developers, even if you work alone. SCM systems offer more than just backup; they allow you total freedom to develop, knowing that you will be able to revert to a particular revision of code at any time. They also allow teams to develop features in separate branches before merging them into one product for release. Implicit in most SCM systems is version control - the ability the stamp a particular revision or set of revisions as "version 1.0", "versions 1.1", etc.

SVN and Trac are two very popular tools used to create SCM systems. Best of all, they are both open-source, so setting up your SCM system is free!

SVN works as the engine room of the operation. It is a very popular and powerful software version control engine. SVN does all the work of version control: checking-in, checking-out, creating branches, merging branches, comparing revisions, adding new code to the repository, etc. Trac is a web interface, a "web-based project management system" which interacts with SVN.It als comes with some added extras, including a ticket system, for recording bugs and feature requests and assigning them to a developer to fix.

But I digress. Suffice to say, SVN and trac work well together. I personally use them every day and couldn't do without them.

For this tutorial, we are going to set our SCM server up on Linux - again because it's free, but also because for this sort of thing, Linux is the best way to go. (It is easier to install in Linux, and there are some neat scripted add-ons which would just be a pain to set up in a Windows environment - more on that later).

I'll proceed in this order:
  1. Install Linux.
  2. Install and configure SVN and Apache.
  3. Install and configure trac.
  4. Trac-SVN Synchronization.
  5. Using trac and SVN.

Install Linux

Ubuntu Linux is my preferred distro, so were going to get the latest release of Ubuntu Server. You can either:
I'm going to install it from the ISO, because I want to show how to install Linux too. if you already have Linux installed, skip to svn server setup.

Step 1 - Choose your language then begin the installation by selecting "Install Ubuntu Server":
Step 2 - The installer will begin by going through various steps asking you for your country, language and keyboard layout. One these are set to your liking, it will begin to install OS components:

Step 3 - You will now be asked to choose a name for the machine - this is just to make it easy to identify on your network:

Step 4 - After a couple more screens, you will be shown the partitioning options. If you have enough expertise to know what encrypted LVM is, why are you reading this guide!! Otherwise, just leave the default selection and hit enter (there are a few more option screens after this, but 99% of people will want to simply hit Yes on every one):

Step 5 - After the partitioning is complete (2 steps), the OS will begin to install. Go have a cup of coffee ;) :

Step 6 - Set up the full name, default username, and password for the new user:

Step 7 - Choose Home Directory Encryption and http proxy settings - if unsure, just choose No and (blank) for these:

Step 8 - the installer will now configure "apt" - this is basically the Linux equivalent of Windows update:

Step 9 - Select and Install Software. I would recommend that you choose "Install security updates automatically". If you choose "No automatic updates", you will need to periodically run the command "sudo apt-get update" to load the latest security updates for Linux packages. (Note - to update non-security programs you will still need to run apt-get, but this doesn't really present an issue unless you want to install a new package which depends on packages that are already installed. Even then, the package manager will sort it out for you.)

Step 10 - Select the server type. This step automatically installs certain packages for you depending on what you want to do with Linux. In this case, choose LAMP Server (Linux, Apache, MySQL, PHP) since SVN and trac need these packages:

Step 11 - After a few more steps, the installation should be complete. Enter your login name and password to log in to Linux.

By default there will be no Graphical User Interface (GUI) since this is a server. But, for our purposes, having a desktop will be useful.

Step 12 - Install a desktop window manager. There are 2 ways to do this.
  1. The "Everything but the kitchen sink" approach. This installs the GUI and many more packages which you may not need. To do this enter the command: sudo aptitude install ubuntu-desktop. The drawback of this approach is that it may take a good while to download the packages (about 366MB to download, using 1.9GB of space when unpacked).
  2. If you just want to install the Ubuntu Linux desktop without any extras like OpenOffice, etc, the command is sudo aptitude install --without-recommends ubuntu-desktop. In contrast, this is about 118MB to download, using 630MB of space when unpacked:

Step 13 - Once that is done, start up the Desktop GUI. Simply enter startx and voila!:


Install and configure SVN and Apache

To make your SVN server accessible via the HTTP protocol, we need to install a web server. Apache 2 is tried and tested to integrate well with svn (and trac) so we'll use that.

Step 1 - If apache is not already installed, run the command: 
$ sudo aptitude install apache2

Step 2 - With this SVN installation, we are going to create a main /svn parent directory with the repository for my project under it. That way, you can add a directory for each repository/project. This keeps everything nice and organized, and helps when backing up. First, we need to get the right packages:
$ sudo aptitude install subversion libapache2-svn

Step 3 - Next we can set the global SVN settings:
$ sudo gedit /etc/apache2/mods-enabled/dav_svn.conf &

Edit the file so that it looks like the following (comment lines removed):
<Location /svn>
  DAV svn

  SVNParentPath /svn
  
  AuthType Basic
  AuthName "Subversion Repository"
  AuthUserFile /etc/apache2/dav_svn.passwd
  AuthzSVNAccessFile /etc/apache2/authz_svn.access

  Require valid-user
</Location>

Step 4 - Create our first SVN user:
$ sudo htpasswd -cm /etc/apache2/dav_svn.passwd johndoe

Next, enter and confirm your password:
$ New password: <your pass>
$ Re-type new password: <same again>

Note, when adding subsequent users, the command is slightly different:
$ sudo htpasswd -m /etc/apache2/dav_svn.passwd jimdoe

As you may have noticed, we removed the "c" from the flag - because we aren't creating the password file this time around. Note, when the passwords are saved in the file - dav_svn.passwd, they are hashed for security.

Step 5 - Now we can set up the authorization for our new user. This basically controls which repositories he has access to and what he can do in them (read, write, etc). We do this by creating the file authz_svn.access:
$ sudo gedit /etc/apache2/authz_svn.access &

Let's allow our first user access to a repository (one which is not created yet ;)). Add this to authz _svn.access and save it. Note the commented lines, which are not needed, but show how you can setup group access levels.

#[groups]
#developers = dev1, dev2



[project1:/]
#@developers = rw
johndoe = rw

Adding more SVN users and changing permissions is self-explanotory.

Step 6 - Restart Apache:
$ sudo apache2ctl restart


At this stage you get an error message that reads similar to: "apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1 for ServerName",

This is easy to fix - 
1. Edit your apache conf.d file:
$ sudo gedit /etc/apache2/conf.d/fqdn
2. Add the line ServerName localhost.
3. You should now be able to restart apache.

Step 7 - Create the /svn parent directory and initial project dir, then assign permissions to give apache permission to access the repository:
$ sudo mkdir /svn
$ sudo svnadmin create /svn/project1
$ sudo chmod -R 777 /svn
$ sudo chown -R www-data:www-data /svn

You should now be able to browse your empty repository:


Step 8 - Run an svn import to create the initial structure for the repository:
$ sudo mkdir /tmp/svninit
sudo mkdir /tmp/svninit/branches
sudo mkdir /tmp/svninit/trunks
sudo mkdir /tmp/svninit/tags
$sudo svn import /tmp/svninit http://localhost/svn/project1 -m "initial import" --username johndoe

When you browse the repo now, it will be at revision 1, with the new directory structure.

Install and configure trac

As a prerequisite you will need to install python before installing trac:
$ sudo aptitude install libapache2-mod-python libapache2-svn python-setuptools python-subversion

Trac will install with sudo apt-get install trac command, but I would recommend that you get the latest stable build off the edgewall trac website as the Ubuntu repositories may not be up to date. At the time of writing, that is version 0.12:

$ sudo easy_install http://ftp.edgewall.com/pub/trac/Trac-0.12.tar.gz


Now let's create a directory for the trac database to live, and setup access for apache:
$ sudo mkdir /var/lib/trac
$ sudo chown -R www-data:www-data /var/lib/trac
$ sudo ln -s /var/lib/trac /trac

Now we must create a new site for apache:
$ sudo gedit /etc/apache2/sites-available/trac

Add the following markup to the file and save:
<Location /trac>
SetHandler mod_python
PythonInterpreter main_interpreter
PythonHandler trac.web.modpython_frontend
PythonOption TracEnvParentDir /var/lib/trac
PythonOption TracUriRoot /trac
</Location>

<LocationMatch "/trac/[^/]+/login">
AuthType Basic
Authname "Trac"
AuthUserFile /etc/apache2/dav_svn.passwd
Require valid-user
</LocationMatch>

Next, enable the trac site and reload apache:
$ sudo a2ensite trac
$ sudo /etc/init.d/apache2 reload

Next, add this markup to trac.ini:
$ sudo gedit /etc/trac.ini
[header_logo]
alt = Project1logo
height = -1
link =
src = /logo.gif
width = -1


Finally, initialize the trac environment for your project (this is where trac keeps the database for wiki pages, tickets, reports, and so on):
$ sudo trac-admin /trac/project1 initenv

This will ask you for some details about your project. Anything you are unsure of, just hit enter to use defaults.

Since version 0.12, trac-admin doesn't ask you for the source code repository details - you have to set this up manually now, but it's easy enough. Just edit your trac.ini file:
$ sudo gedit /etc/trac.ini
[repositories]
project1.dir = /svn/project1
project1.description = My first svn repository.
project1.type = svn
project1.url = http://example.com/svn/project1

Alternatively, add repositories through the trac's Administration page. (See below.) Whatever way you add a repository to trac, you will need to manually synchronize the cache for that repository with trac once. To do this you can run the command:
$ sudo trac-admin /trac/project1 repository resync "project1"

(In the next section we will add post-commit hooks to allow trac to sync with SVN after every commit, so that it always shows the latest revision; but let's finish off the trac setup first.)

Next, we need to reset the ownership of the trac environment to the www-data user so that the trac database is accessible:
$ sudo chown -R www-data:www-data /var/lib/trac
$ sudo apache2ctl restart

You should now see the head revision when you browse http://localhost/trac/project1.

Finally, we need to setup trac permissions and authentication. You can do this through the trac-admin shell command, but startingwith trac 0.11 there is a tab withing the trac site where you can perform administration operations. To see this tab, users need to have the TRAC_ADMIN permission:

$ sudo trac-admin /trac/project1 permission add johndoe TRAC_ADMIN

Now, when you log in to trac, you will see the Admin tab:

If you click on Permission at the left, you can add/remove permissions from user. I recommend removing all but TICKET_VIEW, TIMELINE_VIEW and WIKI_VIEW from "anonymous". This means that unauthenticated users will not be able to browse source code from your SVN repository. However, the exact configuration you choose is up to you.

Trac-SVN Synchronization

Prior to 0.12, Trac synchronized its cache with the SVN repo after every commit. This approach isn't practical ever since multiple repositories were introduced as a new feature to trac. For this reason, explicit synchronization through SVN's post-commit and post-revprop-change scripts is needed. This is essentially where you can instruct SVN to run a program after a commit of a changeset, or after the revision properties change. In this case, the program we will run is trac-admin.

Go to /svn/project1/hooks. Here you will see the 2 files: post-commit.tmpl and post-revprop-change.tmpl.


Add the following lines to post-commit.tmpl:
REPOS="$1"
REV="$2"
TRAC-ENV="/trac/project1"
/usr/bin/trac-admin "$TRAC-ENV" changeset added "$REPOS" "$REV"

Add the following lines to post-revprop-change.tmpl:
REPOS="$1"
REV="$2"
TRAC-ENV="/trac/project1"
/usr/bin/trac-admin "$TRAC-ENV" changeset modified "$REPOS" "$REV"

You may need to alter execute permissions/ownership on trac-admin and/or edit your /etc/sudoers file to not require a password to execute trac-admin. Eg:
username    ALL= NOPASSWD: /path/to/the/executable


Using trac and SVN
I'm going to assume you're in Windows for development, since there are just too many OS possibilities to cover. The best SVN client  I have used in Windows is TortoiseSVN. Get this from http://tortoisesvn.net/downloads.

Once this is installed, you're going to want to create folders for each repository. Each of these is known as a "working copy". It's where you edit your code before commiting it to the repository. If you are working in a team, you will usually want to do you development in a branch before merging it into the trunk. You will become very familiar with this terminology as you use your SVN system.

Right-click on your working copy, select Tortoise SVN -> Checkout.... Then enter the full path of your SVN repository on your server. Checkout into your working copy and you're ready to go. You don't have to checkout the whole repository; in fact if you are checking out from a large existing SVN repo, you will most likely just check out the branch you are developing in.


I've just added a simple file to my working copy and committed it to the repository to prove that the hooks work:

That's pretty much the basics. If I missed anything, or you want anymore info, let me know by commenting.
Cheers!

2 comments:

Anonymous said...

splendid write-up, thank you

jmurax said...

wonderful writeup