feat: add flag to disable password auth (#5991)

Adds a flag --disable-password-auth that prevents the password login
endpoint from working unless the user has the "owner" (aka. site admin)
role.

Adds a subcommand `coder server create-admin-user` which creates a user
directly in the database with the "owner" role, the "admin" role in
every organization, and password auth. This is to avoid lock-out
situations where all accounts have the login type set to an identity
provider and nobody can login.
This commit is contained in:
Dean Sheather 2023-02-07 01:58:21 +11:00 committed by GitHub
parent 968d7e4dc5
commit 4fe221a700
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 1352 additions and 542 deletions

View File

@ -532,7 +532,7 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
{
name: "Start/End out of order",
matches: []match{
//{match: "Continue?", write: "yes"},
// {match: "Continue?", write: "yes"},
},
writeConfig: writeConfig{
ssh: strings.Join([]string{
@ -547,7 +547,7 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
{
name: "Multiple sections",
matches: []match{
//{match: "Continue?", write: "yes"},
// {match: "Continue?", write: "yes"},
},
writeConfig: writeConfig{
ssh: strings.Join([]string{

View File

@ -550,6 +550,12 @@ func newConfig() *codersdk.DeploymentConfig {
Flag: "disable-session-expiry-refresh",
Default: false,
},
DisablePasswordAuth: &codersdk.DeploymentConfigField[bool]{
Name: "Disable Password Authentication",
Usage: "Disable password authentication. This is recommended for security purposes in production deployments that rely on an identity provider. Any user with the owner role will be able to sign in with their password regardless of this setting to avoid potential lock out. If you are locked out of your account, you can use the `coder server create-admin` command to create a new admin user directly in the database.",
Flag: "disable-password-auth",
Default: false,
},
}
}

View File

@ -563,62 +563,13 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co
options.Database = dbfake.New()
options.Pubsub = database.NewPubsubInMemory()
} else {
logger.Debug(ctx, "connecting to postgresql")
sqlDB, err := sql.Open(sqlDriver, cfg.PostgresURL.Value)
sqlDB, err := connectToPostgres(ctx, logger, sqlDriver, cfg.PostgresURL.Value)
if err != nil {
return xerrors.Errorf("dial postgres: %w", err)
return xerrors.Errorf("connect to postgres: %w", err)
}
defer sqlDB.Close()
pingCtx, pingCancel := context.WithTimeout(ctx, 15*time.Second)
defer pingCancel()
err = sqlDB.PingContext(pingCtx)
if err != nil {
return xerrors.Errorf("ping postgres: %w", err)
}
// Ensure the PostgreSQL version is >=13.0.0!
version, err := sqlDB.QueryContext(ctx, "SHOW server_version;")
if err != nil {
return xerrors.Errorf("get postgres version: %w", err)
}
if !version.Next() {
return xerrors.Errorf("no rows returned for version select")
}
var versionStr string
err = version.Scan(&versionStr)
if err != nil {
return xerrors.Errorf("scan version: %w", err)
}
_ = version.Close()
versionStr = strings.Split(versionStr, " ")[0]
if semver.Compare("v"+versionStr, "v13") < 0 {
return xerrors.New("PostgreSQL version must be v13.0.0 or higher!")
}
logger.Debug(ctx, "connected to postgresql", slog.F("version", versionStr))
err = migrations.Up(sqlDB)
if err != nil {
return xerrors.Errorf("migrate up: %w", err)
}
// The default is 0 but the request will fail with a 500 if the DB
// cannot accept new connections, so we try to limit that here.
// Requests will wait for a new connection instead of a hard error
// if a limit is set.
sqlDB.SetMaxOpenConns(10)
// Allow a max of 3 idle connections at a time. Lower values end up
// creating a lot of connection churn. Since each connection uses about
// 10MB of memory, we're allocating 30MB to Postgres connections per
// replica, but is better than causing Postgres to spawn a thread 15-20
// times/sec. PGBouncer's transaction pooling is not the greatest so
// it's not optimal for us to deploy.
//
// This was set to 10 before we started doing HA deployments, but 3 was
// later determined to be a better middle ground as to not use up all
// of PGs default connection limit while simultaneously avoiding a lot
// of connection churn.
sqlDB.SetMaxIdleConns(3)
defer func() {
_ = sqlDB.Close()
}()
options.Database = database.New(sqlDB)
options.Pubsub, err = database.NewPubsub(ctx, sqlDB, cfg.PostgresURL.Value)
@ -1007,7 +958,8 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co
postgresBuiltinURLCmd.Flags().BoolVar(&pgRawURL, "raw-url", false, "Output the raw connection URL instead of a psql command.")
postgresBuiltinServeCmd.Flags().BoolVar(&pgRawURL, "raw-url", false, "Output the raw connection URL instead of a psql command.")
root.AddCommand(postgresBuiltinURLCmd, postgresBuiltinServeCmd)
createAdminUserCommand := newCreateAdminUserCommand()
root.AddCommand(postgresBuiltinURLCmd, postgresBuiltinServeCmd, createAdminUserCommand)
deployment.AttachFlags(root.Flags(), vip, false)
@ -1607,3 +1559,71 @@ func buildLogger(cmd *cobra.Command, cfg *codersdk.DeploymentConfig) (slog.Logge
}
}, nil
}
func connectToPostgres(ctx context.Context, logger slog.Logger, driver string, dbURL string) (*sql.DB, error) {
logger.Debug(ctx, "connecting to postgresql")
sqlDB, err := sql.Open(driver, dbURL)
if err != nil {
return nil, xerrors.Errorf("dial postgres: %w", err)
}
ok := false
defer func() {
if !ok {
_ = sqlDB.Close()
}
}()
pingCtx, pingCancel := context.WithTimeout(ctx, 15*time.Second)
defer pingCancel()
err = sqlDB.PingContext(pingCtx)
if err != nil {
return nil, xerrors.Errorf("ping postgres: %w", err)
}
// Ensure the PostgreSQL version is >=13.0.0!
version, err := sqlDB.QueryContext(ctx, "SHOW server_version;")
if err != nil {
return nil, xerrors.Errorf("get postgres version: %w", err)
}
if !version.Next() {
return nil, xerrors.Errorf("no rows returned for version select")
}
var versionStr string
err = version.Scan(&versionStr)
if err != nil {
return nil, xerrors.Errorf("scan version: %w", err)
}
_ = version.Close()
versionStr = strings.Split(versionStr, " ")[0]
if semver.Compare("v"+versionStr, "v13") < 0 {
return nil, xerrors.New("PostgreSQL version must be v13.0.0 or higher!")
}
logger.Debug(ctx, "connected to postgresql", slog.F("version", versionStr))
err = migrations.Up(sqlDB)
if err != nil {
return nil, xerrors.Errorf("migrate up: %w", err)
}
// The default is 0 but the request will fail with a 500 if the DB
// cannot accept new connections, so we try to limit that here.
// Requests will wait for a new connection instead of a hard error
// if a limit is set.
sqlDB.SetMaxOpenConns(10)
// Allow a max of 3 idle connections at a time. Lower values end up
// creating a lot of connection churn. Since each connection uses about
// 10MB of memory, we're allocating 30MB to Postgres connections per
// replica, but is better than causing Postgres to spawn a thread 15-20
// times/sec. PGBouncer's transaction pooling is not the greatest so
// it's not optimal for us to deploy.
//
// This was set to 10 before we started doing HA deployments, but 3 was
// later determined to be a better middle ground as to not use up all
// of PGs default connection limit while simultaneously avoiding a lot
// of connection churn.
sqlDB.SetMaxIdleConns(3)
ok = true
return sqlDB, nil
}

View File

@ -0,0 +1,262 @@
//go:build !slim
package cli
import (
"fmt"
"os"
"os/signal"
"sort"
"github.com/google/uuid"
"github.com/spf13/cobra"
"golang.org/x/xerrors"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/coder/coder/cli/cliui"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/gitsshkey"
"github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/coderd/rbac"
"github.com/coder/coder/coderd/userpassword"
"github.com/coder/coder/codersdk"
)
func newCreateAdminUserCommand() *cobra.Command {
var (
newUserDBURL string
newUserSSHKeygenAlgorithm string
newUserUsername string
newUserEmail string
newUserPassword string
)
createAdminUserCommand := &cobra.Command{
Use: "create-admin-user",
Short: "Create a new admin user with the given username, email and password and adds it to every organization.",
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
sshKeygenAlgorithm, err := gitsshkey.ParseAlgorithm(newUserSSHKeygenAlgorithm)
if err != nil {
return xerrors.Errorf("parse ssh keygen algorithm %q: %w", newUserSSHKeygenAlgorithm, err)
}
if val, exists := os.LookupEnv("CODER_POSTGRES_URL"); exists {
newUserDBURL = val
}
if val, exists := os.LookupEnv("CODER_SSH_KEYGEN_ALGORITHM"); exists {
newUserSSHKeygenAlgorithm = val
}
if val, exists := os.LookupEnv("CODER_USERNAME"); exists {
newUserUsername = val
}
if val, exists := os.LookupEnv("CODER_EMAIL"); exists {
newUserEmail = val
}
if val, exists := os.LookupEnv("CODER_PASSWORD"); exists {
newUserPassword = val
}
cfg := createConfig(cmd)
logger := slog.Make(sloghuman.Sink(cmd.ErrOrStderr()))
if ok, _ := cmd.Flags().GetBool(varVerbose); ok {
logger = logger.Leveled(slog.LevelDebug)
}
ctx, cancel := signal.NotifyContext(ctx, InterruptSignals...)
defer cancel()
if newUserDBURL == "" {
cmd.Printf("Using built-in PostgreSQL (%s)\n", cfg.PostgresPath())
url, closePg, err := startBuiltinPostgres(ctx, cfg, logger)
if err != nil {
return err
}
defer func() {
_ = closePg()
}()
newUserDBURL = url
}
sqlDB, err := connectToPostgres(ctx, logger, "postgres", newUserDBURL)
if err != nil {
return xerrors.Errorf("connect to postgres: %w", err)
}
defer func() {
_ = sqlDB.Close()
}()
db := database.New(sqlDB)
validateInputs := func(username, email, password string) error {
// Use the validator tags so we match the API's validation.
req := codersdk.CreateUserRequest{
Username: "username",
Email: "email@coder.com",
Password: "ValidPa$$word123!",
OrganizationID: uuid.New(),
}
if username != "" {
req.Username = username
}
if email != "" {
req.Email = email
}
if password != "" {
req.Password = password
}
return httpapi.Validate.Struct(req)
}
if newUserUsername == "" {
newUserUsername, err = cliui.Prompt(cmd, cliui.PromptOptions{
Text: "Username",
Validate: func(val string) error {
if val == "" {
return xerrors.New("username cannot be empty")
}
return validateInputs(val, "", "")
},
})
if err != nil {
return err
}
}
if newUserEmail == "" {
newUserEmail, err = cliui.Prompt(cmd, cliui.PromptOptions{
Text: "Email",
Validate: func(val string) error {
if val == "" {
return xerrors.New("email cannot be empty")
}
return validateInputs("", val, "")
},
})
if err != nil {
return err
}
}
if newUserPassword == "" {
newUserPassword, err = cliui.Prompt(cmd, cliui.PromptOptions{
Text: "Password",
Secret: true,
Validate: func(val string) error {
if val == "" {
return xerrors.New("password cannot be empty")
}
return validateInputs("", "", val)
},
})
if err != nil {
return err
}
// Prompt again.
_, err = cliui.Prompt(cmd, cliui.PromptOptions{
Text: "Confirm password",
Secret: true,
Validate: func(val string) error {
if val != newUserPassword {
return xerrors.New("passwords do not match")
}
return nil
},
})
if err != nil {
return err
}
}
err = validateInputs(newUserUsername, newUserEmail, newUserPassword)
if err != nil {
return xerrors.Errorf("validate inputs: %w", err)
}
hashedPassword, err := userpassword.Hash(newUserPassword)
if err != nil {
return xerrors.Errorf("hash password: %w", err)
}
// Create the user.
var newUser database.User
err = db.InTx(func(tx database.Store) error {
orgs, err := tx.GetOrganizations(ctx)
if err != nil {
return xerrors.Errorf("get organizations: %w", err)
}
// Sort organizations by name so that test output is consistent.
sort.Slice(orgs, func(i, j int) bool {
return orgs[i].Name < orgs[j].Name
})
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), "Creating user...")
newUser, err = tx.InsertUser(ctx, database.InsertUserParams{
ID: uuid.New(),
Email: newUserEmail,
Username: newUserUsername,
HashedPassword: []byte(hashedPassword),
CreatedAt: database.Now(),
UpdatedAt: database.Now(),
RBACRoles: []string{rbac.RoleOwner()},
LoginType: database.LoginTypePassword,
})
if err != nil {
return xerrors.Errorf("insert user: %w", err)
}
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), "Generating user SSH key...")
privateKey, publicKey, err := gitsshkey.Generate(sshKeygenAlgorithm)
if err != nil {
return xerrors.Errorf("generate user gitsshkey: %w", err)
}
_, err = tx.InsertGitSSHKey(ctx, database.InsertGitSSHKeyParams{
UserID: newUser.ID,
CreatedAt: database.Now(),
UpdatedAt: database.Now(),
PrivateKey: privateKey,
PublicKey: publicKey,
})
if err != nil {
return xerrors.Errorf("insert user gitsshkey: %w", err)
}
for _, org := range orgs {
_, _ = fmt.Fprintf(cmd.ErrOrStderr(), "Adding user to organization %q (%s) as admin...\n", org.Name, org.ID.String())
_, err := tx.InsertOrganizationMember(ctx, database.InsertOrganizationMemberParams{
OrganizationID: org.ID,
UserID: newUser.ID,
CreatedAt: database.Now(),
UpdatedAt: database.Now(),
Roles: []string{rbac.RoleOrgAdmin(org.ID)},
})
if err != nil {
return xerrors.Errorf("insert organization member: %w", err)
}
}
return nil
}, nil)
if err != nil {
return err
}
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), "")
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), "User created successfully.")
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), "ID: "+newUser.ID.String())
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), "Username: "+newUser.Username)
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), "Email: "+newUser.Email)
_, _ = fmt.Fprintln(cmd.ErrOrStderr(), "Password: ********")
return nil
},
}
createAdminUserCommand.Flags().StringVar(&newUserDBURL, "postgres-url", "", "URL of a PostgreSQL database. If empty, the built-in PostgreSQL deployment will be used (Coder must not be already running in this case). Consumes $CODER_POSTGRES_URL.")
createAdminUserCommand.Flags().StringVar(&newUserSSHKeygenAlgorithm, "ssh-keygen-algorithm", "ed25519", "The algorithm to use for generating ssh keys. Accepted values are \"ed25519\", \"ecdsa\", or \"rsa4096\". Consumes $CODER_SSH_KEYGEN_ALGORITHM.")
createAdminUserCommand.Flags().StringVar(&newUserUsername, "username", "", "The username of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_USERNAME.")
createAdminUserCommand.Flags().StringVar(&newUserEmail, "email", "", "The email of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_EMAIL.")
createAdminUserCommand.Flags().StringVar(&newUserPassword, "password", "", "The password of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_PASSWORD.")
return createAdminUserCommand
}

