
Trả lời nhanh: Backup Supabase = hai thứ: database (pg_dump qua container db, cron hằng đêm) và file storage (thư mục volumes/storage). Bản sao phải rời khỏi máy, rsync qua tailnet sang VPS/máy khác. Update: backup trước, đọc changelog, git pull + docker compose pull rồi up -d: và luôn thử restore định kỳ, backup chưa từng restore thử là backup trên niềm tin.
Bản cloud của Supabase backup hộ bạn mỗi ngày; bản self-host thì đêm đầu tiên bạn quên là đêm rủi ro bắt đầu. Bài này dựng bộ ba: backup tự động hằng đêm, bản sao rời máy qua tailnet, và quy trình update stack, thứ đáng sợ hơn người ta tưởng vì một lần compose pull kéo theo cả chục service đổi phiên bản. Toàn bộ bằng script dán được, theo phong cách quen của blog.
- Hai tài sản phải giữ: Postgres (pg_dump) và volumes/storage (file người dùng upload)
- Cron 2 giờ sáng: dump nén + xoay vòng 7 ngày, script sẵn trong bài
- Quy tắc 3-2-1 rút gọn cho VPS: bản tại chỗ + bản offsite qua tailnet
- Update: backup → changelog → pull → up, đừng bao giờ pull mù
- Mỗi quý một lần restore thử vào stack tạm, backup phải được chứng minh, không phải được tin
Backup database: pg_dump qua container
#!/bin/bash
# /root/backup-supabase.sh
set -e
D=/root/backups/supabase
mkdir -p $D
docker exec supabase-db pg_dumpall -U postgres | gzip > $D/db-$(date +%F).sql.gz
# xoay vong 7 ngay:
find $D -name "db-*.sql.gz" -mtime +7 -deletechmod +x /root/backup-supabase.sh
crontab -e # them dong:
0 2 * * * /root/backup-supabase.sh >> /var/log/backup-supabase.log 2>&1(Tên container db xem bằng docker compose ps: tùy phiên bản compose có thể khác đôi chút.) pg_dumpall ôm cả roles và mọi database, hợp khẩu vị khôi phục toàn phần; kho lớn muốn dump từng db riêng thì đổi sang pg_dump có chọn lọc. Nguyên lý dump vs PITR đã mổ ở bài backup database, với đa số app trên Supabase self-host, dump hằng đêm là điểm cân đúng.
Đừng quên nửa còn lại: storage và cấu hình
Ảnh đại diện, tài liệu người dùng upload không nằm trong Postgres, chúng nằm ở docker/volumes/storage. Cộng thêm hai file cấu hình quyết định sống còn: .env (mất là mất JWT_SECRET, mọi token, mọi key phải sinh lại) và các file compose đã tùy chỉnh. Gộp vào script:
tar czf $D/storage-$(date +%F).tar.gz -C /duong-dan/supabase/docker volumes/storage
cp /duong-dan/supabase/docker/.env $D/env-$(date +%F).bakGhi chú riêng cho .env: file này là chùm chìa khóa, thư mục backup phải chỉ root đọc được (chmod 700), và khi đẩy offsite thì đường truyền phải kín (phần kế).
Bản sao rời máy: rsync qua tailnet
Backup nằm cùng VPS với dữ liệu chỉ chống được lỗi phần mềm, không chống được mất máy. Đẩy sang một điểm thứ hai (VPS khác, NAS ở nhà) qua tailnet là không mở port nào mà đường đi mã hóa sẵn:
# them vao cuoi script backup:
rsync -az --delete /root/backups/supabase/ [email protected]:/backup/supabase/Mô hình này chính là chiều ngược của bài backup NAS lên VPS, hạ tầng tailnet dựng một lần, chảy được cả hai chiều. Muốn bài bản hơn rsync: restic (mã hóa + dedup + giữ nhiều mốc) cùng công thức đích qua IP tailnet.
Update stack không làm chết dữ liệu
Stack chục service nghĩa là update có bề mặt rộng, kỷ luật bốn bước:
1. /root/backup-supabase.sh # backup tay ngay truoc khi dong
2. Doc changelog/release notes # dac biet cac major cua db va auth
3. cd supabase && git pull
cd docker && docker compose pull
4. docker compose up -d && docker compose ps # cho healthy hetDữ liệu nằm trong volumes nên up -d bình thường không đụng, rủi ro thật nằm ở migration ngầm khi image db/auth nhảy phiên bản lớn: đó là lý do bước 1 và 2 không được cắt. Có bản backup tươi trong tay, tình huống xấu nhất cũng chỉ là dựng lại stack cũ và restore, phiền, nhưng không mất gì.
Restore thử: nghi thức mỗi quý
Backup chưa từng restore là hy vọng, không phải kế hoạch. Mỗi quý một lần, 30 phút: dựng stack Supabase tạm (thư mục khác, cổng khác, hoặc VPS test theo giờ), nạp bản dump mới nhất:
gunzip -c db-2026-09-18.sql.gz | docker exec -i supabase-db-test psql -U postgresrồi mở Studio tạm kiểm vài bảng, thử một lượt đăng nhập. Ghi lại thời gian restore thực tế, con số đó là RTO thật của bạn khi có biến, và là con số đáng biết trước ngày cần đến. Xong nghi thức, hạ stack tạm, yên tâm ba tháng.
Bộ lệnh sao lưu đầy đủ, ba phần
# 1. Co so du lieu docker compose exec -T db pg_dump -U postgres -Fc postgres \ > /root/sao-luu/db-$(date +%F).dump # 2. Kho tep, phan khong nam trong dump tar czf /root/sao-luu/storage-$(date +%F).tar.gz ./volumes/storage # 3. Cau hinh va khoa bi mat tar czf /root/sao-luu/cauhinh-$(date +%F).tar.gz .env docker-compose.yml ./volumes/api # 4. Day ra may khac, khong de cung mot cho rsync -avz /root/sao-luu/ may-luu-tru:/kho/supabase/ # 5. Xoa ban cu hon 30 ngay de khong day o find /root/sao-luu -name "*.dump" -mtime +30 -delete
Phần hai và ba là phần hay bị bỏ sót. Sao lưu mỗi cơ sở dữ liệu thì khôi phục xong sẽ có người dùng nhưng mất hết tệp họ tải lên, và các thành phần không nói chuyện được với nhau vì khóa đã khác.
Diễn tập khôi phục, việc quyết định mọi thứ
| Việc | Tần suất | Cái cần ghi lại |
|---|---|---|
| Kiểm tệp sao lưu có tồn tại và đúng kích thước | Hằng tuần, tự động | Cảnh báo khi tệp nhỏ bất thường |
| Nạp thử bản sao vào một máy khác | Mỗi quý | Thời gian nạp, và bao nhiêu phần trăm dữ liệu đúng |
| Diễn tập đầy đủ: dựng lại toàn bộ stack từ ba tệp | Mỗi nửa năm | Tổng thời gian ngừng thật, ghi thành số |
Bản sao chưa từng khôi phục thử không phải bản sao, chỉ là một tệp làm mình yên tâm. Con số duy nhất đáng tin là thời gian bạn đo được trong lần diễn tập gần nhất.
Cập nhật stack mà không mất dữ liệu
- Chạy đủ ba lệnh sao lưu ở trên, và kiểm tệp đã tạo xong.
- Đọc ghi chú phát hành, chú ý phần thay đổi có phá vỡ tương thích.
- Cập nhật trên một bản dựng thử trước, không cập nhật thẳng bản đang chạy.
- Cập nhật bản thật vào khung giờ ít người dùng, và giữ bản sao trong tầm tay.
- Sau khi cập nhật, chạy lại bộ lệnh kiểm tra: các thành phần có sống, đăng nhập có được, tệp có tải lên được.
Câu hỏi thường gặp
Backup lúc 2h sáng có cần dừng stack không?
Không, pg_dump chụp ảnh nhất quán trong lúc database vẫn phục vụ. Chọn giờ thấp điểm chỉ để giảm cạnh tranh I/O, không phải vì bắt buộc.
Dump của self-host có nạp lên Supabase cloud được không (và ngược lại)?
Được về cơ bản vì cùng là Postgres, đây chính là đường di cư hai chiều (bài migrate của cụm nói kỹ chiều cloud về VPS). Lưu ý các schema hệ thống (auth, storage) cần xử lý theo hướng dẫn di cư thay vì nạp mù toàn bộ.
Volume storage lớn quá, tar mỗi đêm nặng nề thì sao?
Chuyển sang rsync/restic tăng dần (incremental) cho storage, chỉ đồng bộ file thay đổi; giữ tar trọn gói cho mốc tuần. Database vẫn dump trọn hằng đêm vì đó là phần đổi liên tục và nén tốt.
Nên giữ bao nhiêu bản backup?
Khung phổ biến: 7 bản ngày + 4 bản tuần + vài bản tháng, cân giữa dung lượng và độ sâu lịch sử. Sự cố phát hiện muộn (dữ liệu hỏng âm thầm) là lý do cần bản tuần/tháng chứ không chỉ 7 ngày gần nhất.
Bài viết liên quan
- Backup database đúng cách: dump, WAL và PITR trên VPS
- Self-host Supabase trên VPS bằng Docker Compose từng bước
- Chuyển từ Supabase Cloud về VPS: migrate không mất dữ liệu
- Tailscale Funnel & Serve: đưa web ra internet không mở port
- Anthropic tặng $100-$250 credit Claude Code cloud sessions cho gói Pro/Max, nhận trước 7/10
- VPS US cho dropship Amazon Etsy: setup + bản quyền
- Thuê Cloud VPS Việt Nam: hướng dẫn chọn cấu hình cho startup + SaaS nhỏ
- Self-host Cal.com trên VPS thay Calendly cho freelancer VN
- Cài n8n trên VPS bằng Docker: checklist chạy thật



