backup-master: сервер бэкапов, агент и восстановление VPS
Один бинарник backupctl: - server: API для агентов и restore, веб-морда (один админ), SQLite, ретеншн GFS, heavy-части, уведомления ntfy, раздача agent.sh/restore.sh; - backup/plan: сбор по каталогу категорий (files/systemd/xui/compose), горячие дампы Postgres/Mongo/MySQL, снимок x-ui.db, docker-тома, digest образов, проверка crontab, потоковая отправка tar.zst; - restore: провижининг на основе vps_installer с теми же версиями пакетов, recipes 3x-ui/nebula/sing-box нужных версий, восстановление compose с заливкой дампов и закреплением образов по digest. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
1d44d067e9
53 files changed
+7278
No files matched your search
@@ -0,0 +1,47 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gitea.hsrv.site/mrleo1nid/backup-master/internal/manifest"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
const xuiDB = "/etc/x-ui/x-ui.db"
|
||||
|
||||
// snapshotXUI делает консистентную копию базы 3x-ui на горячую (VACUUM INTO),
|
||||
// без логина в панель и без остановки сервиса.
|
||||
func (c *collector) snapshotXUI(mc *manifest.Category) error {
|
||||
if _, err := os.Stat(xuiDB); err != nil {
|
||||
c.warn("xui: нет %s", xuiDB)
|
||||
return nil
|
||||
}
|
||||
dir, err := c.spoolDir(mc.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out := filepath.Join(dir, "x-ui.db")
|
||||
if err := vacuumInto(xuiDB, out); err != nil {
|
||||
c.warn("xui: снимок базы не удался: %v", err)
|
||||
return nil
|
||||
}
|
||||
mc.Dumps = append(mc.Dumps, manifest.Dump{Name: "x-ui.db", Kind: "sqlite", Target: xuiDB})
|
||||
c.add(manifest.MainPart, dumpItem(mc.Name, out, "x-ui.db"))
|
||||
return nil
|
||||
}
|
||||
|
||||
func vacuumInto(src, dst string) error {
|
||||
_ = os.Remove(dst)
|
||||
db, err := sql.Open("sqlite", "file:"+src+"?_pragma=busy_timeout(10000)")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer db.Close()
|
||||
_, err = db.Exec(fmt.Sprintf("VACUUM INTO '%s'", strings.ReplaceAll(dst, "'", "''")))
|
||||
return err
|
||||
}
|
||||
Reference in new issue
Block a user