diff --git a/cli/testdata/server-config.yaml.golden b/cli/testdata/server-config.yaml.golden index b050b662c56fa..cfa3c99d35eca 100644 --- a/cli/testdata/server-config.yaml.golden +++ b/cli/testdata/server-config.yaml.golden @@ -529,9 +529,6 @@ notifications: # Username to use with PLAIN/LOGIN authentication. # (default: , type: string) username: "" - # Password to use with PLAIN/LOGIN authentication. - # (default: , type: string) - password: "" # File from which to load password for use with PLAIN/LOGIN authentication. # (default: , type: string) passwordFile: "" diff --git a/codersdk/deployment.go b/codersdk/deployment.go index d7c1ddce4fec9..2e7316ddeeddd 100644 --- a/codersdk/deployment.go +++ b/codersdk/deployment.go @@ -2419,9 +2419,9 @@ Write out the current server config as YAML to stdout.`, Description: "Password to use with PLAIN/LOGIN authentication.", Flag: "notifications-email-auth-password", Env: "CODER_NOTIFICATIONS_EMAIL_AUTH_PASSWORD", + Annotations: serpent.Annotations{}.Mark(annotationSecretKey, "true"), Value: &c.Notifications.SMTP.Auth.Password, Group: &deploymentGroupNotificationsEmailAuth, - YAML: "password", }, { Name: "Notifications: Email Auth: Password File", diff --git a/codersdk/deployment_test.go b/codersdk/deployment_test.go index b84eda1f7250b..d7eca6323000c 100644 --- a/codersdk/deployment_test.go +++ b/codersdk/deployment_test.go @@ -14,9 +14,10 @@ import ( "github.com/stretchr/testify/require" "gopkg.in/yaml.v3" + "github.com/coder/serpent" + "github.com/coder/coder/v2/coderd/util/ptr" "github.com/coder/coder/v2/codersdk" - "github.com/coder/serpent" ) type exclusion struct { @@ -77,6 +78,9 @@ func TestDeploymentValues_HighlyConfigurable(t *testing.T) { "Provisioner Daemon Pre-shared Key (PSK)": { yaml: true, }, + "Notifications: Email Auth: Password": { + yaml: true, + }, } set := (&codersdk.DeploymentValues{}).Options() diff --git a/docs/admin/notifications.md b/docs/admin/notifications.md new file mode 100644 index 0000000000000..e4cd9a27b5f53 --- /dev/null +++ b/docs/admin/notifications.md @@ -0,0 +1,292 @@ +# Notifications + +Notifications are sent by Coder in response to specific internal events, such as +a workspace being deleted or a user being created. + +**Notifications are currently an experimental feature.** + +## Enable experiment + +In order to activate the notifications feature, you'll need to enable the +`notifications` experiment. + +```bash +# Using the CLI flag +$ coder server --experiments=notifications + +# Alternatively, using the `CODER_EXPERIMENTS` environment variable +$ CODER_EXPERIMENTS=notifications coder server +``` + +More information on experiments can be found +[here](https://coder.com/docs/contributing/feature-stages#experimental-features). + +## Event Types + +Notifications are sent in response to internal events, to alert the affected +user(s) of this event. Currently we support the following list of events: + +### Workspace Events + +_These notifications are sent to the workspace owner._ + +- Workspace Deleted +- Workspace Manual Build Failure +- Workspace Automatic Build Failure +- Workspace Automatically Updated +- Workspace Dormant +- Workspace Marked For Deletion + +### User Events + +_These notifications are sent to users with **owner** and **user admin** roles._ + +- User Account Created +- User Account Deleted +- User Account Suspended +- User Account Activated +- _(coming soon) User Password Reset_ +- _(coming soon) User Email Verification_ + +_These notifications are sent to the user themselves._ + +- User Account Suspended +- User Account Activated + +### Template Events + +_These notifications are sent to users with **template admin** roles._ + +- Template Deleted + +## Configuration + +You can modify the notification delivery behavior using the following server +flags. + +| Required | CLI | Env | Type | Description | Default | +| :------: | ----------------------------------- | --------------------------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------- | ------- | +| ✔️ | `--notifications-dispatch-timeout` | `CODER_NOTIFICATIONS_DISPATCH_TIMEOUT` | `duration` | How long to wait while a notification is being sent before giving up. | 1m | +| ✔️ | `--notifications-method` | `CODER_NOTIFICATIONS_METHOD` | `string` | Which delivery method to use (available options: 'smtp', 'webhook'). See [Delivery Methods](#delivery-methods) below. | smtp | +| -️ | `--notifications-max-send-attempts` | `CODER_NOTIFICATIONS_MAX_SEND_ATTEMPTS` | `int` | The upper limit of attempts to send a notification. | 5 | + +## Delivery Methods + +Notifications can currently be delivered by either SMTP or webhook. Each message +can only be delivered to one method, and this method is configured globally with +[`CODER_NOTIFICATIONS_METHOD`](https://coder.com/docs/reference/cli/server#--notifications-method) +(default: `smtp`). + +Enterprise customers can configured which method to use for each of the +supported [Events](#events); see the [Preferences](#preferences) section below +for more details. + +## SMTP (Email) + +Use the `smtp` method to deliver notifications by email to your users. Coder +does not ship with an SMTP server, so you will need to configure Coder to use an +existing one. + +**Server Settings:** + +| Required | CLI | Env | Type | Description | Default | +| :------: | --------------------------------- | ------------------------------------- | ----------- | ----------------------------------------- | ------------- | +| ✔️ | `--notifications-email-from` | `CODER_NOTIFICATIONS_EMAIL_FROM` | `string` | The sender's address to use. | | +| ✔️ | `--notifications-email-smarthost` | `CODER_NOTIFICATIONS_EMAIL_SMARTHOST` | `host:port` | The SMTP relay to send messages through. | localhost:587 | +| -️ | `--notifications-email-hello` | `CODER_NOTIFICATIONS_EMAIL_HELLO` | `string` | The hostname identifying the SMTP server. | localhost | + +**Authentication Settings:** + +| Required | CLI | Env | Type | Description | +| :------: | ------------------------------------------ | ---------------------------------------------- | -------- | ------------------------------------------------------------------------- | +| - | `--notifications-email-auth-username` | `CODER_NOTIFICATIONS_EMAIL_AUTH_USERNAME` | `string` | Username to use with PLAIN/LOGIN authentication. | +| - | `--notifications-email-auth-password` | `CODER_NOTIFICATIONS_EMAIL_AUTH_PASSWORD` | `string` | Password to use with PLAIN/LOGIN authentication. | +| - | `--notifications-email-auth-password-file` | `CODER_NOTIFICATIONS_EMAIL_AUTH_PASSWORD_FILE` | `string` | File from which to load password for use with PLAIN/LOGIN authentication. | +| - | `--notifications-email-auth-identity` | `CODER_NOTIFICATIONS_EMAIL_AUTH_IDENTITY` | `string` | Identity to use with PLAIN authentication. | + +**TLS Settings:** + +| Required | CLI | Env | Type | Description | Default | +| :------: | ----------------------------------------- | ------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| - | `--notifications-email-force-tls` | `CODER_NOTIFICATIONS_EMAIL_FORCE_TLS` | `bool` | Force a TLS connection to the configured SMTP smarthost. If port 465 is used, TLS will be forced. See https://datatracker.ietf.org/doc/html/rfc8314#section-3.3. | false | +| - | `--notifications-email-tls-starttls` | `CODER_NOTIFICATIONS_EMAIL_TLS_STARTTLS` | `bool` | Enable STARTTLS to upgrade insecure SMTP connections using TLS. Ignored if `CODER_NOTIFICATIONS_EMAIL_FORCE_TLS` is set. | false | +| - | `--notifications-email-tls-skip-verify` | `CODER_NOTIFICATIONS_EMAIL_TLS_SKIPVERIFY` | `bool` | Skip verification of the target server's certificate (**insecure**). | false | +| - | `--notifications-email-tls-server-name` | `CODER_NOTIFICATIONS_EMAIL_TLS_SERVERNAME` | `string` | Server name to verify against the target certificate. | | +| - | `--notifications-email-tls-cert-file` | `CODER_NOTIFICATIONS_EMAIL_TLS_CERTFILE` | `string` | Certificate file to use. | | +| - | `--notifications-email-tls-cert-key-file` | `CODER_NOTIFICATIONS_EMAIL_TLS_CERTKEYFILE` | `string` | Certificate key file to use. | | + +**NOTE:** you _MUST_ use `CODER_NOTIFICATIONS_EMAIL_FORCE_TLS` if your smarthost +supports TLS on a port other than `465`. + +### Send emails using G-Suite + +After setting the required fields above: + +1. Create an [App Password](https://myaccount.google.com/apppasswords) using the + account you wish to send from +2. Set the following configuration options: + ``` + CODER_NOTIFICATIONS_EMAIL_SMARTHOST=smtp.gmail.com:465 + CODER_NOTIFICATIONS_EMAIL_AUTH_USERNAME=@ + CODER_NOTIFICATIONS_EMAIL_AUTH_PASSWORD="" + ``` + +See +[this help article from Google](https://support.google.com/a/answer/176600?hl=en) +for more options. + +### Send emails using Outlook.com + +After setting the required fields above: + +1. Setup an account on Microsoft 365 or outlook.com +2. Set the following configuration options: + ``` + CODER_NOTIFICATIONS_EMAIL_SMARTHOST=smtp-mail.outlook.com:587 + CODER_NOTIFICATIONS_EMAIL_TLS_STARTTLS=true + CODER_NOTIFICATIONS_EMAIL_AUTH_USERNAME=@ + CODER_NOTIFICATIONS_EMAIL_AUTH_PASSWORD="" + ``` + +See +[this help article from Microsoft](https://support.microsoft.com/en-us/office/pop-imap-and-smtp-settings-for-outlook-com-d088b986-291d-42b8-9564-9c414e2aa040) +for more options. + +## Webhook + +The webhook delivery method sends an HTTP POST request to the defined endpoint. +The purpose of webhook notifications is to enable integrations with other +systems. + +**Settings**: + +| Required | CLI | Env | Type | Description | +| :------: | ---------------------------------- | -------------------------------------- | ----- | --------------------------------------- | +| ✔️ | `--notifications-webhook-endpoint` | `CODER_NOTIFICATIONS_WEBHOOK_ENDPOINT` | `url` | The endpoint to which to send webhooks. | + +Here is an example payload for Coder's webhook notification: + +```json +{ + "_version": "1.0", + "msg_id": "88750cad-77d4-4663-8bc0-f46855f5019b", + "payload": { + "_version": "1.0", + "notification_name": "Workspace Deleted", + "user_id": "4ac34fcb-8155-44d5-8301-e3cd46e88b35", + "user_email": "danny@coder.com", + "user_name": "danny", + "user_username": "danny", + "actions": [ + { + "label": "View workspaces", + "url": "https://et23ntkhpueak.pit-1.try.coder.app/workspaces" + }, + { + "label": "View templates", + "url": "https://et23ntkhpueak.pit-1.try.coder.app/templates" + } + ], + "labels": { + "initiator": "danny", + "name": "my-workspace", + "reason": "initiated by user" + } + }, + "title": "Workspace \"my-workspace\" deleted", + "body": "Hi danny\n\nYour workspace my-workspace was deleted.\nThe specified reason was \"initiated by user (danny)\"." +} +``` + +The top-level object has these keys: + +- `_version`: describes the version of this schema; follows semantic versioning +- `msg_id`: the UUID of the notification (matches the ID in the + `notification_messages` table) +- `payload`: contains the specific details of the notification; described below +- `title`: the title of the notification message (equivalent to a subject in + SMTP delivery) +- `body`: the body of the notification message (equivalent to the message body + in SMTP delivery) + +The `payload` object has these keys: + +- `_version`: describes the version of this inner schema; follows semantic + versioning +- `notification_name`: name of the event which triggered the notification +- `user_id`: Coder internal user identifier of the target user (UUID) +- `user_email`: email address of the target user +- `user_name`: name of the target user +- `user_username`: username of the target user +- `actions`: a list of CTAs (Call-To-Action); these are mainly relevant for SMTP + delivery in which they're shown as buttons +- `labels`: dynamic map of zero or more string key-value pairs; these vary from + event to event + +## User Preferences + +All users have the option to opt-out of any notifications. Go to **Account** -> +**Notifications** to turn notifications on or off. The delivery method for each +notification is indicated on the right hand side of this table. + +![User Notification Preferences](../images/user-notification-preferences.png) + +## Delivery Preferences (enterprise) + +Administrators can configure which delivery methods are used for each different +[event type](#event-types). + +![preferences](../images/admin/notification-admin-prefs.png) + +You can find this page under +`https://$CODER_ACCESS_URL/deployment/notifications?tab=events`. + +## Stop sending notifications + +Administrators may wish to stop _all_ notifications across the deployment. We +support a killswitch in the CLI for these cases. + +To pause sending notifications, execute +[`coder notifications pause`](https://coder.com/docs/reference/cli/notifications_pause). + +To resume sending notifications, execute +[`coder notifications resume`](https://coder.com/docs/reference/cli/notifications_resume). + +## Internals + +The notification system is built to operate concurrently in a single- or +multi-replica Coder deployment, and has a built-in retry mechanism. It uses the +configured Postgres database to store notifications in a queue and facilitate +concurrency. + +All messages are stored in the `notification_messages` table. + +Messages older than 7 days are deleted. + +### Message States + +![states](../images/admin/notification-states.png) + +_A notifier here refers to a Coder replica which is responsible for dispatching +the notification. All running replicas act as notifiers to process pending +messages._ + +- a message begins in `pending` state +- transitions to `leased` when a Coder replica acquires new messages from the + database + - new messages are checked for every `CODER_NOTIFICATIONS_FETCH_INTERVAL` + (default: 15s) +- if a message is delivered successfully, it transitions to `sent` state +- if a message encounters a non-retryable error (e.g. misconfiguration), it + transitions to `permanent_failure` +- if a message encounters a retryable error (e.g. temporary server outage), it + transitions to `temporary_failure` + - this message will be retried up to `CODER_NOTIFICATIONS_MAX_SEND_ATTEMPTS` + (default: 5) + - this message will transition back to `pending` state after + `CODER_NOTIFICATIONS_RETRY_INTERVAL` (default: 5m) and be retried + - after `CODER_NOTIFICATIONS_MAX_SEND_ATTEMPTS` is exceeded, it transitions to + `permanent_failure` + +Diagnostic messages will be saved in the `notification_messages` table and will +be logged, in the case of failure. diff --git a/docs/images/admin/notification-admin-prefs.png b/docs/images/admin/notification-admin-prefs.png new file mode 100644 index 0000000000000..435dfbde646c9 Binary files /dev/null and b/docs/images/admin/notification-admin-prefs.png differ diff --git a/docs/images/admin/notification-states.png b/docs/images/admin/notification-states.png new file mode 100644 index 0000000000000..cdd3de7ff0f91 Binary files /dev/null and b/docs/images/admin/notification-states.png differ diff --git a/docs/images/user-notification-preferences.png b/docs/images/user-notification-preferences.png new file mode 100644 index 0000000000000..818de470a7f77 Binary files /dev/null and b/docs/images/user-notification-preferences.png differ diff --git a/docs/manifest.json b/docs/manifest.json index 95cd3b0cb14cf..2a3f92e86abd6 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -501,6 +501,12 @@ "description": "Learn how to monitor the health of your Coder deployment", "path": "./admin/healthcheck.md", "icon_path": "./images/icons/health.svg" + }, + { + "title": "Notifications", + "description": "Learn how to configure notifications", + "path": "./admin/notifications.md", + "icon_path": "./images/icons/info.svg" } ] }, diff --git a/docs/reference/cli/server.md b/docs/reference/cli/server.md index 1ecdd326f1b17..ab97afe956940 100644 --- a/docs/reference/cli/server.md +++ b/docs/reference/cli/server.md @@ -1296,7 +1296,6 @@ Username to use with PLAIN/LOGIN authentication. | ----------- | ----------------------------------------------------- | | Type | string | | Environment | $CODER_NOTIFICATIONS_EMAIL_AUTH_PASSWORD | -| YAML | notifications.email.emailAuth.password | Password to use with PLAIN/LOGIN authentication. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy