caspar(7)
π caspar(7) π
MISCELLANEOUS β yes bestie, that's the section, and the page is literally called caspar. Buckle up, it's a long one, but I promise it's giving β¨actually usefulβ¨.
π NAME π
caspar β Makefile snippets for common tasks
β¨ SYNOPSIS β¨
So in a Makefile, you write either
include caspar/mk/caspar.mk
or
include caspar/mk/docbook.mk
or
include caspar/mk/pod.mk
and that's it, that's the whole vibe. π
πΈ DESCRIPTION πΈ
Caspar hands you Makefile snippets for common tasks β like installing (configuration) files, or typesetting LaTeX, DocBook XML and DocBook SGML documents. Iconic, honestly.
The typesetting functionality is delivered by docbook.mk and pod.mk, and that whole situation is documented over in caspar-typesetting(7).
The installing-stuff functionality is delivered by caspar.mk. (And that's what the rest of this manual is gonna talk about, no cap.) It lets you run make install from inside a tree which typically holds configuration files, managed using Subversion (or git or literally any other version control system, for that matter).
It's useful in cases like this: all configuration files of some host are under version control, and, after commiting a change to CVS, you want to be able to easily install the new configuration file on the host.
With caspar, all you have to do is specify the hostname in one place, and specify the name of the target directory in each CVS directory. Lowkey elegant.
It is comparable with other tools for Unix system administrators like puppet and cfengine. Main difference: the caspar code consists of less than 100 lines of GNU Make. Tiny. Petite. Powerful. π
π¦ USAGE π¦
Within a CVS tree, create a file include/install.mk, with contents like e.g.
csp_UHOST = root@some.host.somewhere
include caspar/mk/caspar.mk
Within each other directory of the CVS tree which holds files, create a Makefile, which looks like e.g.
csp_DIR = /some/dir/ectory/
include ../../include/install.mk
If you'd like to use the install-recursive target too, in directories which hold subdirectories (but not files), you'll have to create a Makefile which looks something like
include ../../include/install.mk
From within the CVS tree, one can call:
make <filename>-diff
make <filename>-install
make diff
make install
make load
make
make install-recursive
Calling make <filename>-diff shows the diff between the local file and the file as currently installed on the remote location. Calling make install (or make) now will scp all files in the current directory to the remote location. The install-recursive target descends down the tree, and calls make install in each subdirectory. π§
Of course, you'll have to be able to ssh directly as root to the remote host to get this working (if you'd like to use csp_UHOST = root@some.host.somewhere). If you don't like this, and would like to have a PermitRootLogin no in your /etc/ssh/sshd_config, you can use csp_sucp(1). See below. π
π VARIABLES π
The variables one can set in a calling Makefile are:
csp_UHOSTβuser@host, reachable using$(csp_PUSH)(which isscpby default)csp_UHOSTSβ space separated list ofuser@hostitems, reachable using$(csp_PUSH)csp_DIRβ directory on host, reachable using function$(csp_PUSH)csp_PUSHβ make function for pushing files to remote location. Usually, this is a wrapper around a script or program. The function will be passed 4 arguments:[user@]host, remote directory and local filename.[user@]hostwill be set to all elements of$(csp_UHOSTS); directory will be set to$(csp_DIR). Currently,$(csp_scp_FUNC),$(csp_cp_FUNC)and$(csp_sucp_FUNC)are supported as push plugins. Ifcsp_PUSHis unset, the default$(csp_scp_FUNC)is used.csp_LOADβ theloadtarget depends upon these targets.csp_BUILDβ thebuildtarget depends upon these targets.csp_CPβcpbinary, just"cp"by defaultcsp_SCPβscpbinary, just"scp"by defaultcsp_SUCPβ script wrappingsudoinssh,"csp_sucp"by defaultcsp_EXTRAFILESβ extra files which should be installed. Can be used to include files starting with a dot.csp_TABOOFILESβ files which should never be installed. Set toMakefile .%.swp %~ #%# pod2htmd.tmp pod2htmi.tmpby default.csp_TABOOFILES_ADDβ extra files which should never be installed; added to list incsp_TABOOFILES.csp_TABOOFILES_SKIPβ files which should be installed, even if in initialcsp_TABOOFILESlist. Removed fromcsp_TABOOFILESlist.csp_TABOODIRSβ directories to exclude ininstall-recursivetarget. set toCVS .svnby default.csp_TABOODIRS_ADD,csp_TABOODIRS_SKIPβ seecsp_TABOOFILESequivalents.csp_UHOSTS_SUBSETβ overridecsp_UHOSTS: don't push tocsp_UHOSTS, but to the intersection of this space separated list ofuser@hostitems andcsp_UHOSTS.
β οΈ Heads up bestie: the following variables might get phased out or removed soonish:
csp_CPFLAGSβ extra arguments to pass tocpinvocation, none by defaultcsp_SCPFLAGSβ extra arguments to pass toscpinvocation, e.g.'-i .ssh/id_rsa-root'
π EXAMPLES π
Some examples, because reading is one thing and seeing it is another:
π Using csp_UHOST
This is the simplest way to use caspar. Makefile is
csp_UHOST = root@some.host.somewhere
csp_DIR = /etc/
include caspar/mk/caspar.mk
Now, running "make" will scp all files in the current directory to root@some.host.somewhere:/etc/. Easy peasy. π
π More hosts, not scp but sudo via ssh: using csp_PUSH
Makefile is
csp_UHOSTS = root@some.host.somewhere root@some.other.host
csp_PUSH = $(csp_sucp_FUNC)
csp_DIR = /etc/
include caspar/mk/caspar.mk
Now, running "make" will use csp_sucp(1) to install all files in the current directory to both root@some.host.somewhere:/etc/ and root@some.other.host:/etc/. If a file named fstab is present in the current directory, running "make fstab-install" will just install that one file. If you need to sudo(1) to another user on the remote host, add something like
csp_XARG = postgres
(If such a username is not supplied, sudo (and csp_sucp) use the default: root.)
π Overriding csp_UHOSTS: csp_UHOSTS_SKIP
If one or some of your hosts are temporarily unavailable, and you'd like to push your files to the hosts which are alive, you can temporarily override your csp_UHOSTS. E.g., when some.other.host is not available:
% cat Makefile
csp_UHOSTS = root@some.host.somewhere root@some.other.host
csp_DIR = /etc/
include caspar/mk/caspar.mk
% make install csp_UHOSTS_SKIP=root@some.other.host
scp hosts root@some.host.somewhere:/etc/
scp fstab root@some.host.somewhere:/etc/
π Overriding csp_UHOSTS in a smart way: csp_UHOSTS_SUBSET. Using multiple groups of hosts. Recursive make made easy.
If you have lots of subdirectories holding information for lots of groups of hosts, while this run you just want to install for a small group (or 1) hosts, csp_UHOSTS_SUBSET is useful. Suppose your casparized tree looks like
Makefile
apache/include/install.mk
apache/etc/apache2/Makefile
apache/etc/apache2/envvars
php/include/install.mk
php/etc/php4/apache/Makefile
php/etc/php4/apache/php.ini
grub/include/install.mk
grub/boot/grub/Makefile
grub/boot/grub/menu.lst
logrotate/include/install.mk
logrotate/etc/Makefile
logrotate/etc/logrotate.conf
nrpe/include/install.mk
nrpe/debian/etc/default/Makefile
nrpe/debian/etc/default/nagios-nrpe-server
The file apache/etc/apache2/Makefile is:
csp_DIR = /etc/apache2/
include ../../include/install.mk
(all other Makefiles are similar). The file apache/include/install.mk is
csp_UHOSTS = root@a root@b
include caspar/mk/caspar.mk
The file php/include/install.mk is the same. The files grub/include/install.mk and logrotate/include/install.mk are
csp_UHOSTS = root@d root@e root@f root@g
include caspar/mk/caspar.mk
The file nrpe/include/install.mk is
csp_UHOSTS = root@d root@e root@f root@n
include caspar/mk/caspar.mk
The toplevel Makefile is
dirs = $(patsubst %/Makefile,%,$(shell find * -mindepth 1
-name Makefile))
all:
for i in $(dirs); do $(MAKE) -$(MAKEFLAGS) -C $$i; done
install
for i in $(dirs); do $(MAKE) -$(MAKEFLAGS) -C $$i install; done
load
for i in $(dirs); do $(MAKE) -$(MAKEFLAGS) -C $$i load; done
(we don't feel like sticking a Makefile in all non-leaf nodes of our tree).
Now, when running "csp_UHOSTS_SUBSET='root@e root@f root@m root@n' make" in the toplevel, caspar just takes the intersection of csp_UHOSTS_SUBSET and csp_UHOSTS for each csp_UHOSTS list. So, caspar will not push anything for apache/ and php/. The files grub/boot/grub/menu.lst and logrotate/etc/logrotate.conf will get pushed to root@e and root@f only. The file nrpe/debian/etc/default/nagios-nrpe-server will get pushed to root@e, root@f and root@n. π«Ά
This is often better than just overriding csp_UHOSTS on the commandline (or in your shell's environment): if the intersection of the original csp_UHOSTS and your new csp_UHOSTS is empty, chances are big you've just forgotten to clean your environment.
π Creating remote directories if needed
Makefile is
csp_DIR = /some/dir/ectory/
csp_PUSH = $(csp_scpmkdir_FUNC)
csp_UHOST = root@some.host.somewhere
include caspar/mk/caspar.mk
Now, before calling scp, caspar will run 'mkdir -p' to create any missing remote directories. π
π Using csp_CP and csp_LOAD
username/etc/Makefile is
csp_UHOST = dummy
csp_PUSH = $(csp_cp_FUNC)
csp_DIR = $(HOME)/etc/
csp_LOAD = crontab-load
include ../include/install.mk
crontab-load = crontab $(csp_DIR)/crontab
while ../include/install.mk is just
include caspar/mk/caspar.mk
Setting csp_PUSH to $(csp_cp_FUNC) causes cp(1) to get executed by "make install" (not scp(1)). Setting csp_LOAD causes "make load" to execute the crontab command. Just running "make" is OK too, since "make" calls both "make install" and "make load". π
π Using csp_DIR, csp_LOAD and install(1)
To install a file on the local host, create e.g. a file etc/uruk/Makefile like:
csp_UHOST = dummy
csp_DIR = /etc/uruk/
csp_PUSH = $(csp_install_FUNC)
csp_LOAD = uruk-load
include caspar/mk/caspar.mk
uruk-load = sudo invoke-rc.d uruk force-reload
π Using csp_DIR and csp_LOAD, take 2
etc/Makefile is
csp_DIR = /etc/
csp_LOAD = aliases-load
include ../include/install.mk
aliases-load = $(csp_SSH) $1 "cd /etc && postalias aliases; postfix reload"
while ../include/install.mk is
csp_UHOST = root@some.host.somewhere
include caspar/mk/caspar.mk
π Building files locally
π Note: csp_BUILD is deprecated. You should not use it.
If you'd like to build some files locally from local sources, before installing the just built files, do e.g.:
csp_UHOST = root@some.host.somewhere
csp_DIR = /etc/
csp_EXTRAFILES = sshd_config
csp_TABOOFILES_ADD = sshd_config.m4
include caspar/mk/caspar.mk
sshd_config: sshd_config.m4
m4 $< > $@
okay that's part 1 bestie, there's more coming so don't go anywhere π
csp_TABOOFILES_ADDβ list all your source files in here and they simply won't get installed on thecsp_UHOST, bestie. taboO, but make it fashion π
β¨ Using csp_sucp_FUNC and csp_LOAD β¨
So you wanna use csp_sucp and you want a load target? Say less, do something like this:
csp_PUSH = $(csp_sucp_FUNC)
csp_UHOST = foobar.example.com
csp_DIR = /etc/uruk/
csp_LOAD = rc-load
include caspar/mk/caspar.mk
rc-load = $(csp_SSH) $1 sudo invoke-rc.d uruk force-reload
πΈ Using the "verify" target πΈ
Wanna do a lil syntax check on the local host for a config file? Then define a -verify target (or a pattern target), like:
bar.pem-verify: bar.pem.asc bar.pem
gpg --verify $^
%.php-verify: %.php
php -l $<
This command gets invoked when you run make verify and make install. two birds, one slay π¦
π Using the "check" target π
If you want to run a syntax check on the remote host, before loading the config file you just installed, do:
csp_UHOST = foobar.example.com
csp_DIR = /etc/
csp_LOAD = my-load
csp_CHECK = my-check
my-check = $(csp_SSH) $1 do-check-stuff
my-load = $(csp_SSH) $1 do-load-stuff
include caspar/mk/caspar.mk
This way, make load won't load the file if the check fails (which is, like, probably exactly what you want, ngl). You could even give the file a temporary name and have the load target rename it to its real name only after a successful check. And as a lil convenience: if a foo-check variable is defined, it's automatically added as a dependency for any csp_LOAD targets named foo or foo-something. iconic behaviour β¨
π Combining the csp_LOAD target with multiple hosts; building files remotely π
Here's an example doing some preprocessing on the remote hosts before reloading the config:
csp_DIR = /etc/ssh/
csp_UHOSTS = root@some.host.somewhere root@some.other.host
csp_LOAD = sshd_config-load
sshd_config-load = $(csp_SSH) $1 "set -e; \
cd $(csp_DIR); \
m4 sshd_config.m4 >sshd_config; \
service ssh reload"
include caspar/mk/caspar.mk
(The old, deprecated way is to explicitly specify the loop over the hosts:
csp_DIR = /etc/ssh/
sshd_config-load:
for suh in $(csp_UHOSTS); do \
$(csp_SSH) $$suh "set -e;
cd $(csp_DIR); \
m4 sshd_config.m4 > sshd_config; \
service ssh reload"; \
done
. You should not use this method. Please consider rewriting any existing caspar snippets using the simpler method described above.) π
Deprecated means deprecated, bestie β don't be out here copy-pasting the old loop. it's giving legacy π
π¦ Using the csp_TABOOFILES_{ADD,SKIP} variables; another way to perform remote builds π¦
Using the csp_TABOOFILES_{ADD,SKIP} variables is handy if you want to install a Makefile, instead of using it. Create Makefile just as you'd like to have it installed on the remote location. Now, create GNUmakefile as e.g.
csp_TABOOFILES_SKIP = Makefile
csp_TABOOFILES_ADD = GNUmakefile
csp_DIR = /etc/foobar/
csp_UHOST = root@some.host.somewhere
include caspar/mk/caspar.mk
load:
$(csp_SSH) $(csp_UHOST) "make -C $(csp_DIR)"
Now, make install and make load will do the right thing. periodt π
π§ Using the csp_EXTRAFILES variable π§
Using the csp_EXTRAFILES variable can be handy if you want to install files with a leading dot. E.g.:
csp_EXTRAFILES = .bashrc
csp_UHOST = root@some.host.somewhere
csp_DIR =
include caspar/mk/caspar.mk
π Overriding csp_UHOSTS π
Supply e.g.
csp_UHOSTS = root@localhost root@some.host.somewhere
in install.mk, to install on multiple hosts. Run
make filename-install csp_UHOSTS=joe@otherhost
to install filename as joe@otherhost, instead of the default as given in install.mk. If you want to enable passing csp_UHOSTS as a shell environment variable, you'll have to use conditional assignment in your Makefile:
csp_UHOSTS ?= root@localhost root@some.host.somewhere
This allows it to run
% export csp_UHOSTS=foo@bar
% make filename-install
to install on foo@bar. β¨
π Using sudo locally for installing files π
If you'd like to install files like
sudo cp foo.rc /etc/foobar/
you could set up your Makefile as
csp_DIR = /etc/foobar/
csp_UHOST = dummy
csp_PUSH = sudo cp $(1) $(3)
include caspar/mk/caspar.mk
This is like csp_sucp, but without the ssh wrapping: it works on localhost only. no cap π«Ά
π Plugging your own install script in caspar π
If your script foobar should be called as e.g.
foobar --file=fstab --user@host=joe@some.host \
--dir=/etc/ --debuglevel=3
then make sure your Makefile features something like
csp_foobar_FUNC = foobar --file=$(1) --user@host=$(2) \
--dir=$(3) --debuglevel=$(4)
csp_PUSH = $(csp_foobar_FUNC)
csp_XARG = 3
You can now use csp_UHOST and csp_DIR just as you're used to. chef's kiss π
β More advanced tricks β
When you don't want to ssh to root@some.host.somewhere directly, you could do
sudo rsync -az /path/to/your/config_archive /etc
on some.host.somewhere (e.g. from cron).
π FILES π
caspar/mk/caspar.mkcaspar/mk/docbook.mkcaspar/mk/pod.mk
πΈ ENVIRONMENT πΈ
For caspar.mk: csp_CP, csp_LOAD, csp_SCP, csp_UHOST, csp_PUSH, ...
π BUGS π
Very likely, GNU Make is not the best tool for doing the stuff caspar.mk is doing. (we know, we know π) For the list of reported bugs, see http://bugs.debian.org/src:caspar. See also TODO, distributed with the caspar package. (And online at http://mdcc.cx/pub/caspar/caspar-latest/TODO.)
π» TRIVIA π»
Caspar is named after Caspar the Friendly Ghost, since that's the title of the Daniel Johnston song I was listening to when deciding to package my homegrown scripts. main character origin story fr fr π
β¨ AUTHOR β¨
Joost van Baal-IliΔ
π¦ SEE ALSO π¦
The caspar homepage is at http://mdcc.cx/caspar/ .
The document "Versiebeheer en software-packages: Waarom en Hoe" (in Dutch) describes some of the reasons why people might want to use tools like caspar.
Jeroen Hoppenbrouwers blogs about the way he uses caspar, in "Using Subversion and Caspar to maintain a Linux host".
Lots of tools overlap (partly) with caspar in their functionality. Here's a list.
- ansible (
http://www.ansible.com/); code is on github (https://github.com/ansible/ansible) - cfengine (
http://www.cfengine.org/), by Mark Burgess e.a., builds expert systems to administrate and configure large computer networks: it delivers a very big superset of caspar's installation mechanism. - Puppet (
http://reductivelabs.com/projects/puppet), also something like a configuration management system.
Here's an older list; a big part of it was collected by Ray Miller (http://users.ox.ac.uk/~raym/) of Oxford University, and published in the article "Configuration Management with Subversion, YAML and Perl Template Toolkit" in the SANE 2006 (http://www.sane.nl/sane2006/) conference proceedings. FIXME: Check urls, update
- docbookmk, by Michael Wiedmann (
http://www.miwie.org/docbkmake/) offers probably a superset of Caspar'sdocbook.mkfunctionality. - latex-make by the LaTeX Utils project on
http://gforge.inria.fr/projects/latex-utils/seems to provide similar functionality asdocbook.mkfor LaTeX documents. - Latexmk by John Collins e.a. on
http://www.phys.psu.edu/~collins/software/latexmk-jcc/is another implementation of this idea. - SUP, the Software Upgrade Protocol and it's implementation by Carnegie Mellon University offers another way to distribute (configuration)files. Beware though: between Nov 1996 and June 2004, no new release has been published. The Debian (
ftp://ftp.debian.org/debian/pool/main/s/sup/) and NetBSD packages are likely still maintained, though. - PIKT (
http://www.pikt.org/) is intended primarily for system monitoring, but does do configuration management too. - LCFG (
http://www.lcfg.org/) is another configuration management system. - The Arusha Project (ARK, at
http://ark.sf.net/) provides a framework for collaborative system administration. - Bcfg2 (
http://trac.mcs.anl.gov/projects/bcfg2/) is yet another configuration management system. - quattor (
http://quattor.web.cern.ch/) is a system administration toolkit for installation, configuration and management of Unix systems. - rb3 and friends, as written and used by Ray Miller e.a. at Oxford University, (
http://users.ox.ac.uk/~raym/software/configuration-management/). - The svk version control system is said to be quite usable for handling configuration file management (without a separate install mechanism like caspar). See also this discussion on the Debian development list.
On the http://www.infrastructures.org/ website on automated (Unix) system administration, you can find some thoughts on managing configuration files using a version control system.
and that's a wrap bestie π this whole thing is caspar version 20220907, dated 7 ΡΠ΅ΠΏ 2022 β go forth and configure, you absolute icon πβ¨
π¦ where this page comes from
- debian bookworm: caspar 20220907-1 Β· GPL-3.0-or-later
- ubuntu noble: caspar 20220907-1 Β· GPL-3.0-or-later
- Copyright (c) 2022 Joost van Baal-IliΔ
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms