Skip to main content
Preslav Rachev
  1. My Writings /Programming /

How to Fix That Ghost Email Configuration Once and for All

·3 mins
Sometimes, the simple solution has been there all along. It takes you a minute to implement it and an eternity of scratching your head and looking in the wrong direction.

Image Source: Midjourney

In my concrete situation, I needed to set up a Ghost instance for a new side project. Since I will need the newsletter emailing functionality, I quickly went to Ghost’s Mailgun settings and set things up.

Ghost has its own Mailgun settings window

Imagine my surprise when soon-to-be subscribers told me that they did not receive a confirmation email with a link upon their subscription. Indeed, when I checked the logs, I noticed that the email sending was rejected because I hadn’t set up Mailgun. Wait a minute, but I just did that!

It turns out that the Mailgun configuration within Ghost is only for sending bulk newsletter emails and not for any transactional ones, like the subscription confirmation mentioned above. Why is that the case? I have no clue, but the fact is that it is extremely confusing and annoying. The transactional email configuration must be added to the config.production.json file and must look something like the following:

 "mail": {
    "transport": "SMTP",
    "options": {
      "service": "Mailgun",
      "host": "smtp.eu.mailgun.org",
      "port": 587,
      "secure": true,
      "auth": {
        "user": "your-mailgun-username",
        "pass": "your-mailgun-password"
      }
    }
 },

But I was not able to edit the config file #

So far, so good. For most of you, this will fix the problem after running a quick ghost restart. Not for me, though. I am using a self-hosting solution called Coolify to spawn Ghost instances, and unfortunately, its default Ghost template sets up a persistent volume for the content folder but not for the root of your installation (where the config files are). Thus, any change I make to any of those will be overwritten upon restart.

After lots of googling and some help from ChatGPT, I found out that Ghost is using a handy library for reading configurations called nconf. What’s great about nconf is that you can emulate any nested JSON configuration using an environment variable with a special syntax. The names of the envvars must be lowercase, and indentations must be marked with two underscore characters (__). If an environment variable with the appropriate name exists, its value will override the corresponding one in the JSON file.

With the above knowledge, I was able to finally set the values I needed:

mail__transport=SMTP
mail__options__service=Mailgun
mail__options__host=smtp.eu.mailgun.org
mail__options__port=587
mail__options__secure=false
mail__options__auth__user=your-mailgun-username
mail__options__auth__pass=your-mailgun-password

After restarting the Ghost instance, I was happy to see that the email issues were no longer there.

Thanks to Coolify and nconf, I was able to override the settings using environment variables

I am hoping that this blog post will save you the headaches I had yesterday.

Have something to say? Join the discussion below 👇

Want to explore instead? Fly with the time capsule 🛸

You may also find these interesting