バックアップ設定 / Rocky Linux9.4 on さくらのVPS

アフィリエイト広告を利用しています

このページの内容が役に立ったら X (旧twitter) でフォローして頂けると励みになります
挨拶や報告は無しで大丈夫です

さくらのVPSにRockyLinux9.4をインストールした覚書です。

今回はサーバのバックアップについて設定していきたいと思います。

重要情報の入った本番サーバだったり個人情報保護法などに引っかかるケースなどがないか注意したうえで検討ください。

なお本番環境で利用される場合はここにある内容だけを鵜呑みにせずセキュリティ専門家に相談されることをお勧めします。

環境

実施日2024-05-18
サーバさくらのVPS 2G
OSRocky Linux9.4
cat /etc/redhat-release
Rocky Linux release 9.4 (Blue Onyx)

ユーザーを作成

バックアップは「backup」という名のユーザーで操作していくこととします。

# ユーザー作成
useradd backup

# ディレクトリを作成
mkdir /home/backup/.ssh

# 公開鍵をセット
vi /home/backup/.ssh/authorized_keys

# 権限を変更
chown -R backup:backup /home/backup/.ssh
chmod 0700 /home/backup/.ssh
chmod 0600 /home/backup/.ssh/authorized_keys

バックアップディレクトリの作成

バックアップディレクトリはユーザー「backup」が管理します。
サーバ側で持つバックアップデータはここに集約します。

次のような形を作成します。

全体のバックアップディレクトリ

mkdir /home/backup/backup
chown backup:backup /home/backup/backup
chmod 0700 /home/backup/backup

ユーザーごとのバックアップディレクトリ

「ユーザー名と同じファイル名.tar.gz」もしくは「ユーザー名と同じディレクトリ」が入る想定です。

mkdir /home/backup/backup/home
chown backup:backup /home/backup/backup/home
chmod 0700 /home/backup/backup/home

MySQL 5.7.44 向けのバックアップディレクトリ

mkdir /home/backup/backup/mysql_5.7.44
chown backup:backup /home/backup/backup/mysql_5.7.44
chmod 0700 /home/backup/backup/mysql_5.7.44

MySQL 8.4.0 向けのバックアップディレクトリ

mkdir /home/backup/backup/mysql_8.4.0
chown backup:backup /home/backup/backup/mysql_8.4.0
chmod 0700 /home/backup/backup/mysql_8.4.0

データベースのバックアップスクリプト

MySQLのバックアップ設定を作成していきます。

このスクリプトは root ユーザーとして接続し、すべてのデータベースを対象にバックアップをする仕組みとしています。

テストサーバ向けを想定しているため、日々増減するデータベースに柔軟に対応できる仕組みを目指します。
特定のデータベースを除外することもできますので詳しくはスクリプトをお読みください。

MySQL 5.7.44 向けのバックアップスクリプト

今回は「MySQL 5.7.44」向けとして作成します。

cd
mkdir cron
vi /root/cron/mysql_dump_5.7.44.sh
#!/bin/sh

# --------------------------------------------------
# MySQLバックアップ 実行
#
# MySQLデータベースをバックアップ
#
# --------------------------------------------------
# $ cd
# $ ./mysql_dump.sh
#
# $ crontab -e
# 0 2 * * * /backup/mysql_dump.sh > /dev/null 2>&1
#
# --------------------------------------------------
# package    aulta sh
# author     takashi shinohara
# copyright  Copyright (c) 2008, takashi shinohara
# link       http://aulta.jp/
# license    http://aulta.jp/licensed.html
# version    0.0.1
# --------------------------------------------------

START=`date +%s`
ST=`date +%s`

MYSQL_VERSION=5.7.44
MYSQL_USER_CONF_DIR=/root

MYSQL_PATH=/usr/local/lib/mysql-$MYSQL_VERSION/bin/mysql
MYSQL_DUMP_PATH=/usr/local/lib/mysql-$MYSQL_VERSION/bin/mysqldump

# MySQLユーザー
# MYSQL_USER=root

# バックアップ先のディレクトリ
# バックアップ先のディレクトリは手動で作成し適切なパーミッションにしておいてください
PATH_BACKUP_BASE=/home/backup/backup/mysql_$MYSQL_VERSION

# バックアップファイルのオーナー
OWNER_BACKUP=backup:backup


PATH_CREATE_DATABASE=$PATH_BACKUP_BASE/_create_database.sql
echo "" >$PATH_CREATE_DATABASE

PATH_IMPORT_DATABASE=$PATH_BACKUP_BASE/_import_database.sh
echo "#!/bin/sh" >$PATH_IMPORT_DATABASE

echo "" >> $PATH_IMPORT_DATABASE
echo "MYSQL_USER=root" >> $PATH_IMPORT_DATABASE
echo "MYSQL_PWD=password" >> $PATH_IMPORT_DATABASE
echo "" >> $PATH_IMPORT_DATABASE
echo "mysql -u \$MYSQL_USER --password=\$MYSQL_PWD < $PATH_CREATE_DATABASE" >> $PATH_IMPORT_DATABASE
echo "" >> $PATH_IMPORT_DATABASE
echo "function importDb(){" >> $PATH_IMPORT_DATABASE
echo "  PATH_SQL=$PATH_BACKUP_BASE/\$1.sql" >> $PATH_IMPORT_DATABASE
echo "  mysql -u \$MYSQL_USER --password=\$MYSQL_PWD \$1 < \$PATH_SQL" >> $PATH_IMPORT_DATABASE
echo "}" >> $PATH_IMPORT_DATABASE
echo "" >> $PATH_IMPORT_DATABASE

function backupDb(){
        echo "CREATE DATABASE /*!32312 IF NOT EXISTS*/ $2 /*!40100 DEFAULT CHARACTER SET utf8 */;" >> $PATH_CREATE_DATABASE
        echo "importDb \"$2\"" >> $PATH_IMPORT_DATABASE
        if test $1 -eq 1; then
                ST=`date +%s`
                PATH_SQL=$2.sql
                rm -f $PATH_SQL.tar.gz
               $MYSQL_DUMP_PATH --defaults-extra-file=$MYSQL_USER_CONF_DIR/mysql_$MYSQL_VERSION_backup.conf $2 --lock-tables --no-create-db > $PATH_SQL
                tar czf $PATH_SQL.tar.gz $PATH_SQL
                chown $OWNER_BACKUP $PATH_SQL.tar.gz
                rm $PATH_SQL
                END=`date +%s`
                # SS=`expr \(${END} - ${ST}\)`
                SS=$[$END - $ST]
                echo "${SS}s."
        fi
}

cd $PATH_BACKUP_BASE

echo "### BACKUP MYSQL ########################################################"
echo ""


for DATABASE in `$MYSQL_PATH --defaults-extra-file=$MYSQL_USER_CONF_DIR/mysql_$MYSQL_VERSION_backup.conf -N -s -e"show databases;"`; do
        echo -n $DATABASE" ... "
        if test $DATABASE = "information_schema"; then
                echo "skip"
                continue
        fi

        if test $DATABASE = "mysql"; then
                echo "skip"
                continue
        fi

        if test $DATABASE = "performance_schema"; then
                echo "skip"
                continue
        fi

        if test $DATABASE = "sys"; then
                echo "skip"
                continue
        fi

        backupDb 1 $DATABASE
done

chown $OWNER_BACKUP $PATH_CREATE_DATABASE
chown $OWNER_BACKUP $PATH_IMPORT_DATABASE


END=`date +%s`
SS=`expr ${END} - ${START}`
echo ""
echo "total time :  ${SS} seconds."
echo ""
echo "#########################################################################"
echo ""
echo ""
exit

MySQL 8.4.0 向けのバックアップスクリプト

続けては「MySQL 8.4.0」向けも作成します。

まずは5.7.44向けのファイルをコピーして 8.4.0 を作成します。

cp /root/cron/mysql_dump_5.7.44.sh /root/cron/mysql_dump_8.4.0.sh
vi /root/cron/mysql_dump_8.4.0.sh

コピーしたらファイルを開き次の個所を変更します。

MYSQL_VERSION=5.7.44
   ▼
MYSQL_VERSION=8.4.0

パーミッションの変更

chmod 0700 /root/cron/mysql_dump_5.7.44.sh
chmod 0700 /root/cron/mysql_dump_8.4.0.sh

接続ユーザーの設定

root パスワードは個別のファイルに設定します。
/root/mysql_「バージョン」_backup.conf というファイルを用意します。

# MYSQL_VERSION=5.7.44 の場合
vi /root/mysql_5.7.44_backup.conf
chmod 0600 /root/mysql_5.7.44_backup.conf

# MYSQL_VERSION=8.4.0 の場合
vi /root/mysql_8.4.0_backup.conf
chmod 0600 /root/mysql_8.4.0_backup.conf
[client]
user = root
password = 'パスワード'
port = 3306

パスワードはシングルクォートで囲む必要が無い場合もありますが、パスワードに記号が含まれているとうまく認識できないときがあるため囲むクセをつけておくと変なトラブルに巻き込まれなくなります。

置き場所を変更する場合はバックアップスクリプトの次の個所を変えます。

MYSQL_USER_CONF_DIR=/root

手動で実行

/root/cron/mysql_dump_5.7.44.sh
/root/cron/mysql_dump_8.4.0.sh

/home/backup/backup/mysql-「バージョン」 にファイルができていれば成功です。

CRONに登録する

実行ファイルをまとめる

1つずつ sh をCRONに設定しても良いのですが、1つが終わったら続けて次のshを実行して欲しいものです。

またバックアップは深夜処理の1つに組み込まれ他の処理も同時に行うことがあると思います。

ということで、1つのshにまとめたほうが都合が良いです。

ここでは、午前 3:00 に実行するCRONという意味で「cron_0300.sh」というファイル名で作成します。

vi /root/cron/cron_0300.sh
#!/bin/sh

/root/cron/mysql_dump_5.7.44.sh

/root/cron/mysql_dump_8.4.0.sh

CRONに登録する

バックアップスクリプトは root ユーザーで登録します。
※必要な権限を与えた一般ユーザーでも構いません

crontab -e
0 3 * * * /root/cron/cron_0300.sh > /dev/null 2>&1

外部からsudoできるようにする

ユーザー名 backup で外部からsudoできるようにし、使えるコマンドをrsyncだけに制限します。

目的

外部から sudo して何をするの?
ってことですが、アップロードファイルのようなデータベースに入れないデータは rsync でまるごと外部サーバにコピーしてしまおうって企みです。

root権限で rsync できるようにしてどうするかは下記をご覧ください。

WEBサイトのバックアップサービスについて

sudoの設定変更

visudo

次の内容を書き加えます。

Host_Alias LOCAL = x.x.x.x 自身のIPアドレス

# スクリプト実行から sudo できるユーザーを制限する
Defaults    requiretty
Defaults:backup !requiretty

## backup
backup LOCAL=(root) NOPASSWD: \
    /usr/bin/rsync

▼の赤字部分が追記対象です。

## Sudoers allows particular users to run various commands as
## the root user, without needing the root password.
##
## Examples are provided at the bottom of the file for collections
## of related commands, which can then be delegated out to particular
## users or groups.
##
## This file must be edited with the 'visudo' command.

## Host Aliases
## Groups of machines. You may prefer to use hostnames (perhaps using
## wildcards for entire domains) or IP addresses instead.
# Host_Alias     FILESERVERS = fs1, fs2
# Host_Alias     MAILSERVERS = smtp, smtp2
Host_Alias LOCAL = xxx.xxx.xxx.xxx

## User Aliases
## These aren't often necessary, as you can use regular groups
## (ie, from files, LDAP, NIS, etc) in this file - just use %groupname
## rather than USERALIAS
# User_Alias ADMINS = jsmith, mikem


## Command Aliases
## These are groups of related commands...

## Networking
# Cmnd_Alias NETWORKING = /sbin/route, /sbin/ifconfig, /bin/ping, /sbin/dhclient, /usr/bin/net, /sbin/iptables, /usr/bin/rfcomm, /usr/bin/wvdial, /sbin/iwconfig, /sbin/mii-tool

## Installation and management of software
# Cmnd_Alias SOFTWARE = /bin/rpm, /usr/bin/up2date, /usr/bin/yum

## Services
# Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig, /usr/bin/systemctl start, /usr/bin/systemctl stop, /usr/bin/systemctl reload, /usr/bin/systemctl restart, /usr/bin/systemctl status, /usr/bin/systemctl enable, /usr/b
in/systemctl disable

## Updating the locate database
# Cmnd_Alias LOCATE = /usr/bin/updatedb

## Storage
# Cmnd_Alias STORAGE = /sbin/fdisk, /sbin/sfdisk, /sbin/parted, /sbin/partprobe, /bin/mount, /bin/umount

## Delegating permissions
# Cmnd_Alias DELEGATING = /usr/sbin/visudo, /bin/chown, /bin/chmod, /bin/chgrp

## Processes
# Cmnd_Alias PROCESSES = /bin/nice, /bin/kill, /usr/bin/kill, /usr/bin/killall

## Drivers
# Cmnd_Alias DRIVERS = /sbin/modprobe

# Defaults specification

#
# Refuse to run if unable to disable echo on the tty.
#
Defaults   !visiblepw

#
# Preserving HOME has security implications since many programs
# use it when searching for configuration files. Note that HOME
# is already set when the the env_reset option is enabled, so
# this option is only effective for configurations where either
# env_reset is disabled or HOME is present in the env_keep list.
#
Defaults    always_set_home
Defaults    match_group_by_gid

# Prior to version 1.8.15, groups listed in sudoers that were not
# found in the system group database were passed to the group
# plugin, if any. Starting with 1.8.15, only groups of the form
# %:group are resolved via the group plugin by default.
# We enable always_query_group_plugin to restore old behavior.
# Disable this option for new behavior.
Defaults    always_query_group_plugin

Defaults    env_reset
Defaults    env_keep =  "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS"
Defaults    env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
Defaults    env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Defaults    env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Defaults    env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"

#
# Adding HOME to env_keep may enable a user to run unrestricted
# commands via sudo.
#
# Defaults   env_keep += "HOME"

Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin

Defaults    requiretty
Defaults:backup !requiretty

## Next comes the main part: which users can run what software on
## which machines (the sudoers file can be shared between multiple
## systems).
## Syntax:
##
##      user    MACHINE=COMMANDS
##
## The COMMANDS section may have other options added to it.
##
## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL

## Allows members of the 'sys' group to run networking, software,
## service management apps and more.
# %sys ALL = NETWORKING, SOFTWARE, SERVICES, STORAGE, DELEGATING, PROCESSES, LOCATE, DRIVERS

## Allows people in group wheel to run all commands
%wheel  ALL=(ALL)       ALL

## Same thing without a password
# %wheel        ALL=(ALL)       NOPASSWD: ALL

## Allows members of the users group to mount and unmount the
## cdrom as root
# %users  ALL=/sbin/mount /mnt/cdrom, /sbin/umount /mnt/cdrom

## Allows members of the users group to shutdown this system
# %users  localhost=/sbin/shutdown -h now

## Read drop-in files from /etc/sudoers.d (the # here does not mean a comment)
#includedir /etc/sudoers.d
# rocky ALL=(ALL)       NOPASSWD: ALL

## backup
backup LOCAL=(root) NOPASSWD: \
    /usr/bin/rsync