Commit 884a5c558b

884a5c558b19627ca9eb25df9b29304d6aea6d62

parent: 9e4827a050

Verified · cmc

cmc <hello@cleberg.net> · 2026-09-28 22:28 UTC

backup: open the database without the key file

Ref #259

Layout: unified · split

.gitbay/wiki/Admin.org +2
@@ -587,6 +587,8 @@ gitbayd admin secrets rotate # new key, reseal, retire the old one (as root)
587587- Missing file: every gitbayd process that opens the database refuses
588588 to run and names the path, including =serve= and, in system mode,
589589 =authorized-keys=. =migrate= does not need it.
590- Backups: =admin backup= and =admin backup --verify= do not need the
591 key file; a restore does.
590592- Wrong key: =serve= stops at startup naming the first row that does
591593 not open; =secrets check= does the same without starting anything.
592594- Upgrade: the first start after the upgrade seals every value still
cmd/gitbayd/backup.go +8 −1
@@ -108,7 +108,14 @@ func runBackup(cfg config.Config, out string, dbOnly bool) error {
108108 defer release()
109109 }
110110
111 st, err := openStore(cfg)
111 // VACUUM INTO copies sealed values as they are, so the backup needs
112 // no key file, and it migrates nothing. store.Open would create a
113 // missing database, so its absence is checked first.
114 dbFile := filepath.Join(cfg.Server.Root, "gitbay.db")
115 if _, err := os.Stat(dbFile); err != nil {
116 return fmt.Errorf("database: %w", err)
117 }
118 st, err := store.Open(dbFile)
112119 if err != nil {
113120 return err
114121 }
cmd/gitbayd/backup_test.go +27
@@ -626,3 +626,30 @@ func TestGCRefusedDuringBackup(t *testing.T) {
626626 t.Fatalf("gc during a backup: %v", err)
627627 }
628628}
629
630// A backup and its verify need no key file: sealed values are copied as
631// they are. A missing database is refused rather than created.
632func TestBackupNeedsNoKeyFile(t *testing.T) {
633 cfg := testConfig(t)
634 out := filepath.Join(t.TempDir(), "b.tar.gz")
635 if err := runBackup(cfg, out, false); !errors.Is(err, fs.ErrNotExist) {
636 t.Fatalf("backup without a database: %v", err)
637 }
638 if _, err := os.Stat(filepath.Join(cfg.Server.Root, "gitbay.db")); !os.IsNotExist(err) {
639 t.Fatalf("backup created a database: %v", err)
640 }
641 s, err := openStore(cfg)
642 if err != nil {
643 t.Fatal(err)
644 }
645 s.Close()
646 if err := os.Remove(cfg.Server.SecretKeyFile); err != nil {
647 t.Fatal(err)
648 }
649 if err := runBackup(cfg, out, false); err != nil {
650 t.Fatalf("backup without the key file: %v", err)
651 }
652 if err := verifyBackup(out, ""); err != nil {
653 t.Fatalf("verify without the key file: %v", err)
654 }
655}