Putting /etc in CVS
Here's how I put my /etc directory under CVS:
First, since some files in /etc are readable only by root, I need to login as root:
$ su -
Next, I set my $CVSROOT environment variable to be /var/lib/cvs:
# export CVSROOT=/vvar/lib/cvs
Next, I check out my CVSROOT directory:
# cd ~
# cvs co CVSROOT
# cd CVSROOT
Next, I'll add an option to instruct CVS to treat all *.gz files as binary:
# echo "*.gz -k 'b'" >>cvswrappers
Next, I'll add an option to instruct CVS to ignore all standard CVS keywords ($Id$, $Header$, etc.), and only expand $Etc$:
# echo "tag=Etc=CVSHeader" >>options
# echo "tagexpand=iEtc" >>options
# echo options >>checkoutlist
# cvs add options
# cvs ci -m 'Instruct CVS to only expand $Etc$'
This previous step is optional, but I do it as many files in /etc already have the CVS keywords $Id$'s, and I don't want existing keywords expanded and the resulting changes checked in to CVS.
Note: These options are a relatively new addition to CVS and may not work in your version.
I change to the /etc directory and create a .cvsignore containing a list of files that change often by the system:
# cd /etc
# echo adjtime >.cvsignore
# echo ioctl.save >>.cvsignore
# echo ld.so.cache >>.cvsignore
# echo motd >>.cvsignore
As the name of the file suggests, this instructs CVS to ignore these files when importing or updating.
You can list any files you want to .cvsignore, including sensitive files such as /etc/passwd. Personally, I like to keep these files in CVS, so I secure the repository instead.
Next, I add non-text files to .cvswrappers. This instructs CVS to not perform keyword expansion ($Id$ to $Id: ... $) on these files:
echo "* -k 'b'" >/etc/alternatives/.cvswrappers
echo "*.p12 -k 'b'" >/etc/ipsec.d/.cvswrappers
echo "*.dat -k 'b'" >/etc/pcmcia/cis/.cvswrappers
cd /etc/terminfo
for i in * ; do echo "* -k 'b'" >$i/.cvswrappers ; done
I then import the /etc directory into a new CVS module, named etc:
# cvs import -m 'Initial import for the /etc directory' etc hostname release-dd-mmm-yyyy
If you want to have several systems' /etc directories in a single CVS repository, you could name the modules hostname_etc, or anything you want.
Next, I restrict the $CVSROOT/etc directory so only the root user has access:
# cd /var/lib/cvs/etc
# chown root.root .
# chmod go-rwx .
This is because there are sensitive files, such as /etc/passwd, in the /etc directory and CVS will add them to the repository with different rights then the rights they have in /etc.
Next, I check out a copy of the new etc module:
# cd /root
# cvs checkout etc
Then, I set the date on all the files to 1/1/1970:
# find etc | xargs touch -t 197001010000
Next, I backed up the /etc directory, just in case:
# tar czf /root/etc.tgz /etc
Then, I copy over just the CVS directories from /root/etc directory to the /etc directory:
# cd /root/etc
# cp --interactive -pRuv . /etc
The -u option instructs cp to only copy files that are new or have changed. As we set the date of all the files to 1/1/1970, the only files copied over will be the CVS directories.
I added the --interactive option to make sure that nothing is overwritten without asking me first. In truth, nothing was overwritten.
Lastly, I check in any changes to CVS. The only changes at this point will be from files containing CVS keywords (i.e., $Etc$):
# cd /etc
# cvs ci -m 'Keyword substitutions (i.e., $Etc$ after initial checkout)'
And finally, I removed the temporary directory, as it's no longer needed.
# rm -fr /root/etc
