Простая система бэкапа конфигов с удаленных хостов

Схема проста:
1. На хосте, куда будем складывать бэкапы, создаем пользователя backup, создаем для него пару ключей (приватный и публичный) для ssh; shell и homedir этому пользователю нужны - собственно, в homedir сложим бэкапы.
2. На остальных хостах заводим такого же пользователя backup (если есть линукс-хосты, то пусть пользователя зовут backuper - имя backup уже занято, и лучше с этим не связываться); складываем в homedir/.ssh этого пользователя публичный ключ в виде файла authorized_keys
3. На тех же хостах разрешаем этому пользователю выполнять "sudo tar *" без пароля.
4. На каждом из хостов заводим файл /usr/local/etc/backup.conf (для Linux - /etc/backup.conf), в котором указываем список директорий и файлов для архивирования.
5. На хосте-хранилище пишем скрипт, который будет выполняться по расписанию в crontab от имени пользователя backup - собственно, на каждый из наших хостов этот пользователь будет заходить по ssh с авторизацией по ключу, запускать tar, который будет считывать из файла список того, что следует архивировать, а после сам архив будет сложен на хост-хранилище.
6. Конфиги самого хоста-хранилища по такой же схеме будем бэкапить на другой хост :)

Реализация.
Итак, хост-хранилище (FreeBSD 7.1) у нас называется share.company.com, все остальные хосты тоже относятся к домену company.com. У нас есть пачка машин с FreeBSD 7.1, одна - с FreeBSD 6.4, и пара - с Debian Linux (в будущем, возможно, добавится хост с Fedora 10).

Готовим хост-хранилище (строку в crontab лучше закомментить, пока не будут выполнены подготовительные работы на всех нужных хостах).

root@share# adduser
username: backup
homedir: /home/backup
shell: /bin/sh
root@share# vipw
Убираем пароль, и в результате получаем подобную строку:
backup:!:1014:1015::0:0:backup operator:/home/backup:/bin/sh

root@share# su backup
backup@share# cd ~
backup@share# mkdir .ssh
backup@share# cd .ssh
backup@share# ssh-keygen -t rsa
backup@share# mv id_rsa.pub authorized_keys
backup@share# exit
root@share# ee /usr/local/sbin/backup-hosts.sh
(пишем скрипт-обходчик)

#!/bin/sh
BSDHOSTS="mantis frank mark abakus butterfly"
LINUXHOSTS="bender qos"
SSH="/usr/bin/ssh -p 2222"
ARCHDIR="/home/backup"
DATE=`/bin/date '+%Y-%m-%d'`
BSDRUSER="backup"
LINUXRUSER="backuper"
BSDTARGETLIST="/usr/local/etc/backup.conf"
LINUXTARGETLIST="/etc/backup.conf"
BSDRSUDO="/usr/local/bin/sudo"
BSDRTAR="/usr/bin/tar"
LINUXRSUDO="/usr/bin/sudo"
LINUXRTAR="/bin/tar"
for HOST in ${BSDHOSTS}; do
if [ ! -d ${ARCHDIR}/${HOST} ]; then
/bin/mkdir ${ARCHDIR}/${HOST}
fi
RHOST="${HOST}.company.com"
${SSH} ${BSDRUSER}@${RHOST} ${BSDRSUDO} ${BSDRTAR} -czf - -T ${BSDTARGETLIST} | \
/bin/dd of=${ARCHDIR}/${HOST}/${DATE}.tar.gz
done
for HOST in ${LINUXHOSTS}; do
if [ ! -d ${ARCHDIR}/${HOST} ]; then
/bin/mkdir ${ARCHDIR}/${HOST}
fi
RHOST="${HOST}.company.com"
${SSH} ${LINUXRUSER}@${RHOST} ${LINUXRSUDO} ${LINUXRTAR} -czf - -T ${LINUXTARGETLIST} | \
/bin/dd of=${ARCHDIR}/${HOST}/${DATE}.tar.gz
done

root@share# ee /etc/crontab

[...skipped...]
2 5 * * * backup /usr/local/sbin/backup-hosts.sh

Теперь разберемся с FreeBSD-машиной, откуда будем забирать бэкапы:

root@mark# adduser
username: backup
homedir: /home/backup
shell: /bin/sh
root@mark# vipw
[...skipped...]
backup:!:1003:1003::0:0:backup operator:/home/backup:/bin/sh

root@mark# cd /home/backup
root@mark# mkdir .ssh
root@mark# cd .ssh
root@mark# ee authorized_keys
(теперь в другой вкладке терминала на share делаем cat /home/backup/.ssh/authorized_keys - и аккуратно, без лишних пробелов, копипастим полученную длинную строку в созданный на mark файл authorized_keys; или любым другим способом переносим публичный ключ юзера backup с машины share на машину mark)

root@mark# chown -R backup:backup /home/backup/.ssh
root@mark# chmod 700 /home/backup/.ssh
root@mark# visudo
[...skipped...]
backup ALL= NOPASSWD: /usr/bin/tar *

root@mark# ee /usr/local/etc/backup.conf
/usr/local/etc
/etc
/usr/local/libexec/nagios/check_bgpsession
/usr/local/libexec/nagios/check_bgpstate
/usr/local/libexec/nagios/check_running
/usr/local/libexec/nagios/check_sysutilization
/usr/local/libexec/nagios/check_utilization
/usr/local/libexec/nagios/check_uptime
/boot/loader.conf
/boot/device.hints

Аналогично готовим линуксовый хост, с той только разницей, что пользователя назовём backuper, список сохраняемого в архив находится в /etc/backup.conf, и путь к tar будет несколько другим:

root@bender# vim /etc/backup.conf
/etc
/boot/grub/menu.lst
/var/www

root@bender# visudo
[...skipped...]
backuper ALL = NOPASSWD: /bin/tar *

Первый прогон скрипта на share делаем таким образом:

root@share# su backup
backup@share# /usr/local/sbin/backup-hosts.sh

Для каждого хоста из 2-х списков нужно ответить yes на вопрос, хотим ли мы коннектиться, после этого fingerprint каждого из этих хостов будет занесен в /home/backup/.ssh/known_hosts - и в следующий раз пользователя backup пустят по ssh без необходимости вводить что-либо вручную. Также на этом этапе лучше всего отловить возможные ошибки в скрипте. Если скрипт нормально отрабатывает - самое время раскомментировать строку в /etc/crontab.

Вот что у меня получилось:

root@share# ls -lR /home/backup/
[...skipped...]
drwxr-xr-x 2 backup backup 512 30 кві 05:02 abakus
drwxr-xr-x 2 backup backup 512 30 кві 05:10 bender
drwxr-xr-x 2 backup backup 512 30 кві 05:10 butterfly
drwxr-xr-x 2 backup backup 512 30 кві 05:02 mark
drwxr-xr-x 2 backup backup 512 30 кві 05:02 frank
drwxr-xr-x 2 backup backup 512 30 кві 05:02 mantis
drwxr-xr-x 2 backup backup 512 30 кві 05:10 qos

/home/backup/abakus:
total 2819280
-rw-r--r-- 1 backup backup 1136619520 28 кві 15:20 2009-04-28.tar.gz
-rw-r--r-- 1 backup backup 875202560 29 кві 05:09 2009-04-29.tar.gz
-rw-r--r-- 1 backup backup 873605120 30 кві 05:10 2009-04-30.tar.gz

/home/backup/bender:
total 175792
-rw-r--r-- 1 backup backup 59924480 28 кві 16:37 2009-04-28.tar.gz
-rw-r--r-- 1 backup backup 59944960 29 кві 05:10 2009-04-29.tar.gz
-rw-r--r-- 1 backup backup 59975680 30 кві 05:10 2009-04-30.tar.gz

/home/backup/butterfly:
total 5568
-rw-r--r-- 1 backup backup 1884160 28 кві 13:37 2009-04-28.tar.gz
-rw-r--r-- 1 backup backup 1884160 29 кві 05:09 2009-04-29.tar.gz
-rw-r--r-- 1 backup backup 1884160 30 кві 05:10 2009-04-30.tar.gz

/home/backup/mark:
total 8880
-rw-r--r-- 1 backup backup 3010560 28 кві 13:22 2009-04-28.tar.gz
-rw-r--r-- 1 backup backup 3010560 29 кві 05:02 2009-04-29.tar.gz
-rw-r--r-- 1 backup backup 3010560 30 кві 05:02 2009-04-30.tar.gz
[...skipped...]

Теперь будет совсем нетрудно реализовать пункт 6 нашей схемы.