From 4a34cfc4a6fbdbde818647b818dc171512fa1253 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sun, 23 Jun 2024 22:06:59 +0200 Subject: [PATCH] Make write-ahead-log default and configurable for sqlite (#1985) * correctly enable WAL log for sqlite this commit makes headscale correctly enable write-ahead-log for sqlite and adds an option to turn it on and off. WAL is enabled by default and should make sqlite perform a lot better, even further eliminating the need to use postgres. It also adds a couple of other useful defaults. Signed-off-by: Kristoffer Dalby * update changelog Signed-off-by: Kristoffer Dalby --------- Signed-off-by: Kristoffer Dalby --- CHANGELOG.md | 1 + config-example.yaml | 4 ++++ hscontrol/db/db.go | 20 ++++++++++++++++++-- hscontrol/types/config.go | 6 +++++- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dce08f68..666e1670 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ after improving the test harness as part of adopting [#1460](https://github.com/ - Add `autogroup:internet` to Policy [#1917](https://github.com/juanfont/headscale/pull/1917) - Restore foreign keys and add constraints [#1562](https://github.com/juanfont/headscale/pull/1562) - Make registration page easier to use on mobile devices +- Make write-ahead-log default on and configurable for SQLite [#1985](https://github.com/juanfont/headscale/pull/1985) ## 0.22.3 (2023-05-12) diff --git a/config-example.yaml b/config-example.yaml index 867f8903..f1bc1631 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -144,6 +144,10 @@ database: sqlite: path: /var/lib/headscale/db.sqlite + # Enable WAL mode for SQLite. This is recommended for production environments. + # https://www.sqlite.org/wal.html + write_ahead_log: true + # # Postgres config # postgres: # # If using a Unix socket to connect to Postgres, set the socket path in the 'host' field and leave 'port' blank. diff --git a/hscontrol/db/db.go b/hscontrol/db/db.go index b87d6da6..69994d02 100644 --- a/hscontrol/db/db.go +++ b/hscontrol/db/db.go @@ -434,13 +434,29 @@ func openDB(cfg types.DatabaseConfig) (*gorm.DB, error) { Msg("Opening database") db, err := gorm.Open( - sqlite.Open(cfg.Sqlite.Path+"?_synchronous=1&_journal_mode=WAL"), + sqlite.Open(cfg.Sqlite.Path), &gorm.Config{ Logger: dbLogger, }, ) - db.Exec("PRAGMA foreign_keys=ON") + if err := db.Exec(` + PRAGMA foreign_keys=ON; + PRAGMA busy_timeout=10000; + PRAGMA auto_vacuum=INCREMENTAL; + PRAGMA synchronous=NORMAL; + `).Error; err != nil { + return nil, fmt.Errorf("enabling foreign keys: %w", err) + } + + if cfg.Sqlite.WriteAheadLog { + if err := db.Exec(` + PRAGMA journal_mode=WAL; + PRAGMA wal_autocheckpoint=0; + `).Error; err != nil { + return nil, fmt.Errorf("setting WAL mode: %w", err) + } + } // The pure Go SQLite library does not handle locking in // the same way as the C based one and we cant use the gorm diff --git a/hscontrol/types/config.go b/hscontrol/types/config.go index ab17cfb0..00934af6 100644 --- a/hscontrol/types/config.go +++ b/hscontrol/types/config.go @@ -81,7 +81,8 @@ type Config struct { } type SqliteConfig struct { - Path string + Path string + WriteAheadLog bool } type PostgresConfig struct { @@ -222,6 +223,8 @@ func LoadConfig(path string, isFile bool) error { viper.SetDefault("database.postgres.max_idle_conns", 10) viper.SetDefault("database.postgres.conn_max_idle_time_secs", 3600) + viper.SetDefault("database.sqlite.write_ahead_log", true) + viper.SetDefault("oidc.scope", []string{oidc.ScopeOpenID, "profile", "email"}) viper.SetDefault("oidc.strip_email_domain", true) viper.SetDefault("oidc.only_start_if_oidc_is_available", true) @@ -443,6 +446,7 @@ func GetDatabaseConfig() DatabaseConfig { Path: util.AbsolutePathFromConfigPath( viper.GetString("database.sqlite.path"), ), + WriteAheadLog: viper.GetBool("database.sqlite.write_ahead_log"), }, Postgres: PostgresConfig{ Host: viper.GetString("database.postgres.host"),