Hey everyone,
I just wanted to share my tutorial to setup Ghost to be accessible on the clearnet, but also as onion service.
Goal:
- One blog to maintain
- One DigitalOcean instance
- HTTPS on clearnet
- HTTP to HTTPS redirect on clearnet page
- One tor onion service
- HTTP on onion service
Challenge:
Ghost always redirects port 80 to 443. This breaks the normal TOR service configuration, as we would use HTTP (the TOR network is per default encrypted).
If we use port 443 in our TOR config, it works but every visitor will be greeted with an ugly SSL cert warning. Which is to be expected, because we now serve the certificate with the name of the clearnet site, for example wwww.my-site.com, on an onion site, for example 248080dsfasf.onion.
Solution:
Setup one Ghost instance for the clearnet and setup a second instance for the onion service but which is linked to the content and database of the clearnet version. The onion service instance can be configured to serve HTTP, while the clearnet version works with HTTP to HTTPS forward (always use HTTPS on the clearnet!)
Steps:
Prepare:
- Install Ghost via DigitalOcean template
- Update installation:
sudo apt-get update && sudo apt-get upgrade -y && sudo apt-get dist-upgrade && sudo do-release-upgrade
Install TOR services:
- Link Tor Project | Set up Your Onion Service
- Verify your Ubuntu release (we need this for the apt sources list):
*lsb_release -c
- Install apt transport https
apt install apt-transport-https
- Create a new sources list for the TOR packages (my release is Ubuntu focal)
vi /etc/apt/sources.list.d/tor.list
and add
deb [arch=amd64] https://deb.torproject.org/torproject.org focal main
deb-src [arch=amd64] https://deb.torproject.org/torproject.org focal main
- add the keys for the TOR sources
curl https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gpg --import
gpg --export A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89 | apt-key add -
- Update and install keyring
apt update && apt install tor deb.torproject.org-keyring
- Install TOR services
apt install tor
Configure your TOR services:
- Edit torrc
vi /etc/tor/torrc
- Set your hidden service params. This will create a configuration in the HiddenServiceDir. You can name it whatever you want. The port will be used to redirect incoming traffic (from the TOR network) on port 80 to port 8080.
HiddenServiceDir /var/lib/tor/your-website-name-here/
HiddenServicePort 80 127.0.0.1:8080
Retrieve tor onion name:
- Restart tor services
sudo systemctl restart tor
- Get your onion address
cat /var/lib/tor/your-website-name-here/hostname
- Result will look like this:
nytimes3xbfgragh.onion
Duplicate nginx config:
- Copy site config
cp /etc/nginx/sites-available/your-ghost-site-ssl.conf cp /etc/nginx/sites-available/your-ghost-site-onion.conf
- Your new onion site config has to listen to the same port as configured in torrc above, we need to adapt the server_name, root and proxy_pass, for which we need a new local port number:
server {
# same as in torrc
listen 8080;
# your onion service name which we retrieved above:
server_name nytimes3xbfgragh.onion;
# the new root for the copy of our clearnet ghost installation.
root /var/www/ghost.onion/system/nginx-root;
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;
# new local port number for the second Ghost instance which serves the onion version
proxy_pass http://127.0.0.1:2369;
}
location ~ /.well-known {
allow all;
}
client_max_body_size 50m;
}
- Link it to sites enabled
cd /etc/nginx/sites-enabled
ln -s ../your-ghost-site-onion.conf
- Restart nginx
systemctl restart nginx
Duplicate the clearnet Ghost installation:
- As root
mkdir /var/www/ghost.onion
chown ghost-mgr /var/www/ghost.onion
chgrp ghost-mgr /var/www/ghost.onion
- As ghost-mgr, copy the content
sudo -i -u ghost-mgr
cp /var/www/ghost/* /var/www/ghost.onion/
- Run ghost setup
cd /var/www/ghost.onion
ghost setup
- Change the name to the HTTP(!) onion url (simply changing the config file didnt work for me, so I did it like this)
http://nytimes3xbfgragh.onion
Edit the config file for your onion service:
*Manually set the new port number for the onion service, to receive requests from nginx.
- Make sure the contentPath is still linked to the clearnet version of Ghost
- It should look like this:
vi /var/www/ghost.onion/config.production.json
{
"url": "http://nytimes3xbfgragh.onion",
"server": {
"port": 2369,
"host": "127.0.0.1"
},
"database": {
"client": "mysql",
"connection": {
"host": "localhost",
"user": "ghost",
"password": "password",
"database": "ghost_production"
}
},
"mail": {
"transport": "Direct"
},
"logging": {
"transports": [
"file",
"stdout"
]
},
"process": "systemd",
"paths": {
"contentPath": "/var/www/ghost/content"
}
}
Start ghost
- Start ghost via ghost start in the directory of /var/www/ghost.onion
- It also asked me to create a systemctl entry which I did.
Now you should have a clearnet address:
www.my-site.com
which redirects you from insecure http to secure https
And you have a tor onion service which is accessible via http:
http://nytimes3xbfgragh.onion
Tip:
You can also advertise your onion address to a browser like Brave.
Just add the following line to your nginx ssl config of your clearnet page:
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;
# add this new header
add_header onion-location http://nytimes3xbfgragh.onion;
}
I hope this helps!
Cheers,
Tom
EDIT:
Unfortunately this doesnt work. When I add a new entry on the clearnet page, it is not update on the onion instance.
However when I go to my publisher profile on the onion site, I can see the new entry. Clicking it produces a 404 error.
I have to manually restart the ghost instance, then it works.