I have the exact same issues as described in this post: Ghost portal membership not working , however, that thread ends without a final resolution and I’m stuck on the same last question on how to configure behind a reverse proxy.
- What’s your URL? This is the easiest way for others to help you
Server will likely be offline, due to the issue, but the content at the link above is virtually identical to my situation.
- What version of Ghost are you using? If it’s not the latest, please update Ghost first before opening your topic
5.35.1
- How was Ghost installed and configured?
Ghost is running currently as 3 distinct instances in 3 different docker files.
- What Node version, database, OS & browser are you using?
Node 16.19.1, mysql 8 (Amazon RDS), Alpine Linux, Safari/Chome
- What errors or information do you see in the console?
Same conditions as in prior thread. Reverse proxy from https->http results in failures in sign-ups and portal customization, despite still being hosted under nginx HTTPS certificate. Attempting to use ghost https results in handshaking issues with SSL and site not accessible at all.
- What steps could someone else take to reproduce the issue you’re having?
It took me about two weeks to get everything working with nginx, so direct reproduction might be a bit much without transfering “scrubbed” versions of all of my configuration files. Though in principal it’s just three docker ghost instances and one docker nginx instance. The reverse proxy setup was the challenging part as there’s dozens of ways to configure it. Though everything seems to be performing as expected now on the nginx side. I haven’t found any examples of internal docker redirects with nginx and https, given it’s all running on the same internal shared network address across the docker instances.
Background…
I’m running multiple Ghost instances behind an nginx reverse proxy. The nginx reverse proxy is handling the SSL certificates and automated maintenance of those certs. All of the ghost instances and nginx are running in their own docker instances with a shared docker network. So nginx is dispatching requests over http internal to the docker network. Only nginx is exposed on port 80 and 443 (except when enabled for my debug testing).
Ghost seems to be making internal decisions based on its “url” parameter. So even if nginx is setup for https only, it assumes its insecure and portal/sign-up doesn’t function as described in the linked post above.
If I change the ghost url to include https, then nginx can’t redirect to the ghost instances as it fails SSL handshaking.
Given nginx already manages all of my letsencrypt certificates centrally and I will have other content served under the same domain it doesn’t make sense to let ghost manage the letsencrypt process on its own.
If it’s possible to point ghost at my existing certificates, that may help with the SSL handshaking issue, but that’s getting pretty deep into the weeds of the cert management process.
Editted:
Here is a clean copy of the nginx.conf file.
upstream siteone {
server ghost1:8030;
}
upstream sitetwo {
server ghost2:8031;
}
upstream sitethree {
server ghost3:8032;
}
server {
listen 80;
listen [::]:80;
server_name siteone.com sitetwo.com sitethree.com;
location / {
return 301 https://$host$request_uri;
}
location ~ /.well-known/acme-challenge {
allow all;
root /tmp/acme_challenge;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl http2;
server_name sitethree.com;
ssl_certificate /etc/letsencrypt/live/sharedkey/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sharedkey/privkey.pem;
location / {
proxy_pass http://sitethree;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl http2;
server_name sitetwo.com;
ssl_certificate /etc/letsencrypt/live/sharedkey/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sharedkey/privkey.pem;
location / {
proxy_pass http://sitetwo;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl http2;
server_name siteone.com;
ssl_certificate /etc/letsencrypt/live/sharedkey/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sharedkey/privkey.pem;
location / {
proxy_pass http://siteone;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
}
Here is a clean copy of the docker-compose.yaml being used to host the service.
version: "3.3"
services:
nginx:
container_name: 'nginx-service'
build:
context: .
dockerfile: docker/nginx.Dockerfile
ports:
- 80:80
- 443:443
volumes:
- ./config:/etc/nginx/conf.d
- /etc/letsencrypt:/etc/letsencrypt:ro
- /tmp/acme_challenge:/tmp/acme_challenge
networks:
- app
restart: always
ghost1:
container_name: 'ghost1'
image: ghost:alpine
restart: always
expose:
- "8030"
ports:
- 8030:8030
environment:
database__client: mysql
database__connection__host: <aws_address>.rds.amazonaws.com
database__connection__user: admin
database__connection__password: <mysql_password>
database__connection__database: ghostone
url: http://siteone.com
NODE_ENV: production
volumes:
- /home/ec2-user/ghost1/content:/var/lib/ghost/content
- /home/ec2-user/ghost1/config.production.json:/var/lib/ghost/config.production.json:z
networks:
- app
ghost2:
container_name: 'ghost2'
image: ghost:alpine
restart: always
expose:
- "8031"
ports:
- 8031:8031
environment:
database__client: mysql
database__connection__host: <aws_address>.rds.amazonaws.com
database__connection__user: admin
database__connection__password: <mysql_password>
database__connection__database: ghosttwo
url: http://sitetwo.com
NODE_ENV: production
volumes:
- /home/ec2-user/ghost2/content:/var/lib/ghost/content
- /home/ec2-user/ghost2/config.production.json:/var/lib/ghost/config.production.json:z
networks:
- app
ghost3:
container_name: 'ghost3'
image: ghost:alpine
restart: always
expose:
- "8032"
ports:
- 8032:8032
environment:
database__client: mysql
database__connection__host: <aws_address>.rds.amazonaws.com
database__connection__user: admin
database__connection__password: <mysql_password>
database__connection__database: ghostthree
url: http://sitethree.com
NODE_ENV: production
volumes:
- /home/ec2-user/ghost3/content:/var/lib/ghost/content
- /home/ec2-user/ghost3/config.production.json:/var/lib/ghost/config.production.json:z
networks:
- app
networks:
app:
driver: bridge