View File

@ -0,0 +1,269 @@
package cli_test
import (
"context"
"database/sql"
"fmt"
"runtime"
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/coder/coder/cli/clitest"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/database/postgres"
"github.com/coder/coder/coderd/rbac"
"github.com/coder/coder/coderd/userpassword"
"github.com/coder/coder/pty/ptytest"
"github.com/coder/coder/testutil"
)
//nolint:paralleltest, tparallel
func TestServerCreateAdminUser(t *testing.T) {
const (
username = "dean"
email = "dean@example.com"
password = "SecurePa$$word123"
)
verifyUser := func(t *testing.T, dbURL, username, email, password string) {
t.Helper()
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
sqlDB, err := sql.Open("postgres", dbURL)
require.NoError(t, err)
defer sqlDB.Close()
db := database.New(sqlDB)
pingCtx, pingCancel := context.WithTimeout(ctx, testutil.WaitShort)
defer pingCancel()
_, err = db.Ping(pingCtx)
require.NoError(t, err, "ping db")
user, err := db.GetUserByEmailOrUsername(ctx, database.GetUserByEmailOrUsernameParams{
Email: email,
})
require.NoError(t, err)
require.Equal(t, username, user.Username, "username does not match")
require.Equal(t, email, user.Email, "email does not match")
ok, err := userpassword.Compare(string(user.HashedPassword), password)
require.NoError(t, err)
require.True(t, ok, "password does not match")
require.EqualValues(t, []string{rbac.RoleOwner()}, user.RBACRoles, "user does not have owner role")
// Check that user is admin in every org.
orgs, err := db.GetOrganizations(ctx)
require.NoError(t, err)
orgIDs := make(map[uuid.UUID]struct{}, len(orgs))
for _, org := range orgs {
orgIDs[org.ID] = struct{}{}
}
orgMemberships, err := db.GetOrganizationMembershipsByUserID(ctx, user.ID)
require.NoError(t, err)
orgIDs2 := make(map[uuid.UUID]struct{}, len(orgMemberships))
for _, membership := range orgMemberships {
orgIDs2[membership.OrganizationID] = struct{}{}
assert.Equal(t, []string{rbac.RoleOrgAdmin(membership.OrganizationID)}, membership.Roles, "user is not org admin")
}
require.Equal(t, orgIDs, orgIDs2, "user is not in all orgs")
}
t.Run("OK", func(t *testing.T) {
t.Parallel()
if runtime.GOOS != "linux" || testing.Short() {
// Skip on non-Linux because it spawns a PostgreSQL instance.
t.SkipNow()
}
connectionURL, closeFunc, err := postgres.Open()
require.NoError(t, err)
defer closeFunc()
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()
sqlDB, err := sql.Open("postgres", connectionURL)
require.NoError(t, err)
defer sqlDB.Close()
db := database.New(sqlDB)
pingCtx, pingCancel := context.WithTimeout(ctx, testutil.WaitShort)
defer pingCancel()
_, err = db.Ping(pingCtx)
require.NoError(t, err, "ping db")
// Insert a few orgs.
org1Name, org1ID := "org1", uuid.New()
org2Name, org2ID := "org2", uuid.New()
_, err = db.InsertOrganization(ctx, database.InsertOrganizationParams{
ID: org1ID,
Name: org1Name,
CreatedAt: database.Now(),
UpdatedAt: database.Now(),
})
require.NoError(t, err)
_, err = db.InsertOrganization(ctx, database.InsertOrganizationParams{
ID: org2ID,
Name: org2Name,
CreatedAt: database.Now(),
UpdatedAt: database.Now(),
})
require.NoError(t, err)
root, _ := clitest.New(t,
"server", "create-admin-user",
"--postgres-url", connectionURL,
"--ssh-keygen-algorithm", "ed25519",
"--username", username,
"--email", email,
"--password", password,
)
pty := ptytest.New(t)
root.SetOutput(pty.Output())
root.SetErr(pty.Output())
errC := make(chan error, 1)
go func() {
err := root.ExecuteContext(ctx)
t.Log("root.ExecuteContext() returned:", err)
errC <- err
}()
pty.ExpectMatch("Creating user...")
pty.ExpectMatch("Generating user SSH key...")
pty.ExpectMatch(fmt.Sprintf("Adding user to organization %q (%s) as admin...", org1Name, org1ID.String()))
pty.ExpectMatch(fmt.Sprintf("Adding user to organization %q (%s) as admin...", org2Name, org2ID.String()))
pty.ExpectMatch("User created successfully.")
pty.ExpectMatch(username)
pty.ExpectMatch(email)
pty.ExpectMatch("****")
require.NoError(t, <-errC)
verifyUser(t, connectionURL, username, email, password)
})
//nolint:paralleltest
t.Run("Env", func(t *testing.T) {
if runtime.GOOS != "linux" || testing.Short() {
// Skip on non-Linux because it spawns a PostgreSQL instance.
t.SkipNow()
}
connectionURL, closeFunc, err := postgres.Open()
require.NoError(t, err)
defer closeFunc()
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()
t.Setenv("CODER_POSTGRES_URL", connectionURL)
t.Setenv("CODER_SSH_KEYGEN_ALGORITHM", "ecdsa")
t.Setenv("CODER_USERNAME", username)
t.Setenv("CODER_EMAIL", email)
t.Setenv("CODER_PASSWORD", password)
root, _ := clitest.New(t, "server", "create-admin-user")
pty := ptytest.New(t)
root.SetOutput(pty.Output())
root.SetErr(pty.Output())
errC := make(chan error, 1)
go func() {
err := root.ExecuteContext(ctx)
t.Log("root.ExecuteContext() returned:", err)
errC <- err
}()
pty.ExpectMatch("User created successfully.")
pty.ExpectMatch(username)
pty.ExpectMatch(email)
pty.ExpectMatch("****")
require.NoError(t, <-errC)
verifyUser(t, connectionURL, username, email, password)
})
t.Run("Stdin", func(t *testing.T) {
t.Parallel()
if runtime.GOOS != "linux" || testing.Short() {
// Skip on non-Linux because it spawns a PostgreSQL instance.
t.SkipNow()
}
connectionURL, closeFunc, err := postgres.Open()
require.NoError(t, err)
defer closeFunc()
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()
root, _ := clitest.New(t,
"server", "create-admin-user",
"--postgres-url", connectionURL,
"--ssh-keygen-algorithm", "rsa4096",
)
pty := ptytest.New(t)
root.SetIn(pty.Input())
root.SetOutput(pty.Output())
root.SetErr(pty.Output())
errC := make(chan error, 1)
go func() {
err := root.ExecuteContext(ctx)
t.Log("root.ExecuteContext() returned:", err)
errC <- err
}()
pty.ExpectMatch("> Username")
pty.WriteLine(username)
pty.ExpectMatch("> Email")
pty.WriteLine(email)
pty.ExpectMatch("> Password")
pty.WriteLine(password)
pty.ExpectMatch("> Confirm password")
pty.WriteLine(password)
pty.ExpectMatch("User created successfully.")
pty.ExpectMatch(username)
pty.ExpectMatch(email)
pty.ExpectMatch("****")
require.NoError(t, <-errC)
verifyUser(t, connectionURL, username, email, password)
})
t.Run("Validates", func(t *testing.T) {
t.Parallel()
if runtime.GOOS != "linux" || testing.Short() {
// Skip on non-Linux because it spawns a PostgreSQL instance.
t.SkipNow()
}
connectionURL, closeFunc, err := postgres.Open()
require.NoError(t, err)
defer closeFunc()
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()
root, _ := clitest.New(t,
"server", "create-admin-user",
"--postgres-url", connectionURL,
"--ssh-keygen-algorithm", "rsa4096",
"--username", "$",
"--email", "not-an-email",
"--password", "x",
)
pty := ptytest.New(t)
root.SetOutput(pty.Output())
root.SetErr(pty.Output())
err = root.ExecuteContext(ctx)
require.Error(t, err)
require.ErrorContains(t, err, "'email' failed on the 'email' tag")
require.ErrorContains(t, err, "'username' failed on the 'username' tag")
})
}

View File

@ -47,12 +47,34 @@ func Server(vip *viper.Viper, _ func(context.Context, *coderd.Options) (*coderd.
},
}
var (
newUserDBURL string
newUserSSHKeygenAlgorithm string
newUserUsername string
newUserEmail string
newUserPassword string
)
createAdminUserCommand := &cobra.Command{
Use: "create-admin-user",
Short: "Create a new admin user with the given username, email and password and adds it to every organization.",
Hidden: true,
RunE: func(cmd *cobra.Command, args []string) error {
serverUnsupported(cmd.ErrOrStderr())
return nil
},
}
// We still have to attach the flags to the commands so users don't get
// an error when they try to use them.
postgresBuiltinURLCmd.Flags().BoolVar(&pgRawURL, "raw-url", false, "Output the raw connection URL instead of a psql command.")
postgresBuiltinServeCmd.Flags().BoolVar(&pgRawURL, "raw-url", false, "Output the raw connection URL instead of a psql command.")
createAdminUserCommand.Flags().StringVar(&newUserDBURL, "postgres-url", "", "URL of a PostgreSQL database. If empty, the built-in PostgreSQL deployment will be used (Coder must not be already running in this case). Consumes $CODER_POSTGRES_URL.")
createAdminUserCommand.Flags().StringVar(&newUserSSHKeygenAlgorithm, "ssh-keygen-algorithm", "ed25519", "The algorithm to use for generating ssh keys. Accepted values are \"ed25519\", \"ecdsa\", or \"rsa4096\". Consumes $CODER_SSH_KEYGEN_ALGORITHM.")
createAdminUserCommand.Flags().StringVar(&newUserUsername, "username", "", "The username of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_USERNAME.")
createAdminUserCommand.Flags().StringVar(&newUserEmail, "email", "", "The email of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_EMAIL.")
createAdminUserCommand.Flags().StringVar(&newUserPassword, "password", "", "The password of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_PASSWORD.")
root.AddCommand(postgresBuiltinURLCmd, postgresBuiltinServeCmd)
root.AddCommand(postgresBuiltinURLCmd, postgresBuiltinServeCmd, createAdminUserCommand)
deployment.AttachFlags(root.Flags(), vip, false)

View File

