mirror of
https://github.com/juanfont/headscale.git
synced 2026-04-25 10:08:41 +02:00
db: enforce strict version upgrade path
Add a version check that runs before database migrations to ensure users do not skip minor versions or downgrade. This protects database migrations and allows future cleanup of old migration code. Rules enforced: - Same minor version: always allowed (patch changes either way) - Single minor upgrade (e.g. 0.27 -> 0.28): allowed - Multi-minor upgrade (e.g. 0.25 -> 0.28): blocked with guidance - Any minor downgrade: blocked - Major version change: blocked - Dev builds: warn but allow, preserve stored version The version is stored in a purpose-built database_versions table after migrations succeed. The table is created with raw SQL before gormigrate runs to avoid circular dependencies. Updates #3058
This commit is contained in:
@@ -63,6 +63,11 @@ func NewHeadscaleDatabase(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = checkVersionUpgradePath(dbConn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("version check: %w", err)
|
||||
}
|
||||
|
||||
migrations := gormigrate.New(
|
||||
dbConn,
|
||||
gormigrate.DefaultOptions,
|
||||
@@ -760,6 +765,20 @@ AND auth_key_id NOT IN (
|
||||
return nil, fmt.Errorf("migration failed: %w", err)
|
||||
}
|
||||
|
||||
// Store the current version in the database after migrations succeed.
|
||||
// Dev builds skip this to preserve the stored version for the next
|
||||
// real versioned binary.
|
||||
currentVersion := types.GetVersionInfo().Version
|
||||
if !isDev(currentVersion) {
|
||||
err = setDatabaseVersion(dbConn, currentVersion)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(
|
||||
"storing database version: %w",
|
||||
err,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Validate that the schema ends up in the expected state.
|
||||
// This is currently only done on sqlite as squibble does not
|
||||
// support Postgres and we use our sqlite schema as our source of
|
||||
|
||||
Reference in New Issue
Block a user