Thursday, January 03, 2008
Subversion repository creation cheatsheet
Whenever I setup new SVN repositories, I always create a unix group for people who need read/write access to the repository. If the repository is named "tgh-public", then I choose to name the group as "svn-tgh-public".

I also generally designate a single user as the initial owner of the SVN repository folder under /var/svn. Alternately, you could just leave the repository owned by root.

# cd /var/svn
(your repositories may be stored elsewhere)
# /usr/sbin/groupadd svn-repositoryname
# svnadmin create /var/svn/repositoryname
# chmod -R 770 repositoryname
# chmod -R g+s repositoryname/db
# chown -R username:svn-repositoryname repositoryname
# /usr/sbin/usermod -a -G svn-repositoryname username

Notes:

  • You'll want to repeat the "usermod" command for each person who will have access to the new repository.
  • The chmod value of 770 means that anyone who is either the "username" or who belongs to the "svn-repositoryname" group will be able to access this repository via SVN+SSH and make changes.
  • If you want to allow public reads, then you should use a chmod value of 774 which allows everyone read access to the folders.
  • Forgetting to set the sticky bit for the group will result in a repository that breaks as different users edit the contents. If you dig through the contents of the FSFS directories, you'll see that files were created with ownership username:username instead of belonging to the group who is responsible for that repository.

Labels:

Wednesday, July 04, 2007
Setting up svn+ssh on an alternate point for TortoiseSVN
This builds off a post to the TortoiseSVN user list: Specifying custom port for svn+ssh: a workaround

  1. Right-click on the Pageant icon in the system tray (I'm assuming that you're loading the SSH public key that you use for SVN into Pageant).
  2. Choose "New Session"
  3. Enter the hostname / IP address and SSH port that you'll be connecting to. If you're going to connect as "svn+ssh://thomas@svn.tgharold.com:2222", then this would be "svn.tgharold.com" and "2222".
  4. Go back to the "Session" tab and name the session as "svn.tgharold.com:2222".

Now you will be able to use both TortoiseSVN and the command-line version of SVN to talk to your repository over the alternate SSH port.

Why do this?

This is useful for cases where you want to put a SVN server on a publicly accessible IP address. What you will find is that if you leave SSH running on the default port, you will be inviting attacks on your SSH server. On the other hand, if you put the SSH server on an alternate port, you'll find that it gets attacked a lot less often (1-2 orders of magnitude difference would be likely).

Since mid-Oct of last year (around 8.5 months), we've logged 90,300 attack attempts against our SSH server. Usually they come in batches of attempting to guess accounts that normally exist or by attacking a list of common usernames. Since we don't allow root login, we don't allow password authentication, we only allow public key authentication and our SSH keys are limited to running "svnserve -t", we have yet to see a break-in attempt succeed.

Labels: , ,

Thursday, May 31, 2007
FSVS for sysadmins
Notes: This entry was based on v1.1.4. The 1.1.5 and later versions of FSVS also place a few files in /etc/fsvs.

Original post follows

Okay, I'm heading back to trying FSVS again for doing system configuration management. The FSVS website has some documentation, but for the full documentation you'll want to download the source tarball and look in the "doc/" folder.

Resource links (and other useful information):

FSVS (fsvs.tigris.org) - the home page for FSVS. See also the Purpose of FSVS and Backup pages.

Subversion (software) - The SubVersion explanatory page over at Wikipedia.

SSH tricks - One of the most important documents to read if you want to setup secure SSH access to your SVN server. It specifies how to lock things down so that "/usr/bin/svnserve" is the only thing they can do with a particular public key.

Setting up Subversion in Linux

Creating Subversion Repositories

Now, here's what I do know about FSVS:

- It uses SubVersion for the backend storage. Which means that if you already have a SVN server up and running, you can use it for the FSVS storage. This also means that you could pull configuration files down onto your laptop with SVN to take a gander at the revision history of a particular file.

- FSVS doesn't pollute your directories with ".svn" folders. Instead, it keeps a central storage database elsewhere (by default this goes in /var/spool/fsvs, but you can move it). This WAA (Working copy Administrative Area) directory only contains file lists and hashes. It does not contain "pristine copies" of any files, so it will use up a lot less space then ".svn" folders.

- FSVS will keep track of file metadata (such as timestamps, chmod flags, etc. - see the FSVS website for particulars). I'm not sure whether this includes information needed by SELinux.

- You can use FSVS to push changes to machines. Not something that I'm interested in (yet), but I might use it down the road.

- And most (all?) tricks you can use in SVN repositories apply to FSVS. Such as cloning a machine from another's configuration using "svn cp" or comparing files between two machines. Or creating a branch for a new configuration.

- FSVS allows you to make "empty" commits to the repository. If nothing has changed in the system and you do a fsvs ci -m "commit message" then FSVS will create a new revision in the repository, but with no actual changes. That may come in handy in certain circumstances.

The method to my madness

My preference for system administration is to have a separate user account and SSH key for each machine that I manage. This allows me to use a no-password SSH key on the machine so that I can do svn/fsvs commands easily (or script svn/fsvs commands). Because the SSH server is locked down, and the keys are locked down with the "command=" syntax of SSH - I'm not terribly worried about keys that don't have passwords. Since SVN doesn't allow you to permanently delete files from a repository, there's a limited amount of damage that an attacker could do if they swipe the private key.

(Lastly, because the SSH private key is stored inside of /root/, it means they've cracked the server security already. We're just trying to limit the damage and keep them from being able to erase things on the central SVN server.)

Naturally, after talking about SSH keys, I'm only using the "svn+ssh" method of accessing the central repositories.

SSH Security considerations

On the SVN server, you should edit /etc/ssh/sshd_config and verify that the following are enforced in the SSH daemon configuration:

AllowTcpForwarding no
X11Forwarding no
PermitTunnel no

That eliminates most abuses that are possible, even if someone edits their ~/.ssh/authorized_key file on the SVN server.

Creating a user account on the SSH server

Make sure you have a naming scheme in place. For us, regular developers and administrators get normal looking usernames (i.e. "thomas" or "tgh" or "haroldt"). For machine accounts, we prefix the server name with "sys-" to create the username (i.e. "sys-fw1", "sys-mail1", "sys-gracie"). Which should make it easy to see if a machine has been added to groups that it shouldn't be in. Any groups that are used to control access to SVN directories are prefixed with "svn-repositoryname" such as "svn-sys-fw" (which owns the "sys-fw" repository).

A) On the client machine:

Login as root (or "su" to root).

# cd /root/
(skip the next 2 commands if the .ssh subfolder already exists)
# mkdir .ssh
# chmod .ssh 700
# cd .ssh
# /usr/bin/ssh-keygen -N '' -C 'svn key for root@hostname' -t rsa -b 2048 -f root@hostname
# cp /root/.ssh/root@svn /root/.ssh/id_rsa
# cat root@hostname.pub
(copy this into the clipboard or send it to the SVN server or the SVN server administrator)

B) On the SVN server

Note: You should use some sort of random password creator (or the output of /dev/random or /dev/urandom) to create a long password that can be copied and pasted into the password prompt. Since we're using SSH keys, the account doesn't need a password that anyone knows.

(I know there's a better way to do make an account with an unguessable password, yet still allow SSH access via pub keys, but I can't find it at the moment.)

# useradd -m username
(i.e. "useradd -m sys-fw1-pri")
# passwd username
(paste in a super-long randomized password, such as a few bytes from /dev/urandom shoved through md5sum)
# cd /home/username
# su username
$ mkdir .ssh
$ chmod 700 .ssh
$ cd .ssh
$ cat > root@hostname.pub
(paste in the public key file from the client system)
$ cat root@hostname.pub >> authorized_keys
$ chmod 600 *

Now to lock the key down, edit the ~/.ssh/authorized_keys file and put the following on the front of the key line that will be used by the client machine:

command="/usr/bin/svnserve -t -r /var/svn",no-agent-forwarding,no-pty

This forces the connection to run the "svnserve" command in tunnel mode. So this SSH key cannot be used to login or run any other commands on the server. It also changes the SVN root path to /var/svn. You will want to also add "no-port-forwarding" and "no-X11-forwarding" if you have not disabled those in your /etc/ssh/sshd_config file.

We now have a user account that can be used with SVN. Go ahead and [Ctrl-D] to escape the "su username" session and get back into the root account.

Setting up the repository (on the SVN server)

Reasons to use a common repository for all similar machines:
- Ability to do a svn diff between two different machines
- Ability to clone machines ("svn cp")
- Backup scripts are less complex (fewer repositories)
- You can "svn diff" between machines

Reasons to use individual repositories
- Easy to secure using chmod/chown
- Easy to get report sizes on how much space a machine is using on the repository server
- Easy to dump/load an individual machine's repository
- Easy to take a machine offline and remove the repository to save space
- A machine's SSH key can only be used to look at their repository (unless you configure per-directory authentication in SVN)

Note: I'm using "username", "hostname" and "machinename" fairly interchangeably on this page. (Someday I'll go back and clean it up.)

On the SVN server:

# cd /var/svn
(your repositories may be stored elsewhere)
# svnadmin create /var/svn/sys-machinename
# chmod -R 770 sys-machinename
# chmod -R g+s sys-machinename/db
# chown -R sys-machinename:sys-machinename sys-machinename

