Thought I’d just chime in here to give the direct route, with an explanation - while third-ing the automagical route.
If you’re on a minimal server (i.e. an E2-Micro on GCP) you’re going to have a hard time doing anything. Ideally, shutdown your Ghost instance, and MySQL, so that you have some guts driving your actions. Whichever direction you choose to take.
Note
In both routes below, replace instances of domain.ext with your domain and domain extension. So if your domain was excuse.me, you’d replace domain.ext with excuse.me
Automagical Route
The above answers cleverly show you how to use the Ghost CLI (as the official guide directs) to (while adding in instruction to properly point the www host first):
-
Add an A record to your domain’s dns entries for your www host:
www A 3600 <ipaddresstoserver>
Then, after traversing to your Ghost instance directory (via cd /var/www/<your_ghost_instance>
):
-
Configure Ghost temporarily for your www domain so that the Ghost CLI can work its magic:
ghost config url https://www.domain.ext
-
Set up ssl automatically with nginx for the www domain:
ghost setup nginx ssl
-
Configure your Ghost instance back to the original domain:
ghost config url https://domain.ext
-
Manually edit the nginx configuration for your www domain so that it permanently redirects to the non-www variant:
- Replace the 5 lines in the
location / {}
block with:
return 301 https://domain.ext$request_uri;
-
Test nginx to ensure you did everything correctly:
sudo nginx -t
-
Reload nginx if the test passed:
sudo systemctl restart nginx
NOTE: Review the steps if it fails
-
If needed (shouldn’t) restart your Ghost instance:
ghost restart
That should do it!
Direct (Manual) Route
The direct method to do this is as follows:
-
Configure the A records for the non-www, www, and remote server host name for your Ghost instance server via your domain’s dns entries:
-
The naked (non-www) domain:
<blank> A 3600 <ip_address_to_remote_host>
-
The www host:
www A 3600 <ip_address_to_remote_host>
-
The remote server host (here for example purpose, its host):
host CNAME 3600 domain.ext.
Now on your server (that you can now ssh into via ssh host.domain.ext
), traverse to your Ghost instance (cd /var/www/<your_ghost_instance_directory
) and:
-
Configure a www-variant host for nginx:
sudo cp /etc/nginx/sites-available/domain.ext.conf /etc/nginx/sites-available/www.domain.ext.conf`
-
Configure a www-variant SSL host for nginx:
sudo cp /etc/nginx/sites-available/domain.ext-ssl.conf /etc/nginx/sites-available/www.domain.ext-ssl.conf
-
Link both configurations to sites-enabled (this let’s you edit the file in sites-available, and as long as it’s linked in sites-enabled, it’s live):
WWW (on port 80):
sudo ln -s /etc/nginx/sites-available/www.domain.ext.conf /etc/nginx/sites-enabled/www.domain.ext.conf
WWW SSL (on port 443):
sudo ln -s /etc/nginx/sites-available/www.domain.ext-ssl.conf /etc/nginx/sites-enabled/www.domain.ext-ssl.conf
Now we want to make some edits to the configurations so as to derive our www-variants from the non-www variants that already existed:
-
In /etc/nginx/sites-available/www.domain.ext.conf
-
In /etc/nginx/sites-available/www.domain.ext-ssl.conf
:
-
Update server_name to:
www.domain.ext
-
Update ssl_certificate so that all parts of the path with domain.ext
are updated to:
www.domain.ext
-
Update ssl_certificate_key so that all parts of the path and key filename are changed from domain.ext
to:
www.domain.ext
-
Replace the 5 lines in the location / {}
block with:
return 301 https://domain.ext$request_uri;
-
Test that nginx configuration syntax is correct:
sudo nginx -t
NOTE If the test fails, review all parts up to this point
-
Restart nginx in order to reload the configuration:
sudo systemctl restart nginx
NOTE Ensure that nginx restarted via sudo systemctl status nginx
before moving forward. If you have any issues, review the instructions up to this point.
-
Generate the SSH certificates for the www-variant domain:
-
First update the letsencrypt’s binary:
sudo /etc/letsencrypt/acme.sh --upgrade --home /etc/letsencrypt --force
-
Next request to issue the certificate:
sudo /etc/letsencrypt/acme.sh --issue --home /etc/letsencrypt --server letsencrypt --domain www.domain.ext --webroot /var/www/<your_ghost_instance>/system/nginx-root --reloadcmd "nginx -s reload" --accountemail <you>@<email>.<provider> --keylength 2048 --force
IMPORTANT!: Be sure to update the domain, the path to your ghost instance, and your account email* in the above command.
-
If you had shut everything down to give your E2 Micro some guts, then:
-
Start MySQL:
sudo systemctl start mysql
-
Start your Ghost instance:
ghost start
If you otherwise left everything running but need to restart Ghost (you shouldn’t need to in this case), then:
-
Restart your Ghost instance:
ghost restart
That should do it!
Conclusion
That’s how you can add an ssh certificate for every alternate domain and host you’d like to separately manage certificates for. I think it’s the ideal way to handle certificates in Ghost, even though you should be able to manage multiple hosts, or a wildcard, in a single domain (IIRC letsencrypt did not have any policy against that, but I could be outdated).
Renewal
With regards to renewal, there’s a straightforward automatic renewal configured by Ghost when you setup ssl on the primary domain, that will function for every certificate that is in the letsencrypt home (so any additional certificate you add, without having to do anything more than simply add the certificate).
To ensure you’re system is setup for that, run:
sudo crontab -l
You should see something akin to:
18 9 * * * "/etc/letsencrypt"/acme.sh --cron --home "/etc/letsencrypt" > /dev/null
If you don’t see the above as a result, you could attempt adding it manually:
crontab -e
Then use the example above to fill out the fields for your instance.
Manual Renewal
If the automatic renewal should ever fail (hey, it happens), there is no longer a way to manually renew it using the Ghost cli (from what I understand), but you could try using acme.sh
in a couple of ways:
-
Attempt to manually run the cron (perhaps it was a temporary issue):
sudo /etc/letsencrypt/acme.sh --cron --home /etc/letsencrypt --force
-
Attempt to leverage acme.sh
directly to renew a specific domain:
sudo /etc/letsencrypt/acme.sh --renew --home /etc/letsencrypt --domain domain.ext --force
Thanks
Albeit a bit selfishly, as this was the first result I found on the official forum for managing certificates, I’ve provided a thorough reply in hopes of covering future needs for myself - as well as for others.