A very minimal http server with automatic tls certificate handling and privilege dropping

3b3606d update changelog

20 days ago

90125b7 improve README

20 days ago


treehouse is a very minimal HTTP server with automatic TLS certificate handling and privilege dropping. I personally use it to serve https://inimeg.space from an old Raspberry Pi.

#Privilege Dropping

treehouse needs to be started as root in order to bind to the privileged http and https ports 80 and 443. However, as soon as this is accomplished, it uses the setgid and setuid syscalls to (by default) become nobody. As a result, treehouse can only serve files that are world-readable (or belong to nobody).

It is possible to set gid and uid to other values besides the default 65534 (nobody).

#Automatic TLS Certificate Handling

treehouse uses autocert to automatically obtain certificates from Let's Encrypt.


A directory for treehouse to store its certificates needs to be provided with the mandatory secdir flag. If the specified path does not exist, it will be created (like mkdir -p). treehouse will also chown this directory to restrict access to the nobody user and group. It currently doesn't chmod an existing directory, a non-existing directory will however be created with 0700 permissions.

To make sure that treehouse can not accidentally serve its private TLS keys, it is an error to specify a secdir that is a subdirectory of docroot.

#Serving Domains

treehouse expects subdirectories in the docroot directory that are named according to the domain that is to be served. It will only attempt to obtain TLS certificates matching the directory names it saw on startup.

#Usage Example

I use treehouse like this:

Under ~/Public, I have a subdirectory called inimeg.space, containing some static html files. This directory gets detected when treehouse starts up.

sudo ~/bin/treehouse -secdir /etc/treehouse/secrets --docroot ~/Public
2023/03/02 Running as root, dropping privileges
2023/03/02 using /home/benthor/Public as docroot
2023/03/02 using /etc/treehouse/secret as secdir
2023/03/02 handling domain http(s)://inimeg.space
2023/03/02 serving HTTPS
2023/03/02 serving HTTP

Since treehouse also serves regular HTTP, you can also test your setup without necessarily invoking autocert. Just create a directory named under your docroot, add an index.html to it and start treehouse.

#Building treehouse

You need some version of Go (version 1.x) installed. Even versions that are several years out of date should still work fine. Just do

go build .

Note that Cgo is not required, To build a static binary that still works even after your libc is updated, simply do

CGO_ENABLED=0 go build .

#Cross Compiling

Here is how I cross compile treehouse into a binary that I can deploy on my old Raspberry Pi 2:

CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 go build -trimpath -ldflags "-X main.Version=$(git describe)" -v .


The goal is to eventually publish a version 1.0 that can be considered complete and stable. The following items need to be done (in no particular order):

  • [ ] nail down certificate storage, including proper permission handling
  • [ ] be less snarky in error responses
  • [ ] add switches to disable either http or https
  • [ ] improve sanity checking of provided arguments



  • add improved README
  • restructure code for earlier privilege dropping
  • fix directory traversal, check against docroot instead of working dir
  • remove reverse proxy support in the name of lean-ness


  • add support for versioning
  • fix autocert: listen on port 80 for ACME "http-01" challenge responses
  • redirect anything on port 80 to https and the first -domain FQDN


  • add very basic reverse proxy support
  • typo fix in documentation


  • improve logging


  • first release