Notes:
- A chmod of "770" allows read/write access to everyone in the same group.
- A chmod of "700" only allows read/write to the owner account.
- The third octet should probably always be "0" to prevent the repository from being world-readable.

Verifying the connection (on the client)

You will need to customize the following URL to point at your SVN repository location.

# svn info svn+ssh://sys-machinename@svn.intra.example.com/sys-machinename/

That should prompt you to accept the server's public key, then display a response fron the SVN server. If things don't work, then you've got connectivity (firewall), account (wrong name? wrong key?) or permissions (chmod or chown goofs?).

Installing FSVS (on the client)

Notes:

In order for the install to succeed, you must have installed the "subversion", "subversion-devel" "apr", "apr-devel", "gcc" and "ctags" packages. Two others that you need are "gdbm" and "pcre" (and the associated developer packages). There may be other dependencies that will also be installed that are required by those packages. The following command worked for me on CentOS5:

# yum install subversion subversion-devel ctags apr apr-devel gcc gdbm gdbm-devel pcre pcre-devel

Head on over to the official project page at freshmeat.net and download the tarball. This is currently "fsvs-1.14.tar.gz". Extract the tarball to a folder somewhere (i.e. /root/fsvs-1.14.tar.gz) and use a terminal session to go to that folder.

# cat README
(look for the section that talks about the install)
# cd src
# make
(you will receive a message that the Makefile has now been updated and that you need to run make again)
# make
(you should see a large stream of gcc output with the following at the end)
-rwxr-xr-x 1 root root 201510 May 31 09:54 fsvs
(you must see the above line to know that you got a good compile)
# cp fsvs /usr/local/bin

At this point, FSVS *should* be installed correctly.

Getting started with FSVS

By default, FSVS will want to use /var/spool/fsvs unless you define the "WAA" variable and point it somewhere else. So according to the README you will need to create that folder and then initialize it (which lets FSVS create the administrative files it needs).

Note #1: I'm not sure how large /var/spool/fsvs will get. You may eventually want to break it off into a separate LVM volume of its own. Since it is mostly file lists and hashes, it shouldn't get too large, but you may want to put it on an ext3 volume with more inodes then normal.

Note #2: You should read both the README and the output of "fsvs help urls".

# mkdir -p /var/spool/fsvs
# chmod 700 /var/spool/fsvs
# cd /
# fsvs urls svn+ssh://username@machine/path/to/repos
(The "fsvs urls" won't display any confirmation text.)

The above will connect the root folder to the repository path. You could also do multiple URLs and only link sub-folders (such as /etc, /usr, /home) up against the SVN repository.

Setting up ignore filters

After telling FSVS that we want to use "/" as our working copy, we'll want to also tell it to ignore various directories and files. While this tends to be somewhat similar across Linux distributions, you should also plan on modifying this list to match your distribution.

Make sure you read "fsvs-*/doc/IGNORING" and the output of "# fsvs help ignore".

# fsvs ignore ./backup
# fsvs ignore ./dev
# fsvs ignore ./mnt
# fsvs ignore './proc/*'
# fsvs ignore ./sys
# fsvs ignore ./tmp
# fsvs ignore ./var/tmp
# fsvs ignore ./var/spool

In addition you may wish to initially ignore all of the binary file directories (such as ./lib, ./lib64, ./sbin, ./usr, ./var) and focus solely on /etc, /home, /boot and /root. That will give you a much slimmer listing when you "fsvs status" from the root directory.

You can use the "fsvs ignore dump" and "fsvs ignore load" commands to backup your listing, edit it, then load it back into FSVS. Note that you must be in the base directory of your working copy, otherwise "fsvs ignore dump" will return an empty listing.

# cd /
# fsvs ignore dump > ~/fsvs-ignore.txt
# vi ~/fsvs-ignore.txt
# sort ~/fsvs-ignore.txt | fsvs ignore load

My initial listing on CentOS5 is:

./backup
./dev
./lost+found
./media
./mnt
./proc/*
./selinux
./sys
./tmp
./var/named/chroot/proc
./var/spool
./var/tmp


Putting /etc under version control

Assuming that you setup FSVS where "/" (root) is the base of the working copy, we can now add the contents of /etc to SVN.

# cd /
# fsvs commit -m "Base check-in of /etc" /etc
# fsvs commit -m "Base check-in of /boot" /boot

If you want to deep-commit a single folder (such as /usr/local/sbin) without doing the intervening folders:

# cd /
# fsvs commit -m "Base check-in" /usr/local/sbin

Working with FSVS

Create a test file in /etc

# cat > /etc/testfile.txt
foo
# fsvs commit -m "Checking in a test file" /etc/testfile.txt

Now delete the test file

# rm testfile.txt
# fsvs status .
D... 4 ./etc/testfile
.mC. dir ./etc
# fsvs commit -m "Removed test file" .
Committing to svn+ssh://sys-fw1-pri@svn.example.com/sys-fw1-pri
.mC. dir ./etc
D... 4 ./etc/testfile
committed revision 7 on 2007-06-04T00:17:13.808327Z as sys-fw1-pri


That just scratches the surface, but covers the majority of day-to-day use. Unlike SVN, FSVS knows (assumes) that when a file is missing that it should implicity do a "delete" operation in the repository to make the repository match the file system.

Other useful commands to know are "fsvs unversion" and "fsvs diff".

Labels: , , ,

Friday, October 27, 2006
PuTTY and SubVersion on Windows 2003
One thing we use SubVersion for in the office is for tracking configuration changes to our Linux servers. Everything under /etc or any other file that we change by hand (or with configuration tools) gets put into SVN which tracks the changes. It's possible to do the same thing under Windows (although not everything can be tracked).

A) Install PuTTY on the Win2003 server

1. The usual defaults are fine (install to C:\Program Files\PuTTY)

2. Create a public key (RSA, 2048 bit, no passphrase) and save it somewhere on the Windows 2003 server hard drive. I'd recommend an easy-to-type location because you'll be referencing constantly in batch files.

Security implications:

- Make sure that the account on the SVN server is a limited account, maybe even with a restricted shell. Just in case the authorized_keys file restriction is ever removed by accident.

- Setting the authorized_keys file to only allow "svnserve -t" as a command will keep most attackers from gaining console access to the server. But you're relying on the security of the svnserver application to not have an buffer/overflow exploits that allow shell access.

- Our decision was that the public key on the Win2003 server did not need a passphrase. The risks are worth it in order to be able to script svn commands to shove log files across the wire to the central SVN server every hour.

3. Upload the public key to your SVN server, configure it in the authorized_keys file and restrict it to only allowing command="svnserve -t".

# su accountname
# cd /home/accountname
# mkdir .ssh
# chmod 700 .ssh
# cd .ssh
# cat > machinename@svn.pub
(paste in PuTTY key)
# ssh-keygen -i -f machinename@svn.pub >> authorized_keys
# vi authorized_keys
(add command="svnserve -t" to the front of the new key line)
# chmod 600 *

4. Fire up PuTTY and attempt to connect to your SVN server. That will cache the server's public key in PuTTY's records.

B) Install the SubVersion Win32 command-line client on the server.

1. Install SVN to the default location

2. Right-click on My Computer, Properties, Advanced, Environment Variables

3. Under System Variables, click "New":
Variable name: SVN_ASP_DOT_NET_HACK
Variable value (can be anything at all): _svn

4. Under System Variables, highlight "PATH" and click "Edit". Add ";C:\Program Files\PuTTY" to the end of the PATH statement (which assumes you installed PuTTY to that location)

5. Under User Variables, click "New":
Variable name: SVN_SSH
plink -ssh -l user -pw password
- "user" should be your username on the SVN server
- the "-pw password" is optional if you did not put a passphrase on your key

C) Add the base set of directories to the server.

1. Check connectivity to the SVN server

C:\ svn list svn+ssh://user@svn.example.com/var/svn/repos

(if that doesn't work, go back and verify SSH connectivity)

2. Create a "C" folder in the root of the repository to represent your "C" drive. I usually do it on another system in a temporary folder.

3. Do the default checkout to the root of C: and D:

C:\ svn co svn+ssh://user@svn.example.com/var/svn/repos/C .
D:\ svn co svn+ssh://user@svn.example.com/var/svn/repos/D .
(note the "." at the end of the command)

4. Start adding folders and files to the SVN repository.

C:\ svn add -N Data
C:\ svn add -N Data\Logs
C:\ svn ci -m "log folder"

Labels: , , ,

Wednesday, June 14, 2006
SubVersion for Linux Administrators
Updated: 26 Aug 2006

I *think* I have this figured out. After banging my head against the wall for a few months, I finally figured out how to put my /etc configuration folder (and config files) into SubVersion so that I have version control over them.

Assumptions:

  1. You need to have SubVersion 1.2 or 1.3 (or later) installed
  2. You have a folder called /var/svn where you keep your repositories
  3. I'm assuming that you've su'd to the root account
  4. Make sure you have a clean system (run etc-update first)

I think that's the only requirements.

Step #1 - Create the repository

The name of the repository can be anything you want. I tend to name it after the machine name (but you could use the name "system", "config", "admin" or anything else). In this particular case, I'm setting it up on a machine called "nogitsune" which is my Gentoo AMD64 system.

Creating the repository is easy:

# svnadmin create /var/svn/nogitsune

Replace "nogitsune" with the preferred name of your repository. I'd suggest keeping the name as short as possible in case you have to type it by hand later (i.e. "nogitsune", "copper", "alpha", "san1pri", "xen-athens").

Step #2 - Checkout the repository to the root folder

nogitsune etc # cd /
nogitsune / # svn co file:///var/svn/nogitsune .
Checked out revision 0.
nogitsune / # svn status
? media
? lib64
? tgh
? root
? home
? var
? lost+found
? software
? sbin
? mnt
? tmp
? opt
? boot
? proc
? backup
? lib
? bin
? usr
? lib32
? etc
? dev
? sys
nogitsune / #


As long as the "svn status" command returns something like the above, we know that we've connected properly to the SubVersion repository. You can also look for the ".svn" directory in the root.

nogitsune / # ls -la .svn
total 40
drwxr-xr-x 7 root root 4096 Jun 14 21:28 .
drwxr-xr-x 24 root root 4096 Jun 14 21:28 ..
-r--r--r-- 1 root root 118 Jun 14 21:28 README.txt
-r--r--r-- 1 root root 0 Jun 14 21:28 empty-file
-r--r--r-- 1 root root 283 Jun 14 21:28 entries
-r--r--r-- 1 root root 2 Jun 14 21:28 format
drwxr-xr-x 2 root root 4096 Jun 14 21:28 prop-base
drwxr-xr-x 2 root root 4096 Jun 14 21:28 props
drwxr-xr-x 2 root root 4096 Jun 14 21:28 text-base
drwxr-xr-x 6 root root 4096 Jun 14 21:28 tmp
drwxr-xr-x 2 root root 4096 Jun 14 21:28 wcprops
nogitsune / # cat .svn/entries

xmlns="svn:">
committed-rev="0"
name=""
committed-date="2006-06-15T01:26:51.238552Z"
url="file:///var/svn/nogitsune"
kind="dir"
uuid="21f0cb31-3916-0410-ae38-e44852334012"
revision="0"/>

nogitsune / #


Step #3 - Adding directories and files to SubVersion

It's important to understand a little bit how "svn add" and "svn commit" work hand-in-hand. Just because we've issued the "svn add" command does not mean that our changes have been pushed to the repository. That requires using the "svn commit" command.

For the first example, I'm going to push the contents of /boot into the Subversion repository.

nogitsune / # mount /boot
nogitsune / # ls -la /boot
total 41261
drwxr-xr-x 4 root root 2048 Nov 29 2005 .
drwxr-xr-x 24 root root 4096 Jun 14 21:28 ..
-rw-r--r-- 1 root root 0 Jul 27 2005 .keep
-rw-r--r-- 1 root root 917680 Nov 12 2005 System.map-2.6.13-12Nov2005
-rw-r--r-- 1 root root 910027 Nov 12 2005 System.map-2.6.13-12Nov2005-2300
-rw-r--r-- 1 root root 910027 Nov 12 2005 System.map-2.6.13-12Nov2005-2330
-rw-r--r-- 1 root root 898088 Nov 12 2005 System.map-2.6.13-13Nov2005
-rw-r--r-- 1 root root 898098 Nov 13 2005 System.map-2.6.13-13Nov2005-1700
-rw-r--r-- 1 root root 917799 Nov 13 2005 System.map-2.6.13-13Nov2005-1810
-rw-r--r-- 1 root root 917372 Nov 13 2005 System.map-2.6.13-13Nov2005-1948
-rw-r--r-- 1 root root 837348 Nov 14 2005 System.map-2.6.13-14Nov2005-1500
-rw-r--r-- 1 root root 918716 Nov 14 2005 System.map-2.6.13-14Nov2005-1600
-rw-r--r-- 1 root root 846033 Nov 21 2005 System.map-2.6.13-21Nov2005-2300
-rw-r--r-- 1 root root 888601 Nov 22 2005 System.map-2.6.13-22Nov2005-0030
-rw-r--r-- 1 root root 890145 Nov 29 2005 System.map-2.6.13-29Nov2005-2148
-rw-r--r-- 1 root root 916779 Nov 8 2005 System.map-2.6.13-8Nov2005
-rw-r--r-- 1 root root 919480 Nov 9 2005 System.map-2.6.13-9Nov2005
lrwxrwxrwx 1 root root 1 Nov 8 2005 boot -> .
-rw-r--r-- 1 root root 23975 Nov 12 2005 config-2.6.13-12Nov2005
-rw-r--r-- 1 root root 23749 Nov 12 2005 config-2.6.13-12Nov2005-2300
-rw-r--r-- 1 root root 23738 Nov 12 2005 config-2.6.13-12Nov2005-2330
-rw-r--r-- 1 root root 23782 Nov 12 2005 config-2.6.13-13Nov2005
-rw-r--r-- 1 root root 23197 Nov 13 2005 config-2.6.13-13Nov2005-1700
-rw-r--r-- 1 root root 24091 Nov 13 2005 config-2.6.13-13Nov2005-1810
-rw-r--r-- 1 root root 24106 Nov 13 2005 config-2.6.13-13Nov2005-1948
-rw-r--r-- 1 root root 22579 Nov 14 2005 config-2.6.13-14Nov2005-1500
-rw-r--r-- 1 root root 23986 Nov 14 2005 config-2.6.13-14Nov2005-1600
-rw-r--r-- 1 root root 23084 Nov 21 2005 config-2.6.13-21Nov2005-2300
-rw-r--r-- 1 root root 23427 Nov 22 2005 config-2.6.13-22Nov2005-0030
-rw-r--r-- 1 root root 23416 Nov 29 2005 config-2.6.13-29Nov2005-2148
-rw-r--r-- 1 root root 23986 Nov 8 2005 config-2.6.13-8Nov2005
-rw-r--r-- 1 root root 23964 Nov 9 2005 config-2.6.13-9Nov2005
drwxr-xr-x 2 root root 1024 Nov 9 2005 grub
-rw-r--r-- 1 root root 2139460 Nov 12 2005 kernel-2.6.13-12Nov2005
-rw-r--r-- 1 root root 2081829 Nov 12 2005 kernel-2.6.13-12Nov2005-2300
-rw-r--r-- 1 root root 2081802 Nov 12 2005 kernel-2.6.13-12Nov2005-2330
-rw-r--r-- 1 root root 2056584 Nov 12 2005 kernel-2.6.13-13Nov2005
-rw-r--r-- 1 root root 2064792 Nov 13 2005 kernel-2.6.13-13Nov2005-1700
-rw-r--r-- 1 root root 2105823 Nov 13 2005 kernel-2.6.13-13Nov2005-1810
-rw-r--r-- 1 root root 2099454 Nov 13 2005 kernel-2.6.13-13Nov2005-1948
-rw-r--r-- 1 root root 1958868 Nov 14 2005 kernel-2.6.13-14Nov2005-1500
-rw-r--r-- 1 root root 2142469 Nov 14 2005 kernel-2.6.13-14Nov2005-1600
-rw-r--r-- 1 root root 2008155 Nov 21 2005 kernel-2.6.13-21Nov2005-2300
-rw-r--r-- 1 root root 2017013 Nov 22 2005 kernel-2.6.13-22Nov2005-0030
-rw-r--r-- 1 root root 2024425 Nov 29 2005 kernel-2.6.13-29Nov2005-2148
-rw-r--r-- 1 root root 2139807 Nov 8 2005 kernel-2.6.13-8Nov2005
-rw-r--r-- 1 root root 2151371 Nov 9 2005 kernel-2.6.13-9Nov2005
drwx------ 2 root root 12288 Nov 8 2005 lost+found
nogitsune / # svn add -N boot
A boot
nogitsune / # cd boot
nogitsune boot # ls -la .svn
total 11
drwxr-xr-x 7 root root 1024 Jun 14 21:33 .
drwxr-xr-x 5 root root 2048 Jun 14 21:33 ..
-r--r--r-- 1 root root 118 Jun 14 21:33 README.txt
-r--r--r-- 1 root root 0 Jun 14 21:33 empty-file
-r--r--r-- 1 root root 190 Jun 14 21:33 entries
-r--r--r-- 1 root root 2 Jun 14 21:33 format
drwxr-xr-x 2 root root 1024 Jun 14 21:33 prop-base
drwxr-xr-x 2 root root 1024 Jun 14 21:33 props
drwxr-xr-x 2 root root 1024 Jun 14 21:33 text-base
drwxr-xr-x 6 root root 1024 Jun 14 21:33 tmp
drwxr-xr-x 2 root root 1024 Jun 14 21:33 wcprops
nogitsune boot # svn add .keep System* config* kernel* grub boot
A .keep
A System.map-2.6.17-25Aug2006-2300
A config-2.6.17-25Aug2006-2300
A (bin) kernel-2.6.17-25Aug2006-2300
A grub
A grub/menu.lst
A (bin) grub/splash.xpm.gz
A grub/grub.conf.sample
A (bin) grub/e2fs_stage1_5
A (bin) grub/fat_stage1_5
A (bin) grub/ffs_stage1_5
A (bin) grub/iso9660_stage1_5
A (bin) grub/jfs_stage1_5
A (bin) grub/minix_stage1_5
A (bin) grub/reiserfs_stage1_5
A (bin) grub/stage1
A (bin) grub/stage2
A (bin) grub/stage2_eltorito
A (bin) grub/ufs2_stage1_5
A (bin) grub/vstafs_stage1_5
A (bin) grub/xfs_stage1_5
A grub/grub.conf
A boot
nogitsune boot # svn status
? boot
? lost+found
A .
A grub
A grub/grub.conf
A grub/stage1
A grub/stage2
A grub/e2fs_stage1_5
A grub/xfs_stage1_5
A grub/vstafs_stage1_5
A grub/fat_stage1_5
A grub/grub.conf.sample
A grub/menu.lst
A grub/ffs_stage1_5
A grub/stage2_eltorito
A grub/iso9660_stage1_5
A grub/ufs2_stage1_5
A grub/jfs_stage1_5
A grub/reiserfs_stage1_5
A grub/minix_stage1_5
A grub/splash.xpm.gz
A .keep
A System.map-2.6.17-25Aug2006-2300
A kernel-2.6.17-25Aug2006-2300
A config-2.6.17-25Aug2006-2300
nogitsune boot # cd /
nogitsune / # svn commit -m "Initial snapshot of /boot"
Adding boot
Adding boot/.keep
Adding boot/System.map-2.6.17-25Aug2006-2300
Adding boot/boot
Adding boot/config-2.6.17-25Aug2006-2300
Adding boot/grub
Adding (bin) boot/grub/e2fs_stage1_5
Adding (bin) boot/grub/fat_stage1_5
Adding (bin) boot/grub/ffs_stage1_5
Adding boot/grub/grub.conf
Adding boot/grub/grub.conf.sample
Adding (bin) boot/grub/iso9660_stage1_5
Adding (bin) boot/grub/jfs_stage1_5
Adding boot/grub/menu.lst
Adding (bin) boot/grub/minix_stage1_5
Adding (bin) boot/grub/reiserfs_stage1_5
Adding (bin) boot/grub/splash.xpm.gz
Adding (bin) boot/grub/stage1
Adding (bin) boot/grub/stage2
Adding (bin) boot/grub/stage2_eltorito
Adding (bin) boot/grub/ufs2_stage1_5
Adding (bin) boot/grub/vstafs_stage1_5
Adding (bin) boot/grub/xfs_stage1_5
Adding (bin) boot/kernel-2.6.17-25Aug2006-2300
Transmitting file data ......................
Committed revision 1.
nogitsune / #


Most of that should be self explanatory. You can see that I use "svn add -N boot" from the / (root) directory to add the /boot directory, then I move into the /boot folder and issue a selective "svn add". Pay attention to the "-N" option which prevents the add from recursing down through subdirectories. You should also take care to only add files that you control as an administrator to the svn repository (avoid adding things like "lost+found" or "._cfg*" files).

If you want to version control something that is 3 levels deep, you need to "svn add -N foldername" for each level in the tree until you get deep enough to add the file. It might be possible to do it faster in one command, but I'm still learning SubVersion.

For the second example, I'm going to add everything in /etc to SubVersion.

# cd /
# svn add -N etc
# cd etc
# svn add *
# svn commit -m "Initial snapshot of /etc"


That's the basics. For the third example, I'll show how to add custom scripts stored in /usr/local/sbin.

# cd /
# svn add -N usr ; cd usr
# svn add -N local ; cd local
# svn add -N sbin ; cd sbin
# svn add *
# cd /
# svn commit -m "Initial snapshot of /usr/local/sbin"


Step #4 - Creating a cron job to backup your SubVersion repositories

On my systems, I create a folder called /backup which is a separate set of spindles that I mount for quick backups. Under that folder, I create a sub-folder called "subversion".

# ls -l /backup/subversion
total 96
-rw-r--r-- 1 root root 20 Nov 30 2005 dev.svnadmin.dump.2005.11.gz
-rw-r--r-- 1 root root 20 Dec 31 02:00 dev.svnadmin.dump.2005.12.gz
-rw-r--r-- 1 root root 20 Jan 31 02:00 dev.svnadmin.dump.2006.01.gz
-rw-r--r-- 1 root root 20 Feb 28 02:00 dev.svnadmin.dump.2006.02.gz
-rw-r--r-- 1 root root 20 Mar 31 02:00 dev.svnadmin.dump.2006.03.gz
-rw-r--r-- 1 root root 20 Apr 30 02:00 dev.svnadmin.dump.2006.04.gz
-rw-r--r-- 1 root root 20 May 31 02:00 dev.svnadmin.dump.2006.05.gz
-rw-r--r-- 1 root root 20 Jun 14 02:00 dev.svnadmin.dump.2006.06.gz
-rw-r--r-- 1 root root 20 Nov 30 2005 photo.svnadmin.dump.2005.11.gz
-rw-r--r-- 1 root root 20 Dec 31 02:00 photo.svnadmin.dump.2005.12.gz
-rw-r--r-- 1 root root 20 Jan 31 02:00 photo.svnadmin.dump.2006.01.gz
-rw-r--r-- 1 root root 20 Feb 28 02:00 photo.svnadmin.dump.2006.02.gz
-rw-r--r-- 1 root root 20 Mar 31 02:00 photo.svnadmin.dump.2006.03.gz
-rw-r--r-- 1 root root 20 Apr 30 02:00 photo.svnadmin.dump.2006.04.gz
-rw-r--r-- 1 root root 20 May 31 02:00 photo.svnadmin.dump.2006.05.gz
-rw-r--r-- 1 root root 20 Jun 14 02:00 photo.svnadmin.dump.2006.06.gz
-rw-r--r-- 1 root root 20 Nov 30 2005 web.svnadmin.dump.2005.11.gz
-rw-r--r-- 1 root root 20 Dec 31 02:00 web.svnadmin.dump.2005.12.gz
-rw-r--r-- 1 root root 20 Jan 31 02:00 web.svnadmin.dump.2006.01.gz
-rw-r--r-- 1 root root 20 Feb 28 02:00 web.svnadmin.dump.2006.02.gz
-rw-r--r-- 1 root root 20 Mar 31 02:00 web.svnadmin.dump.2006.03.gz
-rw-r--r-- 1 root root 20 Apr 30 02:00 web.svnadmin.dump.2006.04.gz
-rw-r--r-- 1 root root 20 May 31 02:00 web.svnadmin.dump.2006.05.gz
-rw-r--r-- 1 root root 20 Jun 14 02:00 web.svnadmin.dump.2006.06.gz


As you can see from my backup folder, I have 3 repositories being backed up (dev, photo, web) and I rotate to a new backup filename every month. It's not ideal because a bad backup could cause me to lose up to 30 days of work, but it meets my needs. More risk-adverse admins may want to switch to a new backup file on a daily basis.

To create this backup, I use the following script:

nogitsune / # cd /usr/local/sbin
nogitsune sbin # ls -l svndaily.sh
-rwxr-xr-x 1 root root 646 Nov 27 2005 svndaily.sh
nogitsune sbin # cat svndaily.sh
#!/bin/sh
# backup subversion repositories to /backup/subversion/filename.year.month.gz
# notice the use of the backtick character (`) instead of single-quote character (')
# overwrites the backup file every day

BACKUPDATE=`date +%Y.%m`
#echo $BACKUPDATE

# svnadmin dump /var/svn/reponame | gzip -c > /backup/subversion/reponame.svnadmin.dump.${BACKUPDATE}.gz
svnadmin dump /var/svn/dev | gzip -c > /backup/subversion/dev.svnadmin.dump.${BACKUPDATE}.gz
svnadmin dump /var/svn/photo | gzip -c > /backup/subversion/photo.svnadmin.dump.${BACKUPDATE}.gz
svnadmin dump /var/svn/web | gzip -c > /backup/subversion/web.svnadmin.dump.${BACKUPDATE}.gz

nogitsune sbin #


Note: Each of the "svnadmin dump" lines should be all on one line and not split across two lines.

As far as I know, svndump is adequate to the task of backing up SubVersion repositories.

Labels:

Friday, February 11, 2005
SubVersion Links
Experiences with SubVersion (first-hand user account of using SubVersion compared to CVS)

Version Control System Comparison

Why Bitkeeper Isn't Right For Free Software

Labels:

Tuesday, May 11, 2004
SubVersion install on Gentoo
Working on setting up subversion on the box. I've already emerged in the apache and subversion ebuilds, now I'm working on some other configuration information. My plan is to store my respository in /svn, in it's own logical volume. (Very similar to when I created my "media" logical volume in the vgmedia volume group.)

# lvcreate -L4G -nsvn vguser
# mke2fs -j -c /dev/vguser/svn
# mkdir /svn
# mount /dev/vguser/svn /svn
# nano -w /etc/fstab

SubVersion book, chapter 6, section 4 covers how to configure Apache2 for SVN. One key thing that bit me is that if you already have apache2 installed, you need to also set the apache2 USE flag prior to emerging subversion.

More later... I have to wait for apache/subversion to re-emerge.

Labels: ,