In an Ubuntu 24.04 LTS LXC container running on my ProxMox server I successfully installed Ghost and it was running fine locally under http://192.168.0.101:2368.
Eventually, I want my blog to be reachable from the internet via https, of course.
- I created a subdomain for one of my domains: blog.wops.de
- I edited the CNAME DNS record to point that subdomain to my fixed dynamic DNS name, let’s call it abcde.myfritz.net – and I didn’t forget the trailing dot in this CNAME configuration.
- In my Fritz!Box router I opened port 443 and routed it to the Ghost container’s local IP 192.168.0.101
- nginx is running in that container, too, and is configured for https and to pass-through the requests to 127.0.0.1:2368
- I created a Letsencrypt certificate for blog.wops.de which is referenced in nginx’s config, too.
- I configured Ghost’s address to be https://blog.wops.de
- When I now navigate in a browser to this URL I get this (German) message from my router.
This translates roughly to:
The DNS-Rebind protection of your FRITZ! Box has rejected your request for security reasons.
The host header of your request does not match the name of the FRITZ! Box matches.
If you access the FRITZ! Box, please add this as an exception in the user interface of your FRITZ! Box under “Home Network > Network > Network Settings” in the “DNS Rebind Protection” section.
- If I do this and navigate to my blog URL again I’m presented with my router’s login page!?!?!
- In my router’s configuration I already switched OFF that my router’s interface should be available from the internet via https.
Here’s my nginx conf file for the blog:
# HTTP-zu-HTTPS-Umleitung
server {
listen 80;
server_name blog.wops.de;
# Leitet alle HTTP-Anfragen zu HTTPS weiter
return 301 https://$host$request_uri;
}
# HTTPS-Serverblock
server {
listen 443 ssl http2;
server_name blog.wops.de;
# SSL-Zertifikate von Let's Encrypt
ssl_certificate /etc/letsencrypt/live/blog.wops.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/blog.wops.de/privkey.pem;
# Zusaetzliche SSL-Sicherheitsoptionen
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_stapling on;
ssl_stapling_verify on;
# HSTS (HTTP Strict Transport Security)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# Proxy-Einstellungen fuer Ghost
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:2368; # Ghost laeuft standardmaessig auf Port 2368
client_max_body_size 50m; # Erlaubt groessere Uploads
}
}
Here’s the ghost doctor
output:
stefan@ghost:/var/www/ghost$ ghost doctor
Love open source? We’re hiring JavaScript Engineers to work on Ghost full-time.
https://careers.ghost.org
✔ Checking system Node.js version - found v18.19.1
✔ Checking logged in user
✔ Ensuring user is not logged in as ghost user
✔ Checking if logged in user is directory owner
✔ Checking current folder permissions
System checks failed with message: 'Linux version is not Ubuntu 16, 18, 20, or 22'
Some features of Ghost-CLI may not work without additional configuration.
For local installs we recommend using `ghost install local` instead.
? Continue anyway? Yes
System stack check skipped
ℹ Checking system compatibility [skipped]
✔ Checking for a MySQL installation
+ sudo systemctl is-active ghost_192-168-0-101
? Sudo Password [hidden]
Instance is currently running
ℹ Validating config [skipped]
✔ Checking folder permissions
✔ Checking file permissions
✔ Checking content folder ownership
✔ Checking memory availability
✔ Checking binary dependencies
✔ Checking free space
✔ Checking systemd unit file
✔ Checking systemd node version - found v18.19.1
stefan@ghost:/var/www/ghost$
Here’s the ghost ls
output:
stefan@ghost:/var/www/ghost$ ghost ls
Love open source? We’re hiring JavaScript Engineers to work on Ghost full-time.
https://careers.ghost.org
+ sudo systemctl is-active ghost_192-168-0-101
┌───────────────┬────────────────┬─────────┬──────────────────────┬──────────────────────┬──────┬─────────────────┐
│ Name │ Location │ Version │ Status │ URL │ Port │ Process Manager │
├───────────────┼────────────────┼─────────┼──────────────────────┼──────────────────────┼──────┼─────────────────┤
│ 192-168-0-101 │ /var/www/ghost │ 5.105.0 │ running (production) │ https://blog.wops.de │ 2368 │ systemd │
└───────────────┴────────────────┴─────────┴──────────────────────┴──────────────────────┴──────┴─────────────────┘
stefan@ghost:/var/www/ghost$
Here’s the config.production.json
file (DB password redacted):
stefan@ghost:/var/www/ghost$ cat config.production.json
{
"url": "https://blog.wops.de",
"server": {
"port": 2368,
"host": "127.0.0.1"
},
"database": {
"client": "mysql",
"connection": {
"host": "127.0.0.1",
"user": "ghost_user",
"password": "<redacted>",
"database": "ghost_db"
}
},
"mail": {
"transport": "Direct"
},
"logging": {
"transports": [
"file",
"stdout"
]
},
"process": "systemd",
"paths": {
"contentPath": "/var/www/ghost/content"
}
}
And here’s a screenshot of my router’s configuration for port 443 (IPv4 only):
The problem is also that I now can’t log into my Ghost blog anymore to make changes, write posts etc. because it’s no longer available under it’s initial, local, http-only address http://192.168.0.101:2368 – because it’s address is configured to be https://blog.wops.de, which doesn’t work.
Of course, I want to write further blog posts locally and don’t want to be dependent on a working internet connection for my locally hosted Ghost blog!
How can I configure Ghost so that it is fully accessible locally, too?
Any help much appreciated!