Skip to content

Email

CPM sends four kinds of mail, all through an SMTP server you name under Settings → Email:

  • Password reset links, from Forgot your password? on the sign-in page.
  • Invitations, so an administrator can create an account and let its owner choose the password.
  • Certificate alerts, a digest for the administrators when a certificate is about to expire.
  • Notifications, when something an administrator should know about happens: an agent gone offline, a host whose upstream keeps failing, an account disabled after failed sign-ins.

Until a server and a sender address are saved, none of these is offered: the sign-in page has no reset link, and Users has no invitation option.

Settings → Email → SMTP Server takes the server, its port and encryption, an optional username and password, and the address mail is sent from. The application name is shown as the sender.

  • STARTTLS (port 587) is the default, and refuses a server that does not offer it rather than sending the password in the clear. Implicit TLS (port 465) encrypts from the first byte. None is for a relay on a network you trust, such as a local Postfix.
  • The password is encrypted at rest and never sent back to the browser. Leave the field empty to keep the stored one.
  • Send test email sends a message with the saved settings - to you, or to an address you give - and shows the server’s refusal word for word when there is one.

Each field has an environment variable (SMTP_HOST, SMTP_PORT, SMTP_SECURITY, SMTP_USERNAME, SMTP_PASSWORD, SMTP_FROM), honoured until a value is saved in Settings. With SMTP_ENABLED left unset, naming a server is enough to turn email on.

Forgot your password? appears on the password step of the sign-in page. It asks for the username or email address and always answers the same way, whether or not an account matched, so it can’t be used to find out who has one.

  • Local accounts only. An account that signs in through single sign-on has no password here, and a reset email would hand it one that goes around its identity provider.
  • The link works once, for an hour, and only the newest one works. Asking again from the same address is limited to three times an hour.
  • It is never logged. The token travels in the link’s #fragment, which browsers don’t send, so it stays out of Caddy’s access log - and out of analytics, when the dashboard is served through Caddy.
  • Saving the new password signs out everywhere else, forward-auth portal sessions included. Two-factor sign-in still applies afterwards: a mailbox is not a second factor.

Creating a user under Users offers Email an invitation beside Set one now. The account is created at once, with no password; its owner gets a link, valid for seven days, to choose one. If the mail server refuses the message, the account is kept and the invitation can be sent again.

The same place in a user’s details sends a fresh link later: Send invitation for an account still without a password, Email a reset link for one with.

Twice a day the controller looks at every certificate - imported ones, and the ones each agent’s Caddy manages - and emails a digest of those that have fewer days left than the threshold under Settings → Email → Notifications (14 by default; 0 turns alerts off).

  • Caddy renews on its own. A managed certificate is reported only once it is also in the last quarter of its life, well past the point Caddy starts renewing, so an alert means renewal is failing. Caddy’s short-lived internal certificates don’t trigger one every day.
  • Once per stage. Each certificate is reported as it nears expiry, and once more if it expires. A renewed certificate starts over.
  • Recipients are the addresses you list, or every active administrator with a deliverable address when the list is empty.

Settings → Email → Notifications has a switch for each kind of event, all on by default. A switch turned off there is off for everyone. Within that, each administrator chooses for themselves under Profile → Notifications:

  • Which events they are told about.
  • Email, to their account’s address. Until they choose, an administrator is emailed when the Recipients list is empty or names them, which is who was emailed before the choice existed.
  • Browser notifications, to each browser they turn them on in. These work with or without email set up. They need HTTPS (or localhost), and on an iPhone or iPad the dashboard added to the Home Screen.

Addresses in the Recipients list that are not an administrator’s get every enabled event, so a team inbox can keep receiving them.

An event the current settings rule out is greyed out on both pages, with what it needs instead: upstream errors without the access log in JSON, a locked administrator without account locking, a disabled account without disabling after failed sign-ins, a new release without the update check, and a failing GeoIP update without GeoIP downloads set up. Its stored choice is kept for when it applies again.

A disabled account receives nothing, administrator or not. Tell the owner of a disabled account (off by default) sends that account’s own address one email when it is disabled, by an administrator or after failed sign-ins, and nothing more while it stays disabled.

Event What raises it Told again when
Account disabled An account disabled after failed sign-ins, or the last active administrator kept enabled instead -
Administrator locked The per-account lock engaging on an administrator (at most hourly per account) -
New administrator An administrator account created, or a user made one: on Users, over the API, or by an identity provider’s groups -
Agent offline An agent that had connected, gone longer than a threshold (5 minutes) It is back
Upstream errors A proxy host answering 502, 503 or 504 a number of times (10) within some minutes (5) A whole window without one
Caddy configuration refused Caddy refusing a configuration, on the whole fleet or one agent A configuration loads again
Agent failures An agent reporting a failed Caddy build, optional service or L4 port change, or log files it cannot read or prune (so its disk may fill) The operation applies
GeoIP update failing The GeoIP update failing three runs in a row It works again
CRS plugin switched off A CRS plugin Caddy refused, switched off so the rest loads -
New release A newer release, once per version, while the update check is on -
  • One email and one browser notification a minute at most. Whatever happens within a minute goes out together. A problem is told once however long it lasts, and its recovery once; one that is over before it goes out costs nothing at all.
  • A failed email is retried every five minutes for a day, to whoever did not get it; a browser notification is sent once. The block shows when a notification was last sent, how many are waiting, and the last error. Send a test notification emails everyone notifications are emailed to, straight away; Send a test under Profile pushes to that browser alone.
  • Nothing is queued while there is nowhere to send it - no email and no browser turned on - so setting one up later does not bring a backlog.
  • Times are in UTC, and say so: an email has no reader whose time zone could be asked.

The controller times an agent from when it first saw it disconnected. After the controller itself restarts, every agent gets the whole threshold to reconnect before anyone is told. An agent that never connected, is switched off or has been unpaired is no news.

These are counted from Caddy’s access log, so access logging must be on, in JSON, under Settings → Observability → Access Logging; the block says so when it is not. ClickHouse is not needed: while this notification is on and it can be sent somewhere, each agent reads its access log and sends the controller counts of 502, 503 and 504 answers per host and minute, analytics or not. A logged name that is not one of your proxy hosts is ignored. The access log does not record which upstream answered, so the email names the host.

The counts are kept in memory. After the controller restarts, nothing is called recovered until a whole window has passed.