Redirect www to non-www

Hey team, I’m new to Ghost - sorry for questions :slight_smile:

Seems, I just installed Ghost on https://onlinehikes.com

But, there is no redirect from e.g. https://www.onlinehikes.com/blog/how-to-enable-custom-thumbnails-in-youtube/ to non-www

I followed steps here Www to non-www on Digitalocean setup and here GoDaddy Community

But, still https://www.onlinehikes.com/blog/how-to-enable-custom-thumbnails-in-youtube/ doesn’t redirect…

Hi Andrii.

You need to make some changes in nginx to make this work. There are a few different ways.

The easiest (but not the cleanest) way I’ve found is to get into the command line:

ghost config url https://www.onlinehikes.com
ghost setup nginx ssl

This creates the necessary SSL certificates and Nginx files to handle redirecting properly.

Run ghost config url https://onlinehikes.com to reset the domain setting.

Then you need to edit the two new Nginx files that are created (you’ll see them printed in the console) starting with www.onlinehikes.com (one will have -ssl in the name and one won’t).

Within the server block add a new line (do the same in both files):

return 301 https://onlinehikes.com$request_uri;

This will direct all traffic to your www domain, to your non-www domain.

Like I said, this may not be the cleanest way to do this but it’s the easiest I’ve discovered. Alternatively you could edit the existing Nginx files and create the SSL certificates from the command line. If anyone has any feedback on this, I’d love to hear it.

4 Likes

What worked for me was:

  1. Configuring only the A records following this DigitalOcean tutorial
  2. For nginx I followed the Ghost docs (similar to what dan wrote). I pasted the redirect differently according to the docs instead.
  3. Reload nginx by running systemctl reload nginx and authenticating as the ghost user.
  4. To check that it worked, use curl -I https://www.yoursite.com and you should get a 301 Moved Permanently response.

Step 2 in detail

The nginx configuration files can be found in /etc/nginx/sites-available.

I pasted the return 301 https://yoursite.com$request_uri; line into the location block, like the documentation suggested.

So this:

    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;
    }

Becomes:

    location / {
        return 301 https://yoursite.com$request_uri;
    }

I went ahead to configure the http files to redirect to https as well.

4 Likes

Registered just to say this: Thank you Dan. This helped me very much!

PS: I used the version in sites-available and not the sites-enabled folder. That worked for me.

2 Likes

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):

  1. 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>):

  1. Configure Ghost temporarily for your www domain so that the Ghost CLI can work its magic:

    ghost config url https://www.domain.ext
    
  2. Set up ssl automatically with nginx for the www domain:

    ghost setup nginx ssl
    
  3. Configure your Ghost instance back to the original domain:

    ghost config url https://domain.ext
    
  4. 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;

  5. Test nginx to ensure you did everything correctly:

    sudo nginx -t
    
  6. Reload nginx if the test passed:

    sudo systemctl restart nginx
    

    NOTE: Review the steps if it fails

  7. 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:

  1. 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:

  1. Configure a www-variant host for nginx:

    sudo cp /etc/nginx/sites-available/domain.ext.conf /etc/nginx/sites-available/www.domain.ext.conf`
    
  2. 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
    
  3. 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:

  1. In /etc/nginx/sites-available/www.domain.ext.conf

    • Update server_name to:

      www.domain.ext

    • Replace the 5 lines in the location / {} block with:

      return 301 https://domain.ext$request_uri;

  2. 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;

  3. Test that nginx configuration syntax is correct:

    sudo nginx -t
    

    NOTE If the test fails, review all parts up to this point

  4. 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.

  5. 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.

  6. If you had shut everything down to give your E2 Micro some guts, then:

    1. Start MySQL:

      sudo systemctl start mysql
      
    2. 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:

    1. 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:

  1. Attempt to manually run the cron (perhaps it was a temporary issue):

    sudo /etc/letsencrypt/acme.sh --cron --home /etc/letsencrypt --force
    
  2. 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.

1 Like