Using Subversion to version control /etc
I use svn to version control my /etc directory and I should say it has proven to be very useful and mostly practical.
Why
The why is simple to answer. Almost all of us have either
- Accidentally messed up our config file(s) and suffered hours of rework
- Or have created a plethora of config.bak, config.orig, etc files and have no idea if/when to clean them up
- Worse of all, remember using a certain configuration in the past, but can't quite get it to work again
If any of these resembles your thoughts/actions then you will benefit from version controlling your config files.
How
Note: Before you start typing in the commands scroll down for either the command list or for a script!
Create the SVN repository. One usual location is /var, but this can be anywhere
# cd /var
Create a top level directory to hold all repositories
# mkdir svn-repos
Change directory
# cd svn-repos
Create a repository (which creates a directory) to hold /etc's repository
# svnadmin create svn-etc
Make it root access only
# chmod 700 svn-etc
Let's go and add the files in /etc to version control
# cd /etc
Now /etc is not an empty directory and already has the files we want to version control. However SVN is very friendly and will not complain making a current directory with files as the SVN working directory.
So let's checkout the empty repository to establish /etc as the working directory for the repository.
# svn checkout file:///var/svn-repos/svn-etc /etc
Let's check the status of our new working directory. It should list all the files inside /etc as unknown status (?)
# svn status
Now we need to check in the files and put them on version control. The command below should generate the “svn add” commands to check them all in
# ls -l|awk '{print “svn add ” $8}'
Execute the output of command above
Or just run the single command:
# svn status | grep -v “ \.” | grep “^\?” | awk '{print $2}' | xargs svn add
The grep -v command is used to eliminate files starting with . such as .pwd.lock
Or even better:
svn add * --force
However, I believe this might check files starting with dot (such as .pwd.lock). If that happens remove these before commit. This can be done with the
# svn revert <path/to/file>
Let's commit the checked in files
# svn commit -m “Initial Version”
All steps together
cd /var mkdir svn-repos cd svn-repos svnadmin create svn-etc chmod 700 svn-etc cd /etc svn checkout file:///var/svn-repos/svn-etc /etc #svn status svn add * --force #svn revert <path/to/file> svn commit -m "Initial Version"
Other considerations
There are a number of other considerations to think about when doing VC for /etc (and elsewhere). If not this will become of those things that was a great idea to start off and then has no meaning.
/etc is not just all config
Although /etc is for saving configurations files, it is NOT purely a settings only directory. It does have other transient files. It is best to either not include them in the VC or not restore the checked in version. Commits are ok, but they will add space with no real value. Having said that, it might give you some history on these files that will help with knowledge about these files.
Moving/Deleting files in /etc
If ever you decide to MOVE files, remember to use the svn command and not the Linux/UNIX mv. Do an “svn move <source> <target>”. If not you will end up just copying rather than moving. If that happens, you will have to just do an SVN delete of the original file. The same goes for delete. Just do an SVN delete rather than a regular rm.
Piece meal commits
Another advantage of SVN is that you can commit individual directories or sub-directories. So if you are working on changing multiple config files you can commit just the ones that you want to version control at the moment. It also helps with keeping each revision number linked only to one set of configuration changes.
Other advantages
There are more advantages to just “saving” your files against accidental modifications. VC also gives you the advantage of identifying what is getting changed outside of your preview. Outside of MY preview? Yes, every time you install something (usually with apt-get) a lot of things can happen and you may not be aware of all of them. When I installed john (the ripper) the other day I realized that it has also added (a niced) cron job to regularly (as in daily!) check for passwords to crack. Now while this is great, not so for a system where I don't have anyone except me! So I instantly commented out the cron. You might want to make it monthly or yearly depending on your case. So there you go, I could VC /etc just for this reason alone. So periodically do a
# svn status
to see what is uncommited out there
Commit regularly
It's easy to “forget” that /etc is in version control and have a ton of uncommitted configuration. This is actually a pain point if you do not pay attention to this often. You might end up modifying files that have not been committed and permanently loose changes. Or you might have such a long list that you might commit them all together and not really document the changes (which might come in handy days/weeks/months/years from now)
One way to keep reminded is to have a cron count “svn status” output and email it to you if it exceeds some threshold or if there are uncommitted changes that are a few days or more old.
Backup your SVN repository
Make backup of your SVN repository daily. svn-fast-backup is a great python script that can be scheduled daily to keep your svn repos backed up - and only backed up if they change. Google svn-fast-backup to find the latest version.
To quickly add new files
Use this command snippet to quick add all the new files. If you want to undo the add operation do an “svn revert /path/to/file”
svn status|grep "?"|awk '{print $2}'|xargs svn add
Script to do it all
Below is a script that you can use to do the steps fast for this or any other repository
# New respository creation - modify the 1st two lines # # Name of the repository REPO_NAME=svn-etc # The directory that will be going into the repository WDIR_PATH=/etc # The location of the repository (make sure directory is already created) REPO_LOCA=/var/svn-repos # mkdir -p $REPO_LOCA cd $REPO_LOCA # Create the repository svnadmin create $REPO_NAME chmod 700 $REPO_NAME # cd $WDIR_PATH SVNFILE="file://${REPO_LOCA}/$REPO_NAME" svn checkout $SVNFILE $WDIR_PATH echo "Run thes two commands to add all files and commit" echo "svn add * --force" echo 'svn commit -m "Initial Version"' # svn status # # To update repo.db - This is a text file to keep track of created repositories # If repo.db does not already exist create it with these two lines below (without the #) #SVN_Repository | Location | Working_Dir_Path | Notes #---------------------------------------------------------------------------------------------- # echo "${REPO_LOCA}/$REPO_NAME | LOCAL? | $WDIR_PATH | SOME NOTES" >> $REPO_LOCA/repo.db
Repeat above for a different directory to come under version control
# New respository creation - modify the 1st two lines REPO_NAME=svn-www-common-vcs WDIR_PATH=/www/common/vcs # etc .....
Things to Watch out for
Invariably there are always issues when stepping away from the normal (as in here, it is uncommon to put /etc on VCS). Any time you create a new user, the .svn directory in /etc/skel will get copied over! So remember to delete it!
Refer to: VCS of web directory for considerations on using VC for web folders.