Backup và khôi phục self-hosted app không mất cấu hình dễ như chơi

03/05/2026 · P T P · Chung

Vì sao nhiều bản backup “thành công” vẫn khiến bạn mất cấu hình?

Một nghịch lý rất phổ biến khi vận hành self-hosted app là: backup xong, file vẫn đầy đủ, database vẫn restore được, nhưng đến lúc khôi phục thì ứng dụng lại “mất trí nhớ”. Reverse proxy không chạy, OAuth lỗi callback, cron biến mất, volume mount sai đường dẫn, API key không còn, hoặc tệ hơn là app khởi động được nhưng hành vi khác hoàn toàn trước đó.

Nguyên nhân thường không nằm ở dữ liệu người dùng, mà nằm ở phần cấu hình vận hành: file .env, docker-compose.yml, secrets, volume mapping, network, job scheduler, chứng chỉ TLS, thậm chí cả phiên bản image. Với self-hosted app, backup đúng không chỉ là sao chép database, mà là phải sao lưu được toàn bộ trạng thái cần thiết để tái tạo hệ thống.

Bài viết này là hướng dẫn thực chiến để bạn backup và khôi phục dữ liệu cho self-hosted app mà không mất cấu hình, áp dụng tốt cho các ứng dụng chạy bằng Docker, Docker Compose, VM hoặc cài trực tiếp trên Linux server.

Hiểu đúng: cần backup những gì?

Nhiều người chỉ backup thư mục dữ liệu hoặc export database. Cách đó chưa đủ. Một self-hosted app thường có 4 lớp quan trọng:

1. Dữ liệu ứng dụng

Đây là phần dễ thấy nhất:

– Database: PostgreSQL, MySQL, MariaDB, SQLite
– File upload: ảnh, tài liệu, media
– Cache cần giữ lại trong một số hệ thống đặc thù
– Logs quan trọng nếu cần audit hoặc điều tra sự cố

Nếu chỉ giữ phần này, bạn mới có “nội dung”, chưa có “cách ứng dụng hoạt động”.

2. Cấu hình ứng dụng

Đây là phần hay bị bỏ sót nhất:

– File .env
docker-compose.yml hoặc compose.yaml
– File config riêng: config.yml, settings.json, app.ini
– Biến môi trường trong systemd service
– Reverse proxy config như Nginx, Caddy, Traefik
– Webhook URL, callback URL, domain, port

Mất phần này, app có thể chạy lại nhưng không còn đúng cấu hình ban đầu.

3. Secrets và danh tính hệ thống

Đây là phần quyết định app có “nhận ra chính nó” hay không:

– API keys
– JWT secret
– Session secret
– Encryption key
– OAuth client secret
– SSH key, private key
– TLS certificate và ACME account data

Nếu thay đổi các secret này khi restore, người dùng có thể bị đăng xuất hàng loạt, token cũ vô hiệu, hoặc dữ liệu mã hóa không giải được.

4. Bối cảnh triển khai

Nhiều hệ thống restore lỗi vì thiếu “ngữ cảnh” vận hành:

– Phiên bản image Docker
– Tên volume
– Port mapping
– Tên network
– Cronjob hoặc lịch backup
– User/group permission
– Firewall rule quan trọng
– Mount path trên host

Nói ngắn gọn: backup để khôi phục không phải là backup file, mà là backup khả năng tái tạo hệ thống.

Nguyên tắc vàng để backup mà không mất cấu hình

Backup theo nguyên tắc “app + data + config + secret”

Một gói backup an toàn nên luôn bao gồm:

Dữ liệu: database dump hoặc snapshot volume
Cấu hình: compose file, env file, config file
Secrets: khóa bí mật, chứng chỉ, token quan trọng
Metadata triển khai: phiên bản app, image tag, thư mục mount, hướng dẫn restore

Bạn có thể hình dung mỗi ứng dụng nên có một thư mục backup logic như sau:

backup/
  app-name/
    compose.yaml
    .env
    config/
    secrets/
    db/
    uploads/
    restore-notes.txt

Cấu trúc này giúp việc khôi phục nhất quán hơn rất nhiều so với việc “gom đại” nhiều file rải rác.

