Running Ghost in a WSL2 Docker container on Windows Server 2022
This will set up Ubuntu on Windows server 2022 with Docker running in WSL2, configured to host Linux apps with IIS acting as a reverse proxy and using a SSL. Then the Ghost docker container can be set up. In particular this shows how to fix the Too Many Redirects error that comes from using a https domain in Ghost from behind a reverse proxy.
Server Configuration
To use IIS as a reverse proxy to the WSL2 containers install Application Request Routing 3.0 using the Web Platform Installer. The URL Rewrite feature should also be installed if it isn't already. See:
Enable ARR under the server's IIS Home by selecting Application Request Routing Cache, then Server Proxy Settings... Check "Enable proxy", HTTP version: "Pass through", "Reverse rewrite host in response header" and the header "X-Forwarded-For" should be listed for the Custom Headers.
WSL2 and Docker need to be installed. Follow the guide and related links here: https://learn.microsoft.com/en-us/windows/wsl/tutorials/wsl-containers
Ghost Installation
The instructions below use the official Docker image for Ghost: https://hub.docker.com/_/ghost/
Create a folder in Ubuntu home
for the docker compose YAML file. I named it scripts
. In the new folder create a file called ghost-stack.yml
.
version: '3.1'
services:
ghost:
image: ghost:latest
restart: always
ports:
- 3001:2368
environment:
# see https://ghost.org/docs/config/#configuration-options
database__client: mysql
database__connection__host: db
database__connection__user: root
database__connection__password: ABCDEF123456
database__connection__database: ghost
# this url value is just an example, and is likely wrong for your environment!
url: https://example.com
# contrary to the default mentioned in the linked documentation, this image defaults to NODE_ENV=production (so development mode needs to be explicitly specified if desired)
#NODE_ENV: development
volumes:
- /home/ghost/content:/var/lib/ghost/content
db:
image: mysql:8.0
restart: always
environment:
MYSQL_ROOT_PASSWORD: ABCDEF123456
volumes:
- /home/ghost/mysql:/var/lib/mysql
You can change the port number to something other than 3001, change the url
to you domain, and use a unique password for mysql.
From within the scripts
folder run:docker-compose -f ghost-stack.yml up
IIS Configuration
Create a folder in your IIS Sites for the Ghost site, for example examplecom
, this will only have one file.
In IIS create a new website, pointing to examplecom
. Bind your domain name, for example example.com
bound to port 80 of an available IP address.
Go into the site's settings and select "URL Rewrite", then on the right menu select "View Server Variables". Select "Add..." and enter HTTP_X_FORWARDED_PROTO
. Without sending this header variable you will get a "Too Many Redirects" error when using https for the domain name.
In the examplecom
folder for the IIS site add a web.config
file:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<clear />
<rule name="HTTP Redirect" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" appendQueryString="false" />
</rule>
<rule name="JSGhost" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
<action type="Rewrite" url="http://localhost:3001/{R:1}" />
<serverVariables>
<set name="HTTP_X_FORWARDED_PROTO" value="https" />
</serverVariables>
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
This forwards any non-https traffic to https, and it configures the reverse proxy that sends all of the traffic to the IIS site to the Ghost docker image, while setting the header that tells Ghost that the HTTPS has already been handled. Change the port number if you used something other than 3001.
Set up a SSL certificate for the IIS site with the method of your choice, like win-acme: https://www.win-acme.com/
You should now be able to go to example.com and see the Ghost site. The admin URL will be example.com/ghost where you can configure your password and other site settings.
If you need to change any of the docker compose settings make sure to stop the containers first, then edit the yaml file, then restart the containers.