Ghost 6 on Ubuntu 24.04 on Azure User Guide
Overview
Ghost is the leading open-source headless CMS and publishing platform. Powering newsletters, magazines, and membership sites, Ghost combines a clean writing experience with native support for paid subscriptions, email delivery, and a fast Casper storefront theme. The cloudimg image installs Ghost 6.36 from the official ghost-cli alongside Node.js 22 LTS, MySQL 8, and nginx — all wired together by hand for predictable single-VM behaviour.
What is included:
- Ghost 6.36.x installed via the official
ghost-cliat/var/www/ghost, owned by theghostsystem user - Node.js 22 LTS from NodeSource (deb.nodesource.com node_22.x)
- MySQL 8 from Ubuntu noble main with a per-VM
ghost_userand rotated password - nginx from Ubuntu noble main reverse-proxying TCP 80 to Ghost on 127.0.0.1:2368
ghost_localhost.service(Type=simple, User=ghost) —node current/index.jsfrom/var/www/ghostghost-6-firstboot.service(one-shot) rotating MySQL root +ghost_userpasswords and recreating theghost_proddatabase on first boot- Storefront at
http://<vm-ip>/, Admin UI + setup wizard athttp://<vm-ip>/ghost/ - 24/7 cloudimg support
Prerequisites
Active Azure subscription, SSH key, VNet + subnet, and a Network Security Group that exposes TCP 22 to your management CIDR and TCP 80 to your readers (or to your CDN / Front Door / Application Gateway, with TLS terminated upstream). Standard_B2s (2 vCPU, 4 GB RAM) is comfortable for Ghost plus MySQL plus nginx as a single-tenant publication. For high-traffic membership sites, move to D4s/D8s and put MySQL on Azure Database for MySQL Flexible Server.
Step 1: Deploy from the cloudimg gallery
In the Azure Portal, create a new VM from cloudimgGallery/ghost-6-ubuntu-24-04, choose Standard_B2s, attach your SSH key, and place the VM in a subnet whose NSG allows inbound TCP 22 (SSH) and TCP 80 (HTTP). Wait for provisioning to finish and copy the public IP from the VM Overview blade.
Step 2: SSH to the VM
ssh azureuser@<vm-ip>
Step 3: Service status
sudo systemctl status ghost_localhost.service nginx.service mysql.service --no-pager | head -30

Step 4: Confirm Ghost is listening
ss -tln | grep -E ':(80|2368|3306) '
Port 80 is nginx (public), 2368 is the Ghost Node process bound to 127.0.0.1, and 3306 is MySQL (also 127.0.0.1).
Step 5: Storefront round-trip
curl -sI http://127.0.0.1/ | head -5
A 200 OK from nginx confirms the reverse proxy is forwarding to Ghost successfully. Browse to http://<vm-ip>/ from your laptop to see the default Casper theme welcome page.

Step 6: Claim the owner account
Browse to http://<vm-ip>/ghost/ in your browser. On a fresh VM, Ghost detects there is no owner yet and redirects you to the setup wizard at /ghost/#/setup. Fill in the site title, your name, your email address, and a strong password. Ghost owns this flow — the cloudimg firstboot does not pre-create an owner, so you are the only person with access to the admin.

Step 7: Admin dashboard
After completing the setup wizard, Ghost signs you in and lands you on the admin dashboard. The left-hand sidebar lists Posts, Pages, Tags, Members, and Settings — your editorial workspace.

Step 8: Database round-trip
sudo mysql -u root -p"$(sudo grep ^MYSQL_ROOT_PASSWORD= /stage/scripts/ghost-credentials.log | cut -d= -f2-)" -e "SHOW DATABASES;" 2>/dev/null | grep -E '(ghost_prod|mysql|information_schema)'
You should see ghost_prod in the list — that is the per-VM database that Ghost initialized via knex migrations on first boot.
Step 9: Read the per-VM credentials
sudo cat /stage/scripts/ghost-credentials.log
The file is mode 0600, root-owned. It contains MYSQL_ROOT_PASSWORD, GHOST_DB_PASSWORD, the database name and user, and the URLs you need for backups, scripted content imports, or migrating to managed MySQL later. Keep this file off-VM in your secrets manager.
Step 10: Components
| Component | Path |
|---|---|
| Ghost install | /var/www/ghost/ |
| Ghost CLI | /usr/bin/ghost (npm global) |
| Node.js 22 LTS | /usr/bin/node |
| systemd unit | /etc/systemd/system/ghost_localhost.service |
| Production config | /var/www/ghost/config.production.json |
| MySQL data | /var/lib/mysql/ |
| nginx site | /etc/nginx/sites-enabled/ghost-cloudimg.conf |
| Firstboot script | /usr/local/sbin/ghost-6-firstboot.sh |
| Firstboot sentinel | /var/lib/cloudimg/ghost-6-firstboot.done |
| Credentials | /stage/scripts/ghost-credentials.log (mode 0600 root:root) |
Step 11: Authoring your first post
In the admin UI, click Posts in the sidebar, then New post. Ghost's editor is markdown-aware with rich blocks for images, embeds, bookmarks, and email-only call-to-actions. When you publish, Ghost regenerates the storefront and your post is live at http://<vm-ip>/<slug>/. Use Pages for evergreen content (About, Contact) and Tags to organise the storefront's category navigation.
Step 12: Production hardening
- Front the VM with TLS: terminate HTTPS at Azure Application Gateway or Front Door, or run
certbot --nginxon the VM after pointing your apex DNS at the public IP. Then updateurlin/var/www/ghost/config.production.jsontohttps://your-domainandsudo systemctl restart ghost_localhost. - Move MySQL off the VM: provision Azure Database for MySQL Flexible Server, restore the
ghost_prodschema, and update thedatabase.connectionblock inconfig.production.jsonto point at the managed endpoint. Keep the VM-local MySQL stopped after the migration. - Email delivery: set the
mailsection inconfig.production.jsonto your SMTP provider (Mailgun, SendGrid, Amazon SES) so member sign-ups and post broadcasts deliver reliably. - Backups: schedule
mysqldump ghost_prodand a tarball of/var/www/ghost/contentto Azure Blob Storage or AWS S3. Thecontent/directory holds uploaded images, themes, and member exports. - Restrict the NSG: lock TCP 22 down to your management CIDR and front TCP 80/443 with your CDN's IP range only.
- Patch monthly:
sudo apt-get update && sudo apt-get -y upgrade && sudo reboot. Subscribe to https://ghost.org/changelog/ for Ghost releases — upgrade withsudo -u ghost ghost updatefrom/var/www/ghost.
Licensing
Ghost is MIT licensed — free to use commercially. cloudimg provides commercial support separately. support@cloudimg.co.uk.