diff --git a/hscontrol/db/db.go b/hscontrol/db/db.go index 6841f446..478614fb 100644 --- a/hscontrol/db/db.go +++ b/hscontrol/db/db.go @@ -704,6 +704,29 @@ AND auth_key_id NOT IN ( }, Rollback: func(db *gorm.DB) error { return nil }, }, + { + // Clear user_id on tagged nodes. + // Tagged nodes are owned by their tags, not a user. + // Previously user_id was kept as "created by" tracking, + // but this prevents deleting users whose nodes have been + // tagged, and the ON DELETE CASCADE FK would destroy the + // tagged nodes if the user were deleted. + // Fixes: https://github.com/juanfont/headscale/issues/3077 + ID: "202602201200-clear-tagged-node-user-id", + Migrate: func(tx *gorm.DB) error { + err := tx.Exec(` +UPDATE nodes +SET user_id = NULL +WHERE tags IS NOT NULL AND tags != '[]' AND tags != ''; + `).Error + if err != nil { + return fmt.Errorf("clearing user_id on tagged nodes: %w", err) + } + + return nil + }, + Rollback: func(db *gorm.DB) error { return nil }, + }, }, ) diff --git a/hscontrol/db/schema.sql b/hscontrol/db/schema.sql index 41e817ee..781446c0 100644 --- a/hscontrol/db/schema.sql +++ b/hscontrol/db/schema.sql @@ -79,6 +79,8 @@ CREATE TABLE nodes( ipv6 text, hostname text, given_name varchar(63), + -- user_id is NULL for tagged nodes (owned by tags, not a user). + -- Only set for user-owned nodes (no tags). user_id integer, register_method text, tags text,