Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat(coderd): add retention policy configuration#21021

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
mafredri wants to merge2 commits intomain
base:main
Choose a base branch
Loading
frommafredri/feat-coderd-db-retention-policy
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletionscli/testdata/coder_server_--help.golden
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -696,6 +696,35 @@ updating, and deleting workspace resources.
Number of provisioner daemons to create on start. If builds are stuck
in queued state for a long time, consider increasing this.

RETENTION OPTIONS:
Configure data retention policies for various database tables. Retention
policies automatically purge old data to reduce database size and improve
performance. Setting a retention duration to 0 disables automatic purging for
that data type.

--api-keys-retention duration, $CODER_API_KEYS_RETENTION (default: 7d)
How long expired API keys are retained before being deleted. Keeping
expired keys allows the backend to return a more helpful error when a
user tries to use an expired key. Set to 0 to disable automatic
deletion of expired keys.

--audit-logs-retention duration, $CODER_AUDIT_LOGS_RETENTION (default: 0)
How long audit log entries are retained. Set to 0 to use the global
retention value, or to disable if global is also 0. We advise keeping
audit logs for at least a year, and in accordance with your compliance
requirements.

--connection-logs-retention duration, $CODER_CONNECTION_LOGS_RETENTION (default: 0)
How long connection log entries are retained. Set to 0 to use the
global retention value, or to disable if global is also 0.

