From c79ebe2282e2e61e6f265293d708026a4fc8541e Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 31 Oct 2025 15:44:01 +0100 Subject: [PATCH] db: ignore _litestream tables when validating Fixes #2826 Signed-off-by: Kristoffer Dalby --- hscontrol/db/db.go | 12 +++++++++++- .../sqlite/headscale_0.26.1_schema-litestream.sql | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 hscontrol/db/testdata/sqlite/headscale_0.26.1_schema-litestream.sql diff --git a/hscontrol/db/db.go b/hscontrol/db/db.go index e18f2e5d..6cf4138c 100644 --- a/hscontrol/db/db.go +++ b/hscontrol/db/db.go @@ -962,7 +962,17 @@ AND auth_key_id NOT IN ( ctx, cancel := context.WithTimeout(context.Background(), contextTimeoutSecs*time.Second) defer cancel() - if err := squibble.Validate(ctx, sqlConn, dbSchema); err != nil { + opts := squibble.DigestOptions{ + IgnoreTables: []string{ + // Litestream tables, these are inserted by + // litestream and not part of our schema + // https://litestream.io/how-it-works + "_litestream_lock", + "_litestream_seq", + }, + } + + if err := squibble.Validate(ctx, sqlConn, dbSchema, &opts); err != nil { return nil, fmt.Errorf("validating schema: %w", err) } } diff --git a/hscontrol/db/testdata/sqlite/headscale_0.26.1_schema-litestream.sql b/hscontrol/db/testdata/sqlite/headscale_0.26.1_schema-litestream.sql new file mode 100644 index 00000000..3fc2b319 --- /dev/null +++ b/hscontrol/db/testdata/sqlite/headscale_0.26.1_schema-litestream.sql @@ -0,0 +1,14 @@ +CREATE TABLE `migrations` (`id` text,PRIMARY KEY (`id`)); +CREATE TABLE `users` (`id` integer PRIMARY KEY AUTOINCREMENT,`created_at` datetime,`updated_at` datetime,`deleted_at` datetime,`name` text,`display_name` text,`email` text,`provider_identifier` text,`provider` text,`profile_pic_url` text); +CREATE INDEX `idx_users_deleted_at` ON `users`(`deleted_at`); +CREATE TABLE `pre_auth_keys` (`id` integer PRIMARY KEY AUTOINCREMENT,`key` text,`user_id` integer,`reusable` numeric,`ephemeral` numeric DEFAULT false,`used` numeric DEFAULT false,`tags` text,`created_at` datetime,`expiration` datetime,CONSTRAINT `fk_pre_auth_keys_user` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE SET NULL); +CREATE TABLE `api_keys` (`id` integer PRIMARY KEY AUTOINCREMENT,`prefix` text,`hash` blob,`created_at` datetime,`expiration` datetime,`last_seen` datetime); +CREATE UNIQUE INDEX `idx_api_keys_prefix` ON `api_keys`(`prefix`); +CREATE TABLE IF NOT EXISTS "nodes" (`id` integer PRIMARY KEY AUTOINCREMENT,`machine_key` text,`node_key` text,`disco_key` text,`endpoints` text,`host_info` text,`ipv4` text,`ipv6` text,`hostname` text,`given_name` varchar(63),`user_id` integer,`register_method` text,`forced_tags` text,`auth_key_id` integer,`expiry` datetime,`last_seen` datetime,`approved_routes` text,`created_at` datetime,`updated_at` datetime,`deleted_at` datetime,CONSTRAINT `fk_nodes_user` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE,CONSTRAINT `fk_nodes_auth_key` FOREIGN KEY (`auth_key_id`) REFERENCES `pre_auth_keys`(`id`)); +CREATE TABLE `policies` (`id` integer PRIMARY KEY AUTOINCREMENT,`created_at` datetime,`updated_at` datetime,`deleted_at` datetime,`data` text); +CREATE INDEX `idx_policies_deleted_at` ON `policies`(`deleted_at`); +CREATE UNIQUE INDEX idx_provider_identifier ON users (provider_identifier) WHERE provider_identifier IS NOT NULL; +CREATE UNIQUE INDEX idx_name_provider_identifier ON users (name,provider_identifier); +CREATE UNIQUE INDEX idx_name_no_provider_identifier ON users (name) WHERE provider_identifier IS NULL; +CREATE TABLE _litestream_seq (id INTEGER PRIMARY KEY, seq INTEGER); +CREATE TABLE _litestream_lock (id INTEGER);