ne pas hésiter donc à bien relire les règles
_avant_ de les exécuter.
NOTE:
- à priori les règles sont pensées pour être exécutées
- plusieurs fois selon les erreurs que l'on rencontre
+ à priori les commandes sont idempotentes,
+ i.e. pensées pour être exécutées plusieurs fois
+ selon les erreurs que l'on rencontre
ou les modifications que l'on y apporte.
TASK: obtenir une installation chrootable
TASK: obtenir une installation démarable
@host % ~/tool/ateliers/host/chroot
@host % export TRACE=1 LANG=C LC_CTYPE=C
- @host % /root/tool/vm/local/init # TODO: revoir ça
+ @host % /root/tool/ateliers/local/init # TODO: revoir ça
@host % exit
TASK: initialiser la VM
@host % ~/tool/ateliers/xen-vm-configure
@host % host/xen-vm-start
@remote % remote/luks-key-disk-send
TASK: pousser des changements locaux sur la VM
- @remote % remote/git-push
- @local % local/git-reset
+ @remote % remote/git-push -f local
TASK: se connecter interactivement en root à la VM avec une connection SSH persistante
@remote % remote/mosh -l root
TASK: générer une autorité de certification et des sous-certificats TLS
--- /dev/null
+MAILTO=backup
+# m h dom mon dow user command
+0 3 * * * backup bin/mysql-backup '\%' -- --full-if-older-than 90D && bin/duplicity-remove mysql -maxdepth 1 -- remove-all-but-n-full 1 --force
-readonly PATH=$PATH:/usr/sbin:/sbin
+PATH=$PATH:/usr/sbin:/sbin
readonly local_domainname="heureux-cyclage.org"
readonly local_hostname="ateliers"
readonly local_fqdn="$local_hostname.$local_domainname"
-sudo test -f /etc/nginx/x509.d/\"$site\"/key.pem ||
-printf '%s\n' "$(tput rev)run before: remote/runit-configure nginx -- $site$(tput sggr0)" && exit 1
+hint="run before: remote/runit-configure nginx -- $site"
+assert "sudo test -f /etc/nginx/x509.d/\"$site\"/key.pem" hint
sudo install -m 664 -o www -g www \
"$tool"/var/pub/x509/git.heureux-cyclage.org/crt+ca.pem \
-sudo test -f /etc/nginx/x509.d/\"$site\"/key.pem ||
-printf '%s\n' "$(tput rev)run before: remote/runit-configure nginx -- $site$(tput sgr0)" && exit 1
+hint="run before: remote/runit-configure nginx -- $site"
+assert "sudo test -f /etc/nginx/x509.d/\"$site\"/key.pem" hint
sudo install -m 664 -o www -g www \
"$tool"/var/pub/x509/questionnaires.heureux-cyclage.org/crt+ca.pem \
pool=lhc_quest
sudo adduser php5_"$pool" www-"$site"
sudo adduser www-"$site"-tls www-"$site"
-~mysql/bin/createuser php5_"$pool"
-~mysql/bin/createdb php5_"$pool"
+"$tool"/local/mysql-user-create php5_"$pool"
+"$tool"/local/mysql-database-create php5_"$pool"
-sudo test -f /etc/nginx/x509.d/\"$site\"/key.pem &&
-sudo test -f ~wiki-$site/etc/ssh/id_rsa ||
-printf '%s\n' "$(tput rev)run before: remote/runit-configure nginx -- $site$(tput sgr0)" && exit 1
+hint="run before: remote/runit-configure nginx -- $site"
+assert "sudo test -f /etc/nginx/x509.d/\"$site\"/key.pem" hint
+assert "sudo test -f ~wiki-$site/etc/ssh/id_rsa" hint
"$tool"/local/apt-get-install ikiwiki \
libsearch-xapian-perl
-sudo test -f /etc/nginx/x509.d/\"$site\"/key.pem ||
-printf '%s\n' "$(tput rev)run before: remote/runit-configure nginx -- $site$(tput sgr0)" && exit 1
+hint="run before: remote/runit-configure nginx -- $site"
+assert "sudo test -f /etc/nginx/x509.d/\"$site\"/key.pem" hint
sudo install -m 664 -o www -g www \
"$tool"/var/pub/x509/stats.heureux-cyclage.org/crt+ca.pem \
pool=lhc_stats
-sudo adduser php5_"$pool" www-"$site"
+sudo adduser php5_"$pool" www-"$site"
sudo adduser www-"$site"-tls www-"$site"
-~mysql/bin/createuser php5_"$pool"
-~mysql/bin/createdb php5_"$pool"
+"$tool"/local/mysql-user-create php5_"$pool"
+"$tool"/local/mysql-database-create php5_"$pool"
-sudo test -f /etc/nginx/x509.d/\"$site\"/key.pem ||
-printf '%s\n' "$(tput rev)run before: remote/runit-configure nginx -- $site$(tput sgr0)" && exit 1
+hint="run before: remote/runit-configure nginx -- $site"
+assert "sudo test -f /etc/nginx/x509.d/\"$site\"/key.pem" hint
sudo install -m 664 -o www -g www \
"$tool"/var/pub/x509/www.heureux-cyclage.org/crt+ca.pem \
-sudo test -f /etc/nginx/x509.d/\"$site\"/key.pem ||
-printf '%s\n' "$(tput rev)run before: remote/runit-configure nginx -- $site$(tput sgr0)" && exit 1
+hint="run before: remote/runit-configure nginx -- $site"
+assert "sudo test -f /etc/nginx/x509.d/\"$site\"/key.pem" hint
sudo install -m 664 -o www -g www \
"$tool"/var/pub/x509/sympa.heureux-cyclage.org/crt+ca.pem \
# See man 5 aliases for format
abuse: root
admin: root
+backup: root
contact: root
hostmaster: root
mailer-daemon: root
--- /dev/null
+export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+! getent group sudo | cut -f 4 -d : | tr , '\n' | grep -Fqx "$USER" ||
+PATH="$HOME/src/$(hostname)/local:$PATH"
--- /dev/null
+. "$tool"/etc/local.sh
--- /dev/null
+Defaults env_keep = " \
+ EDITOR \
+ GIT_AUTHOR_NAME \
+ GIT_AUTHOR_EMAIL \
+ GIT_COMMITTER_NAME \
+ GIT_COMMITTER_EMAIL \
+ "
--- /dev/null
+%sudo ALL=(ALL) NOPASSWD: /usr/bin/etckeeper unclean
--- /dev/null
+# NOTE: permet à backup de rentrer dans les fichiers des bases de données
+# afin de faire un mysqlhotcopy(1).
+backup ALL=(root) NOPASSWD: /usr/bin/find \
+ /home/mysql/data -mindepth 1 -maxdepth 1 -type d -exec \
+ install -d -m 750 -o mysql -g backup {} +
--- /dev/null
+%sudo ALL=(ALL) NOPASSWD: /bin/sh -e -f -u -c \
+ case $(/usr/bin/passwd --status "$SUDO_USER") in \
+ ("$SUDO_USER L "*) /usr/bin/passwd $SUDO_USER;; esac
"$tool"/local/apt-get-install dovecot-imapd dovecot-managesieved dovecot-sieve
"$tool"/local/insserv-remove dovecot
-sudo test -f /etc/dovecot/\"$local_domainname\"/imap/x509/key.pem ||
-printf '%s\n' "$(tput rev)run before: remote/runit-configure dovecot$(tput sgr0)" && exit 1
+hint="run before: remote/runit-configure $sv"
+assert 'sudo test -f /etc/dovecot/$local_domainname/imap/x509/key.pem' hint
sudo install -m 400 -o root -g root \
"$tool"/var/pub/x509/imap."$local_domainname"/crt+crl.self-signed.pem \
eval "home=~$sv"
-"$tool"/local/adduser mysql \
+"$tool"/local/adduser "$sv" \
--disabled-login \
--disabled-password \
--group \
--home "$home" \
--shell /bin/false \
--system
-"$tool"/local/adduser mysql-data \
+"$tool"/local/adduser "$sv"-data \
--disabled-login \
--disabled-password \
--group \
--no-create-home \
--shell /bin/false \
--system
-sudo usermod --home "$home" mysql
-sudo adduser mysql mysql-data
-sudo install -d -m 755 -o mysql -g mysql \
- "$home" \
- "$home"/bin
+sudo usermod --home "$home" "$sv"
+sudo adduser "$sv" "$sv"-data
+sudo install -d -m 755 -o "$sv" -g "$sv" \
+ "$home"
sudo rm -rf /etc/mysql
-sudo install -d -m 750 -o mysql -g mysql-data \
+sudo install -d -m 750 -o "$sv" -g "$sv"-data \
/etc/mysql \
/etc/mysql/conf.d \
"$home"/etc
sudo ln -fns \
- /etc/mysql \
+ /etc/mysql \
"$home"/etc/mysql
-sudo install -m 644 -o mysql -g mysql \
+sudo install -m 644 -o "$sv" -g "$sv" \
"$tool"/etc/mysql/my.cnf \
/etc/mysql/my.cnf
if sudo test ! -d "$home"/data
then
- sudo install -d -m 750 -o mysql -g mysql-data \
+ sudo install -d -m 750 -o "$sv" -g "$sv"-data \
"$home"/data
- sudo -u mysql mysql_install_db \
+ sudo -u "$sv" mysql_install_db \
--datadir="$home"/data \
--no-defaults
fi
-sudo find "$tool"/etc/mysql/bin/ -type f -perm /+x -exec \
- install -m 755 -o root -g root \
- -t /home/mysql/bin/ {} +
-
sudo ln -fns \
../sv/"$sv" \
/etc/service/"$sv"
"$tool"/local/runit-sv-start "$sv"
-while ! sudo -u mysql mysql -u mysql </dev/null
+while ! sudo mysql -u root </dev/null
do sleep 1; done
-# NOTE:
-# - ajoute l'accès par socket Unix à mysql
-# - ajoute les droits de super-utilisateur à mysql
-# - supprime l'accès par mot-de-passe à root
-# - supprime les bases de données de l'utilisateurice anonyme
-# - supprime l'utilisateurice anonyme
-# NOTE: mémo :
-# GRANT USAGE ON *.* TO 'root'@'*' IDENTIFIED WITH auth_socket;
-# CREATE USER 'root'@'localhost' IDENTIFIED WITH auth_socket;
-# UPDATE mysql.user SET Password='' WHERE user='root';
-# DELETE FROM mysql.user WHERE user = 'root' AND host NOT IN ('localhost', '127.0.0.1', '::1');
sudo mysql -u root --batch --verbose <<-EOF
- DELETE FROM mysql.user WHERE user = 'root' and plugin = '';
+ -- NOTE: supprime le login anonyme
+ DELETE FROM mysql.db WHERE User = '';
+ DELETE FROM mysql.user WHERE User = '';
- DROP PROCEDURE IF EXISTS mysql.create_user_mysql;
- DELIMITER //
- CREATE PROCEDURE mysql.create_user_mysql ()
- BEGIN
- IF NOT (EXISTS (SELECT User
- FROM mysql.user
- WHERE User='mysql'
- AND Host='localhost'
- LIMIT 1))
- THEN GRANT ALL PRIVILEGES ON *.* TO 'mysql'@'localhost' IDENTIFIED WITH auth_socket;
- END IF;
- END;
- //
- CALL mysql.create_user_mysql();
- DROP PROCEDURE mysql.create_user_mysql;
- UPDATE mysql.user SET grant_priv='Y',super_priv='Y' WHERE user='mysql';
- DELETE FROM mysql.db WHERE user = '';
- DELETE FROM mysql.user WHERE user = '';
-
- DROP PROCEDURE IF EXISTS mysql.create_user;
- CREATE PROCEDURE mysql.create_user (username VARCHAR(16), hostname VARCHAR(60))
- BEGIN
- IF NOT (EXISTS (SELECT User
- FROM mysql.user
- WHERE User = username
- AND Host = hostname
- LIMIT 1))
- THEN
- SET @QUERY = CONCAT("CREATE USER ", username, "@", hostname, " IDENTIFIED WITH auth_socket");
- PREPARE stmt FROM @QUERY;
- EXECUTE stmt;
- END IF;
- END;
- //
+ -- NOTE: supprime l'accès par mot-de-passe à root
+ DELETE FROM mysql.user WHERE User = 'root' and Plugin = '';
- DROP PROCEDURE IF EXISTS mysql.create_database;
- CREATE PROCEDURE mysql.create_database (dbname VARCHAR(16), username VARCHAR(16), hostname VARCHAR(60))
- BEGIN
- IF NOT (EXISTS (SELECT SCHEMA_NAME
- FROM INFORMATION_SCHEMA.SCHEMATA
- WHERE SCHEMA_NAME = dbname
- LIMIT 1))
- THEN
- SET @QUERY = CONCAT("CREATE DATABASE ", dbname, " CHARACTER SET utf8 COLLATE utf8_general_ci");
- PREPARE stmt FROM @QUERY;
- EXECUTE stmt;
- END IF;
- SET @QUERY = CONCAT("GRANT ALL PRIVILEGES ON ", dbname, ".* TO ", username, "@", hostname);
+ DROP PROCEDURE IF EXISTS mysql.create_super_user;
+ DELIMITER //
+ CREATE PROCEDURE mysql.create_super_user (username VARCHAR(16), hostname VARCHAR(60))
+ BEGIN
+ IF NOT (EXISTS (SELECT User
+ FROM mysql.user
+ WHERE User = username
+ AND Host = hostname
+ LIMIT 1))
+ THEN
+ SET @QUERY = CONCAT("CREATE USER ", username, "@", hostname, " IDENTIFIED WITH auth_socket");
PREPARE stmt FROM @QUERY;
EXECUTE stmt;
- END;
+ END IF;
+ END;
//
+ CALL mysql.create_super_user('mysql', 'localhost');
+ GRANT ALL PRIVILEGES ON *.* TO 'mysql'@'localhost';
+ UPDATE mysql.user SET Grant_priv='Y',Super_priv='Y' WHERE User='mysql';
+
+ CALL mysql.create_super_user('backup', 'localhost');
+ GRANT EVENT,LOCK TABLES,RELOAD,SELECT,SHOW VIEW ON *.* TO 'backup'@'localhost';
+
FLUSH PRIVILEGES;
EOF
+sudo adduser backup "$sv"-data
+sudo adduser backup "$sv"
+
+sudo find "$tool"/local/backup \
+ -mindepth 1 -maxdepth 1 -type f \
+ -exec install -m 750 -o backup -g backup \
+ -t ~backup/bin {} +
+sudo install -m 640 -o root -g root \
+ "$tool"/etc/cron.d/mysql-backup \
+ /etc/cron.d/mysql-backup
+sudo install -m 640 -o root -g root \
+ "$tool"/etc/sudoers.d/mysql-backup \
+ /etc/sudoers.d/mysql-backup
sv=${PWD#/etc/sv/}
eval "home=~$sv"
-install -d -m 1771 -o "$sv" -g "$sv" \
+install -d -m 1710 -o "$sv" -g "$sv"-data \
/run/mysqld \
/run/mysqld/sock
-sudo test -f /etc/postfix/$local_domainname/smtpd/x509/key.pem ||
-printf '%s\n' "$(tput rev)run before: remote/runit-configure dovecot$(tput sgr0)" && exit 1
+hint="run before: remote/runit-configure $sv"
+assert 'sudo test -f /etc/postfix/$local_domainname/smtpd/x509/key.pem' hint
sudo debconf-set-selections <<-EOF
postfix postfix/main_mailer_type select No configuration
sudo install -d -m 1751 -o postgres -g postgres-data \
/home/postgresql \
/home/postgresql/etc \
- /home/postgresql/bin \
/etc/postgresql \
/etc/postgresql/9.1 \
/etc/postgresql/9.1/main
sudo install -m 640 -o postgres -g postgres-data \
"$tool"/etc/postgresql/9.1/main/postgresql.conf \
/etc/postgresql/9.1/main/postgresql.conf
-sudo find "$tool"/etc/postgresql/bin/ -type f -perm /+x -exec \
- install -m 755 -o root -g root \
- -t /home/postgresql/bin/ {} +
sudo ln -fns \
../sv/"$sv" \
sudo mount -t sysfs sys /mnt/$local_fqdn/sys
mountpoint -q /mnt/$local_fqdn/dev ||
sudo mount --bind /dev /mnt/$local_fqdn/dev
-if test -d /mnt/$local_fqdn/root/src/vm/.git
+if test -d /mnt/$local_fqdn/root/src/$local_hostname/.git
then
- mountpoint -q /mnt/$local_fqdn/root/src/vm ||
- sudo mount --bind "$tool" /mnt/$local_fqdn/root/src/vm
+ mountpoint -q /mnt/$local_fqdn/root/src/$local_hostname ||
+ sudo mount --bind "$tool" /mnt/$local_fqdn/root/src/$local_hostname
else
- sudo rsync -a "$tool"/ /mnt/$local_fqdn/root/src/vm
+ sudo rsync -a "$tool"/ /mnt/$local_fqdn/root/src/$local_hostname
fi
sudo chroot /mnt/$local_fqdn /bin/bash || true
"$tool"/host/chroot-clean
. "$tool"/etc/host.sh
-set -x
-test "$(hostname --fqdn)" = "$local_host"
+. "$tool"/lib/log.sh
+assert 'test "$(hostname --fqdn)" = "$local_host"'
+
+export TRACE=${TRACE-set}
+test "$TRACE" = '' || set -x
-#!/bin/sh
-
export TERM=${TERM:-linux}
readonly tput_rev=${nocolor:-$(tput rev)}
readonly tput_sgr0=${nocolor:-$(tput sgr0)}
for var in "$@"
do
local val="$(eval printf %s "\"\${$var:-}\"" || false)" || false
- printf >&2 ": %s%s%s=%s%s%s" "$tput_bold$tput_setaf_0" "$var" "$tput_sgr0" "$tput_bold$tput_setaf_0" "$val" "$tput_sgr0"
+ printf >&2 ": %s%s%s=%s%s%s" "$tput_bold$tput_setaf_0" "$var" "$tput_sgr0" "$tput_rev" "$val" "$tput_sgr0"
done
printf >&2 ": %s%s%s\n" "$tput_rev" "$comment" "$tput_sgr0"
}
-warn () {
- local -
- set +x
- printf >&2 "%sWARNING%s" "$tput_setaf_3" "$tput_sgr0"
- local comment="$1"
- shift
- local var
- for var in "$@"
- do
- local val="$(eval printf %s "\"\${$var:-}\"" || false)" || false
- printf >&2 ": %s%s%s=%s%s%s" "$tput_bold$tput_setaf_0" "$var" "$tput_sgr0" "$tput_bold$tput_setaf_0" "$val" "$tput_sgr0"
- done
- printf >&2 ": %s%s%s" "$tput_rev" "$comment" "$tput_sgr0"
- local x
- if ! [ ${WARNING_CONTINUE:+set} ]
- then
- printf >&2 " (press Enter to continue)"
- read x
- else
- printf >&2 "\n"
- fi
- }
error () {
local -
set +x
+++ /dev/null
-#!/bin/sh -eux
-tool=${0%/*}/..
-ssh \
- -o StrictHostKeyChecking=yes \
- -o UserKnownHostsFile="$tool"/etc/openssh/known_hosts \
- -o HashKnownHosts=no \
- "$@"
+++ /dev/null
-#!/bin/sh
-set -e -f -u
-tool=${0%/*}/..
-gpg --decrypt "$tool"/var/sec/ssh/$SSH_ID.pass.gpg
+++ /dev/null
-Subproject commit 08a91875445c68ece50807be0eae28d1b7dd67a9
tool=$(readlink -e "${0%/*}/..")
. "$tool"/local/lib.sh
+user=$1; shift
getent passwd "$user" >/dev/null ||
-sudo adduser "$@" "$user"
+sudo /usr/sbin/adduser "$@" "$user"
--- /dev/null
+#!/bin/sh -eu
+# SYNTAX: $duplicity_options
+${TRACE:+set -x}
+
+while IFS=: read -r type trust size algo keyid date x x x x x cap x
+ do case $type,$cap in
+ (sub,e) encrypt_key=${keyid#????????};;
+ (sub,s) sign_key=$keyid;;
+ esac done <<-EOF
+ $(gpg --list-public-keys --with-colons \
+ -- "backup+$(hostname)@$(domainname)")
+ EOF
+
+/usr/bin/duplicity \
+ --archive-dir ~backup/archive \
+ --gpg-options --trusted-key="$sign_key" \
+ --encrypt-key "$encrypt_key" \
+ --sign-key "${sign_key#????????}" \
+ --use-agent \
+ -vw ${TRACE:+--verbosity info} \
+ "$@"
--- /dev/null
+#!/bin/sh -eu
+# SYNTAX: $data_dir $find_options -- $duplicity_options
+${TRACE:+set -x}
+
+test "$(id -u)" = "$(id -u backup)"
+
+data_dir=$1; shift
+find_options=
+while [ $# -gt 0 ]
+ do case $1 in
+ (--) shift; break;;
+ (*) find_options="$find_options $1"; shift;;
+ esac
+ done
+
+find ~backup/data/"$data_dir" -mindepth 1 $find_options -type d \
+ -printf '--name\0%P\0file://%p\0' |
+xargs -0rn3 ${TRACE:+-t} ~backup/bin/duplicity "$@"
--- /dev/null
+#!/bin/sh -eu
+# SYNTAX: $database_pattern -- $duplicity_options
+tool=$(readlink -e "${0%/*}/.")
+${TRACE:+set -x}
+
+database_pattern=$1; shift
+test ! "${1-}" = -- || shift
+
+install -d -m 770 -o backup -g backup \
+ ~backup/archive/mysql \
+ ~backup/data/mysql
+
+test "${TRACE:+set}" || no_print_statistics="-vw --no-print-statistics"
+"$tool"/mysql-snapshot "$database_pattern" \
+ -- "$tool"/duplicity \
+ --name 'mysql/"$database"' \
+ $no_print_statistics \
+ "$@" \
+ ~backup/snapshot/mysql/'"$database"' \
+ file:///home/backup/data/mysql/'"$database"'
--- /dev/null
+#!/bin/sh -eu
+# SYNTAX: $database_pattern -- $snapshot_eval
+# DESCRIPTION: crée un instantané pour chaque base de données MySQL $database donnée
+# DESCRIPTION: dans ~backup/snapshot/mysql/"$database",
+# DESCRIPTION: puis évalue $snapshot_eval,
+# DESCRIPTION: puis efface l'instantané.
+${TRACE:+set -x}
+
+test "$(id -u)" = "$(id -u backup)"
+
+database_pattern=$1; shift
+test ! "${1-}" = -- || shift
+test ! $# = 0 || set -- :
+
+install -d -m 770 -o backup -g backup \
+ ~backup/snapshot/mysql
+
+snapshot () {
+ local database="$1"; shift
+ test ! -e ~backup/snapshot/mysql/$database
+ # NOTE: soit une sauvegarde est déjà en cours,
+ # soit une précédente a échoué.
+ can_hotcopy=yes
+ while IFS=' ' read -r table engine
+ do
+ case $engine in
+ (MyISAM|ARCHIVE) :;;
+ (*) can_hotcopy=no;;
+ esac
+ done <<-EOF
+ $(mysql -u backup --batch --skip-column-names <<-EOF
+ SELECT table_name,engine
+ FROM information_schema.tables
+ WHERE table_schema = '$database';
+ EOF
+ )
+ EOF
+ case $can_hotcopy in
+ (yes)
+ cd /
+ sudo -u root find ~mysql-data -mindepth 1 -maxdepth 1 -type d -exec \
+ install -d -m 750 -o mysql -g backup {} +
+ cd - >/dev/null 2>&1
+ test "${TRACE:+set}" || quiet=--quiet
+ mysqlhotcopy --method=cp -u backup ${quiet:-} \
+ "$database" ~backup/snapshot/mysql
+ ;;
+ (no)
+ install -d -m 770 -o backup -g backup \
+ ~backup/snapshot/mysql/"$database"
+ mysqldump --opt --events -u backup ${TRACE:+--verbose} \
+ --result-file ~backup/snapshot/mysql/$database/dump.sql \
+ "$database"
+ ;;
+ esac
+ eval "$@"
+ rm -rf \
+ ~backup/snapshot/mysql/"$database"
+ }
+
+exit=0
+while IFS=' ' read -r database
+ do if ! snapshot "$database" "$@"
+ then
+ exit=1
+ cat >&2 <<-EOF
+ ERROR: snapshot "$database" "$@"
+ EOF
+ fi
+ done <<-EOF
+ $(mysql -u backup --batch --skip-column-names <<-EOF
+ SELECT schema_name
+ FROM information_schema.schemata
+ WHERE schema_name NOT IN ('information_schema', 'performance_schema')
+ AND schema_name LIKE '$database_pattern';
+ EOF
+ )
+ EOF
+exit $exit
"$tool"/local/user-root-configure
"$tool"/local/boot-configure
"$tool"/local/sysctl-configure
-"$tool"/local/user-configure
+"$tool"/local/duplicity-configure
"$tool"/local/gitolite-configure
"$tool"/local/shorewall-configure
"$tool"/local/runit-configure '*' -- '*'
+"$tool"/local/user-configure
sudo \
DEBIAN_FRONTEND=noninteractive \
DEBIAN_PRIORITY=low \
- dpkg-reconfigure "$@"
+ /usr/sbin/dpkg-reconfigure "$@"
"$home"/etc/gpg \
"$home"/etc/ssh
sudo install -d -m 770 -o backup -g backup \
- "$home"/mysql \
- "$home"/postgres
+ "$home"/bin \
+ "$home"/archive \
+ "$home"/data \
+ "$home"/snapshot
getent group sudo backup |
while IFS=: read -r group x x users
do while test -n "$users" && IFS=, read -r user users <<-EOF
sudo install -m 640 -o backup -g backup /dev/stdin \
"$home"/etc/ssh/authorized_keys
sudo ln -fns etc/gpg "$home"/.gnupg
-#sudo adduser backup mysql-data
-#sudo adduser backup postgres-data
--- /dev/null
+#!/bin/sh -eu
+tool=$(readlink -e "${0%/*}/..")
+. "$tool"/local/lib.sh
+
+LANG=C gpg \
+ --homedir "$tool"/var/pub/openpgp \
+ --no-default-keyring \
+ --no-permission-warning \
+ --secret-keyring /dev/null \
+ "$@"
--- /dev/null
+#!/bin/sh -eu
+# SYNTAX: $sv
+tool=$(readlink -e "${0%/*}/..")
+. "$tool"/local/lib.sh
+
+sv="$1"
+#sudo chmod u+x /etc/init.d/"$sv"
+sudo insserv --force --remove "$sv"
+sudo test ! -x /etc/init.d/"$sv" ||
+sudo /etc/init.d/"$sv" stop
+sudo chmod ugo-x /etc/init.d/"$sv"
. "$tool"/etc/local.sh
-set -x
-test "$(hostname --fqdn)" = "$local_fqdn"
+. "$tool"/lib/log.sh
+assert 'test "$(hostname --fqdn)" = "$local_fqdn"'
+
+export TRACE=${TRACE-set}
+test "$TRACE" = '' || set -x
$(cat /etc/securetty)
xvc0
EOF
+find "$tool"/etc/profile.d -type f -name "*.sh" -exec \
+ sudo install -t /etc/profile.d -m 664 -o root -g root {} +
--- /dev/null
+#!/bin/sh -eu
+# SYNTAX: $databases [...]
+tool=$(readlink -e "${0%/*}/..")
+TRACE=${TRACE:-}
+. "$tool"/local/lib.sh
+
+for database in $(sudo -u backup find ~backup/data/mysql \
+ -mindepth 1 -maxdepth 1 -type d \
+ ${@:+-false $(printf -- '-or -name %s\n' "$@")} \
+ -printf '%f\n')
+ do
+ # NOTE: 0.9765625 = $(units -1 kilobytes kibibytes)
+ size=$(bc <<-EOF
+ scale=0; print ($(sudo -u backup du -ks ~backup/data/mysql/"$database" | cut -f 1) * 0.9765625 / 1), " Kio"
+ EOF
+ )
+ info '' database size
+ cat <<-EOF
+ ${tput_setaf_0}${tput_bold}
+ $(sudo -u backup ~backup/bin/duplicity 2>/dev/null \
+ --name mysql/"$database" \
+ collection-status \
+ file:///home/backup/data/mysql/"$database")
+ ${tput_sgr0}
+ EOF
+ done
-#!/bin/sh -eux
+#!/bin/sh -eu
+tool=$(readlink -e "${0%/*}/..")
+. "$tool"/local/lib.sh
+
db="$1"
user="${2:-$1}"
-sudo -u mysql mysql --batch --verbose <<-EOF
+sudo -u mysql mysql -u mysql --batch --verbose <<-EOF
+ DROP PROCEDURE IF EXISTS mysql.create_database;
+ DELIMITER //
+ CREATE PROCEDURE mysql.create_database (dbname VARCHAR(16), username VARCHAR(16), hostname VARCHAR(60))
+ BEGIN
+ IF NOT (EXISTS (SELECT SCHEMA_NAME
+ FROM INFORMATION_SCHEMA.SCHEMATA
+ WHERE SCHEMA_NAME = dbname
+ LIMIT 1))
+ THEN
+ SET @QUERY = CONCAT("CREATE DATABASE ", dbname, " CHARACTER SET utf8 COLLATE utf8_general_ci");
+ PREPARE stmt FROM @QUERY;
+ EXECUTE stmt;
+ END IF;
+ SET @QUERY = CONCAT("GRANT ALL PRIVILEGES ON ", dbname, ".* TO ", username, "@", hostname);
+ PREPARE stmt FROM @QUERY;
+ EXECUTE stmt;
+ END;
+ //
CALL mysql.create_database('$db', '$user', 'localhost');
EOF
-#!/bin/sh -eux
+#!/bin/sh -eu
+tool=$(readlink -e "${0%/*}/..")
+. "$tool"/local/lib.sh
+
user="$1"
sudo -u mysql mysql -u mysql --batch --verbose <<-EOF
+ DROP PROCEDURE IF EXISTS mysql.create_user;
+ DELIMITER //
+ CREATE PROCEDURE mysql.create_user (username VARCHAR(16), hostname VARCHAR(60))
+ BEGIN
+ IF NOT (EXISTS (SELECT User
+ FROM mysql.user
+ WHERE User = username
+ AND Host = hostname
+ LIMIT 1))
+ THEN
+ SET @QUERY = CONCAT("CREATE USER ", username, "@", hostname, " IDENTIFIED WITH auth_socket");
+ PREPARE stmt FROM @QUERY;
+ EXECUTE stmt;
+ END IF;
+ END;
+ //
CALL mysql.create_user('$user', 'localhost');
EOF
sudo adduser "$user" mysql-data
while [ $# -gt 0 ]
do case $1 in
(--) shift; break;;
- (*) services="$services ${1#etc/sv/}"; shift;;
+ (*) services="$services ${1#/etc/sv/}"; shift;;
esac
done
#for sv in $(sudo find /etc/sv \
tool=$(readlink -e "${0%/*}/..")
. "$tool"/local/lib.sh
-user="$1"; shift
+user=$1; shift
"$tool"/local/adduser "$user" --disabled-password "$@"
# NOTE: le mot-de-passe doit être initialisé par l'utilisateur à l'aide de passwd-init .
eval home="~$user"
sudo install -m 640 -o "$user" -g "$user" \
"$tool"/var/pub/ssh/"$user".key \
"$home"/etc/ssh/authorized_keys
-gpg \
- --homedir "$tool"/var/pub/openpgp/ \
- --no-default-keyring \
- --secret-keyring /dev/null \
- --export |
+"$tool"/local/gpg-local --export |
sudo -u "$user" gpg --import -
tool=$(readlink -e "${0%/*}/..")
. "$tool"/local/lib.sh
+user=$1; shift
"$tool"/local/user-configure
-user=$1
"$tool"/local/adduser "$user" --disabled-password
eval home="~$user"
sudo adduser "$user" sudo
sudo install -m 640 -o root -g root \
"$tool"/var/pub/ssh/"$user".key \
"$home"/etc/ssh/authorized_keys
-gpg \
- --homedir "$tool"/var/pub/openpgp/ \
- --no-default-keyring \
- --secret-keyring /dev/null \
- --export |
+"$tool"/local/gpg-local --export |
sudo -u "$user" gpg --import -
"$tool"/local/initramfs-configure
"$tool"/local/user-root-configure
#!/bin/sh -eu
-# SYNTAX: $user
tool=$(readlink -e "${0%/*}/..")
. "$tool"/local/lib.sh
/etc/skel/var/run/ssh
sudo ln -fns etc/ssh /etc/skel/.ssh
sudo ln -fns etc/gpg /etc/skel/.gnupg
-sudo install -m 640 -o root -g root /dev/stdin \
- /etc/sudoers.d/passwd-init <<-EOF
- %sudo ALL=(ALL) NOPASSWD: /bin/sh -e -f -u -c \\
- case \$(/usr/bin/passwd --status "\$SUDO_USER") in \\
- ("\$SUDO_USER L "*) /usr/bin/passwd \$SUDO_USER;; esac
- EOF
-sudo install -m 640 -o root -g root /dev/stdin \
- /etc/sudoers.d/etckeeper-unclean <<-EOF
- %sudo ALL=(ALL) NOPASSWD: /usr/bin/etckeeper unclean
- EOF
-sudo install -m 640 -o root -g root /dev/stdin \
- /etc/sudoers.d/env_keep <<-EOF
- Defaults env_keep = " \\
- EDITOR \\
- GIT_AUTHOR_NAME \\
- GIT_AUTHOR_EMAIL \\
- GIT_COMMITTER_NAME \\
- GIT_COMMITTER_EMAIL \\
- "
- EOF
+sudo find "$tool"/etc/sudoers.d \
+ -mindepth 1 -maxdepth 1 -type f -exec \
+ install -m 640 -o root -g root \
+ -t /etc/sudoers.d {} +
+sudo install -m 640 -o root -g root \
+ "$tool"/etc/sudoers.d/passwd-init \
+ /etc/sudoers.d/passwd-init
+sudo install -m 640 -o root -g root \
+ "$tool"/etc/sudoers.d/etckeeper-unclean \
+ /etc/sudoers.d/etckeeper-unclean
+sudo install -m 640 -o root -g root \
+ "$tool"/etc/sudoers.d/env_keep \
+ /etc/sudoers.d/env_keep
sudo install -m 755 -o root -g root \
"$tool"/local/passwd-init \
/usr/local/bin/passwd-init
--- /dev/null
+#!/bin/sh -eu
+# SYNTAX: $path $rsync_options
+# DESCRIPTION: récupère les données sauvegardées automatiquement par duplicity localement ;
+# DESCRIPTION: les anciennes versions des données sont déplacées dans un dossier daté.
+tool=$(readlink -e "${0%/*}/..")
+. "$tool"/remote/lib.sh
+
+path=${1-}; test ! "${1+set}" || shift
+date=${date:-$(date +'%Y%m%d+%H%M%S%z')}
+mkdir -p \
+ "$tool"/var/backup/current \
+ "$tool"/var/backup/"$date"
+rsync \
+ --backup \
+ --backup-dir ../"$date" \
+ --compress-level=0 \
+ --delete \
+ --delete-during \
+ --inplace \
+ ${TRACE:+--itemize-changes} \
+ --links \
+ --partial \
+ ${TRACE:+--progress} \
+ --recursive \
+ --rsh "$tool/remote/ssh -o Compression=no" \
+ --times \
+ "$@" \
+ backup@"$local_fqdn":data/"$path" \
+ "$tool"/var/backup/current
tool=$(readlink -e "${0%/*}/..")
. "$tool"/remote/lib.sh
-gpg --export-options export-reset-subkey-passwd \
+PATH=/usr/lib/gnupg2:"$PATH"
+
+IFS= read -r pass <<-EOF
+ $(gpg --decrypt "$tool"/var/sec/openpgp/backup+"$local_hostname"@"$local_domainname".pass.gpg)
+ EOF
+for fpr in $(remote/gpg --list-secret-keys --with-colons --with-fingerprint --with-fingerprint \
+ -- "backup+$local_hostname@$local_domainname" | grep '^fpr:' | cut -d : -f 10)
+ do gpg-preset-passphrase --preset -v $fpr <<-EOF
+ $pass
+ EOF
+ done
+
+"$tool"/remote/gpg --export-options export-reset-subkey-passwd \
--export-secret-subkeys "backup+$local_hostname@$local_domainname" |
-"$tool"/remote/ssh gpg --import -
+"$tool"/remote/ssh backup@$local_fqdn gpg --import -
. "$tool"/remote/lib.sh
git remote rm host || true
-git remote add host $local_host:src/vm
+git remote add host $local_host:src/$local_hostname
git config --replace remote.host.push HEAD:refs/remotes/master
git remote rm local || true
-git remote add local $local_fqdn:src/vm
+git remote add local $local_fqdn:src/$local_hostname
git config --replace remote.local.push HEAD:refs/remotes/master
git submodule update --init
tool=$(readlink -e "${0%/*}/..")
. "$tool"/remote/lib.sh
-remote=${1:-$local_fqdn}; shift
-GIT_SSH="$tool"/remote/ssh git push -v "$remote" "$@"
+GIT_SSH="$tool"/remote/ssh git push -v "$@"
%commit
EOF
fi
-caps=$(
- "$tool"/remote/gpg --with-colons --fixed-list-mode --with-fingerprint --list-secret-keys \
- -- "$uid" |
- sed -e 's/^ssb\(:[^:]*\)\{11\}.*/\1/;t;d'
- )
+caps=$("$tool"/remote/gpg --with-colons --fixed-list-mode --with-fingerprint --list-secret-keys \
+ -- "$uid" | grep '^ssb:' | cut -d : -f 12)
for cap in ${subkey_caps:-}
do
- test ! "$caps" = "$(printf %s "$caps" | sed -e 's/'"$cap"'//g')" ||
+ printf '%s\n' $caps | grep -Fqx "$cap" ||
printf '%s\n' 8 s e $cap q 4096 ${expire:-0} save |
"$tool"/remote/gpg --keyid-format "long" --with-colons --fixed-list-mode --expert \
--passphrase-fd 3 --command-fd 0 --edit-key "$uid" addkey 3<<-EOF
-. "$tool"/etc/local.sh
-set -x
-test ! "$(hostname --fqdn)" = "$local_fqdn"
-test ! "$(hostname --fqdn)" = "$local_host"
+. "$tool"/etc/remote.sh
+. "$tool"/lib/log.sh
+assert 'test ! "$(hostname --fqdn)" = "$local_fqdn"'
+assert 'test ! "$(hostname --fqdn)" = "$local_host"'
+
+export TRACE=${TRACE-set}
+test "$TRACE" = '' || set -x
+++ /dev/null
-#!/bin/sh -eu
-tool=$(readlink -e "${0%/*}/..")
-. "$tool"/remote/lib.sh
-
-mkdir -p "$tool"/var/backup/mysql
-"$tool"/remote/ssh -l backup '
- for db in $(sudo -u backup mysql -u backup --skip-column-names <<-EOF
- SELECT schema_name
- FROM information_schema.schemata
- WHERE schema_name NOT IN ("information_schema", "performance_schema");
- EOF
- ); do
- echo $db
- done
- '
-#!/bin/sh -eux
-tool=${0%/*}/..
+#!/bin/sh -eu
+tool=$(readlink -e "${0%/*}/..")
+. "$tool"/remote/lib.sh
+
ssh \
-o StrictHostKeyChecking=yes \
-o UserKnownHostsFile="$tool"/etc/openssh/known_hosts \
-#!/bin/sh
-set -e -f -u
-tool=${0%/*}/..
+#!/bin/sh -eu
+tool=$(readlink -e "${0%/*}/..")
+. "$tool"/remote/lib.sh
+
gpg --decrypt "$tool"/var/sec/ssh/$SSH_ID.pass.gpg