Skip to content

Instantly share code, notes, and snippets.

@thefloweringash
Last active February 9, 2019 21:13
Show Gist options
  • Save thefloweringash/1f44500cc22116558382efb1555d7dff to your computer and use it in GitHub Desktop.
Save thefloweringash/1f44500cc22116558382efb1555d7dff to your computer and use it in GitHub Desktop.
dirvish package for nix
{ stdenv, fetchurl, makeWrapper, perl, coreutils, rsync, bzip2, gzip, findutils,
perlPackages
}:
stdenv.mkDerivation {
name = "dirvish";
src = fetchurl {
url = "http://dirvish.org/dirvish-1.2.1.tgz";
sha256 = "1kbxa1irszp2zw8hd5qzqnrrzb4vxfivs1vn64yxnj0lak1jjzvb";
};
nativeBuildInputs = [ makeWrapper ];
buildInputs = [ rsync perl coreutils ] ++ (with perlPackages; [ TimeParseDate TimePeriod ]);
executables = [ "dirvish dirvish-runall dirvish-expire dirvish-locate" ];
manpages = [ "dirvish.8 dirvish-runall.8 dirvish-expire.8 dirvish-locate.8" "dirvish.conf.5" ];
buildPhase = ''
HEADER="#!${perl}/bin/perl
\$CONFDIR = \"/etc/dirvish\";
"
mkdir -p $out/bin
for executable in $executables; do
(
echo "$HEADER"
cat $executable.pl
cat loadconfig.pl
) > $executable
chmod +x $executable
done
'';
installPhase = ''
mkdir -p $out/bin
cp --target-directory=$out/bin $executables
for manpage in $manpages; do
if [[ $manpage =~ \.([[:digit:]]+)$ ]]; then
section=''${BASH_REMATCH[1]}
mkdir -p $out/man/man$section
cp --target-directory=$out/man/man$section $manpage
else
echo "Couldn't determine man page section by filename"
exit 1
fi
done
'';
postFixup = ''
for executable in $executables; do
wrapProgram $out/bin/$executable \
--set PATH "${stdenv.lib.makeBinPath [ rsync coreutils findutils ]}" \
--set PERL5LIB "$PERL5LIB"
done
'';
}
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.dirvish;
writeList = xs: concatMapStringsSep "\n" (x: "\t${x}") xs;
writeValue = name: value:
if value == true then "${name}: 1"
else if value == false then "${name}: 0"
else if isList value then "${name}:\n${writeList value}"
else if isInt value then "${name}: ${toString value}"
else if isString value then "${name}: ${value}"
else throw "Unsupported value type";
writeExtraOptions = opts: concatStringsSep "\n" (
mapAttrsToList writeValue opts);
sshWrapper = { known-hosts, port, ... }:
let
knownHostsFile = pkgs.writeText "dirvish-known-hosts" (
concatMapStrings (x: "${x}\n") known-hosts);
in
pkgs.runCommand "dirvish-ssh" {
buildInputs = [ pkgs.makeWrapper ];
} ''
makeWrapper ${pkgs.openssh}/bin/ssh $out \
--add-flags "-oIdentityFile=${cfg.key-file} -oGlobalKnownHostsFile=${knownHostsFile} -oPort=${toString port}"
'';
vaultConfigFile = name: { client, extraOptions, ... }@vaultCfg: {
"dirvish/vaults/${name}.conf".text = ''
client: ${client}
rsh: ${sshWrapper vaultCfg}
${writeExtraOptions vaultCfg.extraOptions}
'';
};
in
{
options.services.dirvish = with types; {
image-default = mkOption {
type = string;
default = "%Y%m%d-%H%M";
description = ''
Default image name.
'';
};
expire-rules = mkOption {
type = listOf string;
default = [
"wd { sun } +3 months"
"md { 1 } +5 years"
];
description = ''
List of expiration rules.
'';
};
expire-default = mkOption {
type = string;
default = "+30 days";
description = ''
Default expiration rule.
'';
};
key-file = mkOption {
type = string;
description = ''
SSH key to identify this host.
'';
};
banks = mkOption {
type = listOf string;
default = [];
description = ''
List of directories containing vaults.
'';
};
log-format = mkOption {
type = enum [ "text" "gzip" "bzip2" ];
default = "text";
description = ''
Specify format for the image log file.
'';
};
index-format = mkOption {
type = enum [ "none" "text" "gzip" "bzip2" ];
default = "none";
description = ''
Create an index file listing all files in the image.
'';
};
xdev = mkOption {
type = bool;
default = true;
description = ''
Do not cross mount-points when traversing the tree on the client.
'';
};
startAt = mkOption {
type = either str (listOf str);
default = "22:04";
description = ''
When to run backups;
'';
};
vaults = mkOption {
type = attrsOf (submodule {
options = {
client = mkOption {
type = string;
description = ''
Hostname to backup
'';
};
port = mkOption {
type = int;
default = 22;
description = ''
SSH port to connect to
'';
};
known-hosts = mkOption {
type = listOf string;
default = [];
description = ''
List of known hosts in OpenSSH format.
'';
};
extraOptions = mkOption {
type = attrs;
default = {};
description = ''
Extra key-value options to include
'';
};
};
});
default = {};
description = ''
Vaults to back up
'';
};
};
config = mkIf (cfg.vaults != {}) (mkMerge [
{
environment.etc."dirvish/master.conf".text = ''
Dirvish: ${pkgs.dirvish}/bin/dirvish
image-default: ${cfg.image-default}
log: ${cfg.log-format}
index: ${cfg.index-format}
${writeValue "xdev" cfg.xdev}
${writeValue "expire-rule" cfg.expire-rules}
expire-default: ${cfg.expire-default}
${writeValue "bank" cfg.banks}
${writeValue "Runall" (attrNames cfg.vaults)}
'';
environment.systemPackages = [ pkgs.dirvish ];
systemd.services.dirvish = {
script = ''
${pkgs.dirvish}/bin/dirvish-expire
${pkgs.dirvish}/bin/dirvish-runall
'';
startAt = cfg.startAt;
};
}
{
environment.etc = mkMerge (mapAttrsToList vaultConfigFile cfg.vaults);
}
]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment