thenug.net

building this site

this site runs entirely on hardware i own, in my house, on my network. no vps, no vercel, no s3. here's how it works.

the stack

Eleventy converts markdown files and nunjucks templates into plain static HTML at build time. no javascript ships to the browser. no database. no runtime rendering. just files.

Fastify serves those files. it's a lightweight node.js web framework — overkill for pure static, but it leaves room to add api routes later if needed.

Docker packages both into a container image. the Dockerfile is a two-stage build: one stage installs dependencies and runs the eleventy build, a second stage copies just the output and runs fastify. the final image is small.

Gitea is a self-hosted git server. the source for this site lives there. think github, but on my lan.

Gitea Actions handles CI/CD. it's compatible with GitHub Actions syntax. when i push to the main branch, a runner picks up the job, SSHes into the server, rebuilds the Docker image, and restarts the container. the whole deploy takes about 30 seconds.

Nginx Proxy Manager sits in front of everything and handles SSL termination via Let's Encrypt. Cloudflare proxies the domain.

architecture

browser
  └── Cloudflare (DNS + proxy)
        └── Nginx Proxy Manager (SSL termination)
              └── Fastify container (serves static HTML)
                    └── Eleventy-built _site/

git push
  └── Gitea (self-hosted git)
        └── Gitea Actions runner
              └── SSH to server
                    └── docker build + restart container

everything runs on a single server on my home network. the only thing external is Cloudflare in front of the domain.

the flow

writing a post works like this:

  1. create a markdown file in src/posts/
  2. add front matter (title, date, layout)
  3. git push
  4. done — the site rebuilds and deploys automatically

the post you're reading right now was written exactly that way.

why bother

cloud hosting is fine. but running things yourself is more interesting. you learn more, you control everything, and nothing disappears because a free tier got axed.

the whole setup cost nothing beyond hardware i already had.

page size

the initial HTML for this page is under 4KB. no web fonts, no external scripts, no tracking. the CSS is inlined in the <head> so there's one request for the first paint.

this keeps things fast on slow connections and keeps the site simple to reason about.

the code

source lives on a self-hosted Gitea instance — local only, not public. but the stack is straightforward enough to replicate with any self-hosted git setup.

eli5

the site is like a book that gets reprinted every time a new page is added. Eleventy is the printing press — it takes the writing (markdown) and produces finished pages (HTML) ahead of time. Fastify is the librarian who hands those pages to anyone who asks. Docker is the box everything lives in so it runs the same way anywhere. Gitea is a filing cabinet where all the source material is stored. when a new page gets added to the filing cabinet, a robot (Gitea Actions) notices, reprints the book, and puts the new edition on the shelf — all automatically. Cloudflare and Nginx Proxy Manager are the front desk staff who handle visitors before they ever reach the shelf.


← back to blog