Skip to content

Ghost Config — config.production.json, URL, Mail and Database Settings

DodaTech Updated 2026-06-28 9 min read

In this tutorial, you'll learn how to configure Ghost by editing config.production.json — setting the site URL, connecting mail transport for newsletters, configuring the database, and tuning storage adapters and cache settings.

What You'll Learn

  • The location and structure of Ghost configuration files
  • Editing config.production.json and config.development.json
  • Setting the site URL and configuring the server
  • Configuring mail transport (SMTP, Mailgun, SendGrid)
  • Database connection settings for MySQL
  • Storage adapters: local, S3, Google Cloud
  • Configuring cache adapters: Redis, built-in
  • Environment variables and the config hierarchy
  • Validating and reloading configuration

Why It Matters

The configuration file is Ghost's central nervous system. Every external service your Ghost site connects to — the database, the email provider, the storage backend — is configured here. A typo in the database hostname takes your site offline. A missing mail API key means no newsletters go out. Understanding the config file structure gives you control over every aspect of your Ghost installation and helps you diagnose problems quickly.

Real-World Use

Your Ghost site is running on a VPS but emails are not sending. You check the admin panel and see no errors, but newsletters are stuck in the outbox. You open config.production.json, find that the Mailgun API key has an extra character from a copy-paste error, fix it, and restart Ghost. Emails start flowing within seconds. Without knowing where the mail config lives, you would be searching through admin panels and forums for hours.

Learning Path

