From: Julien Moutinho Date: Sat, 20 Apr 2013 17:03:19 +0000 (+0200) Subject: Correction : {host,local,remote}/ : duplicity + MySQL. X-Git-Url: https://git.cyclocoop.org/?p=lhc%2Fateliers.git;a=commitdiff_plain;h=a11ad78672a096632b15a660509d7dd5f7c5eae5 Correction : {host,local,remote}/ : duplicity + MySQL. --- diff --git a/README b/README index a52bf87..ca4ce74 100644 --- a/README +++ b/README @@ -6,8 +6,9 @@ ATTENTION: 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 @@ -25,7 +26,7 @@ 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 @@ -45,8 +46,7 @@ TASK: démarrer la VM @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 diff --git a/etc/cron.d/mysql-backup b/etc/cron.d/mysql-backup new file mode 100644 index 0000000..f5642db --- /dev/null +++ b/etc/cron.d/mysql-backup @@ -0,0 +1,3 @@ +MAILTO=backup +# m h dom mon dow user command +0 3 */24 * * backup bin/mysql-backup '\%' -- --full-if-older-than 90D && bin/duplicity-remove mysql -maxdepth 1 -- remove-all-but-n-full 1 --force diff --git a/etc/local.sh b/etc/local.sh index 2e43d8f..991a27f 100644 --- a/etc/local.sh +++ b/etc/local.sh @@ -1,4 +1,4 @@ -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" diff --git a/etc/nginx/site.d/gitweb-tls/local.sh b/etc/nginx/site.d/gitweb-tls/local.sh index 8a1a8b6..eed94a4 100644 --- a/etc/nginx/site.d/gitweb-tls/local.sh +++ b/etc/nginx/site.d/gitweb-tls/local.sh @@ -1,5 +1,5 @@ -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 \ diff --git a/etc/nginx/site.d/lhc-questionnaires-tls/local.sh b/etc/nginx/site.d/lhc-questionnaires-tls/local.sh index 2219391..ef7611a 100644 --- a/etc/nginx/site.d/lhc-questionnaires-tls/local.sh +++ b/etc/nginx/site.d/lhc-questionnaires-tls/local.sh @@ -1,5 +1,5 @@ -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 \ diff --git a/etc/nginx/site.d/lhc-questionnaires/local.sh b/etc/nginx/site.d/lhc-questionnaires/local.sh index e407240..580e992 100644 --- a/etc/nginx/site.d/lhc-questionnaires/local.sh +++ b/etc/nginx/site.d/lhc-questionnaires/local.sh @@ -1,5 +1,5 @@ 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" diff --git a/etc/nginx/site.d/lhc-remorque/local.sh b/etc/nginx/site.d/lhc-remorque/local.sh index ee73d00..0824349 100644 --- a/etc/nginx/site.d/lhc-remorque/local.sh +++ b/etc/nginx/site.d/lhc-remorque/local.sh @@ -1,6 +1,6 @@ -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 diff --git a/etc/nginx/site.d/lhc-stats-tls/local.sh b/etc/nginx/site.d/lhc-stats-tls/local.sh index cc04380..56fd0be 100644 --- a/etc/nginx/site.d/lhc-stats-tls/local.sh +++ b/etc/nginx/site.d/lhc-stats-tls/local.sh @@ -1,5 +1,5 @@ -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 \ diff --git a/etc/nginx/site.d/lhc-stats/local.sh b/etc/nginx/site.d/lhc-stats/local.sh index 31bc2be..5f87955 100644 --- a/etc/nginx/site.d/lhc-stats/local.sh +++ b/etc/nginx/site.d/lhc-stats/local.sh @@ -1,5 +1,5 @@ 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" diff --git a/etc/nginx/site.d/lhc-www-tls/local.sh b/etc/nginx/site.d/lhc-www-tls/local.sh index aed7539..be4604c 100644 --- a/etc/nginx/site.d/lhc-www-tls/local.sh +++ b/etc/nginx/site.d/lhc-www-tls/local.sh @@ -1,5 +1,5 @@ -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 \ diff --git a/etc/nginx/site.d/sympa/local.sh b/etc/nginx/site.d/sympa/local.sh index 5b6dcba..2a2f232 100644 --- a/etc/nginx/site.d/sympa/local.sh +++ b/etc/nginx/site.d/sympa/local.sh @@ -1,5 +1,5 @@ -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 \ diff --git a/etc/postfix/aliases.m4 b/etc/postfix/aliases.m4 index 02790e7..5b4a6e3 100644 --- a/etc/postfix/aliases.m4 +++ b/etc/postfix/aliases.m4 @@ -1,6 +1,7 @@ # See man 5 aliases for format abuse: root admin: root +backup: root contact: root hostmaster: root mailer-daemon: root diff --git a/etc/profile.d/path.sh b/etc/profile.d/path.sh new file mode 100644 index 0000000..022054d --- /dev/null +++ b/etc/profile.d/path.sh @@ -0,0 +1,3 @@ +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" diff --git a/etc/remote.sh b/etc/remote.sh new file mode 100644 index 0000000..c4d10f9 --- /dev/null +++ b/etc/remote.sh @@ -0,0 +1 @@ +. "$tool"/etc/local.sh diff --git a/etc/sudoers.d/env_keep b/etc/sudoers.d/env_keep new file mode 100644 index 0000000..93bf2aa --- /dev/null +++ b/etc/sudoers.d/env_keep @@ -0,0 +1,7 @@ +Defaults env_keep = " \ + EDITOR \ + GIT_AUTHOR_NAME \ + GIT_AUTHOR_EMAIL \ + GIT_COMMITTER_NAME \ + GIT_COMMITTER_EMAIL \ + " diff --git a/etc/sudoers.d/etckeeper-unclean b/etc/sudoers.d/etckeeper-unclean new file mode 100644 index 0000000..6a965eb --- /dev/null +++ b/etc/sudoers.d/etckeeper-unclean @@ -0,0 +1 @@ +%sudo ALL=(ALL) NOPASSWD: /usr/bin/etckeeper unclean diff --git a/etc/sudoers.d/mysql-backup b/etc/sudoers.d/mysql-backup new file mode 100644 index 0000000..5d58810 --- /dev/null +++ b/etc/sudoers.d/mysql-backup @@ -0,0 +1,5 @@ +# 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 {} + diff --git a/etc/sudoers.d/passwd-init b/etc/sudoers.d/passwd-init new file mode 100644 index 0000000..6be02f3 --- /dev/null +++ b/etc/sudoers.d/passwd-init @@ -0,0 +1,3 @@ +%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 diff --git a/etc/sv/dovecot/local.sh b/etc/sv/dovecot/local.sh index 9b0f37b..df5aa38 100644 --- a/etc/sv/dovecot/local.sh +++ b/etc/sv/dovecot/local.sh @@ -1,8 +1,8 @@ "$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 \ diff --git a/etc/sv/mysql/local.sh b/etc/sv/mysql/local.sh index 54abbf3..847f870 100644 --- a/etc/sv/mysql/local.sh +++ b/etc/sv/mysql/local.sh @@ -3,14 +3,14 @@ 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 \ @@ -18,108 +18,81 @@ eval "home=~$sv" --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 &1 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 diff --git a/etc/sv/postfix/local.sh b/etc/sv/postfix/local.sh index 8d6230d..2c64f52 100644 --- a/etc/sv/postfix/local.sh +++ b/etc/sv/postfix/local.sh @@ -1,5 +1,5 @@ -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 diff --git a/etc/sv/postgres/local.sh b/etc/sv/postgres/local.sh index cb8eee6..1bcd0f6 100644 --- a/etc/sv/postgres/local.sh +++ b/etc/sv/postgres/local.sh @@ -24,7 +24,6 @@ sudo rm -rf \ 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 @@ -64,9 +63,6 @@ sudo install -m 640 -o postgres -g postgres /dev/stdin \ 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" \ diff --git a/host/chroot b/host/chroot index 3ea00c4..1367155 100755 --- a/host/chroot +++ b/host/chroot @@ -15,12 +15,12 @@ mountpoint -q /mnt/$local_fqdn/sys || 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 diff --git a/host/lib.sh b/host/lib.sh index 8eb2dfa..c6ebc9e 100644 --- a/host/lib.sh +++ b/host/lib.sh @@ -1,3 +1,6 @@ . "$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 diff --git a/lib/log.sh b/lib/log.sh index e302960..d8aea8a 100644 --- a/lib/log.sh +++ b/lib/log.sh @@ -1,5 +1,3 @@ -#!/bin/sh - export TERM=${TERM:-linux} readonly tput_rev=${nocolor:-$(tput rev)} readonly tput_sgr0=${nocolor:-$(tput sgr0)} @@ -19,32 +17,10 @@ info () { 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 diff --git a/lib/ssh b/lib/ssh deleted file mode 100755 index 2ebd542..0000000 --- a/lib/ssh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -eux -tool=${0%/*}/.. -ssh \ - -o StrictHostKeyChecking=yes \ - -o UserKnownHostsFile="$tool"/etc/openssh/known_hosts \ - -o HashKnownHosts=no \ - "$@" diff --git a/lib/ssh-pass b/lib/ssh-pass deleted file mode 100755 index 8da082a..0000000 --- a/lib/ssh-pass +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -set -e -f -u -tool=${0%/*}/.. -gpg --decrypt "$tool"/var/sec/ssh/$SSH_ID.pass.gpg diff --git a/lib/tool/sh b/lib/tool/sh deleted file mode 160000 index 08a9187..0000000 --- a/lib/tool/sh +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 08a91875445c68ece50807be0eae28d1b7dd67a9 diff --git a/local/adduser b/local/adduser index 08950fe..83e4ee9 100755 --- a/local/adduser +++ b/local/adduser @@ -2,5 +2,6 @@ tool=$(readlink -e "${0%/*}/..") . "$tool"/local/lib.sh +user=$1; shift getent passwd "$user" >/dev/null || -sudo adduser "$@" "$user" +sudo /usr/sbin/adduser "$@" "$user" diff --git a/local/backup/duplicity b/local/backup/duplicity new file mode 100755 index 0000000..a26f5fd --- /dev/null +++ b/local/backup/duplicity @@ -0,0 +1,21 @@ +#!/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} \ + "$@" diff --git a/local/backup/duplicity-remove b/local/backup/duplicity-remove new file mode 100755 index 0000000..5143736 --- /dev/null +++ b/local/backup/duplicity-remove @@ -0,0 +1,18 @@ +#!/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 "$@" diff --git a/local/backup/mysql-backup b/local/backup/mysql-backup new file mode 100755 index 0000000..cbd0b20 --- /dev/null +++ b/local/backup/mysql-backup @@ -0,0 +1,20 @@ +#!/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"' diff --git a/local/backup/mysql-snapshot b/local/backup/mysql-snapshot new file mode 100755 index 0000000..5140ffc --- /dev/null +++ b/local/backup/mysql-snapshot @@ -0,0 +1,79 @@ +#!/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 diff --git a/local/configure b/local/configure index 48dee54..b9192be 100755 --- a/local/configure +++ b/local/configure @@ -14,7 +14,8 @@ tool=$(readlink -e "${0%/*}/..") "$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 diff --git a/local/dpkg-reconfigure b/local/dpkg-reconfigure index b4ab82a..fe3db88 100755 --- a/local/dpkg-reconfigure +++ b/local/dpkg-reconfigure @@ -5,4 +5,4 @@ tool=$(readlink -e "${0%/*}/..") sudo \ DEBIAN_FRONTEND=noninteractive \ DEBIAN_PRIORITY=low \ - dpkg-reconfigure "$@" + /usr/sbin/dpkg-reconfigure "$@" diff --git a/local/duplicity-configure b/local/duplicity-configure index 6c81e05..95a8fc0 100755 --- a/local/duplicity-configure +++ b/local/duplicity-configure @@ -17,8 +17,10 @@ sudo install -d -m 750 -o backup -g backup \ "$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 @@ -31,5 +33,3 @@ while IFS=: read -r group x x users 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 diff --git a/local/gpg-local b/local/gpg-local new file mode 100755 index 0000000..2596f81 --- /dev/null +++ b/local/gpg-local @@ -0,0 +1,10 @@ +#!/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 \ + "$@" diff --git a/local/insserv-remove b/local/insserv-remove new file mode 100755 index 0000000..624858d --- /dev/null +++ b/local/insserv-remove @@ -0,0 +1,11 @@ +#!/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" diff --git a/local/lib.sh b/local/lib.sh index 4f000ac..8ae4069 100644 --- a/local/lib.sh +++ b/local/lib.sh @@ -1,3 +1,6 @@ . "$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 diff --git a/local/login-configure b/local/login-configure index 956b2da..0251cdf 100755 --- a/local/login-configure +++ b/local/login-configure @@ -28,3 +28,5 @@ sudo install -m 644 -o root -g root /dev/stdin \ $(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 {} + diff --git a/local/mysql-backup-status b/local/mysql-backup-status new file mode 100755 index 0000000..9a17eec --- /dev/null +++ b/local/mysql-backup-status @@ -0,0 +1,26 @@ +#!/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 diff --git a/local/mysql-database-create b/local/mysql-database-create index adc6ecd..18a5985 100755 --- a/local/mysql-database-create +++ b/local/mysql-database-create @@ -1,6 +1,27 @@ -#!/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 diff --git a/local/mysql-user-create b/local/mysql-user-create index 1b234fa..50bb6d1 100755 --- a/local/mysql-user-create +++ b/local/mysql-user-create @@ -1,6 +1,25 @@ -#!/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 diff --git a/local/runit-configure b/local/runit-configure index 06cb218..8332233 100755 --- a/local/runit-configure +++ b/local/runit-configure @@ -16,7 +16,7 @@ if test $# = 0 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 \ diff --git a/local/user-add b/local/user-add index f734444..e5874f1 100755 --- a/local/user-add +++ b/local/user-add @@ -3,7 +3,7 @@ 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" @@ -11,9 +11,5 @@ sudo adduser "$user" users 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 - diff --git a/local/user-admin-add b/local/user-admin-add index 97ad0d2..0ba1683 100755 --- a/local/user-admin-add +++ b/local/user-admin-add @@ -3,19 +3,15 @@ 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 diff --git a/local/user-configure b/local/user-configure index fc825f7..85b6cb0 100755 --- a/local/user-configure +++ b/local/user-configure @@ -1,5 +1,4 @@ #!/bin/sh -eu -# SYNTAX: $user tool=$(readlink -e "${0%/*}/..") . "$tool"/local/lib.sh @@ -20,26 +19,19 @@ sudo install -d -m 770 -o root -g root \ /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 diff --git a/remote/backup-fetch b/remote/backup-fetch new file mode 100755 index 0000000..b8c5ccd --- /dev/null +++ b/remote/backup-fetch @@ -0,0 +1,29 @@ +#!/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 diff --git a/remote/duplicity-key-send b/remote/duplicity-key-send index 650e219..52ff14a 100755 --- a/remote/duplicity-key-send +++ b/remote/duplicity-key-send @@ -2,6 +2,18 @@ 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 - diff --git a/remote/git-configure b/remote/git-configure index 0601208..77c6ec3 100755 --- a/remote/git-configure +++ b/remote/git-configure @@ -3,9 +3,9 @@ tool=$(readlink -e "${0%/*}/..") . "$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 diff --git a/remote/git-push b/remote/git-push index 8c6a241..164dccf 100755 --- a/remote/git-push +++ b/remote/git-push @@ -2,5 +2,4 @@ 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 "$@" diff --git a/remote/gpg-gen-key b/remote/gpg-gen-key index fc7ddf7..8a47b03 100755 --- a/remote/gpg-gen-key +++ b/remote/gpg-gen-key @@ -30,14 +30,11 @@ if ! "$tool"/remote/gpg --list-keys -- "$uid" >/dev/null %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 diff --git a/remote/lib.sh b/remote/lib.sh index c87432d..3c7659f 100644 --- a/remote/lib.sh +++ b/remote/lib.sh @@ -1,4 +1,7 @@ -. "$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 diff --git a/remote/mysql-backup b/remote/mysql-backup deleted file mode 100755 index 0879dfd..0000000 --- a/remote/mysql-backup +++ /dev/null @@ -1,15 +0,0 @@ -#!/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 - ' diff --git a/remote/ssh b/remote/ssh index 2ebd542..b506244 100755 --- a/remote/ssh +++ b/remote/ssh @@ -1,5 +1,7 @@ -#!/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 \ diff --git a/remote/ssh-pass b/remote/ssh-pass index 8da082a..2cf063f 100755 --- a/remote/ssh-pass +++ b/remote/ssh-pass @@ -1,4 +1,5 @@ -#!/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 diff --git a/var/.gitignore b/var/.gitignore index b687655..ec001c7 100644 --- a/var/.gitignore +++ b/var/.gitignore @@ -1 +1,2 @@ +backup sec diff --git a/var/pub/openpgp/trustdb.gpg b/var/pub/openpgp/trustdb.gpg index 927bd68..86cd72c 100644 Binary files a/var/pub/openpgp/trustdb.gpg and b/var/pub/openpgp/trustdb.gpg differ