Our source code repository is currently hosted at the offshore development site and there is no external access to it (neither through the Internet nor a VPN). While this is certainly desirable from a security standpoint, I’d really love to see what the developers are actually working on.
I asked the director there to put me on the mailing list for commits. He replied they didn’t have such a system since all the developers sat in the same room. Plus, the developers weren’t so thrilled about getting a bunch of commit mails in their inbox every day. I immediately thought what about vacation or sick leave? What about a lunch break? Are these guys really together 24/7? And how much work is it to setup a mail filter anyways?
I asked him how long it would take to set up mail notifications and he said he’d look into it. The next day, he told me that it wasn’t so straightforward to implement and what was my real reason for wanting this information anyways? Wait a minute, I thought, I’m flying completely blind here – with no clue what’s being worked on – and they’re not even willing to throw me a bone?
To resolve this I decided to create our own repository and migrate the source code from the offshore site. I’ll have complete control of the code then – able to setup permissions, branches, and email notifications. Plus, the new server will double as a continuous integration server when we’re ready for that step.
My requirements for a Subversion repository are fairly straightforward. It needs to be secure, fast and reliable. Initially, I took a look at some of the commercial providers (beanstalk, unfuddle and SVNRepository.com to name a few). But, as we are developing here in Europe, I was worried about lag times and network overhead going across the Atlantic Ocean. A self-hosting option here in Europe would not only be cheap, but, I’d eventually be able to set up my own continuous integration server.
So, I leased the cheapest possible virtual server from HostEurope for 13 EUR / month (including FTP backup). I get root access on a Debian 4 server, 256MB RAM and a 15GB harddisk partition. There’s no charge for upgrading (or downgrading) the virtual host environment so I’ll be able to upgrade with a button push when I’m ready for more RAM and horsepower. Let me show you how I set it up.
Installing Subversion
The base install instructions from subversionary.org worked right out of the box. I have a Debian 4.0 host and installed Subversion using apt-get:
sudo apt-get update
sudo apt-get install subversion subversion-tools
The subversion-tools package includes (among other things) some handy perl scripts which we’ll make use of later for our commit hooks.
Repository User Configuration
Now to create the svn user (without a login shell) who will own all the repository files, and the developers will be using the repository. We’ll add the developers directly to the svn group:
sudo useradd svn -s /bin/false
sudo useradd dan -G svn
sudo useradd mark -G svn
sudo useradd susie -G svn
Creating the Repository
I created the repository in /var/svn and assured the correct ownership:
sudo mkdir -p /var/svn
sudo svnadmin create /var/svn/repos
sudo chown -R svn.svn /var/svn
Securing the Server
We want the repository to be available only via ssh. As we’ll eventually disable password based authentication all together, let’s copy the public keys of the all users to their home directories:
scp id_dsa.dan.pub kis1.hosteurope.net:/home/dan/.ssh/authorized_keys
*nix folks won’t have a problem handing over a public key. For Windows users, point them to the standard PuTTy tools from Simon Tatham.
Now, let’s secure the sandbox for these accounts by specifying the ‘command’ option to run svnserve in each users’ authorized_keys file (as one line):
sudo vi /home/dan/.ssh/authorized_keys
command="svnserve -t -r /var/svn/repos --tunnel-user=dan", no-port-forwarding,no-agent-forwarding,no-x11-forwarding,no-pty [dans-ssh-key]
The ‘-r /var/svn/repos’ parameter not only lets us hide the full path from the users, it restricts their access to just this repository – this basically becomes their root directory. The other options ensure there’s no funny business allowed with port forwarding or other types of connection attempts.
Initial Checkout
From your local machine, you should now be able to verify the availability of your secure subversion repository:
svn co svn+ssh://dan@kis1.hosteurope.net/ local-dev
Revision 0.
svn info
URL: svn+ssh://dan@kis1.hosteurope.net
Repository Root: svn+ssh://dan@kis1.hosteurope.net
touch local-dev/test.txt
svn add local-dev/test.txt
A local-dev/test.txt
svn ci -m "initial commit"
Adding test.txt
Transmitting file data .
Committed revision 1.
Congratulations! You’ve verified read and write capabilities to your ssh secured repository. The basic install is done.
Now that you’ve also verified public key authentication works, you can further lock down your server by disabling ssh password authentication.
sudo vi /etc/sshd/ssh.conf
...
PasswordAuthentication no
**WARNING** Before you do this, ensure you’ve either created a separate admin account for yourself (including appropriate permissions in /etc/sudoers) or have placed your public key in the authorized_keys file of the root user (and that the root user is allowed to login as some systems have this disabled by default). Failing to do this will basically lock you out of your server if you’ve added the ‘command=”svnserve…’ option to your user account’s authorized_keys file!
Just restart your sshd daemon
sudo /etc/init.d/ssh restart
and you’ve made your server even more secure.
Next week, I’ll show you how to setup fine grained read-write permissions and generate email notifications per commit using built-in subversion hook scripts. Subscribe here so you won’t miss it!
Hi Dan,
Great article, and I’m looking forward to the second part of it! Thanks!
LikeLike
Hi Ricardo,
glad you liked it…was fun to research and write about it. Second part was even cooler ;).
Wishing you a Happy New Year!
LikeLike
Hi Dan,
Thanks, and I wish you also a great 2009!
Greetings,
Ricardo
LikeLike
Dear Dan,
great to see – took me a while to finish svn server – unfortunatly I did not found your page first.
A small article about svn hooks could be helpful – I am lost in there.
best regards,
eric
LikeLike
Hi Eric,
you’re absolutely right – I failed to backlink the subsequent article on svn hooks. I hope this helps you!
LikeLike
Hi All,
I want to deploy this simple ruby on rails application using capistrano, from local machine to unfuddle.com account. and I have account on unfuddle.. http://feeder.unfuddle.com/svn/feeder_fd
I have a local SVN Repository on my root path
/root/svn/#{application name},
This is my config/deploy.rb file..
set :application, “feeder2”
set :repository, “file:///root/svn/feeder2” #here i dont know wht to put ???????????????????????? Do i need to put here this http://feeder.unfuddle.com/svn/feeder_fd or my local SVN repo ???????????
set :scm, :subversion
# Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none`
role :web, “127.0.0.1:3000” # Your HTTP server, Apache/etc
role :app, “127.0.0.1:3000” # This may be the same as your `Web` server
role :db, “127.0.0.1:3000”, :primary => true # This is where Rails migrations will run
role :db, “127.0.0.1:3000”
set :deploy_via, :remote_cache
set :server_name, “http://feeder.unfuddle.com”
# If you are using Passenger mod_rails uncomment this:
# if you’re still using the script/reapear helper you will need
# these http://github.com/rails/irs_process_scripts
# namespace :deploy do
# task :start {}
# task :stop {}
# task :restart, :roles => :app, :except => { :no_release => true } do
# run “#{try_sudo} touch #{File.join(current_path,’tmp’,’restart.txt’)}”
# end
# end
How do I get this running ? I want to do it ASAP, Can u please help me,
and ya wht is the meaning of this statement ??
svn co svn+ssh://dan@kis1.hosteurope.net/ local-dev
let me correct if i m wrong ?
1) dan is username,,but which username? username of repo account of unfudlle ???
2) kis1.hosteurope.net is subdomain like mine is feeder.unfuddle.com ???
and after doing this ? How to deploy an application using cap deploy:setup, :check or anything else ????
Awating for Reply
Naresh
LikeLike
woah, Naresh, wait a minute. You’re mixing up everything here. Let me try to sort it out for you:
First of all, you cannot deploy your app to unfuddle.com. Unfuddle.com is your SVN repository – the place where your code lives. AFAIK, they do not provide any hosting space for deploying your applications. Your deploy.rb shows that you want to deploy to localhost. That sounds ok. When you use unfuddle.com as your SVN repository, you do not need a local one. You let capistrano check out your app from the unfuddle repo to your local server.
That said, you should set your unfuddle SVN repo in your deploy.rb file as the :repository.
When defining roles, you must not use any port numbers (:3000 in your case).
The :server_name is the name of the host you want to deploy your application to – in your case: localhost.
And last but not least, you do not have to care too much about that svn co statement as capistrano will do the checkout from unfuddle to your localhost for you.
Hope this helps to get you back on track.
LikeLike
Hi Dan,
I am having trouble with…
sudo vi /home/dan/.ssh/authorized_keys
command=”svnserve -t -r /var/svn/repos –tunnel-user=dan”,
no-port-forwarding,no-agent-forwarding,no-x11-forwarding,no-pty
[dans-ssh-key]
Can you explain a little about what is going on here, as when I run this vi seems to be trying to open 5 files. Also what is supposed to be in the place of [dans-ssh-key] is it the key iteself?
Any help would be appreciated.
Gary
LikeLike
The idea here is twofold. First, we will only allow the user access to the system with public/private key exchange. Second, by editing the user’s authorized_keys file ( i.e. /home/dan/.ssh/authorized_keys ), we drastically limit the commands they are able to execute on the remote server. In the example I gave above, exactly one: ‘svnserve’.
/var/svn/repos was the directory where my svn server repository lived. The no forwarding params effectively shutdown the possibility for any monkey business on this server for the user. Their only interaction will be with subversion. And yes, [dans-ssh-key] is the user’s public key, to be entered with a space delimiter after the ‘no-pty’ param in my example above.
I’ve updated the format of the post to hopefully better communicate my idea, so take another look at that sample code.
LikeLike
Thanks Dan,
That is all clear now. And thanks on behalf of everyone who may have been confused for editing the post.
Gary
LikeLike
Hi Dan,
Nice to see this. Any tips or pointers or links for me to secure the SVN Sever hosted on Ubuntu (or any specific version of Linux) with LDAP Authentication ?
Thanks
VC
LikeLike