Add sqlite write permission check and preStart chown

- newSqliteStore now checks directory writability before opening
- Immediate SELECT 1 ping catches readonly DB early
- Systemd preStart chown ensures db file ownership is correct
- Fixes: SQLITE_READONLY_CANTINIT (1032)
This commit is contained in:
didier committed 2026-06-04 09:23:59 -04:00
1 parent 55081bc5aa
commit d5cae6efa9
2 files changed
+22

No files matched your search

+6
View File
@@ -122,6 +122,12 @@
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
after = [ "network.target" ]; after = [ "network.target" ];
preStart = ''
if [ -f "${builtins.toString cfg.sqlitePath}" ]; then
chown st-pierre:st-pierre "${builtins.toString cfg.sqlitePath}"
fi
'';
serviceConfig = { serviceConfig = {
User = "st-pierre"; User = "st-pierre";
Group = "st-pierre"; Group = "st-pierre";
+16
View File
@@ -6,6 +6,7 @@ import (
"embed" "embed"
"encoding/json" "encoding/json"
"fmt" "fmt"
"os"
"strings" "strings"
"github.com/pressly/goose/v3" "github.com/pressly/goose/v3"
@@ -20,6 +21,16 @@ type sqliteStore struct {
} }
func newSqliteStore(path string) (*sqliteStore, error) { func newSqliteStore(path string) (*sqliteStore, error) {
dir := path
if idx := strings.LastIndexByte(path, '/'); idx > 0 {
dir = path[:idx]
if fi, err := os.Stat(dir); err != nil {
return nil, fmt.Errorf("sqlite dir %s: %w", dir, err)
} else if fi.Mode().Perm()&0200 == 0 {
return nil, fmt.Errorf("sqlite dir %s is not writable (mode %o)", dir, fi.Mode().Perm())
}
}
db, err := sql.Open("sqlite", path) db, err := sql.Open("sqlite", path)
if err != nil { if err != nil {
return nil, fmt.Errorf("open sqlite: %w", err) return nil, fmt.Errorf("open sqlite: %w", err)
@@ -27,6 +38,11 @@ func newSqliteStore(path string) (*sqliteStore, error) {
db.SetMaxOpenConns(1) db.SetMaxOpenConns(1)
if _, err := db.Exec("SELECT 1"); err != nil {
db.Close()
return nil, fmt.Errorf("sqlite ping: %w", err)
}
goose.SetBaseFS(embedMigrations) goose.SetBaseFS(embedMigrations)
if err := goose.SetDialect("sqlite3"); err != nil { if err := goose.SetDialect("sqlite3"); err != nil {