--global-retention duration, $CODER_GLOBAL_RETENTION (default: 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I feel like this is overcomplicating matters. Why do we need this? As an operator, I'd want to either use the defaults or choose retention for each topic. Having this fallback adds complexity and might make it hard for folks to reason about.

Copy link
MemberAuthor

@mafredrimafredriDec 1, 2025
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

It’s listed as a nice-to-have in the ticket:#20743

I do see your point as well, I could go either way here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

When it comes to irrevocably deleting data, clear and explicit > convenient every time IMO.

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Makes sense to me. Are you OK with us removing this@bpmct?

Default retention policy for audit logs, connection logs, and API
keys. Individual retention settings override this value when set to a
non-zero duration. Does not affect AI Bridge retention. Set to 0 to
disable (data is kept indefinitely unless individual settings are
configured).

TELEMETRY OPTIONS:
Telemetry is critical to our ability to improve Coder. We strip all personal
information before sending data to our servers. Please only disable telemetry
Expand Down
25 changes: 25 additions & 0 deletionscli/testdata/server-config.yaml.golden
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -755,3 +755,28 @@ aibridge:
# (token, prompt, tool use).
# (default: 60d, type: duration)
retention: 1440h0m0s
# Configure data retention policies for various database tables. Retention
# policies automatically purge old data to reduce database size and improve
# performance. Setting a retention duration to 0 disables automatic purging for
# that data type.
retention:
# Default retention policy for audit logs, connection logs, and API keys.
# Individual retention settings override this value when set to a non-zero
# duration. Does not affect AI Bridge retention. Set to 0 to disable (data is kept
# indefinitely unless individual settings are configured).
# (default: 0, type: duration)
global: 0s
# How long audit log entries are retained. Set to 0 to use the global retention
# value, or to disable if global is also 0. We advise keeping audit logs for at
# least a year, and in accordance with your compliance requirements.
# (default: 0, type: duration)
audit_logs: 0s
# How long connection log entries are retained. Set to 0 to use the global
# retention value, or to disable if global is also 0.
# (default: 0, type: duration)
connection_logs: 0s
# How long expired API keys are retained before being deleted. Keeping expired
# keys allows the backend to return a more helpful error when a user tries to use
# an expired key. Set to 0 to disable automatic deletion of expired keys.
# (default: 7d, type: duration)
api_keys: 168h0m0s
24 changes: 24 additions & 0 deletionscoderd/apidoc/docs.go
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

24 changes: 24 additions & 0 deletionscoderd/apidoc/swagger.json
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

73 changes: 73 additions & 0 deletionscodersdk/deployment.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -501,6 +501,7 @@ type DeploymentValues struct {
WebTerminalRenderer serpent.String `json:"web_terminal_renderer,omitempty" typescript:",notnull"`
AllowWorkspaceRenames serpent.Bool `json:"allow_workspace_renames,omitempty" typescript:",notnull"`
Healthcheck HealthcheckConfig `json:"healthcheck,omitempty" typescript:",notnull"`
Retention RetentionConfig `json:"retention,omitempty" typescript:",notnull"`
CLIUpgradeMessage serpent.String `json:"cli_upgrade_message,omitempty" typescript:",notnull"`
TermsOfServiceURL serpent.String `json:"terms_of_service_url,omitempty" typescript:",notnull"`
Notifications NotificationsConfig `json:"notifications,omitempty" typescript:",notnull"`
Expand DownExpand Up@@ -813,6 +814,28 @@ type HealthcheckConfig struct {
ThresholdDatabase serpent.Duration `json:"threshold_database" typescript:",notnull"`
}

// RetentionConfig contains configuration for data retention policies.
// These settings control how long various types of data are retained in the database
// before being automatically purged. Setting a value to 0 disables retention for that
// data type (data is kept indefinitely).
type RetentionConfig struct {
// Global is the default retention policy for audit logs, connection logs,
// and API keys. Individual retention settings override this value when set
// to a non-zero duration. Does not affect AI Bridge retention which has its
// own setting.
Global serpent.Duration `json:"global" typescript:",notnull"`
// AuditLogs controls how long audit log entries are retained.
// Set to 0 to use the global retention value.
AuditLogs serpent.Duration `json:"audit_logs" typescript:",notnull"`
// ConnectionLogs controls how long connection log entries are retained.
// Set to 0 to use the global retention value.
ConnectionLogs serpent.Duration `json:"connection_logs" typescript:",notnull"`
// APIKeys controls how long expired API keys are retained before being deleted.
// Keys are only deleted if they have been expired for at least this duration.
// Defaults to 7 days to preserve existing behavior.
APIKeys serpent.Duration `json:"api_keys" typescript:",notnull"`
}

type NotificationsConfig struct {
// The upper limit of attempts to send a notification.
MaxSendAttempts serpent.Int64 `json:"max_send_attempts" typescript:",notnull"`
Expand DownExpand Up@@ -1180,6 +1203,11 @@ func (c *DeploymentValues) Options() serpent.OptionSet {
Name: "AI Bridge",
YAML: "aibridge",
}
deploymentGroupRetention = serpent.Group{
Name: "Retention",
Description: "Configure data retention policies for various database tables. Retention policies automatically purge old data to reduce database size and improve performance. Setting a retention duration to 0 disables automatic purging for that data type.",
YAML: "retention",
}
)

httpAddress := serpent.Option{
Expand DownExpand Up@@ -3363,6 +3391,51 @@ Write out the current server config as YAML to stdout.`,
YAML: "retention",
Annotations: serpent.Annotations{}.Mark(annotationFormatDuration, "true"),
},
// Retention settings
{
Name: "Global Retention",
Description: "Default retention policy for audit logs, connection logs, and API keys. Individual retention settings override this value when set to a non-zero duration. Does not affect AI Bridge retention. Set to 0 to disable (data is kept indefinitely unless individual settings are configured).",
Flag: "global-retention",
Env: "CODER_GLOBAL_RETENTION",
Value: &c.Retention.Global,
Default: "0",
Group: &deploymentGroupRetention,
YAML: "global",
Annotations: serpent.Annotations{}.Mark(annotationFormatDuration, "true"),
},
{
Name: "Audit Logs Retention",
Description: "How long audit log entries are retained. Set to 0 to use the global retention value, or to disable if global is also 0. We advise keeping audit logs for at least a year, and in accordance with your compliance requirements.",
Flag: "audit-logs-retention",
Env: "CODER_AUDIT_LOGS_RETENTION",
Value: &c.Retention.AuditLogs,
Default: "0",
Group: &deploymentGroupRetention,
YAML: "audit_logs",
Annotations: serpent.Annotations{}.Mark(annotationFormatDuration, "true"),
},
{
Name: "Connection Logs Retention",
Description: "How long connection log entries are retained. Set to 0 to use the global retention value, or to disable if global is also 0.",
Flag: "connection-logs-retention",
Env: "CODER_CONNECTION_LOGS_RETENTION",
Value: &c.Retention.ConnectionLogs,
Default: "0",
Group: &deploymentGroupRetention,
YAML: "connection_logs",
Annotations: serpent.Annotations{}.Mark(annotationFormatDuration, "true"),
},
{
Name: "API Keys Retention",
Description: "How long expired API keys are retained before being deleted. Keeping expired keys allows the backend to return a more helpful error when a user tries to use an expired key. Set to 0 to disable automatic deletion of expired keys.",
Flag: "api-keys-retention",
Env: "CODER_API_KEYS_RETENTION",
Value: &c.Retention.APIKeys,
Default: "7d",
Group: &deploymentGroupRetention,
YAML: "api_keys",
Annotations: serpent.Annotations{}.Mark(annotationFormatDuration, "true"),
},
{
Name: "Enable Authorization Recordings",
Description: "All api requests will have a header including all authorization calls made during the request. " +
Expand Down
78 changes: 78 additions & 0 deletionscodersdk/deployment_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -689,3 +689,81 @@ func TestNotificationsCanBeDisabled(t *testing.T) {
})
}
}

func TestRetentionConfigParsing(t *testing.T) {
t.Parallel()

tests := []struct {
name string
environment []serpent.EnvVar
expectedGlobal time.Duration
expectedAuditLogs time.Duration
expectedConnectionLogs time.Duration
expectedAPIKeys time.Duration
}{
{
name: "Defaults",
environment: []serpent.EnvVar{},
expectedGlobal: 0,
expectedAuditLogs: 0,
expectedConnectionLogs: 0,
expectedAPIKeys: 7 * 24 * time.Hour, // 7 days default
},
{
name: "GlobalRetentionSet",
environment: []serpent.EnvVar{
{Name: "CODER_GLOBAL_RETENTION", Value: "90d"},
},
expectedGlobal: 90 * 24 * time.Hour,
expectedAuditLogs: 0,
expectedConnectionLogs: 0,
expectedAPIKeys: 7 * 24 * time.Hour,
},
{
name: "IndividualRetentionSet",
environment: []serpent.EnvVar{
{Name: "CODER_AUDIT_LOGS_RETENTION", Value: "30d"},
{Name: "CODER_CONNECTION_LOGS_RETENTION", Value: "60d"},
{Name: "CODER_API_KEYS_RETENTION", Value: "14d"},
},
expectedGlobal: 0,
expectedAuditLogs: 30 * 24 * time.Hour,
expectedConnectionLogs: 60 * 24 * time.Hour,
expectedAPIKeys: 14 * 24 * time.Hour,
},
{
name: "AllRetentionSet",
environment: []serpent.EnvVar{
{Name: "CODER_GLOBAL_RETENTION", Value: "90d"},
{Name: "CODER_AUDIT_LOGS_RETENTION", Value: "365d"},
{Name: "CODER_CONNECTION_LOGS_RETENTION", Value: "30d"},
{Name: "CODER_API_KEYS_RETENTION", Value: "0"},
},
expectedGlobal: 90 * 24 * time.Hour,
expectedAuditLogs: 365 * 24 * time.Hour,
expectedConnectionLogs: 30 * 24 * time.Hour,
expectedAPIKeys: 0, // Explicitly disabled
},
}

for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

dv := codersdk.DeploymentValues{}
opts := dv.Options()

err := opts.SetDefaults()
require.NoError(t, err)

err = opts.ParseEnv(tt.environment)
require.NoError(t, err)

assert.Equal(t, tt.expectedGlobal, dv.Retention.Global.Value(), "global retention mismatch")
assert.Equal(t, tt.expectedAuditLogs, dv.Retention.AuditLogs.Value(), "audit logs retention mismatch")
assert.Equal(t, tt.expectedConnectionLogs, dv.Retention.ConnectionLogs.Value(), "connection logs retention mismatch")
assert.Equal(t, tt.expectedAPIKeys, dv.Retention.APIKeys.Value(), "api keys retention mismatch")
})
}
}
6 changes: 6 additions & 0 deletionsdocs/reference/api/general.md
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

Loading
Loading

[8]ページ先頭

©2009-2025 Movatter.jp