Why Squarespace's July 2026 price increase changes the calculation
Squarespace moved from $23 to $29 per month on its Core plan in July 2026, billed as ~$348/year at renewal. This is not the first increase — the Business plan had already risen by 33% between 2022 and 2024 — and Squarespace pricing does not include paid newsletters without commission or root access to your server.
Ghost, by contrast, is software you install on your own infrastructure. You only pay for the VPS that runs it. No surcharge when you cross a traffic threshold, no commission on paid subscriptions, no dependency on a third party's pricing policy.
The break-even calculation is straightforward: if your VPS costs 99 DH/month and your domain depending on the extension, you are ahead within the first year compared to Squarespace Core at $348.
What self-hosted Ghost gives you that Squarespace does not
- Paid newsletters with zero commission — Stripe connects directly; Ghost takes no percentage of your subscriber revenue, unlike the 10% fee on Squarespace's Core plan.
- Root server access — you can modify the nginx configuration, set caching rules, install an analytics proxy or connect Ghost to your data pipeline.
- Open-source themes — hundreds of Ghost themes are available on GitHub without extra licences; customising them only requires knowledge of Handlebars.
- Full portable export — Ghost exports your content as structured JSON and your subscribers as CSV; you can import these files into any other Ghost instance without losing metadata.
- Predictable cost — the VPS price does not vary with your traffic or subscriber count; only a voluntary upgrade changes the bill.
- Updates on your schedule — you decide when to move to the next major version, avoiding forced migrations that have broken Squarespace themes in the past.
Total cost over 3 years: Squarespace Core vs Ghost on a ServOrbit VPS
Scroll the table
| Item | Squarespace Core | Ghost on ServOrbit VPS |
|---|---|---|
| Platform subscription (year 1) | ~$29/month ($348/year) | 99 DH/month × 12 |
| Platform subscription (year 2) | ~$29/month or more ($348/year) | 99 DH/month × 12 |
| Platform subscription (year 3) | ~$29/month or more ($348/year) | 99 DH/month × 12 |
| Domain (.com, per year) | Included in plan | depending on registrar |
| Paid newsletter commission | 10% of revenue | 0% — direct Stripe |
| SSH / root access | Not available | Included |
| Backups | Not included (paid add-on) | Weekly backups included |
| Assisted migrations | No | Included on request |
Prerequisites before you start
Ghost is built on Node.js and uses MySQL (or MariaDB) as its database. Recommended resources for a personal or professional blog with moderate traffic:
Server: 1 vCPU, 1 GB RAM minimum — Ghost runs comfortably on 512 MB at steady state, but theme build spikes and migrations need headroom. A VPS Start covers most use cases.
Storage: 10 GB is enough to start; plan for 20 GB if you publish images or audio files regularly for a podcast.
Software: Node.js 22 LTS or later, npm, MySQL 8 or MariaDB 10.6+, nginx as a reverse proxy, certbot for TLS certificates.
Domain name: a domain pointing to your VPS IP; SSL will be provisioned automatically by Ghost CLI via Let's Encrypt.
SSH access: an ED25519 or RSA key configured on the server — Ghost CLI refuses root installations, so you will need a dedicated system user.
Active Squarespace account until the migration date: article export is done from the administration panel.
Migrating from Squarespace to Ghost on a VPS: steps
Export your content from Squarespace
From your Squarespace dashboard, go to Settings → Advanced → Import / Export Content, then click Export. Squarespace produces an XML file in the WordPress Extended RSS (WXR) format. This format is recognised by Ghost conversion tools — Ghost does not read Squarespace XML natively, but
ghost-gscanand third-party converters handle WXR.Also export your subscribers: Marketing → Email Subscribers → Export, which produces a CSV file with addresses, subscription statuses and sign-up dates. Keep this CSV carefully — it is your list, and it cannot be recovered after the account is closed.
Prepare the VPS server
Connect via SSH to your VPS:
ssh [email protected]. Update packages, then install Node.js 22 via the NodeSource repository:curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -sudo apt-get install -y nodejsThen install MySQL and nginx:
sudo apt-get install -y mysql-server nginxSecure MySQL with
sudo mysql_secure_installation, then create the Ghost database and user:sudo mysql -u root -p -e "CREATE DATABASE ghostdb; CREATE USER 'ghostuser'@'localhost' IDENTIFIED BY 'strong_password'; GRANT ALL ON ghostdb.* TO 'ghostuser'@'localhost'; FLUSH PRIVILEGES;"Finally, create a non-root system user for Ghost:
sudo adduser ghost-runner.Install Ghost CLI and Ghost
Install Ghost CLI globally:
sudo npm install ghost-cli@latest -gCreate the installation directory and transfer ownership to your Ghost user:
sudo mkdir -p /var/www/ghostsudo chown ghost-runner:ghost-runner /var/www/ghostsudo chmod 775 /var/www/ghostSwitch to the Ghost user, then run the installation:
su - ghost-runnercd /var/www/ghost && ghost installGhost CLI will ask a series of questions: production URL (e.g.
https://your-domain.com), MySQL login details, and will offer to configure nginx and SSL automatically. Answer yes to both — Ghost CLI writes the nginx configuration and calls certbot to provision the Let's Encrypt certificate.Convert and import Squarespace content
The Squarespace XML file must be converted to Ghost JSON format before import. Use the
@tryghost/migratetool:npx @tryghost/migrate squarespace --pathToFile export-squarespace.xmlThe tool produces a
ghost-import.jsonfile. Check its structure: each post should have atitle, aslug, astatusand anhtmlfield. Images are referenced by Squarespace URL — they will be downloaded during import if you pass the--scrape mediaoption.Log into the Ghost administration interface (
https://your-domain.com/ghost), create your admin account, then go to Settings → Advanced → Migrations → Import content and upload the JSON file. Ghost processes the import in the background and notifies you by email when done.Import your email subscribers
In Ghost Admin, go to Members → Import members and upload your Squarespace CSV file. Ghost recognises the
email,nameandsubscribed_to_emailscolumns. Map the columns if the headers differ.Imported subscribers are marked as 'free members' by default. If some had a paid subscription on Squarespace, you will need to update them manually or via the Ghost Admin API (
PATCH /admin/members/{id}) once Stripe is configured.Then configure Stripe in Ghost Admin → Settings → Subscriptions to enable paid newsletters. Enter your Stripe API key and set your subscription prices.
Set up 301 redirects from old URLs
Squarespace generates URLs in the format
/blog/post-titleor/post-titledepending on the template. Ghost uses/{slug}/by default. If your URLs differ, create aredirects.yamlfile in the Ghost directory (/var/www/ghost/content/data/redirects.yaml):from: /blog/{slug}to: /{slug}permanent: trueRestart Ghost to apply the redirects:
ghost restart. Check each old URL withcurl -I https://your-domain.com/blog/first-post— the response should return a301pointing to the new URL.If your domain was previously hosted at Squarespace, update the DNS records (
AorCNAME) to point to your VPS IP. DNS propagation takes between a few minutes and 48 hours.Check the sitemap and submit to Google Search Console
Ghost automatically generates a sitemap at
https://your-domain.com/sitemap.xml. Open it in a browser and verify that all your posts appear with the correct URLs.In Google Search Console, add your domain as a property if not already done, then submit the sitemap via Indexing → Sitemaps. This speeds up re-indexing of your content on the new URLs.
If your domain had authority on Squarespace, the 301 redirects transfer the SEO signal to the new URLs — expect a few weeks for rankings to stabilise. Avoid changing post slugs at this point: each additional modification adds a step to the redirect chain.
Cancel Squarespace after validation
Do not cancel your Squarespace subscription until you have verified that the content is correctly imported into Ghost, that DNS points to your VPS and that the redirects work. Allow a minimum 48-hour overlap for DNS propagation to complete.
In Squarespace, go to Settings → Billing & account → Cancel site. Squarespace keeps the site live until the end of the billing period — during this window, a visitor with the old URL in cache will still see your old site, which is normal and expected.
Save one final copy of the Squarespace XML and subscriber CSV before confirming the cancellation.
Before pushing Ghost to production, harden the default nginx configuration that Ghost CLI generated. Add security headers in the server block: add_header X-Frame-Options SAMEORIGIN;, add_header X-Content-Type-Options nosniff; and add_header Referrer-Policy strict-origin-when-cross-origin;. Also enable nginx rate-limiting on /ghost/api/admin/ to slow down brute-force attempts on the admin interface. Test the configuration with nginx -t before reloading: nginx -s reload.
Troubleshooting: common errors during migration
Ghost is already running after an interrupted installation. If Ghost CLI installation was interrupted, it may leave an orphaned process. Stop it cleanly: ghost stop, then rerun ghost install. If ghost stop returns an error, identify the process with pm2 list and stop it manually: pm2 stop ghost.
Error: EACCES: permission denied during JSON import. The Ghost user does not have access to the content/data directory. Check permissions: ls -la /var/www/ghost/content/ — the data directory must belong to ghost-runner. Fix with sudo chown -R ghost-runner:ghost-runner /var/www/ghost/content/.
Squarespace images no longer display after migration. Image URLs in the imported JSON still point to images.squarespace.com. Ghost can download them automatically if you pass the --scrape media option during @tryghost/migrate conversion. Alternatively, from Ghost Admin → Settings → Advanced, run 'Re-download external images'.
SSL certificate is not renewed. Ghost CLI delegates renewal to certbot. Check that the systemd certbot timer is active: systemctl status certbot.timer. If it is inactive, restart it: sudo systemctl enable --now certbot.timer and test renewal: sudo certbot renew --dry-run.
301 redirects return a 302. Ghost interprets some redirects as temporary if the permanent value is missing or set to false in redirects.yaml. Check the file, correct the value and restart Ghost: ghost restart.
After migration: routine maintenance
A self-hosted Ghost instance requires minimal but regular maintenance. Ghost updates take one command: ghost update. Before any major update (for example, Ghost 5 → 6), check the official changelog for breaking changes with your theme.
Backups are weekly on ServOrbit entry-level plans — verify that they cover the /var/www/ghost/content directory and your MySQL database. You can supplement with an automated local MySQL dump: mysqldump -u ghostuser -p ghostdb > /var/backups/ghost-$(date +%F).sql.
Monitor disk usage: Ghost compresses images on import, but an active blog accumulates several gigabytes over time. Check usage from your ServOrbit client area or on the command line: df -h /var/www/ghost/content.
To go further on Ghost hosting and Caddy as an alternative to nginx, see our guides heberger-ghost and deployer-avec-caddy. To compare total cost of ownership between SaaS and self-hosted for other tools, read saas-vs-self-hosted-comparatif-cout-2026.