@ -6,316 +6,362 @@ Usage:
coder server [command]
Commands:
create-admin-user Create a new admin user with the given username, email and password and adds it to every organization.
postgres-builtin-serve Run the built-in PostgreSQL deployment.
postgres-builtin-url Output the connection URL for the built-in PostgreSQL deployment.
Flags:
--access-url string External URL to access your deployment.
This must be accessible by all
provisioned workspaces.
Consumes $CODER_ACCESS_URL
--api-rate-limit int Maximum number of requests per minute
allowed to the API per user, or per IP
address for unauthenticated users.
Negative values mean no rate limit. Some
API endpoints have separate strict rate
limits regardless of this value to
prevent denial-of-service or brute force
attacks.
Consumes $CODER_API_RATE_LIMIT (default 512)
--cache-dir string The directory to cache temporary files.
If unspecified and $CACHE_DIRECTORY is
set, it will be used for compatibility
with systemd.
Consumes $CODER_CACHE_DIRECTORY (default
"~/.cache/coder")
--dangerous-allow-path-app-sharing Allow workspace apps that are not served
from subdomains to be shared. Path-based
app sharing is DISABLED by default for
security purposes. Path-based apps can
make requests to the Coder API and pose a
security risk when the workspace serves
malicious JavaScript. Path-based apps can
be disabled entirely with
--disable-path-apps for further security.
Consumes
$CODER_DANGEROUS_ALLOW_PATH_APP_SHARING
--dangerous-allow-path-app-site-owner-access Allow site-owners to access workspace
apps from workspaces they do not own.
Owners cannot access path-based apps they
do not own by default. Path-based apps
can make requests to the Coder API and
pose a security risk when the workspace
serves malicious JavaScript. Path-based
apps can be disabled entirely with
--disable-path-apps for further security.
Consumes
$CODER_DANGEROUS_ALLOW_PATH_APP_SITE_OWNER_ACCESS
--dangerous-disable-rate-limits Disables all rate limits. This is not
recommended in production.
Consumes $CODER_RATE_LIMIT_DISABLE_ALL
--derp-config-path string Path to read a DERP mapping from. See:
https://tailscale.com/kb/1118/custom-derp-servers/
Consumes $CODER_DERP_CONFIG_PATH
--derp-config-url string URL to fetch a DERP mapping on startup.
See:
https://tailscale.com/kb/1118/custom-derp-servers/
Consumes $CODER_DERP_CONFIG_URL
--derp-server-enable Whether to enable or disable the embedded
DERP relay server.
Consumes $CODER_DERP_SERVER_ENABLE
(default true)
--derp-server-region-code string Region code to use for the embedded DERP
server.
Consumes $CODER_DERP_SERVER_REGION_CODE
(default "coder")
--derp-server-region-id int Region ID to use for the embedded DERP
server.
Consumes $CODER_DERP_SERVER_REGION_ID
(default 999)
--derp-server-region-name string Region name that for the embedded DERP
server.
Consumes $CODER_DERP_SERVER_REGION_NAME
(default "Coder Embedded Relay")
--derp-server-stun-addresses strings Addresses for STUN servers to establish
P2P connections. Set empty to disable P2P
connections.
Consumes
$CODER_DERP_SERVER_STUN_ADDRESSES
(default [stun.l.google.com:19302])
--disable-path-apps Disable workspace apps that are not
served from subdomains. Path-based apps
can make requests to the Coder API and
pose a security risk when the workspace
serves malicious JavaScript. This is
recommended for security purposes if a
--wildcard-access-url is configured.
Consumes $CODER_DISABLE_PATH_APPS
--disable-session-expiry-refresh Disable automatic session expiry bumping
due to activity. This forces all sessions
to become invalid after the session
expiry duration has been reached.
Consumes $CODER_DISABLE_SESSION_EXPIRY_REFRESH
--experiments strings Enable one or more experiments. These are
not ready for production. Separate
multiple experiments with commas, or
enter '*' to opt-in to all available
experiments.
Consumes $CODER_EXPERIMENTS
-h, --help help for server
--http-address string HTTP bind address of the server. Unset to
disable the HTTP endpoint.
Consumes $CODER_HTTP_ADDRESS (default
"127.0.0.1:3000")
--log-human string Output human-readable logs to a given
file.
Consumes $CODER_LOGGING_HUMAN (default
"/dev/stderr")
--log-json string Output JSON logs to a given file.
Consumes $CODER_LOGGING_JSON
--log-stackdriver string Output Stackdriver compatible logs to a
given file.
Consumes $CODER_LOGGING_STACKDRIVER
--max-token-lifetime duration The maximum lifetime duration users can
specify when creating an API token.
Consumes $CODER_MAX_TOKEN_LIFETIME
(default 720h0m0s)
--oauth2-github-allow-everyone Allow all logins, setting this option
means allowed orgs and teams must be
empty.
Consumes $CODER_OAUTH2_GITHUB_ALLOW_EVERYONE
--oauth2-github-allow-signups Whether new users can sign up with
GitHub.
Consumes $CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS
--oauth2-github-allowed-orgs strings Organizations the user must be a member
of to Login with GitHub.
Consumes $CODER_OAUTH2_GITHUB_ALLOWED_ORGS
--oauth2-github-allowed-teams strings Teams inside organizations the user must
be a member of to Login with GitHub.
Structured as:
<organization-name>/<team-slug>.
Consumes $CODER_OAUTH2_GITHUB_ALLOWED_TEAMS
--oauth2-github-client-id string Client ID for Login with GitHub.
Consumes $CODER_OAUTH2_GITHUB_CLIENT_ID
--oauth2-github-client-secret string Client secret for Login with GitHub.
Consumes $CODER_OAUTH2_GITHUB_CLIENT_SECRET
--oauth2-github-enterprise-base-url string Base URL of a GitHub Enterprise
deployment to use for Login with GitHub.
Consumes
$CODER_OAUTH2_GITHUB_ENTERPRISE_BASE_URL
--oidc-allow-signups Whether new users can sign up with OIDC.
Consumes $CODER_OIDC_ALLOW_SIGNUPS
(default true)
--oidc-client-id string Client ID to use for Login with OIDC.
Consumes $CODER_OIDC_CLIENT_ID
--oidc-client-secret string Client secret to use for Login with OIDC.
Consumes $CODER_OIDC_CLIENT_SECRET
--oidc-email-domain strings Email domains that clients logging in
with OIDC must match.
Consumes $CODER_OIDC_EMAIL_DOMAIN
--oidc-icon-url string URL pointing to the icon to use on the
OepnID Connect login button
Consumes $CODER_OIDC_ICON_URL
--oidc-ignore-email-verified Ignore the email_verified claim from the
upstream provider.
Consumes $CODER_OIDC_IGNORE_EMAIL_VERIFIED
--oidc-issuer-url string Issuer URL to use for Login with OIDC.
Consumes $CODER_OIDC_ISSUER_URL
--oidc-scopes strings Scopes to grant when authenticating with
OIDC.
Consumes $CODER_OIDC_SCOPES (default
[openid,profile,email])
--oidc-sign-in-text string The text to show on the OpenID Connect
sign in button
Consumes $CODER_OIDC_SIGN_IN_TEXT
(default "OpenID Connect")
--oidc-username-field string OIDC claim field to use as the username.
Consumes $CODER_OIDC_USERNAME_FIELD
(default "preferred_username")
--postgres-url string URL of a PostgreSQL database. If empty,
PostgreSQL binaries will be downloaded
from Maven
(https://repo1.maven.org/maven2) and
store all data in the config root. Access
the built-in database with "coder server
postgres-builtin-url".
Consumes $CODER_PG_CONNECTION_URL
--pprof-address string The bind address to serve pprof.
Consumes $CODER_PPROF_ADDRESS (default
"127.0.0.1:6060")
--pprof-enable Serve pprof metrics on the address
defined by pprof address.
Consumes $CODER_PPROF_ENABLE
--prometheus-address string The bind address to serve prometheus
metrics.
Consumes $CODER_PROMETHEUS_ADDRESS
(default "127.0.0.1:2112")
--prometheus-enable Serve prometheus metrics on the address
defined by prometheus address.
Consumes $CODER_PROMETHEUS_ENABLE
--provisioner-daemon-poll-interval duration Time to wait before polling for a new
job.
Consumes
$CODER_PROVISIONER_DAEMON_POLL_INTERVAL
(default 1s)
--provisioner-daemon-poll-jitter duration Random jitter added to the poll interval.
Consumes
$CODER_PROVISIONER_DAEMON_POLL_JITTER
(default 100ms)
--provisioner-daemons int Number of provisioner daemons to create
on start. If builds are stuck in queued
state for a long time, consider
increasing this.
Consumes $CODER_PROVISIONER_DAEMONS
(default 3)
--provisioner-force-cancel-interval duration Time to force cancel provisioning tasks
that are stuck.
Consumes
$CODER_PROVISIONER_FORCE_CANCEL_INTERVAL
(default 10m0s)
--proxy-trusted-headers strings Headers to trust for forwarding IP
addresses. e.g. Cf-Connecting-Ip,
True-Client-Ip, X-Forwarded-For
Consumes $CODER_PROXY_TRUSTED_HEADERS
--proxy-trusted-origins strings Origin addresses to respect
"proxy-trusted-headers". e.g.
192.168.1.0/24
Consumes $CODER_PROXY_TRUSTED_ORIGINS
--redirect-to-access-url Specifies whether to redirect requests
that do not match the access URL host.
Consumes $CODER_REDIRECT_TO_ACCESS_URL
--secure-auth-cookie Controls if the 'Secure' property is set
on browser session cookies.
Consumes $CODER_SECURE_AUTH_COOKIE
--session-duration duration The token expiry duration for browser
sessions. Sessions may last longer if
they are actively making requests, but
this functionality can be disabled via
--disable-session-expiry-refresh.
Consumes $CODER_MAX_SESSION_EXPIRY
(default 24h0m0s)
--ssh-keygen-algorithm string The algorithm to use for generating ssh
keys. Accepted values are "ed25519",
"ecdsa", or "rsa4096".
Consumes $CODER_SSH_KEYGEN_ALGORITHM
(default "ed25519")
--swagger-enable Expose the swagger endpoint via /swagger.
Consumes $CODER_SWAGGER_ENABLE
--telemetry Whether telemetry is enabled or not.
Coder collects anonymized usage data to
help improve our product.
Consumes $CODER_TELEMETRY_ENABLE
--telemetry-trace Whether Opentelemetry traces are sent to
Coder. Coder collects anonymized
application tracing to help improve our
product. Disabling telemetry also
disables this option.
Consumes $CODER_TELEMETRY_TRACE
--tls-address string HTTPS bind address of the server.
Consumes $CODER_TLS_ADDRESS (default
"127.0.0.1:3443")
--tls-cert-file strings Path to each certificate for TLS. It
requires a PEM-encoded file. To configure
the listener to use a CA certificate,
concatenate the primary certificate and
the CA certificate together. The primary
certificate should appear first in the
combined file.
Consumes $CODER_TLS_CERT_FILE
--tls-client-auth string Policy the server will follow for TLS
Client Authentication. Accepted values
are "none", "request", "require-any",
"verify-if-given", or
"require-and-verify".
Consumes $CODER_TLS_CLIENT_AUTH (default
"none")
--tls-client-ca-file string PEM-encoded Certificate Authority file
used for checking the authenticity of
client
Consumes $CODER_TLS_CLIENT_CA_FILE
--tls-client-cert-file string Path to certificate for client TLS
authentication. It requires a PEM-encoded
file.
Consumes $CODER_TLS_CLIENT_CERT_FILE
--tls-client-key-file string Path to key for client TLS
authentication. It requires a PEM-encoded
file.
Consumes $CODER_TLS_CLIENT_KEY_FILE
--tls-enable Whether TLS will be enabled.
Consumes $CODER_TLS_ENABLE
--tls-key-file strings Paths to the private keys for each of the
certificates. It requires a PEM-encoded
file.
Consumes $CODER_TLS_KEY_FILE
--tls-min-version string Minimum supported version of TLS.
Accepted values are "tls10", "tls11",
"tls12" or "tls13"
Consumes $CODER_TLS_MIN_VERSION (default
"tls12")
--trace Whether application tracing data is
collected. It exports to a backend
configured by environment variables. See:
https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md
Consumes $CODER_TRACE_ENABLE
--trace-honeycomb-api-key string Enables trace exporting to Honeycomb.io
using the provided API Key.
Consumes $CODER_TRACE_HONEYCOMB_API_KEY
--trace-logs Enables capturing of logs as events in
traces. This is useful for debugging, but
may result in a very large amount of
events being sent to the tracing backend
which may incur significant costs. If the
verbose flag was supplied, debug-level
logs will be included.
Consumes $CODER_TRACE_CAPTURE_LOGS
--update-check Periodically check for new releases of
Coder and inform the owner. The check is
performed once per day.
Consumes $CODER_UPDATE_CHECK
--wildcard-access-url string Specifies the wildcard hostname to use
for workspace applications in the form
"*.example.com".
Consumes $CODER_WILDCARD_ACCESS_URL
--access-url string External URL to access your
deployment. This must be accessible
by all provisioned workspaces.
Consumes $CODER_ACCESS_URL
--api-rate-limit int Maximum number of requests per
minute allowed to the API per user,
or per IP address for
unauthenticated users. Negative
values mean no rate limit. Some API
endpoints have separate strict rate
limits regardless of this value to
prevent denial-of-service or brute
force attacks.
Consumes $CODER_API_RATE_LIMIT
(default 512)
--cache-dir string The directory to cache temporary
files. If unspecified and
$CACHE_DIRECTORY is set, it will be
used for compatibility with systemd.
Consumes $CODER_CACHE_DIRECTORY
(default "~/.cache/coder")
--dangerous-allow-path-app-sharing Allow workspace apps that are not
served from subdomains to be shared.
Path-based app sharing is DISABLED
by default for security purposes.
Path-based apps can make requests to
the Coder API and pose a security
risk when the workspace serves
malicious JavaScript. Path-based
apps can be disabled entirely with
--disable-path-apps for further
security.
Consumes
$CODER_DANGEROUS_ALLOW_PATH_APP_SHARING
--dangerous-allow-path-app-site-owner-access Allow site-owners to access
workspace apps from workspaces they
do not own. Owners cannot access
path-based apps they do not own by
default. Path-based apps can make
requests to the Coder API and pose a
security risk when the workspace
serves malicious JavaScript.
Path-based apps can be disabled
entirely with --disable-path-apps
for further security.
Consumes
$CODER_DANGEROUS_ALLOW_PATH_APP_SITE_OWNER_ACCESS
--dangerous-disable-rate-limits Disables all rate limits. This is
not recommended in production.
Consumes $CODER_RATE_LIMIT_DISABLE_ALL
--derp-config-path string Path to read a DERP mapping from.
See:
https://tailscale.com/kb/1118/custom-derp-servers/
Consumes $CODER_DERP_CONFIG_PATH
--derp-config-url string URL to fetch a DERP mapping on
startup. See:
https://tailscale.com/kb/1118/custom-derp-servers/
Consumes $CODER_DERP_CONFIG_URL
--derp-server-enable Whether to enable or disable the
embedded DERP relay server.
Consumes $CODER_DERP_SERVER_ENABLE
(default true)
--derp-server-region-code string Region code to use for the embedded
DERP server.
Consumes
$CODER_DERP_SERVER_REGION_CODE
(default "coder")
--derp-server-region-id int Region ID to use for the embedded
DERP server.
Consumes
$CODER_DERP_SERVER_REGION_ID
(default 999)
--derp-server-region-name string Region name that for the embedded
DERP server.
Consumes
$CODER_DERP_SERVER_REGION_NAME
(default "Coder Embedded Relay")
--derp-server-stun-addresses strings Addresses for STUN servers to
establish P2P connections. Set empty
to disable P2P connections.
Consumes
$CODER_DERP_SERVER_STUN_ADDRESSES
(default [stun.l.google.com:19302])
--disable-password-auth coder server create-admin Disable password authentication.
This is recommended for security
purposes in production deployments
that rely on an identity provider.
Any user with the owner role will be
able to sign in with their password
regardless of this setting to avoid
potential lock out. If you are
locked out of your account, you can
use the coder server create-admin
command to create a new admin user
directly in the database.
Consumes $CODER_DISABLE_PASSWORD_AUTH
--disable-path-apps Disable workspace apps that are not
served from subdomains. Path-based
apps can make requests to the Coder
API and pose a security risk when
the workspace serves malicious
JavaScript. This is recommended for
security purposes if a
--wildcard-access-url is configured.
Consumes $CODER_DISABLE_PATH_APPS
--disable-session-expiry-refresh Disable automatic session expiry
bumping due to activity. This forces
all sessions to become invalid after
the session expiry duration has been
reached.
Consumes
$CODER_DISABLE_SESSION_EXPIRY_REFRESH
--experiments strings Enable one or more experiments.
These are not ready for production.
Separate multiple experiments with
commas, or enter '*' to opt-in to
all available experiments.
Consumes $CODER_EXPERIMENTS
-h, --help help for server
--http-address string HTTP bind address of the server.
Unset to disable the HTTP endpoint.
Consumes $CODER_HTTP_ADDRESS
(default "127.0.0.1:3000")
--log-human string Output human-readable logs to a
given file.
Consumes $CODER_LOGGING_HUMAN
(default "/dev/stderr")
--log-json string Output JSON logs to a given file.
Consumes $CODER_LOGGING_JSON
--log-stackdriver string Output Stackdriver compatible logs
to a given file.
Consumes $CODER_LOGGING_STACKDRIVER
--max-token-lifetime duration The maximum lifetime duration users
can specify when creating an API
token.
Consumes $CODER_MAX_TOKEN_LIFETIME
(default 720h0m0s)
--oauth2-github-allow-everyone Allow all logins, setting this
option means allowed orgs and teams
must be empty.
Consumes
$CODER_OAUTH2_GITHUB_ALLOW_EVERYONE
--oauth2-github-allow-signups Whether new users can sign up with
GitHub.
Consumes
$CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS
--oauth2-github-allowed-orgs strings Organizations the user must be a
member of to Login with GitHub.
Consumes
$CODER_OAUTH2_GITHUB_ALLOWED_ORGS
--oauth2-github-allowed-teams strings Teams inside organizations the user
must be a member of to Login with
GitHub. Structured as:
<organization-name>/<team-slug>.
Consumes
$CODER_OAUTH2_GITHUB_ALLOWED_TEAMS
--oauth2-github-client-id string Client ID for Login with GitHub.
Consumes $CODER_OAUTH2_GITHUB_CLIENT_ID
--oauth2-github-client-secret string Client secret for Login with GitHub.
Consumes
$CODER_OAUTH2_GITHUB_CLIENT_SECRET
--oauth2-github-enterprise-base-url string Base URL of a GitHub Enterprise
deployment to use for Login with
GitHub.
Consumes
$CODER_OAUTH2_GITHUB_ENTERPRISE_BASE_URL
--oidc-allow-signups Whether new users can sign up with
OIDC.
Consumes $CODER_OIDC_ALLOW_SIGNUPS
(default true)
--oidc-client-id string Client ID to use for Login with
OIDC.
Consumes $CODER_OIDC_CLIENT_ID
--oidc-client-secret string Client secret to use for Login with
OIDC.
Consumes $CODER_OIDC_CLIENT_SECRET
--oidc-email-domain strings Email domains that clients logging
in with OIDC must match.
Consumes $CODER_OIDC_EMAIL_DOMAIN
--oidc-icon-url string URL pointing to the icon to use on
the OepnID Connect login button
Consumes $CODER_OIDC_ICON_URL
--oidc-ignore-email-verified Ignore the email_verified claim from
the upstream provider.
Consumes
$CODER_OIDC_IGNORE_EMAIL_VERIFIED
--oidc-issuer-url string Issuer URL to use for Login with
OIDC.
Consumes $CODER_OIDC_ISSUER_URL
--oidc-scopes strings Scopes to grant when authenticating
with OIDC.
Consumes $CODER_OIDC_SCOPES (default
[openid,profile,email])
--oidc-sign-in-text string The text to show on the OpenID
Connect sign in button
Consumes $CODER_OIDC_SIGN_IN_TEXT
(default "OpenID Connect")
--oidc-username-field string OIDC claim field to use as the
username.
Consumes $CODER_OIDC_USERNAME_FIELD
(default "preferred_username")
--postgres-url string URL of a PostgreSQL database. If
empty, PostgreSQL binaries will be
downloaded from Maven
(https://repo1.maven.org/maven2) and
store all data in the config root.
Access the built-in database with
"coder server postgres-builtin-url".
Consumes $CODER_PG_CONNECTION_URL
--pprof-address string The bind address to serve pprof.
Consumes $CODER_PPROF_ADDRESS
(default "127.0.0.1:6060")
--pprof-enable Serve pprof metrics on the address
defined by pprof address.
Consumes $CODER_PPROF_ENABLE
--prometheus-address string The bind address to serve prometheus
metrics.
Consumes $CODER_PROMETHEUS_ADDRESS
(default "127.0.0.1:2112")
--prometheus-enable Serve prometheus metrics on the
address defined by prometheus
address.
Consumes $CODER_PROMETHEUS_ENABLE
--provisioner-daemon-poll-interval duration Time to wait before polling for a
new job.
Consumes
$CODER_PROVISIONER_DAEMON_POLL_INTERVAL (default 1s)
--provisioner-daemon-poll-jitter duration Random jitter added to the poll
interval.
Consumes
$CODER_PROVISIONER_DAEMON_POLL_JITTER (default 100ms)
--provisioner-daemons int Number of provisioner daemons to
create on start. If builds are stuck
in queued state for a long time,
consider increasing this.
Consumes $CODER_PROVISIONER_DAEMONS
(default 3)
--provisioner-force-cancel-interval duration Time to force cancel provisioning
tasks that are stuck.
Consumes
$CODER_PROVISIONER_FORCE_CANCEL_INTERVAL (default 10m0s)
--proxy-trusted-headers strings Headers to trust for forwarding IP
addresses. e.g. Cf-Connecting-Ip,
True-Client-Ip, X-Forwarded-For
Consumes $CODER_PROXY_TRUSTED_HEADERS
--proxy-trusted-origins strings Origin addresses to respect
"proxy-trusted-headers". e.g.
192.168.1.0/24
Consumes $CODER_PROXY_TRUSTED_ORIGINS
--redirect-to-access-url Specifies whether to redirect
requests that do not match the
access URL host.
Consumes $CODER_REDIRECT_TO_ACCESS_URL
--secure-auth-cookie Controls if the 'Secure' property is
set on browser session cookies.
Consumes $CODER_SECURE_AUTH_COOKIE
--session-duration duration The token expiry duration for
browser sessions. Sessions may last
longer if they are actively making
requests, but this functionality can
be disabled via
--disable-session-expiry-refresh.
Consumes $CODER_MAX_SESSION_EXPIRY
(default 24h0m0s)
--ssh-keygen-algorithm string The algorithm to use for generating
ssh keys. Accepted values are
"ed25519", "ecdsa", or "rsa4096".
Consumes $CODER_SSH_KEYGEN_ALGORITHM
(default "ed25519")
--swagger-enable Expose the swagger endpoint via
/swagger.
Consumes $CODER_SWAGGER_ENABLE
--telemetry Whether telemetry is enabled or not.
Coder collects anonymized usage data
to help improve our product.
Consumes $CODER_TELEMETRY_ENABLE
--telemetry-trace Whether Opentelemetry traces are
sent to Coder. Coder collects
anonymized application tracing to
help improve our product. Disabling
telemetry also disables this option.
Consumes $CODER_TELEMETRY_TRACE
--tls-address string HTTPS bind address of the server.
Consumes $CODER_TLS_ADDRESS (default
"127.0.0.1:3443")
--tls-cert-file strings Path to each certificate for TLS. It
requires a PEM-encoded file. To
configure the listener to use a CA
certificate, concatenate the primary
certificate and the CA certificate
together. The primary certificate
should appear first in the combined
file.
Consumes $CODER_TLS_CERT_FILE
--tls-client-auth string Policy the server will follow for
TLS Client Authentication. Accepted
values are "none", "request",
"require-any", "verify-if-given", or
"require-and-verify".
Consumes $CODER_TLS_CLIENT_AUTH
(default "none")
--tls-client-ca-file string PEM-encoded Certificate Authority
file used for checking the
authenticity of client
Consumes $CODER_TLS_CLIENT_CA_FILE
--tls-client-cert-file string Path to certificate for client TLS
authentication. It requires a
PEM-encoded file.
Consumes $CODER_TLS_CLIENT_CERT_FILE
--tls-client-key-file string Path to key for client TLS
authentication. It requires a
PEM-encoded file.
Consumes $CODER_TLS_CLIENT_KEY_FILE
--tls-enable Whether TLS will be enabled.
Consumes $CODER_TLS_ENABLE
--tls-key-file strings Paths to the private keys for each
of the certificates. It requires a
PEM-encoded file.
Consumes $CODER_TLS_KEY_FILE
--tls-min-version string Minimum supported version of TLS.
Accepted values are "tls10",
"tls11", "tls12" or "tls13"
Consumes $CODER_TLS_MIN_VERSION
(default "tls12")
--trace Whether application tracing data is
collected. It exports to a backend
configured by environment variables.
See:
https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md
Consumes $CODER_TRACE_ENABLE
--trace-honeycomb-api-key string Enables trace exporting to
Honeycomb.io using the provided API
Key.
Consumes $CODER_TRACE_HONEYCOMB_API_KEY
--trace-logs Enables capturing of logs as events
in traces. This is useful for
debugging, but may result in a very
large amount of events being sent to
the tracing backend which may incur
significant costs. If the verbose
flag was supplied, debug-level logs
will be included.
Consumes $CODER_TRACE_CAPTURE_LOGS
--update-check Periodically check for new releases
of Coder and inform the owner. The
check is performed once per day.
Consumes $CODER_UPDATE_CHECK
--wildcard-access-url string Specifies the wildcard hostname to
use for workspace applications in
the form "*.example.com".
Consumes $CODER_WILDCARD_ACCESS_URL
Global Flags:
--global-config coder Path to the global coder config directory.

View File

@ -0,0 +1,36 @@
Create a new admin user with the given username, email and password and adds it to every organization.
Usage:
coder server create-admin-user [flags]
Flags:
--email string The email of the new user. If not specified, you will be
prompted via stdin. Consumes $CODER_EMAIL.
-h, --help help for create-admin-user
--password string The password of the new user. If not specified, you will
be prompted via stdin. Consumes $CODER_PASSWORD.
--postgres-url string URL of a PostgreSQL database. If empty, the built-in
PostgreSQL deployment will be used (Coder must not be
already running in this case). Consumes $CODER_POSTGRES_URL.
--ssh-keygen-algorithm string The algorithm to use for generating ssh keys. Accepted
values are "ed25519", "ecdsa", or "rsa4096". Consumes
$CODER_SSH_KEYGEN_ALGORITHM. (default "ed25519")
--username string The username of the new user. If not specified, you will
be prompted via stdin. Consumes $CODER_USERNAME.
Global Flags:
--global-config coder Path to the global coder config directory.
Consumes $CODER_CONFIG_DIR (default "~/.config/coderv2")
--header stringArray HTTP headers added to all requests. Provide as "Key=Value".
Consumes $CODER_HEADER
--no-feature-warning Suppress warnings about unlicensed features.
Consumes $CODER_NO_FEATURE_WARNING
--no-version-warning Suppress warning when client and server versions do not match.
Consumes $CODER_NO_VERSION_WARNING
--token string Specify an authentication token. For security reasons setting
CODER_SESSION_TOKEN is preferred.
Consumes $CODER_SESSION_TOKEN
--url string URL to a deployment.
Consumes $CODER_URL
-v, --verbose Enable verbose output.
Consumes $CODER_VERBOSE

3
coderd/apidoc/docs.go generated
View File

@ -6012,6 +6012,9 @@ const docTemplate = `{
"derp": {
"$ref": "#/definitions/codersdk.DERP"
},
"disable_password_auth": {
"$ref": "#/definitions/codersdk.DeploymentConfigField-bool"
},
"disable_path_apps": {
"$ref": "#/definitions/codersdk.DeploymentConfigField-bool"
},

View File

@ -5343,6 +5343,9 @@
"derp": {
"$ref": "#/definitions/codersdk.DERP"
},
"disable_password_auth": {
"$ref": "#/definitions/codersdk.DeploymentConfigField-bool"
},
"disable_path_apps": {
"$ref": "#/definitions/codersdk.DeploymentConfigField-bool"
},

View File

@ -18,15 +18,15 @@ import (
"github.com/coder/coder/codersdk"
)
var validate *validator.Validate
var Validate *validator.Validate
// This init is used to create a validator and register validation-specific
// functionality for the HTTP API.
//
// A single validator instance is used, because it caches struct parsing.
func init() {
validate = validator.New()
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
Validate = validator.New()
Validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-" {
return ""
@ -44,7 +44,7 @@ func init() {
return valid == nil
}
for _, tag := range []string{"username", "template_name", "workspace_name"} {
err := validate.RegisterValidation(tag, nameValidator)
err := Validate.RegisterValidation(tag, nameValidator)
if err != nil {
panic(err)
}
@ -59,7 +59,7 @@ func init() {
valid := TemplateDisplayNameValid(str)
return valid == nil
}
err := validate.RegisterValidation("template_display_name", templateDisplayNameValidator)
err := Validate.RegisterValidation("template_display_name", templateDisplayNameValidator)
if err != nil {
panic(err)
}
@ -144,7 +144,7 @@ func Read(ctx context.Context, rw http.ResponseWriter, r *http.Request, value in
})
return false
}
err = validate.Struct(value)
err = Validate.Struct(value)
var validationErrors validator.ValidationErrors
if errors.As(err, &validationErrors) {
apiErrors := make([]codersdk.ValidationError, 0, len(validationErrors))

View File

@ -62,8 +62,10 @@ func (api *API) userAuthMethods(rw http.ResponseWriter, r *http.Request) {
}
httpapi.Write(r.Context(), rw, http.StatusOK, codersdk.AuthMethods{
Password: codersdk.AuthMethod{Enabled: true},
Github: codersdk.AuthMethod{Enabled: api.GithubOAuth2Config != nil},
Password: codersdk.AuthMethod{
Enabled: !api.DeploymentConfig.DisablePasswordAuth.Value,
},
Github: codersdk.AuthMethod{Enabled: api.GithubOAuth2Config != nil},
OIDC: codersdk.OIDCAuthMethod{
AuthMethod: codersdk.AuthMethod{Enabled: api.OIDCConfig != nil},
SignInText: signInText,

View File

@ -1028,6 +1028,24 @@ func (api *API) postLogin(rw http.ResponseWriter, r *http.Request) {
return
}
// If password authentication is disabled and the user does not have the
// owner role, block the request.
if api.DeploymentConfig.DisablePasswordAuth.Value {
permitted := false
for _, role := range user.RBACRoles {
if role == rbac.RoleOwner() {
permitted = true
break
}
}
if !permitted {
httpapi.Write(ctx, rw, http.StatusForbidden, codersdk.Response{
Message: "Password authentication is disabled. Only administrators can sign in with password authentication.",
})
return
}
}
if user.LoginType != database.LoginTypePassword {
httpapi.Write(ctx, rw, http.StatusForbidden, codersdk.Response{
Message: fmt.Sprintf("Incorrect login type, attempting to use %q but user is of login type %q", database.LoginTypePassword, user.LoginType),

View File

@ -86,35 +86,6 @@ func TestFirstUser(t *testing.T) {
require.NoError(t, err)
<-called
})
t.Run("LastSeenAt", func(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
client := coderdtest.New(t, nil)
firstUserResp := coderdtest.CreateFirstUser(t, client)
firstUser, err := client.User(ctx, firstUserResp.UserID.String())
require.NoError(t, err)
_ = coderdtest.CreateAnotherUser(t, client, firstUserResp.OrganizationID)
allUsersRes, err := client.Users(ctx, codersdk.UsersRequest{})
require.NoError(t, err)
require.Len(t, allUsersRes.Users, 2)
// We sent the "GET Users" request with the first user, but the second user
// should be Never since they haven't performed a request.
for _, user := range allUsersRes.Users {
if user.ID == firstUser.ID {
require.WithinDuration(t, firstUser.LastSeenAt, database.Now(), testutil.WaitShort)
} else {
require.Zero(t, user.LastSeenAt)
}
}
})
}
func TestPostLogin(t *testing.T) {
@ -191,6 +162,56 @@ func TestPostLogin(t *testing.T) {
require.Contains(t, apiErr.Message, "suspended")
})
t.Run("DisabledPasswordAuth", func(t *testing.T) {
t.Parallel()
dc := coderdtest.DeploymentConfig(t)
dc.DisablePasswordAuth.Value = true
client := coderdtest.New(t, &coderdtest.Options{
DeploymentConfig: dc,
})
first := coderdtest.CreateFirstUser(t, client)
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
// With a user account.
const password = "testpass"
user, err := client.CreateUser(ctx, codersdk.CreateUserRequest{
Email: "test+user-@coder.com",
Username: "user",
Password: password,
OrganizationID: first.OrganizationID,
})
require.NoError(t, err)
userClient := codersdk.New(client.URL)
_, err = userClient.LoginWithPassword(ctx, codersdk.LoginWithPasswordRequest{
Email: user.Email,
Password: password,
})
require.Error(t, err)
var apiErr *codersdk.Error
require.ErrorAs(t, err, &apiErr)
require.Equal(t, http.StatusForbidden, apiErr.StatusCode())
require.Contains(t, apiErr.Message, "Password authentication is disabled")
// Promote the user account to an owner.
_, err = client.UpdateUserRoles(ctx, user.ID.String(), codersdk.UpdateRoles{
Roles: []string{rbac.RoleOwner(), rbac.RoleMember()},
})
require.NoError(t, err)
// Login with the user account.
res, err := userClient.LoginWithPassword(ctx, codersdk.LoginWithPasswordRequest{
Email: user.Email,
Password: password,
})
require.NoError(t, err)
require.NotEmpty(t, res.SessionToken)
})
t.Run("Success", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
@ -437,6 +458,35 @@ func TestPostUsers(t *testing.T) {
require.Len(t, auditor.AuditLogs, 1)
assert.Equal(t, database.AuditActionCreate, auditor.AuditLogs[0].Action)
})
t.Run("LastSeenAt", func(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
client := coderdtest.New(t, nil)
firstUserResp := coderdtest.CreateFirstUser(t, client)
firstUser, err := client.User(ctx, firstUserResp.UserID.String())
require.NoError(t, err)
_ = coderdtest.CreateAnotherUser(t, client, firstUserResp.OrganizationID)
allUsersRes, err := client.Users(ctx, codersdk.UsersRequest{})
require.NoError(t, err)
require.Len(t, allUsersRes.Users, 2)
// We sent the "GET Users" request with the first user, but the second user
// should be Never since they haven't performed a request.
for _, user := range allUsersRes.Users {
if user.ID == firstUser.ID {
require.WithinDuration(t, firstUser.LastSeenAt, database.Now(), testutil.WaitShort)
} else {
require.Zero(t, user.LastSeenAt)
}
}
})
}
func TestUpdateUserProfile(t *testing.T) {

View File

@ -144,6 +144,7 @@ type DeploymentConfig struct {
DisablePathApps *DeploymentConfigField[bool] `json:"disable_path_apps" typescript:",notnull"`
SessionDuration *DeploymentConfigField[time.Duration] `json:"max_session_expiry" typescript:",notnull"`
DisableSessionExpiryRefresh *DeploymentConfigField[bool] `json:"disable_session_expiry_refresh" typescript:",notnull"`
DisablePasswordAuth *DeploymentConfigField[bool] `json:"disable_password_auth" typescript:",notnull"`
// DEPRECATED: Use HTTPAddress or TLS.Address instead.
Address *DeploymentConfigField[string] `json:"address" typescript:",notnull"`

View File

@ -289,6 +289,17 @@ curl -X GET http://coder-server:8080/api/v2/config/deployment \
}
}
},
"disable_password_auth": {
"default": true,
"enterprise": true,
"flag": "string",
"hidden": true,
"name": "string",
"secret": true,
"shorthand": "string",
"usage": "string",
"value": true
},
"disable_path_apps": {
"default": true,
"enterprise": true,

View File

@ -1647,6 +1647,17 @@ CreateParameterRequest is a structure used to create a new parameter value for a
}
}
},
"disable_password_auth": {
"default": true,
"enterprise": true,
"flag": "string",
"hidden": true,
"name": "string",
"secret": true,
"shorthand": "string",
"usage": "string",
"value": true
},
"disable_path_apps": {
"default": true,
"enterprise": true,
@ -2438,6 +2449,7 @@ CreateParameterRequest is a structure used to create a new parameter value for a
| `cache_directory` | [codersdk.DeploymentConfigField-string](#codersdkdeploymentconfigfield-string) | false | | |
| `dangerous` | [codersdk.DangerousConfig](#codersdkdangerousconfig) | false | | |
| `derp` | [codersdk.DERP](#codersdkderp) | false | | |
| `disable_password_auth` | [codersdk.DeploymentConfigField-bool](#codersdkdeploymentconfigfield-bool) | false | | |
| `disable_path_apps` | [codersdk.DeploymentConfigField-bool](#codersdkdeploymentconfigfield-bool) | false | | |
| `disable_session_expiry_refresh` | [codersdk.DeploymentConfigField-bool](#codersdkdeploymentconfigfield-bool) | false | | |
| `experimental` | [codersdk.DeploymentConfigField-bool](#codersdkdeploymentconfigfield-bool) | false | | Experimental Use Experiments instead. |

View File

@ -9,147 +9,149 @@ coder server [flags]
### Options
```
--access-url string External URL to access your deployment. This must be accessible by all provisioned workspaces.
Consumes $CODER_ACCESS_URL
--api-rate-limit int Maximum number of requests per minute allowed to the API per user, or per IP address for unauthenticated users. Negative values mean no rate limit. Some API endpoints have separate strict rate limits regardless of this value to prevent denial-of-service or brute force attacks.
Consumes $CODER_API_RATE_LIMIT (default 512)
--cache-dir string The directory to cache temporary files. If unspecified and $CACHE_DIRECTORY is set, it will be used for compatibility with systemd.
Consumes $CODER_CACHE_DIRECTORY (default "~/.cache/coder")
--dangerous-allow-path-app-sharing Allow workspace apps that are not served from subdomains to be shared. Path-based app sharing is DISABLED by default for security purposes. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. Path-based apps can be disabled entirely with --disable-path-apps for further security.
Consumes $CODER_DANGEROUS_ALLOW_PATH_APP_SHARING
--dangerous-allow-path-app-site-owner-access Allow site-owners to access workspace apps from workspaces they do not own. Owners cannot access path-based apps they do not own by default. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. Path-based apps can be disabled entirely with --disable-path-apps for further security.
Consumes $CODER_DANGEROUS_ALLOW_PATH_APP_SITE_OWNER_ACCESS
--dangerous-disable-rate-limits Disables all rate limits. This is not recommended in production.
Consumes $CODER_RATE_LIMIT_DISABLE_ALL
--derp-config-path string Path to read a DERP mapping from. See: https://tailscale.com/kb/1118/custom-derp-servers/
Consumes $CODER_DERP_CONFIG_PATH
--derp-config-url string URL to fetch a DERP mapping on startup. See: https://tailscale.com/kb/1118/custom-derp-servers/
Consumes $CODER_DERP_CONFIG_URL
--derp-server-enable Whether to enable or disable the embedded DERP relay server.
Consumes $CODER_DERP_SERVER_ENABLE (default true)
--derp-server-region-code string Region code to use for the embedded DERP server.
Consumes $CODER_DERP_SERVER_REGION_CODE (default "coder")
--derp-server-region-id int Region ID to use for the embedded DERP server.
Consumes $CODER_DERP_SERVER_REGION_ID (default 999)
--derp-server-region-name string Region name that for the embedded DERP server.
Consumes $CODER_DERP_SERVER_REGION_NAME (default "Coder Embedded Relay")
--derp-server-stun-addresses strings Addresses for STUN servers to establish P2P connections. Set empty to disable P2P connections.
Consumes $CODER_DERP_SERVER_STUN_ADDRESSES (default [stun.l.google.com:19302])
--disable-path-apps Disable workspace apps that are not served from subdomains. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. This is recommended for security purposes if a --wildcard-access-url is configured.
Consumes $CODER_DISABLE_PATH_APPS
--disable-session-expiry-refresh Disable automatic session expiry bumping due to activity. This forces all sessions to become invalid after the session expiry duration has been reached.
Consumes $CODER_DISABLE_SESSION_EXPIRY_REFRESH
--experiments strings Enable one or more experiments. These are not ready for production. Separate multiple experiments with commas, or enter '*' to opt-in to all available experiments.
Consumes $CODER_EXPERIMENTS
-h, --help help for server
--http-address string HTTP bind address of the server. Unset to disable the HTTP endpoint.
Consumes $CODER_HTTP_ADDRESS (default "127.0.0.1:3000")
--log-human string Output human-readable logs to a given file.
Consumes $CODER_LOGGING_HUMAN (default "/dev/stderr")
--log-json string Output JSON logs to a given file.
Consumes $CODER_LOGGING_JSON
--log-stackdriver string Output Stackdriver compatible logs to a given file.
Consumes $CODER_LOGGING_STACKDRIVER
--max-token-lifetime duration The maximum lifetime duration users can specify when creating an API token.
Consumes $CODER_MAX_TOKEN_LIFETIME (default 720h0m0s)
--oauth2-github-allow-everyone Allow all logins, setting this option means allowed orgs and teams must be empty.
Consumes $CODER_OAUTH2_GITHUB_ALLOW_EVERYONE
--oauth2-github-allow-signups Whether new users can sign up with GitHub.
Consumes $CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS
--oauth2-github-allowed-orgs strings Organizations the user must be a member of to Login with GitHub.
Consumes $CODER_OAUTH2_GITHUB_ALLOWED_ORGS
--oauth2-github-allowed-teams strings Teams inside organizations the user must be a member of to Login with GitHub. Structured as: <organization-name>/<team-slug>.
Consumes $CODER_OAUTH2_GITHUB_ALLOWED_TEAMS
--oauth2-github-client-id string Client ID for Login with GitHub.
Consumes $CODER_OAUTH2_GITHUB_CLIENT_ID
--oauth2-github-client-secret string Client secret for Login with GitHub.
Consumes $CODER_OAUTH2_GITHUB_CLIENT_SECRET
--oauth2-github-enterprise-base-url string Base URL of a GitHub Enterprise deployment to use for Login with GitHub.
Consumes $CODER_OAUTH2_GITHUB_ENTERPRISE_BASE_URL
--oidc-allow-signups Whether new users can sign up with OIDC.
Consumes $CODER_OIDC_ALLOW_SIGNUPS (default true)
--oidc-client-id string Client ID to use for Login with OIDC.
Consumes $CODER_OIDC_CLIENT_ID
--oidc-client-secret string Client secret to use for Login with OIDC.
Consumes $CODER_OIDC_CLIENT_SECRET
--oidc-email-domain strings Email domains that clients logging in with OIDC must match.
Consumes $CODER_OIDC_EMAIL_DOMAIN
--oidc-icon-url string URL pointing to the icon to use on the OepnID Connect login button
Consumes $CODER_OIDC_ICON_URL
--oidc-ignore-email-verified Ignore the email_verified claim from the upstream provider.
Consumes $CODER_OIDC_IGNORE_EMAIL_VERIFIED
--oidc-issuer-url string Issuer URL to use for Login with OIDC.
Consumes $CODER_OIDC_ISSUER_URL
--oidc-scopes strings Scopes to grant when authenticating with OIDC.
Consumes $CODER_OIDC_SCOPES (default [openid,profile,email])
--oidc-sign-in-text string The text to show on the OpenID Connect sign in button
Consumes $CODER_OIDC_SIGN_IN_TEXT (default "OpenID Connect")
--oidc-username-field string OIDC claim field to use as the username.
Consumes $CODER_OIDC_USERNAME_FIELD (default "preferred_username")
--postgres-url string URL of a PostgreSQL database. If empty, PostgreSQL binaries will be downloaded from Maven (https://repo1.maven.org/maven2) and store all data in the config root. Access the built-in database with "coder server postgres-builtin-url".
Consumes $CODER_PG_CONNECTION_URL
--pprof-address string The bind address to serve pprof.
Consumes $CODER_PPROF_ADDRESS (default "127.0.0.1:6060")
--pprof-enable Serve pprof metrics on the address defined by pprof address.
Consumes $CODER_PPROF_ENABLE
--prometheus-address string The bind address to serve prometheus metrics.
Consumes $CODER_PROMETHEUS_ADDRESS (default "127.0.0.1:2112")
--prometheus-enable Serve prometheus metrics on the address defined by prometheus address.
Consumes $CODER_PROMETHEUS_ENABLE
--provisioner-daemon-poll-interval duration Time to wait before polling for a new job.
Consumes $CODER_PROVISIONER_DAEMON_POLL_INTERVAL (default 1s)
--provisioner-daemon-poll-jitter duration Random jitter added to the poll interval.
Consumes $CODER_PROVISIONER_DAEMON_POLL_JITTER (default 100ms)
--provisioner-daemons int Number of provisioner daemons to create on start. If builds are stuck in queued state for a long time, consider increasing this.
Consumes $CODER_PROVISIONER_DAEMONS (default 3)
--provisioner-force-cancel-interval duration Time to force cancel provisioning tasks that are stuck.
Consumes $CODER_PROVISIONER_FORCE_CANCEL_INTERVAL (default 10m0s)
--proxy-trusted-headers strings Headers to trust for forwarding IP addresses. e.g. Cf-Connecting-Ip, True-Client-Ip, X-Forwarded-For
Consumes $CODER_PROXY_TRUSTED_HEADERS
--proxy-trusted-origins strings Origin addresses to respect "proxy-trusted-headers". e.g. 192.168.1.0/24
Consumes $CODER_PROXY_TRUSTED_ORIGINS
--redirect-to-access-url Specifies whether to redirect requests that do not match the access URL host.
Consumes $CODER_REDIRECT_TO_ACCESS_URL
--secure-auth-cookie Controls if the 'Secure' property is set on browser session cookies.
Consumes $CODER_SECURE_AUTH_COOKIE
--session-duration duration The token expiry duration for browser sessions. Sessions may last longer if they are actively making requests, but this functionality can be disabled via --disable-session-expiry-refresh.
Consumes $CODER_MAX_SESSION_EXPIRY (default 24h0m0s)
--ssh-keygen-algorithm string The algorithm to use for generating ssh keys. Accepted values are "ed25519", "ecdsa", or "rsa4096".
Consumes $CODER_SSH_KEYGEN_ALGORITHM (default "ed25519")
--swagger-enable Expose the swagger endpoint via /swagger.
Consumes $CODER_SWAGGER_ENABLE
--telemetry Whether telemetry is enabled or not. Coder collects anonymized usage data to help improve our product.
Consumes $CODER_TELEMETRY_ENABLE (default true)
--telemetry-trace Whether Opentelemetry traces are sent to Coder. Coder collects anonymized application tracing to help improve our product. Disabling telemetry also disables this option.
Consumes $CODER_TELEMETRY_TRACE (default true)
--tls-address string HTTPS bind address of the server.
Consumes $CODER_TLS_ADDRESS (default "127.0.0.1:3443")
--tls-cert-file strings Path to each certificate for TLS. It requires a PEM-encoded file. To configure the listener to use a CA certificate, concatenate the primary certificate and the CA certificate together. The primary certificate should appear first in the combined file.
Consumes $CODER_TLS_CERT_FILE
--tls-client-auth string Policy the server will follow for TLS Client Authentication. Accepted values are "none", "request", "require-any", "verify-if-given", or "require-and-verify".
Consumes $CODER_TLS_CLIENT_AUTH (default "none")
--tls-client-ca-file string PEM-encoded Certificate Authority file used for checking the authenticity of client
Consumes $CODER_TLS_CLIENT_CA_FILE
--tls-client-cert-file string Path to certificate for client TLS authentication. It requires a PEM-encoded file.
Consumes $CODER_TLS_CLIENT_CERT_FILE
--tls-client-key-file string Path to key for client TLS authentication. It requires a PEM-encoded file.
Consumes $CODER_TLS_CLIENT_KEY_FILE
--tls-enable Whether TLS will be enabled.
Consumes $CODER_TLS_ENABLE
--tls-key-file strings Paths to the private keys for each of the certificates. It requires a PEM-encoded file.
Consumes $CODER_TLS_KEY_FILE
--tls-min-version string Minimum supported version of TLS. Accepted values are "tls10", "tls11", "tls12" or "tls13"
Consumes $CODER_TLS_MIN_VERSION (default "tls12")
--trace Whether application tracing data is collected. It exports to a backend configured by environment variables. See: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md
Consumes $CODER_TRACE_ENABLE
--trace-honeycomb-api-key string Enables trace exporting to Honeycomb.io using the provided API Key.
Consumes $CODER_TRACE_HONEYCOMB_API_KEY
--trace-logs Enables capturing of logs as events in traces. This is useful for debugging, but may result in a very large amount of events being sent to the tracing backend which may incur significant costs. If the verbose flag was supplied, debug-level logs will be included.
Consumes $CODER_TRACE_CAPTURE_LOGS
--update-check Periodically check for new releases of Coder and inform the owner. The check is performed once per day.
Consumes $CODER_UPDATE_CHECK
--wildcard-access-url string Specifies the wildcard hostname to use for workspace applications in the form "*.example.com".
Consumes $CODER_WILDCARD_ACCESS_URL
--access-url string External URL to access your deployment. This must be accessible by all provisioned workspaces.
Consumes $CODER_ACCESS_URL
--api-rate-limit int Maximum number of requests per minute allowed to the API per user, or per IP address for unauthenticated users. Negative values mean no rate limit. Some API endpoints have separate strict rate limits regardless of this value to prevent denial-of-service or brute force attacks.
Consumes $CODER_API_RATE_LIMIT (default 512)
--cache-dir string The directory to cache temporary files. If unspecified and $CACHE_DIRECTORY is set, it will be used for compatibility with systemd.
Consumes $CODER_CACHE_DIRECTORY (default "~/.cache/coder")
--dangerous-allow-path-app-sharing Allow workspace apps that are not served from subdomains to be shared. Path-based app sharing is DISABLED by default for security purposes. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. Path-based apps can be disabled entirely with --disable-path-apps for further security.
Consumes $CODER_DANGEROUS_ALLOW_PATH_APP_SHARING
--dangerous-allow-path-app-site-owner-access Allow site-owners to access workspace apps from workspaces they do not own. Owners cannot access path-based apps they do not own by default. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. Path-based apps can be disabled entirely with --disable-path-apps for further security.
Consumes $CODER_DANGEROUS_ALLOW_PATH_APP_SITE_OWNER_ACCESS
--dangerous-disable-rate-limits Disables all rate limits. This is not recommended in production.
Consumes $CODER_RATE_LIMIT_DISABLE_ALL
--derp-config-path string Path to read a DERP mapping from. See: https://tailscale.com/kb/1118/custom-derp-servers/
Consumes $CODER_DERP_CONFIG_PATH
--derp-config-url string URL to fetch a DERP mapping on startup. See: https://tailscale.com/kb/1118/custom-derp-servers/
Consumes $CODER_DERP_CONFIG_URL
--derp-server-enable Whether to enable or disable the embedded DERP relay server.
Consumes $CODER_DERP_SERVER_ENABLE (default true)
--derp-server-region-code string Region code to use for the embedded DERP server.
Consumes $CODER_DERP_SERVER_REGION_CODE (default "coder")
--derp-server-region-id int Region ID to use for the embedded DERP server.
Consumes $CODER_DERP_SERVER_REGION_ID (default 999)
--derp-server-region-name string Region name that for the embedded DERP server.
Consumes $CODER_DERP_SERVER_REGION_NAME (default "Coder Embedded Relay")
--derp-server-stun-addresses strings Addresses for STUN servers to establish P2P connections. Set empty to disable P2P connections.
Consumes $CODER_DERP_SERVER_STUN_ADDRESSES (default [stun.l.google.com:19302])
--disable-password-auth coder server create-admin Disable password authentication. This is recommended for security purposes in production deployments that rely on an identity provider. Any user with the owner role will be able to sign in with their password regardless of this setting to avoid potential lock out. If you are locked out of your account, you can use the coder server create-admin command to create a new admin user directly in the database.
Consumes $CODER_DISABLE_PASSWORD_AUTH
--disable-path-apps Disable workspace apps that are not served from subdomains. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. This is recommended for security purposes if a --wildcard-access-url is configured.
Consumes $CODER_DISABLE_PATH_APPS
--disable-session-expiry-refresh Disable automatic session expiry bumping due to activity. This forces all sessions to become invalid after the session expiry duration has been reached.
Consumes $CODER_DISABLE_SESSION_EXPIRY_REFRESH
--experiments strings Enable one or more experiments. These are not ready for production. Separate multiple experiments with commas, or enter '*' to opt-in to all available experiments.
Consumes $CODER_EXPERIMENTS
-h, --help help for server
--http-address string HTTP bind address of the server. Unset to disable the HTTP endpoint.
Consumes $CODER_HTTP_ADDRESS (default "127.0.0.1:3000")
--log-human string Output human-readable logs to a given file.
Consumes $CODER_LOGGING_HUMAN (default "/dev/stderr")
--log-json string Output JSON logs to a given file.
Consumes $CODER_LOGGING_JSON
--log-stackdriver string Output Stackdriver compatible logs to a given file.
Consumes $CODER_LOGGING_STACKDRIVER
--max-token-lifetime duration The maximum lifetime duration users can specify when creating an API token.
Consumes $CODER_MAX_TOKEN_LIFETIME (default 720h0m0s)
--oauth2-github-allow-everyone Allow all logins, setting this option means allowed orgs and teams must be empty.
Consumes $CODER_OAUTH2_GITHUB_ALLOW_EVERYONE
--oauth2-github-allow-signups Whether new users can sign up with GitHub.
Consumes $CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS
--oauth2-github-allowed-orgs strings Organizations the user must be a member of to Login with GitHub.
Consumes $CODER_OAUTH2_GITHUB_ALLOWED_ORGS
--oauth2-github-allowed-teams strings Teams inside organizations the user must be a member of to Login with GitHub. Structured as: <organization-name>/<team-slug>.
Consumes $CODER_OAUTH2_GITHUB_ALLOWED_TEAMS
--oauth2-github-client-id string Client ID for Login with GitHub.
Consumes $CODER_OAUTH2_GITHUB_CLIENT_ID
--oauth2-github-client-secret string Client secret for Login with GitHub.
Consumes $CODER_OAUTH2_GITHUB_CLIENT_SECRET
--oauth2-github-enterprise-base-url string Base URL of a GitHub Enterprise deployment to use for Login with GitHub.
Consumes $CODER_OAUTH2_GITHUB_ENTERPRISE_BASE_URL
--oidc-allow-signups Whether new users can sign up with OIDC.
Consumes $CODER_OIDC_ALLOW_SIGNUPS (default true)
--oidc-client-id string Client ID to use for Login with OIDC.
Consumes $CODER_OIDC_CLIENT_ID
--oidc-client-secret string Client secret to use for Login with OIDC.
Consumes $CODER_OIDC_CLIENT_SECRET
--oidc-email-domain strings Email domains that clients logging in with OIDC must match.
Consumes $CODER_OIDC_EMAIL_DOMAIN
--oidc-icon-url string URL pointing to the icon to use on the OepnID Connect login button
Consumes $CODER_OIDC_ICON_URL
--oidc-ignore-email-verified Ignore the email_verified claim from the upstream provider.
Consumes $CODER_OIDC_IGNORE_EMAIL_VERIFIED
--oidc-issuer-url string Issuer URL to use for Login with OIDC.
Consumes $CODER_OIDC_ISSUER_URL
--oidc-scopes strings Scopes to grant when authenticating with OIDC.
Consumes $CODER_OIDC_SCOPES (default [openid,profile,email])
--oidc-sign-in-text string The text to show on the OpenID Connect sign in button
Consumes $CODER_OIDC_SIGN_IN_TEXT (default "OpenID Connect")
--oidc-username-field string OIDC claim field to use as the username.
Consumes $CODER_OIDC_USERNAME_FIELD (default "preferred_username")
--postgres-url string URL of a PostgreSQL database. If empty, PostgreSQL binaries will be downloaded from Maven (https://repo1.maven.org/maven2) and store all data in the config root. Access the built-in database with "coder server postgres-builtin-url".
Consumes $CODER_PG_CONNECTION_URL
--pprof-address string The bind address to serve pprof.
Consumes $CODER_PPROF_ADDRESS (default "127.0.0.1:6060")
--pprof-enable Serve pprof metrics on the address defined by pprof address.
Consumes $CODER_PPROF_ENABLE
--prometheus-address string The bind address to serve prometheus metrics.
Consumes $CODER_PROMETHEUS_ADDRESS (default "127.0.0.1:2112")
--prometheus-enable Serve prometheus metrics on the address defined by prometheus address.
Consumes $CODER_PROMETHEUS_ENABLE
--provisioner-daemon-poll-interval duration Time to wait before polling for a new job.
Consumes $CODER_PROVISIONER_DAEMON_POLL_INTERVAL (default 1s)
--provisioner-daemon-poll-jitter duration Random jitter added to the poll interval.
Consumes $CODER_PROVISIONER_DAEMON_POLL_JITTER (default 100ms)
--provisioner-daemons int Number of provisioner daemons to create on start. If builds are stuck in queued state for a long time, consider increasing this.
Consumes $CODER_PROVISIONER_DAEMONS (default 3)
--provisioner-force-cancel-interval duration Time to force cancel provisioning tasks that are stuck.
Consumes $CODER_PROVISIONER_FORCE_CANCEL_INTERVAL (default 10m0s)
--proxy-trusted-headers strings Headers to trust for forwarding IP addresses. e.g. Cf-Connecting-Ip, True-Client-Ip, X-Forwarded-For
Consumes $CODER_PROXY_TRUSTED_HEADERS
--proxy-trusted-origins strings Origin addresses to respect "proxy-trusted-headers". e.g. 192.168.1.0/24
Consumes $CODER_PROXY_TRUSTED_ORIGINS
--redirect-to-access-url Specifies whether to redirect requests that do not match the access URL host.
Consumes $CODER_REDIRECT_TO_ACCESS_URL
--secure-auth-cookie Controls if the 'Secure' property is set on browser session cookies.
Consumes $CODER_SECURE_AUTH_COOKIE
--session-duration duration The token expiry duration for browser sessions. Sessions may last longer if they are actively making requests, but this functionality can be disabled via --disable-session-expiry-refresh.
Consumes $CODER_MAX_SESSION_EXPIRY (default 24h0m0s)
--ssh-keygen-algorithm string The algorithm to use for generating ssh keys. Accepted values are "ed25519", "ecdsa", or "rsa4096".
Consumes $CODER_SSH_KEYGEN_ALGORITHM (default "ed25519")
--swagger-enable Expose the swagger endpoint via /swagger.
Consumes $CODER_SWAGGER_ENABLE
--telemetry Whether telemetry is enabled or not. Coder collects anonymized usage data to help improve our product.
Consumes $CODER_TELEMETRY_ENABLE (default true)
--telemetry-trace Whether Opentelemetry traces are sent to Coder. Coder collects anonymized application tracing to help improve our product. Disabling telemetry also disables this option.
Consumes $CODER_TELEMETRY_TRACE (default true)
--tls-address string HTTPS bind address of the server.
Consumes $CODER_TLS_ADDRESS (default "127.0.0.1:3443")
--tls-cert-file strings Path to each certificate for TLS. It requires a PEM-encoded file. To configure the listener to use a CA certificate, concatenate the primary certificate and the CA certificate together. The primary certificate should appear first in the combined file.
Consumes $CODER_TLS_CERT_FILE
--tls-client-auth string Policy the server will follow for TLS Client Authentication. Accepted values are "none", "request", "require-any", "verify-if-given", or "require-and-verify".
Consumes $CODER_TLS_CLIENT_AUTH (default "none")
--tls-client-ca-file string PEM-encoded Certificate Authority file used for checking the authenticity of client
Consumes $CODER_TLS_CLIENT_CA_FILE
--tls-client-cert-file string Path to certificate for client TLS authentication. It requires a PEM-encoded file.
Consumes $CODER_TLS_CLIENT_CERT_FILE
--tls-client-key-file string Path to key for client TLS authentication. It requires a PEM-encoded file.
Consumes $CODER_TLS_CLIENT_KEY_FILE
--tls-enable Whether TLS will be enabled.
Consumes $CODER_TLS_ENABLE
--tls-key-file strings Paths to the private keys for each of the certificates. It requires a PEM-encoded file.
Consumes $CODER_TLS_KEY_FILE
--tls-min-version string Minimum supported version of TLS. Accepted values are "tls10", "tls11", "tls12" or "tls13"
Consumes $CODER_TLS_MIN_VERSION (default "tls12")
--trace Whether application tracing data is collected. It exports to a backend configured by environment variables. See: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md
Consumes $CODER_TRACE_ENABLE
--trace-honeycomb-api-key string Enables trace exporting to Honeycomb.io using the provided API Key.
Consumes $CODER_TRACE_HONEYCOMB_API_KEY
--trace-logs Enables capturing of logs as events in traces. This is useful for debugging, but may result in a very large amount of events being sent to the tracing backend which may incur significant costs. If the verbose flag was supplied, debug-level logs will be included.
Consumes $CODER_TRACE_CAPTURE_LOGS
--update-check Periodically check for new releases of Coder and inform the owner. The check is performed once per day.
Consumes $CODER_UPDATE_CHECK
--wildcard-access-url string Specifies the wildcard hostname to use for workspace applications in the form "*.example.com".
Consumes $CODER_WILDCARD_ACCESS_URL
```
### Options inherited from parent commands
@ -174,5 +176,6 @@ coder server [flags]
### SEE ALSO
- [coder](coder.md) -
- [coder server create-admin-user](coder_server_create-admin-user.md) - Create a new admin user with the given username, email and password and adds it to every organization.
- [coder server postgres-builtin-serve](coder_server_postgres-builtin-serve.md) - Run the built-in PostgreSQL deployment.
- [coder server postgres-builtin-url](coder_server_postgres-builtin-url.md) - Output the connection URL for the built-in PostgreSQL deployment.

View File

@ -0,0 +1,41 @@
## coder server create-admin-user
Create a new admin user with the given username, email and password and adds it to every organization.
```
coder server create-admin-user [flags]
```
### Options
```
--email string The email of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_EMAIL.
-h, --help help for create-admin-user
--password string The password of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_PASSWORD.
--postgres-url string URL of a PostgreSQL database. If empty, the built-in PostgreSQL deployment will be used (Coder must not be already running in this case). Consumes $CODER_POSTGRES_URL.
--ssh-keygen-algorithm string The algorithm to use for generating ssh keys. Accepted values are "ed25519", "ecdsa", or "rsa4096". Consumes $CODER_SSH_KEYGEN_ALGORITHM. (default "ed25519")
--username string The username of the new user. If not specified, you will be prompted via stdin. Consumes $CODER_USERNAME.
```
### Options inherited from parent commands
```
--global-config coder Path to the global coder config directory.
Consumes $CODER_CONFIG_DIR (default "~/.config/coderv2")
--header stringArray HTTP headers added to all requests. Provide as "Key=Value".
Consumes $CODER_HEADER
--no-feature-warning Suppress warnings about unlicensed features.
Consumes $CODER_NO_FEATURE_WARNING
--no-version-warning Suppress warning when client and server versions do not match.
Consumes $CODER_NO_VERSION_WARNING
--token string Specify an authentication token. For security reasons setting CODER_SESSION_TOKEN is preferred.
Consumes $CODER_SESSION_TOKEN
--url string URL to a deployment.
Consumes $CODER_URL
-v, --verbose Enable verbose output.
Consumes $CODER_VERBOSE
```
### SEE ALSO
- [coder server](coder_server.md) - Start a Coder server

View File

@ -509,6 +509,10 @@
"title": "server",
"path": "./cli/coder_server.md"
},
{
"title": "server create-admin-user",
"path": "./cli/coder_server_create-admin-user.md"
},
{
"title": "server postgres-builtin-serve",
"path": "./cli/coder_server_postgres-builtin-serve.md"

View File

@ -327,6 +327,7 @@ export interface DeploymentConfig {
readonly disable_path_apps: DeploymentConfigField<boolean>
readonly max_session_expiry: DeploymentConfigField<number>
readonly disable_session_expiry_refresh: DeploymentConfigField<boolean>
readonly disable_password_auth: DeploymentConfigField<boolean>
readonly address: DeploymentConfigField<string>
readonly experimental: DeploymentConfigField<boolean>
}