diff --git a/README.md b/README.md index c4e20e5..54c566f 100644 --- a/README.md +++ b/README.md @@ -11,4 +11,51 @@ * Кроме того, необходимо проверить переменные, пути к директориям, которые указаны непосредственно в скриптах. * В скрипте `remote-backup.sh` приведен пример для удаленной синхронизации папки `backups` с другим сервером. -* Скрипт должен быть запущен на другом сервере, нужно правильно указать настройки адреса сервера, пути, и кроме того, на сервере должен быть установлен ключ SSH для доступа. \ No newline at end of file +* Скрипт должен быть запущен на другом сервере, нужно правильно указать настройки адреса сервера, пути, и кроме того, на сервере должен быть установлен ключ SSH для доступа. + + + +------------------------------------------- + +Использование rsync для создания резервных копий на удаленный сервер, при котором инициатором подключения выступает сервер бэкапов, является хорошей практикой, повышающей безопасность ваших данных. Вот несколько советов, чтобы выполнить это правильно и надежно: + +1. **Инвертируйте подключение**: + - Запускайте rsync с сервера бэкапов (сервер B), чтобы подключаться к основному серверу (сервер A) и забирать данные. Таким образом, у злоумышленника, который может получить контроль над сервером A, не будет прямого доступа к серверу B. + +2. **Используйте SSH**: + - Обязательно используйте SSH для передачи данных, чтобы обеспечить шифрование соединения. Rsync может работать через SSH (например, `rsync -avz -e ssh user@serverA:/path/to/data /local/path`). + +3. **Настройте управление доступом**: + - Ограничьте доступ к серверу A только для пользователя, который выполняет резервное копирование. + - Используйте ключи SSH для аутентификации, и храните закрытый ключ на сервере B. + +4. **Модифицируйте права на ключи**: + - Ограничьте права файлового доступа на закрытые ключи, чтобы только соответствующий пользователь мог их читать (`chmod 600`). + +5. **Используйте ограничения SSH**: + - Ограничьте команды, которые могут быть выполнены с использованием ключа SSH, назначив предопределенную команду в файле `authorized_keys` на сервере A. Это можно сделать следующим образом: + ```plaintext + command="rsync --server -logDtprze.iLsfx --delete --numeric-ids . /path/to/data",no-agent-forwarding,no-port-forwarding,no-pty ssh-rsa AAAA... user@hostname + ``` + +6. **Регулярные проверки и уведомления**: + - Настройте уведомления о сбоях и настраивайте регулярные проверки целостности данных. + +Вот пример настроек, чтобы запустить резервное копирование с сервера B (сервера бэкапов): + +1. На сервере B создайте ключ SSH (если он еще не создан): + ```sh + ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa + ``` + +2. Скопируйте публичный ключ на сервер A: + ```sh + ssh-copy-id user@serverA + ``` + +3. На сервере B настройте cron job или systemd timer для регулярного выполнения rsync. Пример крон-задачи для ежедневного выполнения копирования в 2:00 ночи: + ```plaintext + 0 2 * * * /usr/bin/rsync -avz -e ssh user@serverA:/path/to/data /local/path/to/backups + ``` + +Использование этих техник значительно повысит безопасность вашего резервного копирования и уменьшит вероятность компрометации сервера бэкапов в случае взлома основного сервера. \ No newline at end of file diff --git a/acme.sh b/acme.sh new file mode 100644 index 0000000..7147ad8 --- /dev/null +++ b/acme.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +if [ "$(id -u)" != "0" ]; then + echo -e "\033[31mThis script requires superuser rights\033[0m" + exit 0 +fi + +ACME_FILE="/data/secrets/$SERVER_DOMAIN/letsencrypt/$SERVER_DOMAIN.acme.json" +BACKUP_DIR="/backups/acme" +ARCHIVE_FILE="$BACKUP_DIR/$SERVER_DOMAIN.tar.gz" + +# load ACME_BACKUP_PASSWORD +SECRETS_PATH=/data/secrets/$SERVER_DOMAIN/$SERVER_DOMAIN.env +source $SECRETS_PATH + +trap 'echo -e "\033[31mSomething went wrong\033[0m"; exit 1' EXIT +set -e + +export DEBIAN_FRONTEND=noninteractive + +tar -czf - -C "$ACME_FILE" . | openssl enc -aes-256-cbc -e -out "$ARCHIVE_FILE" -pass pass:"$ACME_BACKUP_PASSWORD" -pbkdf2 -iter 100000 + +trap - EXIT +echo "All backups were made successfully. Outdated backups have been deleted" \ No newline at end of file diff --git a/all.sh b/all.sh index 5f9369f..e40d838 100644 --- a/all.sh +++ b/all.sh @@ -1,7 +1,7 @@ #!/bin/bash if [ "$(id -u)" != "0" ]; then - echo -e "\033[31mThis script requires superuser rights.\033[0m" + echo -e "\033[31mThis script requires superuser rights\033[0m" exit 0 fi @@ -10,14 +10,19 @@ set -e export DEBIAN_FRONTEND=noninteractive -docker exec postgres psql -U admin -d postgres -t -A -F',' -c "SELECT d.datname, a.rolname FROM pg_database d JOIN pg_roles a ON d.datdba = a.oid WHERE d.datistemplate = false;" | while IFS=, read -r dbname owner; do +docker exec -i postgres psql -U $POSTGRES_USER -d $POSTGRES_DB -t -A -F',' <<-EOSQL | + SELECT d.datname, a.rolname + FROM pg_database d + JOIN pg_roles a ON d.datdba = a.oid + WHERE d.datistemplate = false; +EOSQL +while IFS=, read -r dbname owner; do bash postgres.sh "$dbname" "$owner" done bash files.sh +bash acme.sh bash cleaner.sh -echo 'Done.' - trap - EXIT -echo "All backups were made successfully. Outdated backups have been deleted." \ No newline at end of file +echo "All backups were made successfully. Outdated backups have been deleted" \ No newline at end of file diff --git a/backups.list b/backups.list deleted file mode 100644 index a719d60..0000000 --- a/backups.list +++ /dev/null @@ -1,3 +0,0 @@ -# /sample/folder/ -/data/appdata/gitea/ -/data/projects/ diff --git a/cleaner.sh b/cleaner.sh index 834df73..2af150a 100644 --- a/cleaner.sh +++ b/cleaner.sh @@ -4,7 +4,7 @@ EXPIRE_DAYS=14 SCAN_DIR=/backups if [ "$(id -u)" != "0" ]; then - echo -e "\033[31mThis script requires superuser rights.\033[0m" + echo -e "\033[31mThis script requires superuser rights\033[0m" exit 0 fi @@ -13,24 +13,26 @@ set -e export DEBIAN_FRONTEND=noninteractive +echo 'Cleaning old backups...' + FILES=$(find $SCAN_DIR -type f) for file in $FILES; do - timestamp=$(date -r $file +%Y%m%d); - echo "Processing $file file.."; - date1yrs=$(date -d "$timestamp" +%Y); - date1days=$(date -d "$timestamp" +%j); - date2yrs=$(date +%Y); - date2days=$(date +%j); - diffYear=$(expr "$date2yrs" - "$date1yrs"); - diffYear2days=$(expr "$diffYear" \* 365); - diffDays=$(expr "$date2days" - "$date1days"); - DAYS=$(expr "$diffYear2days" + "$diffDays"); + timestamp=$(date -r "$file" +%Y%m%d) + echo "Processing $file file.." + date1yrs=$(date -d "$timestamp" +%Y) + date1days=$(date -d "$timestamp" +%j) + date2yrs=$(date +%Y) + date2days=$(date +%j) + diffYear=$((date2yrs - date1yrs)) + diffYear2days=$((diffYear * 365)) + diffDays=$((date2days - date1days)) + DAYS=$((diffYear2days + diffDays)) if [ "$DAYS" -ge $EXPIRE_DAYS ] then - echo "Deleting $file file..."; - rm "$file"; + echo "Deleting $file file..." + rm "$file" fi done diff --git a/files.sh b/files.sh index b2c1f83..23f02f9 100644 --- a/files.sh +++ b/files.sh @@ -10,7 +10,7 @@ set -e export DEBIAN_FRONTEND=noninteractive -BACKUP_LIST="./backups.list" +BACKUP_LIST=/data/$SRV_START_DIR/backups.cfg BACKUP_DIR="/backups/files" # Checking the presence of a backups.list @@ -22,6 +22,8 @@ fi # Creating main directories (if not created) mkdir -p "$BACKUP_DIR" +echo 'Creating files backup...' + # Reading a list of directories for backup while IFS= read -r DIR; do # Ignore lines starting with # @@ -39,7 +41,8 @@ while IFS= read -r DIR; do # Formation of the archive name BASENAME=$(basename "$DIR") - TIMESTAMP=$(date +%Y%m%d%H%M%S) + #TIMESTAMP=$(date +%Y%m%d%H%M%S) + TIMESTAMP=$(date +%d-%m-%Y_%H%M%S) ARCHIVE_NAME="${BASENAME}_${TIMESTAMP}.tar.gz" # Creating a directory to store backups of this folder diff --git a/postgres.sh b/postgres.sh index 3a21d5f..5138fd1 100644 --- a/postgres.sh +++ b/postgres.sh @@ -1,12 +1,12 @@ #!/bin/bash if [ "$(id -u)" != "0" ]; then - echo -e "\033[31mThis script requires superuser rights.\033[0m" + echo -e "\033[31mThis script requires superuser rights\033[0m" exit 0 fi if [ -z "$1" ] || [ -z "$2" ]; then - echo "Please provide both the POSTGRES_DB and POSTGRES_USER as arguments." + echo "Please provide both the POSTGRES_DB and POSTGRES_USER as arguments" exit 1 fi @@ -16,35 +16,36 @@ set -e export DEBIAN_FRONTEND=noninteractive # configuration settings -POSTGRES_DB="$1" -POSTGRES_USER="$2" +PGDB="$1" +PGUSER="$2" CURRENT_MONTH=$(date +%Y-%m) CURRENT_DATE=$(date +%Y-%m-%d) -CURRENT_DATETIME=$(date +%d-%b-%Y_%H_%M_%Z) -BACKUPS_PATH=/data/backups/postgres +#CURRENT_DATETIME=$(date +%d-%b-%Y_%H_%M_%Z) +CURRENT_DATETIME=$(date +%d-%m-%Y_%H%M%S) +BACKUPS_PATH=/backups/postgres DOCKER_SERVICE_NAME=postgres # backup PostgreSQL database -BACKUP_FOLDER=$BACKUPS_PATH/$POSTGRES_DB +BACKUP_FOLDER=$BACKUPS_PATH/$PGDB if [ ! -d "$BACKUP_FOLDER" ]; then mkdir -p "$BACKUP_FOLDER" fi echo 'Creating PostgreSQL backups...' cd "$BACKUP_FOLDER" -if [ -f 'dump_'"$POSTGRES_DB"'.sql' ]; then - rm 'dump_'"$POSTGRES_DB"'.sql' +if [ -f 'dump_'"$PGDB"'.sql' ]; then + rm 'dump_'"$PGDB"'.sql' fi -db_backup_filename=$POSTGRES_DB'_'$CURRENT_DATETIME'.tar.gz' +db_backup_filename=$PGDB'_'$CURRENT_DATETIME'.tar.gz' -docker exec -t postgres pg_dump -U $POSTGRES_USER $POSTGRES_DB > 'dump_'"$POSTGRES_DB"'.sql' +docker exec -t postgres pg_dump -U $PGUSER $PGDB > 'dump_'"$PGDB"'.sql' -tar -cf - 'dump_'"$POSTGRES_DB"'.sql' | gzip -9 > "$db_backup_filename" -rm 'dump_'"$POSTGRES_DB"'.sql' +tar -cf - 'dump_'"$PGDB"'.sql' | gzip -9 > "$db_backup_filename" +rm 'dump_'"$PGDB"'.sql' cd "$BACKUP_FOLDER" md5sum * > MD5SUMS trap - EXIT -echo 'The backup of the '"$POSTGRES_DB"' database was completed successfully.' \ No newline at end of file +echo 'The backup of the '"$PGDB"' database was completed successfully' \ No newline at end of file diff --git a/rozen_backup.sh b/rozen_backup.sh new file mode 100644 index 0000000..d4160b8 --- /dev/null +++ b/rozen_backup.sh @@ -0,0 +1,40 @@ + +#!/bin/bash + +REMOTE_USER=root +SERVER_ORIGIN_DOMAIN=rozenlab.com + +REMOTE_DIR="$REMOTE_USER@$SERVER_ORIGIN_DOMAIN:/backups/" +LOCAL_DIR="/backups/$SERVER_ORIGIN_DOMAIN" + + +ssh $REMOTE_USER@$SERVER_ORIGIN_DOMAIN "mkdir -p /backups" + +# Backup web server: +ssh $REMOTE_USER@$SERVER_ORIGIN_DOMAIN "tar -czvf /backups/www_backup.tar.gz -C /var www" + +# Backup home dir: +ssh $REMOTE_USER@$SERVER_ORIGIN_DOMAIN "tar -czvf /backups/rozen_backup.tar.gz -C /home rozen" + +# Backup sftp dir: +ssh $REMOTE_USER@$SERVER_ORIGIN_DOMAIN "tar -czvf /backups/sftp_backup.tar.gz -C /var/sftp files" + +# Backup gitea app.ini: +ssh $REMOTE_USER@$SERVER_ORIGIN_DOMAIN "tar -czvf /backups/gitea_app_ini_backup.tar.gz -C /etc gitea" + +# Backup gitea data: +ssh $REMOTE_USER@$SERVER_ORIGIN_DOMAIN "tar -czvf /backups/gitea_data_backup.tar.gz -C /var/lib gitea" + +# Backup nginx cfgs: +ssh $REMOTE_USER@$SERVER_ORIGIN_DOMAIN "tar -czvf /backups/nfinx_cfg_backup.tar.gz -C /etc nginx" + + +# Backup wordpress database: +ssh $REMOTE_USER@$SERVER_ORIGIN_DOMAIN "mysqldump -u wp_blog_user -pbdcp8zxzojwz5tuhd3mr wp_blog > /backups/wordpress_backup.sql" + +# Backup gitea database: +ssh $REMOTE_USER@$SERVER_ORIGIN_DOMAIN "mysqldump -u gitea -prq8vtahhm63aims8aqbz gitea > /backups/gitea_backup.sql" + + +# Sync all backups from $REMOTE_DIR to $LOCAL_DIR +rsync -avz --delete $REMOTE_DIR $LOCAL_DIR \ No newline at end of file