Skip to content

Add comprehensive login page customization options #7374

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions docs/FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,40 @@ You can change the config file's location using the `--config` flag or

The default location respects `$XDG_CONFIG_HOME`.

### Login page customization

You can customize the login page appearance using CLI flags or environment variables:

**CLI flags:**
```bash
code-server --login-title "My Code Server" \
--login-env-password-msg "Password set via environment" \
--password-placeholder "Enter password" \
--submit-text "LOGIN"
```

**Environment variables:**
```bash
export CS_LOGIN_TITLE="My Code Server"
export CS_LOGIN_ENV_PASSWORD_MSG="Password set via environment"
export CS_PASSWORD_PLACEHOLDER="Enter password"
export CS_SUBMIT_TEXT="LOGIN"
code-server
```

**Config file:**
```yaml
bind-addr: 127.0.0.1:8080
auth: password
password: your-password
login-title: "My Code Server"
login-env-password-msg: "Password set via environment"
password-placeholder: "Enter password"
submit-text: "LOGIN"
```

CLI flags take priority over environment variables, which take priority over config file settings.

## How do I make my keyboard shortcuts work?

Many shortcuts will not work by default, since they'll be "caught" by the browser.
Expand Down
2 changes: 2 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ code-server.
We also have an in-depth [setup and
configuration](https://coder.com/docs/code-server/latest/guide) guide.

You can also customize the login page appearance - see our [customization guide](./customization.md).

## Questions?

See answers to [frequently asked
Expand Down
147 changes: 147 additions & 0 deletions docs/customization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# Login Page Customization

code-server allows you to customize the login page appearance and messages through CLI arguments, environment variables, or configuration files.

## Available Customization Options

### Branding and Appearance
- **Login Title**: Customize the main title on the login page
- **Welcome Text**: Set custom welcome message
- **App Name**: Change the application branding throughout the interface

### Login Messages
- **Password Instructions**: Customize the message explaining where to find the password
- **Environment Password Message**: Custom message when password is set via `$PASSWORD`
- **Hashed Password Message**: Custom message when password is set via `$HASHED_PASSWORD`

### Form Elements
- **Password Placeholder**: Custom placeholder text for the password field
- **Submit Button**: Custom text for the login button

### Error Messages
- **Rate Limit Message**: Custom message when login attempts are rate limited
- **Missing Password**: Custom message for empty password submissions
- **Incorrect Password**: Custom message for wrong password attempts

## Configuration Methods

### CLI Arguments

```bash
code-server \
--app-name "My Development Server" \
--welcome-text "Welcome to the development environment" \
--login-title "Secure Access Portal" \
--login-below "Please authenticate to continue" \
--password-placeholder "Enter your access code" \
--submit-text "AUTHENTICATE" \
--login-env-password-msg "Access code provided via environment variable" \
--login-rate-limit-msg "Too many attempts. Please wait before trying again." \
--missing-password-msg "Access code is required" \
--incorrect-password-msg "Invalid access code"
```

### Environment Variables

Perfect for Docker deployments and containerized environments:

```bash
# Basic branding
export CS_APP_NAME="My Development Server"
export CS_WELCOME_TEXT="Welcome to the development environment"

# Login page customization
export CS_LOGIN_TITLE="Secure Access Portal"
export CS_LOGIN_BELOW="Please authenticate to continue"
export CS_PASSWORD_PLACEHOLDER="Enter your access code"
export CS_SUBMIT_TEXT="AUTHENTICATE"

# Message customization
export CS_LOGIN_ENV_PASSWORD_MSG="Access code provided via environment variable"
export CS_LOGIN_RATE_LIMIT_MSG="Too many attempts. Please wait before trying again."
export CS_MISSING_PASSWORD_MSG="Access code is required"
export CS_INCORRECT_PASSWORD_MSG="Invalid access code"

code-server
```

### Configuration File

Add to your `~/.config/code-server/config.yaml`:

```yaml
bind-addr: 127.0.0.1:8080
auth: password
password: your-password

# Branding
app-name: "My Development Server"
welcome-text: "Welcome to the development environment"

# Login page
login-title: "Secure Access Portal"
login-below: "Please authenticate to continue"
password-placeholder: "Enter your access code"
submit-text: "AUTHENTICATE"

# Messages
login-env-password-msg: "Access code provided via environment variable"
login-rate-limit-msg: "Too many attempts. Please wait before trying again."
missing-password-msg: "Access code is required"
incorrect-password-msg: "Invalid access code"
```

## Docker Examples

### Basic Docker Deployment with Customization

```bash
docker run -it --name code-server -p 127.0.0.1:8080:8080 \
-v "$PWD:/home/coder/project" \
-e "CS_LOGIN_TITLE=Development Environment" \
-e "CS_LOGIN_ENV_PASSWORD_MSG=Password configured in container environment" \
-e "CS_PASSWORD_PLACEHOLDER=Enter development password" \
-e "CS_SUBMIT_TEXT=ACCESS ENVIRONMENT" \
codercom/code-server:latest
```

### Corporate Branding Example

```bash
docker run -it --name code-server -p 127.0.0.1:8080:8080 \
-v "$PWD:/home/coder/project" \
-e "CS_APP_NAME=ACME Corporation Dev Portal" \
-e "CS_LOGIN_TITLE=ACME Development Portal" \
-e "CS_LOGIN_BELOW=Enter your corporate credentials" \
-e "CS_PASSWORD_PLACEHOLDER=Corporate Password" \
-e "CS_SUBMIT_TEXT=SIGN IN" \
-e "CS_LOGIN_ENV_PASSWORD_MSG=Password managed by IT department" \
codercom/code-server:latest
```

## Priority Order

Settings are applied in the following priority order (highest to lowest):

1. **CLI arguments** - Highest priority
2. **Environment variables** - Medium priority
3. **Config file** - Lowest priority

This allows you to set defaults in your config file and override them with environment variables or CLI arguments as needed.

## Complete Reference

| CLI Argument | Environment Variable | Description |
|--------------|---------------------|-------------|
| `--app-name` | `CS_APP_NAME` | Application name used throughout the interface |
| `--welcome-text` | `CS_WELCOME_TEXT` | Welcome message on login page |
| `--login-title` | `CS_LOGIN_TITLE` | Main title on login page |
| `--login-below` | `CS_LOGIN_BELOW` | Text below the login title |
| `--password-placeholder` | `CS_PASSWORD_PLACEHOLDER` | Password field placeholder text |
| `--submit-text` | `CS_SUBMIT_TEXT` | Login button text |
| `--login-password-msg` | `CS_LOGIN_PASSWORD_MSG` | Message for config file password |
| `--login-env-password-msg` | `CS_LOGIN_ENV_PASSWORD_MSG` | Message when using `$PASSWORD` env var |
| `--login-hashed-password-msg` | `CS_LOGIN_HASHED_PASSWORD_MSG` | Message when using `$HASHED_PASSWORD` env var |
| `--login-rate-limit-msg` | `CS_LOGIN_RATE_LIMIT_MSG` | Rate limiting error message |
| `--missing-password-msg` | `CS_MISSING_PASSWORD_MSG` | Empty password error message |
| `--incorrect-password-msg` | `CS_INCORRECT_PASSWORD_MSG` | Wrong password error message |
24 changes: 24 additions & 0 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,30 @@ docker run -it --name code-server -p 127.0.0.1:8080:8080 \
codercom/code-server:latest
```

### Customizing the login page

You can customize the login page by setting environment variables:

```bash
# Example with login customization
docker run -it --name code-server -p 127.0.0.1:8080:8080 \
-v "$PWD:/home/coder/project" \
-e "CS_LOGIN_TITLE=My Development Environment" \
-e "CS_LOGIN_ENV_PASSWORD_MSG=Password configured via environment variable" \
-e "CS_PASSWORD_PLACEHOLDER=Enter your secure password" \
-e "CS_SUBMIT_TEXT=ACCESS" \
codercom/code-server:latest
```

Available customization environment variables:
- `CS_LOGIN_TITLE` - Custom login page title
- `CS_LOGIN_BELOW` - Custom text below the login title
- `CS_PASSWORD_PLACEHOLDER` - Custom password field placeholder
- `CS_SUBMIT_TEXT` - Custom submit button text
- `CS_LOGIN_PASSWORD_MSG` - Custom message for config file password
- `CS_LOGIN_ENV_PASSWORD_MSG` - Custom message when using `$PASSWORD` env var
- `CS_LOGIN_HASHED_PASSWORD_MSG` - Custom message when using `$HASHED_PASSWORD` env var

Our official image supports `amd64` and `arm64`. For `arm32` support, you can
use a [community-maintained code-server
alternative](https://hub.docker.com/r/linuxserver/code-server).
Expand Down
91 changes: 91 additions & 0 deletions src/node/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs {
verbose?: boolean
"app-name"?: string
"welcome-text"?: string
"login-title"?: string
"login-below"?: string
"password-placeholder"?: string
"submit-text"?: string
"login-password-msg"?: string
"login-env-password-msg"?: string
"login-hashed-password-msg"?: string
"login-rate-limit-msg"?: string
"missing-password-msg"?: string
"incorrect-password-msg"?: string
"abs-proxy-base-path"?: string
/* Positional arguments. */
_?: string[]
Expand Down Expand Up @@ -291,6 +301,46 @@ export const options: Options<Required<UserProvidedArgs>> = {
short: "w",
description: "Text to show on login page",
},
"login-title": {
type: "string",
description: "Custom login page title",
},
"login-below": {
type: "string",
description: "Custom text to show below login title",
},
"password-placeholder": {
type: "string",
description: "Custom placeholder text for password field",
},
"submit-text": {
type: "string",
description: "Custom text for login submit button",
},
"login-password-msg": {
type: "string",
description: "Custom message for config file password",
},
"login-env-password-msg": {
type: "string",
description: "Custom message when password is set from $PASSWORD environment variable",
},
"login-hashed-password-msg": {
type: "string",
description: "Custom message when password is set from $HASHED_PASSWORD environment variable",
},
"login-rate-limit-msg": {
type: "string",
description: "Custom message for login rate limiting",
},
"missing-password-msg": {
type: "string",
description: "Custom message for missing password error",
},
"incorrect-password-msg": {
type: "string",
description: "Custom message for incorrect password error",
},
"abs-proxy-base-path": {
type: "string",
description: "The base path to prefix to all absproxy requests",
Expand Down Expand Up @@ -593,6 +643,47 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
args["disable-proxy"] = true
}

// Login message customization via environment variables
if (process.env.CS_LOGIN_TITLE) {
args["login-title"] = process.env.CS_LOGIN_TITLE
}

if (process.env.CS_LOGIN_BELOW) {
args["login-below"] = process.env.CS_LOGIN_BELOW
}

if (process.env.CS_PASSWORD_PLACEHOLDER) {
args["password-placeholder"] = process.env.CS_PASSWORD_PLACEHOLDER
}

if (process.env.CS_SUBMIT_TEXT) {
args["submit-text"] = process.env.CS_SUBMIT_TEXT
}

if (process.env.CS_LOGIN_PASSWORD_MSG) {
args["login-password-msg"] = process.env.CS_LOGIN_PASSWORD_MSG
}

if (process.env.CS_LOGIN_ENV_PASSWORD_MSG) {
args["login-env-password-msg"] = process.env.CS_LOGIN_ENV_PASSWORD_MSG
}

if (process.env.CS_LOGIN_HASHED_PASSWORD_MSG) {
args["login-hashed-password-msg"] = process.env.CS_LOGIN_HASHED_PASSWORD_MSG
}

if (process.env.CS_LOGIN_RATE_LIMIT_MSG) {
args["login-rate-limit-msg"] = process.env.CS_LOGIN_RATE_LIMIT_MSG
}

if (process.env.CS_MISSING_PASSWORD_MSG) {
args["missing-password-msg"] = process.env.CS_MISSING_PASSWORD_MSG
}

if (process.env.CS_INCORRECT_PASSWORD_MSG) {
args["incorrect-password-msg"] = process.env.CS_INCORRECT_PASSWORD_MSG
}

const usingEnvHashedPassword = !!process.env.HASHED_PASSWORD
if (process.env.HASHED_PASSWORD) {
args["hashed-password"] = process.env.HASHED_PASSWORD
Expand Down
Loading