Ubuntu服务器备份文件权限失控,通常不是备份工具出了问题,而是权限模型在备份、恢复、轮换三个环节中被无意破坏。最常见的场景是:运维用root执行tar或rsync,生成的备份文件默认归属root:root,权限为600或644,但随后又用普通服务账号去读取、上传或清理,导致权限被反复chmod 777。更隐蔽的情况是备份目录设置了ACL或SGID,新写入的文件继承了父目录的宽泛权限,让数据库备份、站点源码备份可以被非授权进程读取。
要解决这个问题,不能只盯着chmod命令,而要从备份文件的生成、存放、访问、清理四个阶段分别建立权限边界。下面直接给出具体做法。
一、先确定备份文件的归属账号和最小权限原则Ubuntu服务器上,备份文件不应该全部归属root。如果备份由数据库账号执行,比如PostgreSQL的postgres用户或MySQL的mysql用户,那么备份文件归属该服务账号即可。如果备份由运维脚本统一执行,建议创建独立的备份系统账号,例如backupuser,并禁止其登录Shell。
sudo useradd --system --home /var/backups --shell /usr/sbin/nologin backupuser
备份目录的属主设为backupuser,权限设为700,这样只有备份账号和root能进入。不要使用755或775,因为备份目录中往往包含数据库连接配置、站点源码、密钥文件等敏感数据。
sudo mkdir -p /var/backups/db /var/backups/www /var/backups/etc sudo chown -R backupuser:backupuser /var/backups sudo chmod 700 /var/backups
对于已经存在的备份文件,先统一修正属主和权限。通常数据库备份文件权限设为600,普通站点备份文件设为640,配置文件备份设为600。不要直接使用chmod -R 777来“解决”权限报错,这会让备份文件可以被任何本地进程读取。
二、用umask控制备份进程生成文件的默认权限很多备份脚本忽略了umask,导致生成的备份文件权限继承Shell默认值。Ubuntu默认umask是022,新建文件权限通常是644,这意味着同组用户和其他用户都能读取。对于数据库备份,这是不可接受的。
在备份脚本开头显式设置umask,例如:
#!/bin/bash umask 077 # 后续生成的备份文件权限为600
如果使用rsync,可以通过--chmod参数直接指定目标文件权限:
rsync -av --chmod=Du=rwx,Dg=,Do=,Fu=rw,Fg=,Fo= /source/ /var/backups/www/
这样目标目录权限为700,文件权限为600,不会因为源目录权限宽泛而污染备份目录。
三、备份目录的SGID和ACL陷阱Ubuntu服务器如果曾经为了方便多人协作,对备份目录设置了SGID或ACL,后续新建的文件和子目录会继承父目录的组权限或扩展ACL。即使脚本里设置了umask,ACL仍可能覆盖默认权限。
检查备份目录是否设置了ACL:
getfacl /var/backups
如果输出中除了user、group、other之外还有额外的条目,说明存在ACL。清除ACL:
setfacl -b /var/backups
同时检查SGID位:
ls -ld /var/backups
如果权限位显示为drwxrws---,说明设置了SGID。移除SGID:
chmod g-s /var/backups
SGID会导致新建文件继承目录的组,如果该组包含多个用户,备份文件就可能被组内其他用户读取。对于备份目录,通常不需要SGID。
四、备份文件访问控制:不要用chmod 777解决读取问题当其他服务需要读取备份文件时,例如监控系统需要检查备份文件大小,或者异地同步脚本需要上传备份,直接chmod 777是最危险的做法。正确方式有两种:
第一种,将需要读取备份的服务账号加入backupuser所在的组,并将备份文件权限设为640。例如监控账号为monitor:
sudo usermod -aG backupuser monitor sudo chmod 640 /var/backups/db/*.sql
第二种,使用sudo配置特定命令的白名单,让服务账号只能执行读取备份的命令,而无法直接访问文件。例如允许monitor执行du命令查看备份目录大小:
monitor ALL=(backupuser) NOPASSWD: /usr/bin/du -sh /var/backups/*
这样既满足监控需求,又不暴露备份文件本身。
五、备份轮换和清理时的权限保持备份轮换脚本经常需要删除旧备份、移动新备份。如果脚本以root执行,删除和移动不会遇到权限问题,但会留下root属主的文件。如果脚本以backupuser执行,需要确保backupuser对备份目录有写权限,并且对旧备份文件有删除权限。
建议轮换脚本统一以backupuser执行,并在脚本中显式设置umask 077。对于find删除旧备份的操作,使用-delete而不是-exec rm,因为-delete由find直接执行,不会受到Shell别名或路径解析影响。
find /var/backups/db -type f -name "*.sql" -mtime +7 -delete
如果备份目录中混有root属主的文件,backupuser可能无法删除。此时需要定期检查并修正属主:
sudo find /var/backups -type f ! -user backupuser -exec chown backupuser:backupuser {} \;
这条命令可以加入cron,每天执行一次,确保备份目录内所有文件都归属backupuser。
六、远程备份同步的权限控制如果使用scp、rsync或rclone将备份同步到远程服务器,本地备份文件的权限不应影响远程端的权限设置。rsync默认会保留权限,如果本地备份文件权限是600,远程端也会是600。但如果远程端备份目录权限宽泛,其他用户仍可能通过目录遍历读取文件。
远程备份目录同样应该设置为700,并且远程备份账号应该独立。例如远程服务器创建backupuser,本地同步脚本使用SSH密钥以backupuser身份登录,不直接使用root。
对于rclone同步到对象存储,权限控制转移到访问密钥和桶策略层面。本地备份文件权限仍然要保持600,避免本地其他进程读取后泄露到日志或错误报告中。
七、加密备份文件的权限补充对于数据库备份和配置文件备份,权限控制之外还应考虑加密。即使权限设置正确,如果备份文件被物理窃取或误传到其他服务器,加密可以提供第二层保护。
使用gpg对称加密备份文件:
gpg --batch --yes --passphrase-file /etc/backup_passphrase -c /var/backups/db/db.sql
加密后的文件权限仍然保持600,并且加密密钥文件权限必须为600,属主为backupuser。
sudo chown backupuser:backupuser /etc/backup_passphrase sudo chmod 600 /etc/backup_passphrase
加密不是权限管控的替代品,而是补充。权限控制防止本地非授权访问,加密防止备份文件脱离服务器后的泄露。
八、审计和监控备份文件权限变化权限设置完成后,需要监控是否有人再次修改。可以使用auditd监控备份目录的权限变更:
sudo auditctl -w /var/backups -p wa -k backup_permission_change
这样任何对备份目录的写入或属性修改都会记录到审计日志。定期检查:
sudo ausearch -k backup_permission_change --start today
如果发现异常chmod或chown操作,可以快速定位是哪个进程或用户修改了权限。
另外,可以编写简单的检查脚本,每天验证备份目录权限和文件权限是否符合预期:
#!/bin/bash
if [ "$(stat -c %a /var/backups)" != "700" ]; then
echo "备份目录权限异常" | mail -s "备份权限告警" admin@example.com
fi
find /var/backups -type f -perm /077 -exec echo "备份文件权限过宽: {}" \;
将脚本加入cron,每天执行一次,可以及时发现权限漂移。
九、常见错误和纠正错误一:备份脚本使用root执行,生成root属主的备份文件,后续用普通账号清理时权限不足,于是chmod 777。纠正:统一使用backupuser执行备份和清理。
错误二:备份目录权限设置为755,任何本地用户都能列出备份文件名。纠正:目录权限设为700。
错误三:使用chown -R后没有同步修改权限,导致属主正确但权限仍为644。纠正:chown和chmod分开执行,先chown再chmod。
错误四:备份文件存放在/tmp目录,依赖系统自动清理,但/tmp目录权限为1777,任何用户都能读取备份文件。纠正:备份文件必须存放在专用备份目录,不能放在/tmp。
错误五:备份脚本中使用了chmod 777来方便远程同步工具读取。纠正:使用组权限或sudo白名单,不要开放其他用户权限。
十、总结权限管控的落地顺序第一步,创建独立的backupuser账号,禁止登录。第二步,建立专用备份目录,属主为backupuser,权限700。第三步,在所有备份脚本中显式设置umask 077。第四步,清除备份目录上的ACL和SGID。第五步,对于需要读取备份的服务账号,使用组权限或sudo白名单。第六步,备份轮换脚本以backupuser执行,定期修正属主。第七步,对敏感备份文件进行gpg加密。第八步,使用auditd和cron脚本监控权限变化。
这套流程不依赖任何额外商业工具,全部基于Ubuntu自带的权限机制和常用命令,可以立即在现有服务器上执行。权限管控的核心不是设置一次就完事,而是让备份文件在整个生命周期内始终处于最小权限边界内,任何一次chmod 777都是对备份安全模型的破坏。