flowchart LR
  A["Ghost Installation"] --> B["Ghost Config
You are here"]:::current B --> C["Ghost Admin"] C --> D["Ghost Labs"] classDef current fill:#38bdf8,color:#0f172a,stroke-width:2px

Configuration File Location

Ghost configuration files live in the root of your Ghost installation directory.

Development (Local)

/your-ghost-directory/config.development.json

Production (Server)

/var/www/ghost/config.production.json

The ghost install local command creates config.development.json. The ghost install (production) command creates config.production.json. Ghost reads the appropriate file based on NODE_ENV.

Config File Structure

Here is a complete config.production.json with all common settings:

{
  "url": "https://blog.example.com",
  "server": {
    "port": 2368,
    "host": "127.0.0.1"
  },
  "database": {
    "client": "mysql",
    "connection": {
      "host": "localhost",
      "port": 3306,
      "user": "ghost_user",
      "password": "your-strong-password",
      "database": "ghost_production"
    }
  },
  "mail": {
    "transport": "SMTP",
    "options": {
      "host": "smtp.mailgun.org",
      "port": 587,
      "auth": {
        "user": "postmaster@mg.example.com",
        "pass": "your-mailgun-smtp-password"
      }
    }
  },
  "logging": {
    "level": "info",
    "transports": ["file", "stdout"]
  },
  "paths": {
    "contentPath": "/var/www/ghost/content"
  },
  "spam": {
    "user_login": {
      "minWait": 1000,
      "maxWait": 3600000,
      "freeRetries": 3
    }
  }
}

Let us examine each section.

The url Setting

The url setting is the most important line in the config file. It must match exactly how visitors access your site.

{
  "url": "https://blog.example.com"
}

Rules for the URL setting:

  • Include the protocol (https:// for production, http:// for local development)
  • Do NOT include a trailing slash
  • Do NOT include a path like /blog unless your site is at a subdirectory
  • Must match your Nginx server_name (otherwise links break)

If the URL is wrong, Ghost generates incorrect links in:

  • Post URLs and permalinks
  • RSS feed URLs
  • Canonical URLs
  • Newsletter email links
  • Sitemap URLs
  • Social sharing previews

The server Section

The server section controls where Ghost binds its Node.js process:

{
  "server": {
    "port": 2368,
    "host": "127.0.0.1"
  }
}
  • port: The port Ghost listens on. Default is 2368. In development, use any available port.
  • host: Set to 127.0.0.1 in production (Nginx is on the same machine). Set to 0.0.0.0 in development to access from other devices on your network.

If you are running multiple Ghost sites on one server, give each a unique port:

{
  "server": {
    "port": 2369
  }
}

The database Section

MySQL Production

{
  "database": {
    "client": "mysql",
    "connection": {
      "host": "localhost",
      "port": 3306,
      "user": "ghost_user",
      "password": "your-strong-password",
      "database": "ghost_production",
      "charset": "utf8mb4"
    },
    "debug": false
  }
}

SQLite Development

{
  "database": {
    "client": "sqlite3",
    "connection": {
      "filename": "/path/to/content/data/ghost.db"
    },
    "debug": false
  }
}

Connection Pool

For MySQL, you can configure the connection pool:

{
  "database": {
    "client": "mysql",
    "connection": { ... },
    "pool": {
      "min": 2,
      "max": 20
    }
  }
}

The pool manages database connections. For high-traffic sites, increase max. For low-traffic sites, keep min low to conserve server resources.

The mail Section

Email configuration is critical for newsletters, password resets, and member notifications.

SMTP (with Mailgun)

{
  "mail": {
    "transport": "SMTP",
    "options": {
      "host": "smtp.mailgun.org",
      "port": 587,
      "auth": {
        "user": "postmaster@mg.example.com",
        "pass": "your-mailgun-smtp-password"
      }
    }
  }
}

Mailgun API (alternative)

{
  "mail": {
    "transport": "Mailgun",
    "options": {
      "apiKey": "your-mailgun-api-key",
      "domain": "mg.example.com"
    }
  }
}

SendGrid

{
  "mail": {
    "transport": "SMTP",
    "options": {
      "host": "smtp.sendgrid.net",
      "port": 587,
      "auth": {
        "user": "apikey",
        "pass": "your-sendgrid-api-key"
      }
    }
  }
}
{
  "mail": {
    "transport": "Direct"
  }
}

The Direct transport tries to deliver email directly from your server. Most cloud providers block port 25, so this rarely works in production. Always use a transactional email service.

The logging Section

Control how Ghost logs information:

{
  "logging": {
    "level": "info",
    "transports": ["file", "stdout"]
  }
}
  • level: error (critical only), warn (warnings + errors), info (normal), debug (verbose)
  • transports: file (writes to content/logs/), stdout (console output visible in journalctl/PM2)

For production, use info level. For debugging, switch to debug.

Storage Adapters

Ghost stores images in content/images/ by default. You can configure alternative storage backends.

Local Storage (Default)

{
  "storage": {
    "active": "ghost-local-file-storage"
  }
}

S3 Storage

{
  "storage": {
    "active": "ghost-s3",
    "ghost-s3": {
      "accessKeyId": "YOUR_AWS_KEY",
      "secretAccessKey": "YOUR_AWS_SECRET",
      "region": "us-east-1",
      "bucket": "my-ghost-images",
      "assetHost": "https://cdn.example.com"
    }
  }
}

Using S3 or a similar object store is recommended for high-traffic sites. It offloads image serving from your Ghost server and lets you use a CDN.

Setting Config via Ghost CLI

You do not always need to edit the JSON file directly. The Ghost CLI provides config commands:

# Set the site URL
ghost config set url https://blog.example.com

# Set mail options
ghost config set mail__transport SMTP
ghost config set mail__options__host smtp.mailgun.org
ghost config set mail__options__auth__user postmaster@mg.example.com

# Set database options
ghost config set database__connection__host db.example.com

# View current config
ghost config show

# Get a specific value
ghost config get url

The double underscores in the key names represent nested properties. mail__options__host maps to mail.options.host in the JSON.

Environment Variables

Ghost also supports environment variables. These override config file values:

# Override URL and database via environment
export url=https://staging.example.com
export database__client=sqlite3
ghost start

Environment variables are useful for:

  • CI/CD pipelines where you want to deploy without hardcoding secrets
  • Docker containers where config is injected via Docker environment
  • Staging environments that mirror production with a different database

The priority order is: environment variables > config file > defaults.

Applying Configuration Changes

After editing config.production.json, restart Ghost:

ghost restart

Or via systemd:

sudo systemctl restart ghost_blog.example.com

The config file is read at startup. Changes do not take effect until Ghost restarts.

Common Mistakes

  1. Forgetting the trailing slash rule: The url field must not have a trailing slash. https://blog.example.com is correct. https://blog.example.com/ breaks relative links in emails and RSS feeds.

  2. Using localhost in a production database connection: If MySQL is on the same server, use localhost (which uses a Unix socket) or 127.0.0.1 (TCP). If MySQL is on a different server, use its IP address and ensure the MySQL user has remote access granted.

  3. Exposing passwords in version control: The config.production.json file contains database passwords and API keys. Never commit this file to Git. Add config.*.json to your .gitignore. Use environment variables in CI/CD.

  4. Setting mail transport to Direct in production: The Direct transport tries to deliver email from your server's own mail system. Most cloud providers block port 25. Use SMTP or Mailgun transport for reliable delivery.

  5. Not restarting after config changes: Editing the config file has no effect until Ghost restarts. Always run ghost restart after changing configuration.

Practice Questions

  1. What does the url field in config.production.json control, and why must it be exact? Answer: The url field defines the canonical site URL. Ghost uses it to generate all internal and external links, including post URLs, RSS feed URLs, canonical URLs, newsletter links, and sitemap entries. If it is wrong, every link on the site breaks.

  2. What are the two mail transport options in Ghost, and when should you use each? Answer: SMTP (Simple Mail Transfer Protocol) connects to an external mail server using host, port, and credentials. It is the most compatible option. Mailgun API uses Mailgun's API directly for sending. Use SMTP for most providers (Mailgun, SendGrid, Postmark). Use Mailgun API for advanced Mailgun users who need delivery optimization features.

  3. How do you override a config setting without editing the JSON file? Answer: Use environment variables. For example, setting database__connection__host=db.example.com overrides the database host at runtime without modifying config.production.json. This is useful for CI/CD and Docker deployments.

  4. Challenge: Set up a local Ghost development environment. Edit the config.development.json file to: change the port to 3000, configure mail to use Mailgun's SMTP server, change the logging level to debug, and set the URL to http://dev.example.com:3000. Restart Ghost and verify each change works.

FAQ

Where is the Ghost config file located?

The config file is in your Ghost installation directory. For production: /var/www/ghost/config.production.json. For development: config.development.json in your local Ghost folder.

Can I use environment variables for all config settings?

Most Ghost config settings support environment variable overrides. Use double underscores for nested keys (e.g., database__connection__host). Check the Ghost documentation for the complete list of supported environment variables.

What happens if I delete or corrupt the config file?

Ghost cannot start without a valid config file. You would need to create a new one using ghost install or by copying from a backup. The Ghost CLI's ghost config commands can regenerate the config file structure.

How do I configure Ghost to use a CDN for images?

Set up an S3-compatible storage adapter (like AWS S3 or DigitalOcean Spaces) in the storage section of config.production.json. Then set the assetHost to your CDN URL. Ghost uploads images to S3 and serves them from the CDN.

Can I have different configs for staging and production?

Yes. Each environment needs its own config file with the correct NODE_ENV. For example, config.staging.json with NODE_ENV=staging. The Ghost CLI supports the --environment flag to specify which environment to use.

Mini Project

Your task: Create a multi-environment Ghost configuration setup.

  1. Create three config files for your local development setup:
    • config.development.json with SQLite, port 2368, and Direct mail
    • config.staging.json with MySQL pointing to a staging database, Mailgun SMTP, and port 2369
    • config.production.json with full MySQL, Mailgun, and logging settings
  2. Write a Shell Script that starts Ghost with the correct config based on the environment variable NODE_ENV.
  3. Test each environment by starting Ghost, creating a post, and verifying the site loads correctly.
  4. Add config.*.json to your .gitignore and document the setup process.

This exercise gives you a deployable configuration Strategy you can use in real Ghost projects.

What's Next

Now that your Ghost configuration is solid, it is time to explore the admin dashboard:

Continue to Lesson 7: Ghost Admin — A complete tour of the admin dashboard, settings, navigation, branding, and integrations.

Related lessons:

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro