Self-Hosting

Custom Email Templates

Configure custom email templates with self-hosted Supabase instance


When running a self-hosted Supabase instance, you can fully customize emails sent by Supabase Auth.

Overview#

Supabase Auth does not read email templates from mounted Docker volumes. Instead, it expects each template to be available at a URL that returns a valid HTML template.

This URL:

  • Does not need to be public
  • Must be reachable from auth service
  • Must return a valid Golang HTML template

To provide templates to Supabase Auth, you need a service that serves static HTML files. This can be any server of your choice. The only requirement is that the auth service must be able to reach it via a HTTP GET request.

This guide uses Caddy for serving templates.

Authentication email templates#

Authentication email templates can be configured using the following environment variables:

  • GOTRUE_MAILER_TEMPLATES_<AUTH_FLOW>: Provide a custom template URL. Falls back to the default template if not set.
  • GOTRUE_MAILER_SUBJECTS_<AUTH_FLOW>: Customize the email subject. Falls back to the default subject if not set.
Auth flowSent
CONFIRMATIONWhen a user signs up and needs to verify their email address
RECOVERYWhen a user requests a password reset
MAGIC_LINKWhen a user requests a magic link for password-less authentication
INVITEWhen a user is invited to join your application via email invitation
EMAIL_CHANGEWhen a user requests to change their email address
REAUTHENTICATIONWhen a user needs to re-authenticate for sensitive operations

For example:

1
GOTRUE_MAILER_TEMPLATES_MAGIC_LINK='<template_url>'
2
GOTRUE_MAILER_SUBJECTS_MAGIC_LINK='<custom_subject>'

Example#

Below is an example configuration for setting up a custom invite template.

Step 1: Create a templates directory#

Create a templates directory inside the existing volumes directory and add your email templates to it.

Your directory structure should look like this:

1
volumes/
2
templates/
3
invite.html

Step 2: Update docker-compose.yml#

Update the auth service to depend on templates-server, and pass the email template environment variables. Then add a templates-server service to serve the templates from ./volumes/templates.

docker-compose.yml
1
services:
2
auth:
3
depends_on:
4
db:
5
condition: service_healthy
6
templates-server: # 👈 new dependency
7
condition: service_started
8
environment:
9
GOTRUE_MAILER_TEMPLATES_INVITE: 'http://templates-server/invite.html'
10
GOTRUE_MAILER_SUBJECTS_INVITE: 'You have been invited'
11
12
templates-server:
13
image: caddy:2-alpine
14
command: ['caddy', 'file-server', '-r', '/templates', '--listen', ':80']
15
volumes:
16
- ./volumes/templates:/templates

What this configuration does#

  • Adds a templates-server service that runs alongside the Supabase services in the same docker network.
  • Serves your custom email template files from the ./volumes/templates directory.
  • Keeps the templates-server private to the Docker network (no published ports), so it is not accessible from outside.
  • Allows the auth service to fetch templates via http://templates-server/<template>.html.

Step 3: Restart containers#

1
docker compose up -d --force-recreate --no-deps auth templates-server

Notification email templates#

Notification email templates can be configured using the following environment variables:

  • GOTRUE_MAILER_NOTIFICATIONS_<NOTIFICATION_TYPE>_ENABLED: Enable the notification email
  • GOTRUE_MAILER_TEMPLATES_<NOTIFICATION_TYPE>_NOTIFICATION: Provide a custom template URL. Falls back to the default template if not set.
  • GOTRUE_MAILER_SUBJECTS_<NOTIFICATION_TYPE>_NOTIFICATION: Customize the email subject. Falls back to the default subject if not set.
Notification TypeSent
PASSWORD_CHANGEDWhen a user's password is changed
EMAIL_CHANGEDWhen a user's email address is changed
PHONE_CHANGEDWhen a user's phone number is changed
MFA_FACTOR_ENROLLEDWhen a new MFA factor is added to the user's account
MFA_FACTOR_UNENROLLEDWhen an MFA factor is removed from the user's account
IDENTITY_LINKEDWhen a new identity is linked to the account
IDENTITY_UNLINKEDWhen an identity is unlinked from the account

For example:

1
GOTRUE_MAILER_NOTIFICATIONS_EMAIL_CHANGED_ENABLED='true'
2
GOTRUE_MAILER_TEMPLATES_EMAIL_CHANGED_NOTIFICATION='<template_url>'
3
GOTRUE_MAILER_SUBJECTS_EMAIL_CHANGED_NOTIFICATION='<custom_subject>'

Example#

Below is an example configuration for setting up a custom password changed notification template.

Step 1: Create the templates directory#

This example reuses the directory created in Auth Email Templates – Step 1 (volumes/templates). Add your notification email templates to this directory.

Your directory structure should look like this:

1
volumes/
2
templates/
3
invite.html
4
password_changed_notification.html

Step 2: Update docker-compose.yml#

Update the auth service in docker-compose.yml to enable password changed notification

docker-compose.yml
1
services:
2
auth:
3
depends_on:
4
db:
5
condition: service_healthy
6
templates-server:
7
condition: service_started
8
environment:
9
GOTRUE_MAILER_NOTIFICATIONS_PASSWORD_CHANGED_ENABLED: 'true' # 👈 enabling the notification is required
10
GOTRUE_MAILER_TEMPLATES_PASSWORD_CHANGED_NOTIFICATION: 'http://templates-server/password_changed_notification.html'
11
GOTRUE_MAILER_SUBJECTS_PASSWORD_CHANGED_NOTIFICATION: 'Your password has been changed'
12
13
templates-server:
14
image: caddy:2-alpine
15
command: ['caddy', 'file-server', '-r', '/templates', '--listen', ':80']
16
volumes:
17
- ./volumes/templates:/templates

Step 3: Restart containers#

1
docker compose up -d --force-recreate --no-deps auth templates-server