Đừng chỉ backup volume sống nếu ứng dụng đang ghi dữ liệu

Copy trực tiếp thư mục volume khi database vẫn đang hoạt động có thể tạo backup không nhất quán. Ví dụ:

– PostgreSQL đang ghi WAL
– MySQL đang flush dữ liệu
– SQLite đang lock file

An toàn hơn là:

– Dùng pg_dump, mysqldump, hoặc công cụ backup chính thức
– Hoặc dừng app ngắn hạn trước khi snapshot volume
– Hoặc dùng filesystem snapshot nếu bạn hiểu rõ cơ chế nhất quán

Với database, logical dump thường dễ restore và ít rủi ro hơn copy nóng volume.

Luôn version hóa cấu hình

Nếu có thể, hãy đưa những file sau vào Git private repository:

compose.yaml
docker-compose.yml
– Nginx/Caddy config
– Tài liệu restore
– Script backup

Không nên commit thẳng secrets thật vào Git nếu không mã hóa, nhưng ít nhất hãy version hóa cấu trúc cấu hình. Khi xảy ra sự cố, bạn biết chính xác hệ thống từng chạy với cấu hình nào.

Ghi lại phiên bản image và dependency

Dùng image tag mơ hồ như latest là một trong những nguyên nhân restore xong nhưng hành vi khác trước. Hãy cố định phiên bản:

image: vaultwarden/server:1.30.5

Nếu restore sau 3 tháng mà image đã lên bản mới, app có thể thay đổi schema, biến môi trường hoặc cách mount dữ liệu.

Quy trình backup thực tế cho self-hosted app

Bước 1: Xác định toàn bộ thành phần của ứng dụng

Trước khi backup, hãy trả lời rõ:

– App dùng database gì?
– File upload nằm ở đâu?
– Config file nằm ở đâu?
– Secrets nằm ở đâu?
– Có reverse proxy riêng không?
– Có cronjob hoặc worker riêng không?

Đây là bước nhiều người bỏ qua, dẫn đến backup thiếu thành phần.

Bước 2: Backup cấu hình trước

Thông thường, hãy backup:

– Thư mục chứa compose.yaml
– File .env
– Thư mục config của app
– File reverse proxy
– Script deploy hoặc script backup

Ví dụ với Docker Compose, những thứ tối thiểu nên giữ là:

compose.yaml
.env
– thư mục ./config
– thư mục ./secrets nếu có

Bước 3: Backup database bằng công cụ phù hợp

Ví dụ thực tế:

– PostgreSQL: pg_dump
– MySQL/MariaDB: mysqldump
– SQLite: copy file sau khi app dừng hoặc đảm bảo trạng thái nhất quán

Điểm quan trọng là đặt tên file backup rõ ràng, có timestamp, ví dụ:

postgres-2025-01-20.sql
mariadb-2025-01-20.sql.gz

Ngoài ra, nên giữ ít nhất:

– 7 bản hằng ngày
– 4 bản hằng tuần
– 3 bản hằng tháng

Cách giữ nhiều lớp lịch sử giúp bạn phục hồi được cả khi lỗi xảy ra âm thầm từ trước.

Bước 4: Backup file dữ liệu và attachments

Nhiều ứng dụng lưu metadata trong database nhưng file thực nằm ở volume riêng. Nếu chỉ restore DB mà thiếu file upload, dữ liệu sẽ “có bản ghi nhưng không mở được”.

Cần backup:

– thư mục upload
– media library
– avatar, attachments
– custom themes hoặc plugin data nếu app hỗ trợ

Bước 5: Backup secrets một cách cẩn thận

Đây là phần nhạy cảm nhất. Hãy backup:

– JWT secret
– encryption key
– OAuth secret
– TLS cert
– private key

Nhưng lưu trữ chúng theo cách an toàn:

– mã hóa file backup
– giới hạn quyền truy cập
– lưu ở vị trí riêng với backup thông thường nếu cần

Một bản backup hoàn chỉnh nhưng lộ secrets cũng nguy hiểm không kém việc mất dữ liệu.

Cách khôi phục để không mất cấu hình

Backup tốt chỉ mới là một nửa. Phần còn lại là restore đúng thứ tự.

1. Khôi phục môi trường trước, dữ liệu sau

Sai lầm phổ biến là restore database ngay, rồi mới đi tìm file config. Cách đúng là:

– dựng lại thư mục ứng dụng
– đặt lại compose.yaml
– đặt lại .env
– khôi phục config
– khôi phục secrets
– đảm bảo network, port, volume path đúng
– sau đó mới restore database và file dữ liệu

Lý do là ứng dụng cần đúng “khung vận hành” trước khi nạp dữ liệu cũ.

2. Giữ nguyên secret cũ nếu muốn app hoạt động liên tục

Nếu bạn thay APP_KEY, JWT_SECRET, SECRET_KEY, nhiều thứ sẽ hỏng âm thầm:

– phiên đăng nhập bị mất
– token API không hợp lệ
– dữ liệu mã hóa không đọc được
– kết nối OAuth bị lỗi

Vì vậy, khi mục tiêu là restore không mất cấu hình, hãy ưu tiên giữ nguyên các secret cũ trừ khi bạn chủ động xoay vòng bảo mật.

3. Restore đúng phiên bản ứng dụng trước

Nếu backup được tạo ở version cũ, hãy restore bằng đúng version đó trước. Sau khi app chạy ổn, mới nâng cấp theo quy trình chuẩn.

Cách này giảm rủi ro:

– schema mismatch
– env var deprecated
– plugin không tương thích
– migration lỗi

4. Kiểm tra đường dẫn và quyền truy cập

Rất nhiều ca restore thất bại vì:

– volume mount sai path
– UID/GID khác server cũ
– file config đọc được nhưng app không có quyền ghi
– cert path không còn tồn tại

Sau restore, hãy kiểm tra ngay:

– app có đọc được config không
– database có kết nối được không
– upload mới có ghi được không
– reverse proxy có route đúng không

Những lỗi thường gặp khi backup self-hosted app

Chỉ backup database

Đây là lỗi số một. Bạn khôi phục được bản ghi, nhưng mất toàn bộ tích hợp, domain, cấu hình và khóa bí mật.

Backup có nhưng không test restore

Một bản backup chưa từng restore thử chỉ là giả định an toàn. Ít nhất mỗi quý nên thử restore lên máy test hoặc VM tạm thời.

Dùng latest thay cho version cố định

Restore xong mà app tự kéo image mới có thể khiến hệ thống khác hoàn toàn trạng thái ban đầu.

Không có tài liệu restore

Đến lúc khẩn cấp, bạn sẽ quên:

– file nào cần đặt ở đâu
– app nào phải khởi động trước
– secret nào là bắt buộc
– câu lệnh restore DB là gì

Một file restore-notes.txt ngắn gọn đôi khi cứu bạn nhiều hơn cả bản backup lớn.

Kết luận: backup tốt là backup khôi phục được nguyên trạng

Với self-hosted app, mục tiêu không chỉ là “lấy lại dữ liệu”, mà là khôi phục lại đúng ứng dụng với đúng cấu hình, đúng secrets và đúng cách vận hành. Hãy nghĩ theo bộ 4: data, config, secrets, deployment context. Thiếu một trong bốn, bạn vẫn có thể restore, nhưng khó đảm bảo hệ thống hoạt động như cũ.

Thực tế nhất, bạn nên bắt đầu ngay với 3 việc:

– lập danh sách đầy đủ những gì mỗi app cần để chạy
– tạo quy trình backup tách riêng database, config, secrets, uploads
– thử restore định kỳ trên môi trường test

Khi đã làm được điều này, backup không còn là thủ tục đối phó, mà trở thành kế hoạch sống còn giúp hệ thống self-hosted của bạn phục hồi nhanh, an toàn và không mất cấu hình khi sự cố xảy ra.

#backup #hosted #khoi #phuc #self
Chia sẻ:
← Trước
Cách chọn VPS, domain và reverse proxy cho self-hosted app chuẩn nhất

Bài viết tương tự

Bình luận

Chưa có bình luận. Hãy là người đầu tiên!