I've been running this blog on Linode for over a year. It costs me $5/month and I have full control over everything. Here is how I set it up.
Why Linode
I looked at DigitalOcean, AWS, Hetzner. Linode ( now Akamai ) gives you a $100 credit for the first 60 days if you use my referral link. That's 20 months free on the $5 plan.
The $5/month Nanode gives you 1GB RAM, 1 CPU, 25GB SSD, and 1TB transfer. That's enough for Ghost, nginx, and a couple more services.
Sign up and create a server
Sign up at linode.com. Create a new Linode, pick Ubuntu 24.04 LTS, pick the $5 Nanode plan, pick a datacenter close to your users. I use Newark ( US East ) because most of my traffic is from the US and Europe.
Set your root password, click Create. The server boots in about 30 seconds.
First SSH login
Copy the IP address from the Linode dashboard and SSH in:
ssh root@YOUR_LINODE_IPBasic hardening
First thing: update, create a user, set up SSH keys, disable root login. I wrote about SSH config before. The short version:
# Update everything
apt update && apt upgrade -y
# Create a user
adduser davide
usermod -aG sudo davide
# Copy your SSH key
mkdir -p /home/davide/.ssh
cp /root/.ssh/authorized_keys /home/davide/.ssh/
chown -R davide:davide /home/davide/.ssh
# Disable root login and password auth
sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart sshdInstall Docker
I run everything in Docker. Ghost, nginx, MySQL — all containers. Makes updates and backups painless.
# Install Docker
apt install -y docker.io docker-compose
systemctl enable docker
systemctl start dockerRun Ghost with docker-compose
Here is my docker-compose.yml ( simplified ):
version: '3'
services:
ghost:
image: ghost:6
restart: always
ports:
- "2368:2368"
environment:
url: https://www.yourdomain.com
database__client: mysql
database__connection__host: db
database__connection__user: ghost
database__connection__password: YOUR_PASSWORD
database__connection__database: ghost
volumes:
- ./ghost:/var/lib/ghost/content
depends_on:
- db
db:
image: mysql:8
restart: always
environment:
MYSQL_ROOT_PASSWORD: YOUR_ROOT_PASSWORD
MYSQL_DATABASE: ghost
volumes:
- ./db:/var/lib/mysql
nginx:
image: nginx:latest
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/logs:/var/log/nginx
depends_on:
- ghostNginx reverse proxy with SSL
Point your domain's DNS to the Linode IP, then set up nginx as a reverse proxy with Let's Encrypt. I have a whole post about SSL too.
# Install certbot
apt install -y certbot python3-certbot-nginx
# Get SSL certificate
certbot --nginx -d yourdomain.com -d www.yourdomain.com
# Certbot auto-renews. Done.What it costs
Total monthly cost:
- Linode Nanode: $5/month
- Domain ( Namecheap ): ~$10/year
- That's it. Under $6/month for a blog that handles thousands of visitors.
If you want to try it, Linode gives you $100 in credit for the first 60 days. More than enough time to decide if it works for you.