For the last decade, the default answer to "where should I host this static site" has been "push it to Netlify, or Vercel, or Cloudflare Pages, and forget about it." That answer is good. It is also expensive in ways that do not show up on the invoice, and in 2026 there is a different answer that is cheaper, faster, more controllable, and not much harder to set up. The setup is one $4 VPS, one Caddy config file, one Cloudflare account, and a weekend of your time. This is what that actually looks like in production, what it costs in real money, and where it stops being worth it.
Fig. 01 — The full stack of a self-hosted static site: git push, build, deploy, serve, cache.
The Cost You Are Not Counting
Netlify's pricing page says "free for personal projects." That is true in the same way that a hotel minibar is "free" — it is free until you use it, and then it is not. A static site with 50,000 monthly visitors, an AdSense integration, a custom domain, and a contact form, on Netlify, costs somewhere between $0 and $19 per month depending on which limits you hit. The bandwidth and build minute limits are generous, but the Functions limit is 125,000 requests per month, the form submission limit is 100 per month on the free tier, and the moment you add a server-side function for anything beyond a contact form, you are paying $19/month and watching the Functions bill creep up.
Vercel is similar, with a more aggressive pricing curve. Cloudflare Pages is the most generous of the three, and if you are doing pure static hosting with no server-side anything, it is genuinely hard to beat. The moment you need a server-side function, you are on Cloudflare Workers, which is its own pricing story.
The cost that does not show up is the vendor lock-in. The build configuration is a netlify.toml or vercel.json that is mostly portable but not entirely. The redirect rules, the header rules, the function definitions, the edge logic, the image optimization — all of these are platform-specific. A site that has been on Netlify for two years has, in its build configuration, a meaningful fraction of the work of rewriting it. Moving off is not impossible, but it is not the one-line push you imagine when you sign up.
The $4 VPS, by contrast, has none of these costs. You pay $4 per month, you run anything you want, and you leave when you want. The trade-off is that you are the ops team.
The Stack
A self-hosted static site in 2026 has four layers, and you can pick each layer independently.
The server. A $4 VPS from a provider like Hetzner, BuyVM, Racknerd, or Vultr gets you 1 vCPU, 1-2 GB of RAM, 20-25 GB of NVMe storage, and 1-2 TB of monthly bandwidth. The location matters less than you think. Pick the one closest to your users, or pick the one closest to your Cloudflare edge. The server is going to do almost no work for a static site. The bottleneck will be the network, not the CPU.
The web server. Caddy is the right choice in 2026. It has automatic HTTPS via Let's Encrypt or ZeroSSL, with no configuration beyond pointing a domain at it. The Caddyfile is five lines:
coderblog.in {
root * /var/www/coderblog
encode zstd gzip
file_server
}
That is the entire web server config. HTTPS is automatic. HTTP/3 is automatic. Compression is automatic. Caddy will request a certificate from Let's Encrypt, renew it before it expires, and serve it. You do not need Certbot, you do not need a renewal cron, you do not need to think about certificates again.
The CDN. Cloudflare's free tier in front of your VPS gives you a global anycast network, a free SSL certificate on the edge, basic DDoS protection, and a cache that will serve 95% of your traffic without ever touching your VPS. Set up Cloudflare, point your nameservers at Cloudflare's nameservers, enable the proxy (the orange cloud in the dashboard), and add a DNS A record pointing at your VPS. Cloudflare will cache your static files at edge nodes around the world.
The deploy pipeline. GitHub Actions, a build step, and an rsync to your VPS. That is the entire pipeline. There is no platform-specific deploy config. The pipeline is in your repo. The deploy target is your server. The whole thing is auditable in five minutes.
The Actual Setup
The full setup, from a clean VPS to a deployed site with HTTPS, takes about an hour the first time and about ten minutes the second time. The steps.
Step 1: Provision the VPS. Spin up a $4 VPS with Ubuntu 24.04 LTS. SSH in. Add a non-root user, give it sudo, disable root SSH login, set up UFW to allow only SSH, HTTP, and HTTPS. Update the system. This is standard hardening and is not specific to static sites.
Step 2: Install Caddy. Caddy has an official apt repository. Add it, install Caddy, open ports 80 and 443 in UFW, enable the Caddy systemd service. Caddy will now serve a placeholder page on port 80. There is no configuration to do for HTTPS yet — that comes in step 4.
Step 3: Point your domain. Add an A record for your apex domain (coderblog.in) and a wildcard A record (*.coderblog.in) at your registrar, pointing at your VPS IP. If you are using Cloudflare, do this in Cloudflare's DNS, with the proxy enabled (orange cloud).
Step 4: Configure Caddy. Write the Caddyfile above, replacing the domain with yours and the root path with where you will put the build output. Run caddy validate to check the syntax, then caddy reload to apply. Caddy will request a Let's Encrypt certificate for your domain, configure HTTPS, and start serving. The whole HTTPS setup is about 30 seconds.
Step 5: Build the site. Whatever your build tool — Statiq, Hugo, Astro, Jekyll, Eleventy, plain HTML — run it locally. The output goes in a dist/ or public/ or output/ directory.
Step 6: Deploy. From your CI pipeline, rsync the build output to /var/www/coderblog/ on the VPS. That is it. The site is live.
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: dotnet run
- name: Sync to server
uses: burnett01/rsync-deployments@6.0.0
with:
switches: --delete
remote_path: /var/www/coderblog/
remote_host: ${{ secrets.VPS_HOST }}
remote_user: deploy
remote_key: ${{ secrets.VPS_SSH_KEY }}
The whole pipeline runs in under a minute for a static site, deploys the new build, and removes the old files. Caddy serves the new files. Cloudflare cache invalidates automatically for HTML, and for everything else the cache expires on its TTL.
Fig. 02 — The real cost of a static site in 2026: self-hosted vs the managed platforms. Same site, same traffic, same operator hours.
The Real Numbers
A static site with 100,000 monthly page views and 1 GB of monthly bandwidth, served from a $4 VPS with Cloudflare in front, costs:
- $4 per month for the VPS
- $0 for Cloudflare (free tier)
- $0 for the domain (assume you already own it)
- 30 minutes of operator time per month for the occasional deploy
- Total: $4 per month
The same site on Netlify costs $0 to $19 per month depending on which limits you cross. The same site on Vercel costs $0 to $20 per month. The same site on Cloudflare Pages costs $0 to $5 per month (because Cloudflare's Workers free tier is more generous). The $4 VPS is cheaper than all three of these in absolute dollars, even before you count the lock-in.
The numbers get more dramatic at scale. A static site with 1 million monthly page views and 10 GB of monthly bandwidth, on a $4 VPS with Cloudflare, still costs $4 per month, because Cloudflare's free tier covers all of that bandwidth and most of the requests never touch the VPS. The same site on Netlify is $19 per month for the Pro tier, with overage charges if you exceed the build minute or function request limits. The same site on Vercel is $20 per month for the Pro tier, with similar overage charges. Self-hosting is not just cheaper. It is the same price at 1,000 views per month and at 10,000,000 views per month, because the bottleneck is Cloudflare, not the VPS.
What You Give Up
The list is short and worth taking seriously.
No instant global preview deploys. Netlify and Vercel have a deploy preview for every pull request, on a unique URL, deployed in seconds. With self-hosting, you either set up your own preview pipeline (doable, takes an afternoon) or you do not have previews. For a solo project this is a non-issue. For a team of 20 it is a real cost.
No platform-specific edge functions. Netlify Edge Functions, Vercel Edge Functions, and Cloudflare Workers are all platform-specific. A server-side function that runs at the edge on Netlify does not run anywhere else. If you write your site using Netlify's edge functions, you are locked in. If you write your site as a plain static site with no server-side code, you can host it anywhere.
No built-in form handling. Netlify Forms and Cloudflare Forms are real products that handle the back end of a contact form. With self-hosting, you either accept form submissions over SMTP, or you run a small backend (a Caddy plugin, a Cloudflare Worker, a tiny serverless function on AWS Lambda) to handle them. The "small backend" part is where the "not much harder" promise breaks down. A static site with forms is not a static site.
No built-in analytics. Netlify Analytics, Vercel Analytics, and Cloudflare Web Analytics are real products. With self-hosting, you add Plausible or Umami or GoatCounter, or you wire up Google Analytics, or you write your own. Each of these is a 30-minute setup. None of them are zero-setup.
The first 5 minutes after a VPS reboot are on you. Cloudflare Pages is always on. A $4 VPS is sometimes off (when you reboot it, when the provider has an incident, when your SSH session times out and you do not notice). For a personal blog this is a non-issue. For a business-critical site it is a real one.
When NOT to Self-Host
The list is also short, and the answer is more often "yes, self-host" than the marketing would have you believe.
- You have non-trivial server-side code. If your site has authentication, a database, a search backend, or any kind of API, you are not hosting a static site. You are hosting a server. Use a platform designed for that, or use a self-managed Kubernetes cluster, but do not pretend a $4 VPS is the right answer for a dynamic site.
- You have a team of more than five engineers. The "30 minutes of operator time per month" stops being 30 minutes when you have five people each doing 30 minutes. The platform-as-a-service calculus changes when the team grows.
- You are not the operator. If you are building a site for someone else and you will not be the one to maintain it, the $15 per month of managed hosting is worth the support ticket you will not have to answer.
- You do not have time to learn Caddy, Cloudflare, and rsync. The setup is not hard, but it is not zero. If you have never configured a web server before, Netlify is the right answer until you have. The learning is worth it in the long run, but not on a deadline.
For a solo developer, a small team, a personal blog, a side project, a documentation site, a portfolio, a marketing site, a prototype that turned into a real product — self-hosting in 2026 is the right default. The $4 VPS is not a compromise. It is the same architecture the platforms use, minus the platform.
The Shape of What Comes Next
The interesting question in 2026 is not "should I self-host" but "what should the self-hosted stack look like in five years." The answer is probably: the same as today, plus a global edge cache that is yours. Cloudflare is currently the obvious choice. Fastly is a better choice for engineers who care about VCL. Bunny CDN is a better choice for engineers who care about price. AWS CloudFront is a better choice for engineers who already have an AWS account. The platform-as-a-service layer is commoditizing, and the self-hosted stack is the underlying infrastructure. The split is happening in every other part of the stack. Web servers are commoditizing against the same backdrop.
A small toolkit to get started, if you have not already: provision a $4 VPS, install Caddy, point a domain at it, set up Cloudflare, write a GitHub Action that does rsync, and push. The first deploy takes an hour. The tenth deploy takes ten minutes. The hundredth deploy is muscle memory. The site is yours, the bill is predictable, and the lock-in is zero. That is the renaissance.
Comments
Discuss the article below. Markdown is supported. Sign in with email or GitHub to leave a comment.