Tame Your Wild Config Herds with CVS
Two of the great joys of Linux are plain-text configuration files and scripting -- combined, they are easy to read, edit, reproduce, deploy and automate. I especially like the ability to create multiple configurations for a program, such as a mail server or backup script, and easily call up different configs for testing.
Every sysadmin develops their own tips and tricks and particular ways of doing things. Scripts and configuration files change and evolve over time. The wise sysadmin keeps backup copies of everything -- you never know when you're going to want to roll back to that script you wrote a year ago. One way is to simply keep copies of everything. CVS (concurrent version system) saves considerable storage space by recording and tracking only changes, and it never forgets anything.
Not Just for Programmers
CVS is widely used to manage software development projects. It keeps a complete history of changes, and who made them. It manages the concurrent editing of files by multiple authors, and controls access. It uses a central repository, and also allows users to have their own personal repositories. It is not a build system, but a way to track and record changes.
It is quite sophisticated and complex, but don't let that scare you. We'll look at the basics of setting up and using a CVS system as a sysadmin repository for managing scripts and configuration files -- it can be very useful for saving what is left of our precious sanity.
With all the different Linux distributions and their different ways of doing things, I shall now cop out and refer you to your own documentation. There are debs, rpms, and sources, take your pick.
In these days of large hard drives, adequate space should not be an issue, just make sure to have enough. Leave room to grow, as CVS is addicting, and you'll find all kinds of uses for it.
I like to put the central repository in /var/cvs, because I keep /var in its own partition, sometimes on its own drive. My local working directory is ~/cvs. /usr/share/cvsroot is also a popular option, as well as /usr/local/cvsroot. The repository is for storage only, as users check out and edit local copies of files. If you are sharing files with others, be sure they have the correct permissions to access the repository. If other users do not need access, it's perfectly fine to create a repository in your /home directory. You still need separate locations for the central repository and the working directory. Think client-server.
The CVS root directory environment variable must be defined, in /etc/profile:
Be sure there are no spaces in the CVS root directory name, such as /cvs root. This will break everything, so use underscores instead:
Take a look in /etc/group and /etc/passwd to see if your installation script created a CVS group and user. If it didn't, do it now. Treate a CVS group:
# groupadd cvs
To create a CVS user:
# useradd -g cvs -d $CVSROOT cvs
If the CVS root directory for the repository has not been created, do it now:
# mkdir $CVSROOT
Run ls to confirm the new directory:
# ls -ld $CVSROOT
Now set group ownership and permissions:
# chgrp -R cvs $CVSROOT
# chmod o-rwx $CVSROOT
# chmod ug+rwx $CVSROOT
Finally, initialize the repository tree:
# cvs init
This also enables history logging. From here, add users as needed. Root, of course, can rampage at will, however we all know that doing things as an ordinary user, as much as possible, is wiser:
# usermod -G cvs carlaChecking Files In and Out
CVS can do a zillion and one things; the five primary commands most users rely on are checkout, update, add, remove, commit and diff. To add new files to a repository, change to the directory they are stored in. You must do this or it won't work. Make sure the directory structure is set up the way you want. The syntax is cvs import modulename vendortag releasetag:
$ cd ~/cvs/postfix_configs
$ cvs import /cvs/postfix postfix ver_1
Don't worry about vendor tags and release tags. Modules are related collections of files, usually the directory tree for a specific project (in this case a collection of Postfix configuration files). Because it is a homegrown project, rather than vendor-supplied, the vendor tags and release tags can be anything. CVS merely requires that they be present.
It is important to use the complete filepath after /home, as illustrated above. If the directory to be imported was /home/postfix_configs, then it would look like this:
$ cd ~/postfix_configs
$ cvs import postfix postfix ver_1
A logfile will open during this operation, using the editor defined in your bash profile. If none is defined, you'll get vi, as that is the default. Making useful log notes is essential, because you will forget what you do. A shortcut is to put your log entry in the command line:
$ cvs import "three versions of main.cf for different connection types" postfix postfix ver_1
Now let's check them back out. Change to the directory you want to download the files into, then check them out from the repository. This creates a postfix directory, with all the files, plus a CVS directory. Don't touch this, it is for CVS internal use only.
$ cvs checkout postfix
CVS main_cf_1 main_cf_2 main_cf_3
So we futz with main.cf_1 for a bit, making it all new and improved. When we're done, it's time to put it back in the repository:
$ cvs commit main.cf_1
A most useful option is the "dry-run" switch; cvs -n [command] lets you see what a command will do before actually doing it.
Execute this from within your local source directory to incorporate any changes made in the central repository. This is more useful when there are multiple authors on a project, for keeping everyone in sync.
Use this for adding files to an existing module, in your local source directory. They will be added to the repository the next time you run the 'cvs commit' command.
This works the same way as cvs add; remove the files from the local directory, then execute cvs commit to affect the repository. The files are moved to the CVS Attic, so they are still available, but not in the way.
Compare your local copy with the version in the repository.
cvs history -a -o
Show all the checked-out modules.
cvs history -a -e
Show all available status information
What Not to Do
The whole purpose of CVS is to track and record all changes. Don't try to be ultra lean and go on CVS housecleaning binges; leave it alone. It's supposed to keep everything forever -- which it does most efficiently.