Site-wide Configuration Management for Debian GNU/Linux
2012-03-29 11:03- Motivation
- Readying the APT Repo server
- Key Generation
- Reprepro
- Nginx Configuration
- Packaging
- Building
- Add to Repository
- Installation on Client Machines
- Automating
I may be a FreeBSD fangirl, but my company is a Debian GNU/Linux shop. This tutorial looks at how I create site configurations with config-package-dev, package them, and make them available on the network.
Motivation
- Exists within APT, so no tools are required on a target machine besides those shipped with the operating system.
- Configuration packages make it easy to distribute a configuration across a site.
- Separation of machine and configuration. Configurations can be installed over a machine of any state, and the machine returns to its previous state upon uninstallation thanks to dpkg-divert.
- Simple codename separation for maintaining compatible but discrete packages across releases, also enabling seamless release upgrades that would otherwise fail due to incompatible configuration, e.g. apache2 during the upgrade from Debian 5 to 6.
- Free (monetarily)
- Free (philosophically)
- Config-package-dev can build configuration packages that transform the in-place configuration files, leaving the configuration package agnostic to config file changes from upstream.
Readying the APT Repo server
Install nginx and reprepro, my favourite confusingly-named but extremely powerful Debian repository manager.
Create a local user repo
who will run reprepro and under whose home directory we will host the repository, then create the directory skeleton for the repository itself.
Key Generation
APT repositories can be signed with a GnuPG private key. To generate one, install gnupg
along with the rng-tools
package.
Start rngd, seeding it with /dev/urandom
. Without rngd, GnuPG may take a very very long time to gather enough entropy for safe key generation, as I experienced on a VMware ESXi virtual machine.
To create the key, run gpg --gen-key
as repo
and follow the prompts. Be sure to place a passphrase on your new key when prompted, or anybody who gets ahold of the private key can sign with it.
Take a peek at gpg --list-secret-keys
and make sure your key matches expectation.
Lastly, export the public component of the key to the document root of the repository so clients can access it.
Reprepro
Reprepro’s configuration lives within the root of the repository, under the HTTP document root. In this setup, it’s /home/repo/public/debian/conf
.
conf/distribution
This file defines the distributions for which we host repositories. It may contain multiple distribution definition blocks, separated from each other by one blank line. Each codename release of Debian (Lenny, Squeeze, Wheezy, et cetera) is a separate distribution in this context.
This working example is a repository hosting the main
and extra
components for Debian 6.0 “Squeeze” on the i386 and amd64 architectures and signed by a GnuPG key with id 013CFE9D
, as seen in the previous section.
conf/options
This file defines configuration for reprepro itself. Most of these are personal preference. They correspond to command line arguments to reprepro.
Nginx Configuration
Define a new virtual host to expose our repository on the network, making sure to deny access to the configuration and database subdirectories. I host with SSL, listening on port 80 only to issue redirects to the SSL host on port 443.
Enable it by symlinking your virtual host configuration file under sites-enabled
, and reload nginx.
Packaging
Packaging is a complex topic, and newcomers would do well to read the Introduction to Debian Packaging.
You should have the package you’re configuring installed on your repository build machine, or file diversion might fail during package construction.
Prerequesites
Install a few necessary build dependencies.
Example Package: Configuration Transformation
This is a working example of a configuration transformation package that, when installed, will disable root logins in OpenSSH, force SSH 2 protocol, disable host-based authentication, and disallow empty passwords.
Create the directory structure for the package.
The control
file names, declares dependencies for, and includes a description for our package.
rules
is a Makefile where we configure config-package-dev for this package, telling it what on-filesystem files we wish to transform.
transform_sshd_config.dashie
is named for the file it’s transforming, /etc/ssh/sshd_config.dashie
, diverted to /etc/ssh/sshd_config
by our package. My transform files are usually written in perl, but that’s not a requirement.
postinst
is a shell script called with the argument configure
after package installation. In this example, it restarts the OpenSSH server to pick up its new configuration.
The package changelog
keeps a history of the package. It can be edited by hand or updated by a tool such as dch
.
compat
is a very simple file, containing only the number of the debhelper version needed by your package. This package, for example, declares a need for debhelper (>= 6.0.0), the version shipped with Debian Lenny.
The copyright
file is simply the license you prefer for the package.
Example Package: Configuration Replacement
This is a working example of a configuration replacement package that, when installed, will install a systemwide zshrc
, a custom ZSH prompt, and a blank .zshrc
in the skeleton home directory. The blank .zshrc
prevents ZSH from prompting users for first-run configuration, instead preferring our system-wide config.
Specify a dependency on ZSH in control
, so the systemwide zshrc
will exist for us to replace.
<name-of-package>.install
is a list of source and destination for files you want dh_install
to install. This simple one-line example says every file in and under the packages’ files
directory should be installed to the root of the filesystem.
In this packages rules
, list the files the package will replace. In this case, the package installs /etc/zsh/zshrc.dashie
and diverts it to /etc/zsh/zshrc
.
This package has a files
directory containing the installed files in their proper tree. The simple dh_install
file above will copy this entire directory tree over the root of the filesystem.
The other required files, changelog
, compat
, and license
, are no different from the previous example.
Building
Run debuild -us -uc
in the package’s top-level directory. The -us
and -uc
arguments tell dpkg-buildpackage
not to cryptographically sign the source or the .changes
file, just the package. If all goes well, you’ll find a
If the build is unsuccessful, example the verbose output for the cause.
Updating Existing Packages
When making changes to a package you’ve already built and distributed, comment your change with dch
, using -i
to increment the package version number, then debuild
as usual. dch
will automatically try to guess your name and email address, but you can specify them with the DEBFULLNAME
and DEBEMAIL
environment variables.
Add to Repository
Use reprepro to add the newly-built .deb
to the repository. Specify the package’s component (main
for packaged software, extra
for configuration packages) and the codename distribution to target.
When prompted, enter your GnuPG key’s passphrase. gpg-agent
can help mitigate annoying successive password prompts.
Installation on Client Machines
With all that mess taken care of, configuring a client machine is as easy as adding your new repository to the APT sources list.
Enabling HTTPS transport for apt.
Adding the repo’s public key to the APT keyring.
…And running apt-get update
.
Your packages should now be available for installation through APT.
Automating
Set a few environment variables in the new user’s .zprofile
or .profile
, depending on your shell of choice. DEBEMAIL
and DEBFULLNAME
will automatically apply to dch
changelogs generated as this user. Aliasing reprepro to reprepro with a basedir argument lets us easily run the command from any directory.
You can permanently specify debuild
arguments in your user’s .devscripts
to save including them manually every time.
Keychain is a handy piece of software to keep gpg-agent alive. Install it with apt-get install keychain
and add an entry with your key ID to your .zprofile
or .profile
.