Skip to content

fix!: deprecate login_type=none, convert existing users to password login - #26851

Merged
jakehwll merged 13 commits into
mainfrom
jakehwll/DEVEX-226-all-services-accounts-all-the-time
Jul 28, 2026
Merged

fix!: deprecate login_type=none, convert existing users to password login#26851
jakehwll merged 13 commits into
mainfrom
jakehwll/DEVEX-226-all-services-accounts-all-the-time

Conversation

@jakehwll

@jakehwll jakehwll commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

🤖 This PR was modified by Coder Agents on behalf of Jake Howell.

Deprecates login_type=none (legacy passwordless machine users) in favour of premium service accounts, and migrates existing accounts off the deprecated path while preserving their identity. Resolves DEVEX-226.

What this does

  • Creation is gatedPOST /users and coder users create reject login_type=none (and the deprecated --disable-login) unless a service account is requested.
  • Existing users are converted — migration 000554_legacy_none_login_to_password rewrites legacy non-system, non–service-account login_type='none' accounts to login_type='password'. Email addresses are preserved and existing API tokens remain valid. Admins can set a password if interactive login is desired.

Why convert to password and not is_service_account?

Migration 000433_add_is_service_account_to_users adds two CHECK constraints:

  • users_email_not_empty: (is_service_account = true) = (email = '')
  • users_service_account_login_type: is_service_account = false OR login_type = 'none'

Turning a real, email-bearing login_type=none user into a service account would require blanking their email. Converting to password instead preserves the account and its email.

⚠️ Breaking / one-way. The down migration cannot restore which users originally had login_type='none'.

Decision log

  • Goal: move existing login_type=none users off the deprecated path while preserving their identity/email.
  • Constraint discovered: the is_service_account CHECK constraints (migration 000433) make a literal none → service account conversion require blanking emails, so this PR converts to password instead to keep emails intact.
  • Implementation: creation-gating in cli/usercreate.go and coderd/users.go, matching test updates, plus the 000554_legacy_none_login_to_password.{up,down}.sql migration.
  • CI fix: the branch was behind main and its migration originally numbered 000534, which collided with main's 000534_drop_chat_model_configs_provider. Merged main and renumbered to 000554 (next free after main's 000553). make gen produces no drift (the migration is data-only).

