Ghost CMS has a setting to make the entire website private to password protect. In my case, I only wanted some pages to be password protected. A simple-ish solution is to use basic authentication on the server side (e.g. auth_basic
on Nginx, htaccess
on Apache, web.config
on Windows IIS)

In my case I'm hosted on DigitalOcean, and the server is running Nginx. They have a detailed guide here:

Once you have auth_basic setup
Once you have the user and password setup, you'll want to change the location
setting so that it protects only certain files or folders. In my case, I created a Protected
collection, and password protected anything under the /protected
path (more on that later). Note that I'm combining the auth_basic
part of the tutorial with the existing configuration for my Ghost website configuration (look for your Ghost folder in /etc/nginx/sites-enabled/
for your-website-name-ssl.conf
).
Here's what I added:
location /protected {
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;
auth_basic "Restricted Content"
auth_basic_user_file /etc/nginx/.htpasswd;
}
Note that you need to copy the proxy part, because you want the server to respond with the Ghost URL mapping, as opposed to serving static files from a folder.
This is where I added a new collection to create a /protected "folder". To do that you need to edit your routes.yaml
file. Here's my example, but Ghost has some thorough explanations on this in their documentation.

Once that's done you need to go into Settings > Lab
and upload your new YAML file.

Since not all of my posts are password protected I also needed to tweak the filter in my theme to include posts with a protected
primary tag:

Now if you try to access any of the posts that have a primary tag set to protected
you get prompted with the server-side authentication.


Keep in mind that these authentication systems are very simple and if you are password protecting something particularly sensitive, you will want to look for a different solution.