harshgulhane.com

← Blog3 min read

How this site runs: one 16 MB Go binary on a small home server

Nine sub-sites, a dozen security tools and a threat-intel collector, served from a small home server behind a Cloudflare Tunnel, with no open ports at home.

#go#docker#cloudflare#self-hosting

This site is a set of small security tools: a link decoder, an OSINT explorer, a redirect tracer, a User-Agent analyzer, a report writer and a few more. All of it runs on a small server at home with an Intel Celeron J4125. That CPU is not fast, so the whole design is about doing as little work per request as possible.

One binary, nine sites

Everything except the website scanner is a single Go program, about 16 MB as a container image:

  • The pages are built into the binary. At startup it renders every page once and compresses it with Brotli and gzip, so a request is a map lookup and a write. On one CPU core that is roughly 60,000 pages a second, far more than this site will ever see.
  • The API is in the same program: the redirect tracer, the OSINT lookups and the User-Agent analyzer. Identical lookups that arrive at the same time share one upstream request, and results are cached for a day.
  • The container has nothing else in it: no shell and no package manager. It runs as a non-root user on a read-only filesystem with every Linux capability dropped.

Nothing open at home

The server opens an outbound connection to Cloudflare and keeps it open, and visitors arrive through that tunnel. My router has no port forwards, my home IP doesn't appear in DNS, and Cloudflare absorbs floods before they reach my connection.

Tools that fetch URLs are dangerous

A redirect tracer is a server that fetches any URL a stranger gives it. That is exactly what attackers want for SSRF: pointing your server at 192.168.1.1, at the cloud metadata address 169.254.169.254, or at the other containers. Checking the URL first is not enough, because DNS can answer differently a second later. So every outbound connection is checked when it connects, against the IP address it actually reached, and private, loopback, link-local and metadata ranges are refused.

Being a good neighbour

  • Every visitor IP gets a rate limit, and the heavy tools have tighter ones plus a cap on how many run at once. A flood from one address is answered with cheap 429s while everyone else is served normally.
  • API keys for the OSINT sources live only in the server's environment. They are never logged or returned, and provider errors are reduced to fixed messages so a URL carrying ?key= can't leak.
  • There are no cookies and no tracking scripts, and the logs don't record your IP address. The visitor totals on the homepage come from Cloudflare's own edge counts, as aggregates only.

More posts to come on the tools themselves and what I learn from running them.