State of in-app subscriptions report is here. Download now

Selfserved Ghost + Webflow integration with Caddy

Vitaly Davydov

Updated: April 17, 2023

4 min read

Content

612cf169f035b485bc03cfa2 webflowghostcaddy min

Modern SaaS applications usually run a landing page, blog, and main app separately. For a landing page, you may want to use Tilda, Webflow, or other web-builders. For a blog, it’s common to use self-hosted CMS such as WordPress, Ghost, or others.

It’s crucially important to index the main domain <your_domain>.com</your_domain> instead of a subdomain blog.<your_domain>.com</your_domain> for SEO purposes. You want as many links to your main domain as possible. The more content on <your_domain>.com/blog</your_domain>, the more Google will index it.

Running Ghost blog on a subdomain such as blog.<your_domain>.com</your_domain> is easy, just create a new A-record in your DNS provider and point it to a machine with running Ghost instance. If you want to run <your_domain>.com</your_domain> on a Webflow and <your_domain>.com/blog</your_domain> being self-hosted Ghost you need a reverse-proxy server.

602057636a5d4c530ec414e7 uuksuwzn 7uwyip5fzuiw p56qcivgumdmrpqcv6 cjcqfcumr6cw2einfygrznvix3u9wpzbtmpvdimajhd4f2fui dwavuholitwafukoptuo otvrr 5xdu k1yavy4mzt3nh
Reverse proxy server

Adjusting Caddy for reverse proxy

From a devops point of view our goals are:

  1. <your_domain>.com</your_domain> -> Webflow
  2. <your_domain>.com/*</your_domain> -> Webflow
  3. <your_domain>.com/blog</your_domain> -> self hosted Ghost blog
  4. blog.<your_domain>.com</your_domain> -> <your_domain>.com/blog</your_domain>

We’re going to use Caddy for reverse proxy. The reason is Docker-friendly config, super fast to deploy without deep knowledge of devops (hey, Nginx). Find the official Caddy image here. Caddy needs you to mount volumes for proper working.

We’ll host Ghost and Caddy on the same machine and in a single docker-compose.yml file.

version: "3.7"
services:
  caddy:
  image: caddy:2
    restart: unless-stopped
    ports:
    - "80:80"
    - "443:443"
    volumes:
    - $PWD/Caddyfile:/etc/caddy/Caddyfile
    - $PWD/site:/srv
    - caddy_data:/data
    - caddy_config:/config
  ghost:
    image: ghost:3
    environment:
    NODE_ENV: production
    url: https://adapty.io/blog
    volumes:
    - ./blog:/var/lib/ghost/content
volumes:
  caddy_data:
  caddy_config:

Now for Caddyfile:

blog.adapty.io {
	redir https://adapty.io/blog{uri}
}
adapty.io {
	redir /blog /blog/
	reverse_proxy /blog/* ghost:2368 {
		#proxy to Ghost container
		header_up Host {host}
	}
	reverse_proxy proxy.webflow.com {
		#proxy to Webflow
		header_up Host {host}
	}
}

Run docker-compose up -d and here you go!

By default, Caddy passes thru incoming headers to the backend—including the Host header—without modifications, with two exceptions:

  • It adds or augments the X-Forwarded-For header field.
  • It sets the X-Forwarded-Proto header field.

Read more in their docs.

Lastly,

Point A record for the main domain to your IP.

10 ideas
to increase
paywall conversion

Get an ebook with insights
and advice from top experts

A record in DNS
Change your DNS A record and point to a VM

In Webflow turn off SSL proxy as Caddy will serve it for you automatically (very cool, yeah? Without a certbot).

advanced publishing options
Turn off SSL in Webflow as Caddy will create a certificate for you

That’s it!

Unlock Industry Insights
Gain the edge with key insights from our State of in-app subscriptions in the US 2023 report. Essential for app professionals!
Get your free report now
Report in app US 2023 (book)

Further reading