Mastodon 媒体存储和数据库备份

写在前面:
本文备份方法我还在验证中,请谨慎使用,最好以防万一多导出一份backup.dump

Why:为什么要备份

定期备份是好习惯,自从体验过一次wordpress搬家以后深刻感受到,有(异地)备份走遍天下都不怕。因为各种教备份的资料都比较全,本文主要是个人记录+学习用,如果想深入了解备份究竟在做什么也可以参考这篇文章。

当你有一份长毛象的异地备份,你可以:

  • 迁移站点到其他服务器
  • 在服务器完全瘫痪时或不小心重装后,依然可以还原所有数据库内容

What:备份哪些内容

俗话说得好,没有经过检验的备份不是好备份。那么最快让我们清楚需要备份什么的方式就是看还原/迁移站点需要什么。

这里参考了非docker站点迁移到dockerdocker迁移到docker 两篇资料,大致上分为三步:

1. 转移配置文件

配置文件也就是你的mastodon安装目录(按照pullopen的教程的话应该是/home/mastodon/mastodon)下的:

1
2
.env.production 
docker-compose.yml

也就是在更改站点设置中最常用的两个文件。

2. 转移数据库

这里有两个方法:

  • 通过备份文件backup.dump 进行转移,也就是备份的最关键内容,通常通过pg_dump导出备份,再通过pg_restore进行还原。

  • 如果是docker,可以直接复制./postgres/./redis/,并对./postgres/赋权,参考将站点从Docker迁移至Docker

3. 转移媒体文件

这里分为两种情况,如果你已经配置了媒体文件在云存储,这一步是不需要的。如果你没有配置过,那么你的所有文件都在./public/system/目录下。具体而言有:

1
2
3
4
5
6
7
$ cd /home/mastodon/mastodon/public/system
$ du -h --max-depth=1
9.6M ./media_attachments
3.3G ./cache
20M ./custom_emojis
13M ./accounts
3.4G .

其中./cache是外站存储,其他都是本站的数据。我们当然希望除了外站存储以外,对本站的所有数据都做好备份。

关于定期清除外站存储,请参考这个嘟文,我的crontab设置:

1
2
3
30 4    * * *   root    docker exec mastodon_web_1 tootctl media remove --days=14 >> /home/mastodon/log/mastodon/all.log 2>&1
30 4 * * * root docker exec mastodon_web_1 tootctl media remove-orphans >> /home/mastodon/log/mastodon/all.log 2>&1
30 4 * * * root docker exec mastodon_web_1 tootctl statuses remove --days=180 >> /home/mastodon/log/mastodon/all.log 2>&1

我是直接启动容器执行tootctl命令,更多相关内容可以通过使用脚本的tootctl或者非docker安装的tootctl了解。

总结:如果是docker的话,直接对除./public/system/cache以外整个文件夹和个别配置文件进行备份即可。

Where:备份放在哪里

本地备份

本文将备份文件和备份脚本都放在/opt/mastodon-backup 下,你也可以选择任何你喜欢的安全位置。

异地备份

最好的备份一定是异地备份。pullopeno3o 都推荐了Scaleway云备份,并附上了详细的资料。

When:什么时候备份

建议设置每天晚上自动备份一次,可以使用crontab创建定时任务。

Who:谁来备份

当然是站长啊还有谁!

How:如何备份

啰嗦了这么久终于到了这一步,我只是希望在我真正操作之前能够明白我在做什么。

这一节脚本主要参考利用Scaleway备份数据库

本地备份

只看脚本的前半部分:

1
2
3
4
5
6
7
8
9
#!/bin/bash
source /etc/profile
now=$(date "+%Y%m%d-%H%M%S")
origin="/home/mastodon/mastodon"
target="scaleway:你的bucket名字"
echo `date +"%Y-%m-%d %H:%M:%S"` " now starting export"
/usr/bin/docker exec pg容器名 pg_dump -U postgres -Fc mastodon_production > ${origin}/backup.dump &&
echo `date +"%Y-%m-%d %H:%M:%S"` " succeed and upload to s3 now"
/usr/bin/zip -P 密码 ${origin}/backup_${now}.zip ${origin}/backup.dump

前面定义了一些路径和时间等,先通过pg_dump导出backup.dump,再将其加密压缩为backup_${now}.zip,但从上文可见,对于docker安装的情况,直接copy文件夹即可,所以我对这部分做了一些改动并参考o3o的配置备份脚本,增加了一些关键信息的备份,我的完整本地备份脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash

# Save this file at /opt/mastodon-backup/backup_local.sh
# Set a cronjob: 0 5 * * * root /bin/bash /opt/mastodon-backup/backup_local.sh >> /opt/mastodon-backup/logs/backup_local.log 2>&1

# Set backup_folder and name
now=$(date "+%Y%m%d-%H%M%S")
origin_folder="/home/mastodon/mastodon"
backup_folder="/opt/mastodon-backup/dbbackup"

# Clean up old backup file
rm -r ${backup_folder}/*

# Generating a mastodon backup exclude cache
echo `date +"%Y-%m-%d %H:%M:%S"` " now starting export"
/usr/bin/zip -P 密码 -rqx=${origin_folder}/public/system/cache/* ${backup_folder}/backup_${now}.zip ${origin_folder}

# Copying important files
cp -r /etc/nginx/sites-available ${backup_folder}
echo `date +"%Y-%m-%d %H:%M:%S"` " done!"

可以单独运行一次脚本看看是否正确备份,运行后查看备份目录:

1
2
3
4
$ ls /opt/mastodon-backup/dbbackup/ -lh
total 76M
-rw-r--r-- 1 root root 76M Feb 20 00:09 backup_20220220-000931.zip
drwxr-xr-x 2 root root 4.0K Feb 20 00:09 sites-available

我将这个脚本存为backup_local.sh,在我配置好Scaleway之前守护我的数据,将其放在crontab下定期运行:

1
0 5 * * * root /bin/bash /opt/mastodon-backup/backup_local.sh.sh >> /opt/mastodon-backup/logs/backup_local.sh.log 2>&1

备份时间设在清除外部缓存半小时后。

异地备份

再看原脚本的后半部分

1
2
3
4
/usr/bin/rclone copy ${origin}/backup_${now}.zip ${target} &&
echo `date +"%Y-%m-%d %H:%M:%S"` " ok all done"
rm -f ${origin}/backup.dump ${origin}/backup_${now}.zip
/usr/bin/rclone --min-age 7d delete ${target}

rclone copy是将压缩后的备份文件按照配置好的设置上传至Scaleway,之后rm -f删除本地的备份文件,最后设置rclone删除大于7天的备份文件。这一步也可以直接在Scaleway删除,参考循环销毁备份文件

在我更改后的脚本,我采取的方法是每次先删除上一次的备份文件,而不是在上传后删除,这样可以在本地和Scaleway都有一个备份。

Scaleway和rclone的设置可参考利用Scaleway备份数据库设置定期异地备份长毛象数据库和关键配置

注意,备份的bucket要和媒体存储的分开,并且设为private!!

可以用

1
rclone ls scaleway:你的bucket名称

查看bucket里的文件,确认是否正常上传和删除。

最终我的完整脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/bin/bash

# Save this file at /opt/mastodon-backup/backup.sh
# Set a cronjob: 0 5 * * * root /bin/bash /opt/mastodon-backup/backup.sh >> /opt/mastodon-backup/logs/backup.log 2>&1

# Loading /etc/profile
source /etc/profile

# Set backup_folder and name
now=$(date "+%Y%m%d-%H%M%S")
origin_folder="/home/mastodon/mastodon"
backup_folder="/opt/mastodon-backup/dbbackup"
target_bucket="scaleway:你的bucket名称"

# Clean up old backup file
rm -r ${backup_folder}/*

# Generating a mastodon backup exclude cache
echo `date +"%Y-%m-%d %H:%M:%S"` " now starting export"
/usr/bin/zip -P 密码 -rqx=${origin_folder}/public/system/cache/* ${backup_folder}/backup_${now}.zip ${origin_folder}

# Copying important files
cp -r /etc/nginx/sites-available/ ${backup_folder}
echo `date +"%Y-%m-%d %H:%M:%S"` " local backup done!"

# upload to scaleway
/usr/bin/rclone copy ${backup_folder}/ ${target_bucket}
echo `date +"%Y-%m-%d %H:%M:%S"` " ok all done"

# delete backup longer than 7d
/usr/bin/rclone --min-age 7d delete ${target_bucket}

单独运行一遍可以成功后,就可以把crontab中的backup_local.sh改为backup.sh啦!这样你就有了一个:

  • 本地和scaleway双重备份
  • 本地保留一天,scaleway保留7天
  • 包含nginx设置和整个mastodon目录

的备份啦!