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) |
| 587 | - Missing file: every gitbayd process that opens the database refuses |
587 | - Missing file: every gitbayd process that opens the database refuses |
| 588 | to run and names the path, including =serve= and, in system mode, |
588 | to run and names the path, including =serve= and, in system mode, |
| 589 | =authorized-keys=. =migrate= does not need it. |
589 | =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. |
| 590 | - Wrong key: =serve= stops at startup naming the first row that does |
592 | - Wrong key: =serve= stops at startup naming the first row that does |
| 591 | not open; =secrets check= does the same without starting anything. |
593 | not open; =secrets check= does the same without starting anything. |
| 592 | - Upgrade: the first start after the upgrade seals every value still |
594 | - 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 { |
| 108 | defer release() |
108 | defer release() |
| 109 | } |
109 | } |
| 110 | |
110 | |
| 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) |
| 112 | if err != nil { |
119 | if err != nil { |
| 113 | return err |
120 | return err |
| 114 | } |
121 | } |
cmd/gitbayd/backup_test.go
+27
| @@ -626,3 +626,30 @@ func TestGCRefusedDuringBackup(t *testing.T) { |
| 626 | t.Fatalf("gc during a backup: %v", err) |
626 | t.Fatalf("gc during a backup: %v", err) |
| 627 | } |
627 | } |
| 628 | } |
628 | } |
| |
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. |
| |
632 | func 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 | } |