The service-account conversion alternative (#27182, which blanked emails) was closed in favour of this password-preserving approach.

Docs follow-up: #27333.

@linear-code

linear-code Bot commented Jun 30, 2026

Copy link
Copy Markdown

DEVEX-226

Comment on lines +8 to +9
-- `prebuilds@system` user should not convert it to service account.
AND is_system = false;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is defensive programming. Things would theoretically continue working if this was a service account, however, we don't want to allow it access to HTTP API key creation AI Bridge auth and Notifications.

@jakehwll jakehwll changed the title fix: all service accounts all the time fix!: migrate login_type=none to service accounts Jun 30, 2026
@jakehwll jakehwll changed the title fix!: migrate login_type=none to service accounts fix!: deprecate login_type=none, convert existing users to password login Jul 20, 2026
@jakehwll
jakehwll marked this pull request as ready for review July 20, 2026 03:13
@github-actions github-actions Bot added the release/breaking This label is applied to PRs to detect breaking changes as part of the release process label Jul 20, 2026
@coderagents

coderagents Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Documentation Check

Updates Needed

  • docs/install/releases/esr-2.29-2.34-upgrade.md - The breaking-changes table entry and the "Migrate headless automation to service accounts" step describe --login-type none as deprecated and advise manual migration. This PR changes that behavior: POST /users and coder users create now reject login_type=none / --disable-login unless --service-account is set, and migration 000554_legacy_none_login_to_password automatically converts existing non-system, non-service-account login_type='none' accounts to login_type='password'. Update the wording from "deprecated" to "blocked at creation," and document the automatic, one-way conversion (preserves email addresses, existing API tokens remain valid). The irreversible-migrations note should also mention 000554.
  • docs/admin/users/headless-auth.md - Add a short note that the legacy passwordless path (--login-type none / --disable-login) is no longer accepted at creation, and point users to service accounts (Premium) or password/GitHub/OIDC accounts (OSS) so admins searching for the old flow land on the replacement.

Note

The migration has been renumbered across rebases onto main (currently 000554); behavior is unchanged. The PR references a docs follow-up (#27333). This checklist tracks the documentation surfaces affected by the behavior change in this PR; close items as they are covered there or here.


Automated review via Coder Agents

Comment thread cli/usercreate.go Outdated
Comment thread cli/usercreate.go Outdated
Comment thread cli/usercreate.go Outdated
Comment thread cli/usercreate.go Outdated
@@ -0,0 +1,9 @@
-- Convert legacy users created with login_type 'none' to password auth.
-- OSS deployments cannot create service accounts without Premium. Existing

@code-asher code-asher Jul 20, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I see that we convert to password to avoid losing the email but why is that important? It seems to me like converting these to system accounts would be a seamless transition; do admins actually care if these types of users have emails?

At least, for premium users it would be seamless. For non-premium users I am not sure what happens if you have service accounts. Is the problem that we only prevent creating the accounts so a non-premium user would be grandfathered into keeping these service accounts? To me that seems reasonable though, and definitely less bad than a breaking change forcing premium users to recreate their accounts.

(I read through this description and the other PR; apologies if I missed some discussion.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I see that we convert to password to avoid losing the email but why is that important? It seems to me like converting these to system accounts would be a seamless transition; do admins actually care if these types of users have emails?

These are not internal coder system accounts, I'm not sure we should blur the line between is_system here.

At least, for premium users it would be seamless. For non-premium users I am not sure what happens if you have service accounts. Is the problem that we only prevent creating the accounts so a non-premium user would be grandfathered into keeping these service accounts?

This was a product decision, we did discuss handing out Service Accounts being grandfathered in but if license enforcement changes in the future we could possibly breaking OSS instances.

There will be product discussion sent out to customers about the migration path here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ooops sorry I meant service accounts, not system accounts 🤦

Gotcha if this was the product decision then so be it 😄

@code-asher code-asher Jul 21, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

fwiw though since we are already breaking both oss and premium instances with this change, seems less worse to break only oss instances later down the line instead 🤷

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@code-asher yeah that was essentially the choice. Having service accounts in OSS is not great because we are introducing an account into OSS that they can't actually get more of (service accounts are premium).

@jakehwll
jakehwll requested a review from code-asher July 21, 2026 05:52

@code-asher code-asher left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good to me!

Comment thread coderd/users.go
req.UserLoginType = codersdk.LoginTypePassword
}

if !req.ServiceAccount && req.UserLoginType == codersdk.LoginTypeNone {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nbd at all but this could be an else and skip the duplicate req.ServiceAccount check.

@@ -0,0 +1,9 @@
-- Convert legacy users created with login_type 'none' to password auth.
-- OSS deployments cannot create service accounts without Premium. Existing

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@code-asher yeah that was essentially the choice. Having service accounts in OSS is not great because we are introducing an account into OSS that they can't actually get more of (service accounts are premium).

@jakehwll
jakehwll merged commit 0e104f3 into main Jul 28, 2026
31 of 32 checks passed
@jakehwll
jakehwll deleted the jakehwll/DEVEX-226-all-services-accounts-all-the-time branch July 28, 2026 11:05
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 28, 2026
@jakehwll jakehwll added cherry-pick/v2.36 Cherry-pick PR targeting release/2.36 cherry-pick labels Jul 28, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

cherry-pick/v2.36 Cherry-pick PR targeting release/2.36 cherry-pick release/breaking This label is applied to PRs to detect breaking changes as part of the release process

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants