Ghost Docker Email Setup: Configure SMTP with Postmark

Share
Ghost Docker Email Setup: Configure SMTP with Postmark
Photo by Philip Oroni / Unsplash

How to Configure Postmark SMTP for Ghost Docker

A working Ghost Docker SMTP configuration is essential for staff login codes,
password resets, invitations, and member messages. This guide connects a
self-hosted Ghost Docker site to Postmark for transactional email without
putting credentials in compose.yml.

Before you start

You need:

  • A running Ghost Docker installation
  • A Postmark server with a verified sender address or domain
  • Shell access to the directory containing .env and compose.yml

This guide follows the official TryGhost/ghost-docker setup. Its Ghost
service already loads configuration from .env, so the Git-tracked Compose
file does not need to be changed.

1. Create a transactional SMTP token in Postmark

Open the Postmark server you want to use, then create or select a Transactional Message Stream. In its settings, enable SMTP access and generate an SMTP Token.

Postmark gives the token two values:

  • The Access Key, which Ghost uses as the SMTP username
  • The Secret Key, which Ghost uses as the SMTP password

Save the Secret Key when you generate it. Postmark does not display it again;
if it is lost, generate a new SMTP Token.

Use a stream-specific SMTP Token here, not an Account API Token or an unrelated Server API Token. Postmark associates each SMTP Token with its Message Stream, which avoids having to select the stream separately in Ghost.

2. Add the Postmark settings to .env

Open the .env file next to compose.yml and add or replace Ghost's mail settings:

mail__transport=SMTP
mail__options__host=smtp.postmarkapp.com
mail__options__port=587
mail__options__secure=false
mail__options__requireTLS=true
mail__options__auth__user=POSTMARK_SMTP_ACCESS_KEY
mail__options__auth__pass=POSTMARK_SMTP_SECRET_KEY
mail__from="Company Name <[email protected]>"

Replace the two credential placeholders with the Access Key and Secret Key from the Postmark SMTP Token. Replace mail__from with an address covered by a verified Postmark sender signature or domain.

Ghost represents nested configuration keys with double underscores. For example, mail.options.auth.user becomes mail__options__auth__user.

Postmark's transactional SMTP endpoint supports STARTTLS on port 587. With Nodemailer, the mail library used by Ghost, which means the connection starts with secure=false and is required to upgrade to TLS through requireTLS=true.

Keep .env out of version control and limit its filesystem permissions:

git check-ignore .env
chmod 600 .env

git check-ignore .env should print the path. If it prints nothing, confirm that .env is included in your repository's .gitignore before continuing.

3. Recreate Ghost and test delivery

Docker Compose does not update an existing container merely because .env changed. Recreate only the Ghost service:

docker compose up -d --force-recreate ghost

Then trigger a transactional message, for example, request a staff login code, send an invitation, or use password reset. Confirm the message appears in Postmark Activity and reaches the recipient.

If delivery fails, inspect Ghost's recent logs:

docker compose logs --since=10m ghost

Troubleshooting Ghost Docker SMTP

Error or symptom Likely cause What to check
EAUTH or SMTP 535 Postmark rejected authentication SMTP is enabled and the SMTP Token Access Key and Secret Key are in the correct fields
Sender or signature rejection The From address is not authorized Verify mail__from or its domain in Postmark
No mail__... variables inside Ghost .env was not passed to the container Confirm the Ghost service has env_file: .env, then force-recreate it

You can safely verify which mail settings reached the container while redacting the credentials:

docker compose exec ghost env |
  awk -F= '/^mail__/ {
    if ($1 ~ /auth__(user|pass)$/) print $1 "=<redacted>";
    else print
  }'

An EAUTH or 535 response means the SMTP connection reached Postmark but authentication was rejected. Changing TLS options will not fix that error; confirm SMTP access and generate a new stream-specific SMTP Token if necessary.

Transactional email is not newsletter delivery

This setup configures transactional messages sent by Ghost, including login codes, password resets, invitations, and member authentication messages. It does not configure Ghost newsletters or other bulk email delivery, which Ghost handles separately.

For additional reference, see the official Ghost Docker installation, Ghost mail configuration, and Postmark SMTP documentation.

Need help with a Ghost project? Our team can assist with custom Ghost
development, Docker deployments, migrations, and reliable email-delivery
configuration.