// Package backup builds a downloadable, optionally encrypted snapshot of // the jsondb directory (servers, clients, users, settings - everything // needed to restore this installation). It never transmits data anywhere // on its own; the archive is only ever returned to an authenticated admin // as an HTTP download, never uploaded automatically. package backup import ( "archive/tar" "bytes" "compress/gzip" "os" "path/filepath" ) // BuildArchive tars+gzips every regular file under dbPath into memory, // preserving paths relative to dbPath so restoring means extracting into a // fresh, empty db directory. func BuildArchive(dbPath string) ([]byte, error) { var buf bytes.Buffer gzw := gzip.NewWriter(&buf) tw := tar.NewWriter(gzw) err := filepath.Walk(dbPath, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { return nil } relPath, err := filepath.Rel(dbPath, path) if err != nil { return err } data, err := os.ReadFile(path) if err != nil { return err } header := &tar.Header{ Name: relPath, Mode: int64(info.Mode().Perm()), Size: int64(len(data)), ModTime: info.ModTime(), } if err := tw.WriteHeader(header); err != nil { return err } _, err = tw.Write(data) return err }) if err != nil { return nil, err } if err := tw.Close(); err != nil { return nil, err } if err := gzw.Close(); err != nil { return nil, err } return buf.Bytes(), nil }