Skip to main content

Introducing Go2Serve: a lightweight static file server

Fast, lightweight, MIT licensed. Go for it!
Fast, lightweight, MIT licensed. Go for it!

I'm releasing Go2Serve, a static file server written in Go. It's a single binary with simple configuration, no runtime dependencies, and secure defaults out of the box. You can learn how to use it in two minutes.

I built Go2Serve because I wanted something between the heavyweight options (Apache, NGINX) and the throwaway ones (Python's 'http.server'). Something I could drop onto a Pi or a VPS, point at a directory, and have it serving files over HTTPS in under a minute with near-zero configuration.

What it does

Go2Serve serves static files. That's it. No CGI, no reverse proxying, no dynamic content. What it does do, it tries to do well:

  • HTTPS with zero configuration: Pass '--domain example.com' and Go2Serve handles Let's Encrypt certificates automatically, including renewal. Manual certificates are also supported, with automatic reload every 60 seconds for zero-downtime rotation.
  • Security defaults: Path traversal protection (including via symlinks), `X-Content-Type-Options`, `X-Frame-Options`, `Referrer-Policy`, and optional HSTS and Content-Security-Policy headers. These are on by default, not buried in a config file you have to remember to write.
  • Per-IP rate limiting: Token bucket rate limiting is enabled out of the box, with proxy-aware client IP extraction when you're behind a load balancer.
  • Lightweight: No CGO, no runtime dependencies. The Docker image is built from `scratch` and contains nothing but the binary and CA certificates. Memory footprint is minimal.

Refer to the README.md for how to automatically install TLS certificates and other configuration options.

Getting started via Docker

Docker offers the fastest installation path:

1. Clone the repository onto your server:

git clone https://github.com/crushdepth/go2serve.git && cd go2serve

2. Edit docker-compose.yml to set your webroot directory:

volumes:
  - /path/to/files:/srv:ro  # <-- change /path/to/files to your intended webroot (the directory you want to serve from)

3. Build and install via docker:

make up

Getting started by building from source

Or build from source with Go 1.26+ and run directly:

1. Build the binary:

go build -o go2serve .

2. Start serving:

./go2serve --root /var/www/html

That's HTTP on port 8080. Add '--domain yourdomain.com' for automatic HTTPS.

Performance

I ran some informal benchmarks on a Raspberry Pi 5 (4-core ARM64 and SSD storage) to get a sense of the ceiling. With rate limiting disabled, Go2Serve sustains around 15,000 requests per second for small files, with p99 latency under 60ms even at 500 concurrent connections. Serving 14KB files barely dents throughput. These aren't numbers you'll ever need for a personal site or project documentation but the server won't fall over under a normal traffic spike. Obviously, on an actual x86 server with decent CPU and RAM it will handle a lot more.

Design principles

Go2Serve leans on the Go standard library wherever possible. The only external dependencies are golang.org/x/crypto and golang.org/x/net, both maintained by the Go team. The emphasis is on doing one thing simply and securely rather than being configurable for every scenario.

The project is on GitHub at github.com/crushdepth/go2serve. It's MIT licensed. Feedback and issues are welcome.

Copyright, all rights reserved.