Why

Started out as an entirely level-headed answer to the above question. In order to avoid figuring out customized solutions like Tailscale has needed to do for reading/writing state into K8s ConfigMaps, it seemed that it would be far more reusable to just present a fake (some might even say networked) filesystem. In my mind, these files had the following properties:

  • Small (< 1MB)
  • Seldom updated, compared with a database
  • Typically a single writer, certainly a single writer at a time (i.e. mastership)
  • Writers don’t care to receive acknowledgements from readers
  • Many readers

What

ConfigFS consists of a server-side gRPC interface for manipulating and accessing files and directory trees and a client side FUSE service that exposes those files as a filesystem.

It turns out that with the advent of Go FUSE it has become quite trivial to build a filesystem using Go. While it may not be the most performant, it nicely fits this use case of seldom changing files. Further, by writing a filesystem it would mean that as long as whichever tool I wanted to use could read/write from a filesystem, I could use it as part of my configuration pipeline. This allowed me to remove my homebrewed Lets Encrypt certificate bot that spoke over Tailscale in favor of lego.

Then by writing it in Go, I could of course embed Tailscale via tsnet which removes the need for kernel level Tailscale or userspace juggling. It just so happens however that I’m typically using ConfigFS in situations where Tailscale is deployed already so from an identity standpoint the FUSE process can ride either it’s own connectivity/identity or that of the host.

Architecture / Use Cases

Traefik edge
Go · FUSE · reads
ConfigFS filesystem

Mounted on every edge node. Traefik reads its routes and TLS material as ordinary files and picks up changes as they land.

tsnet · built in
legocert
Go · FUSE · writes
ConfigFS filesystem

The same mount, the other direction: renews TLS certificates through ACME and writes them back, so the edge finds fresh ones as plain files.

tsnet · built in
Server
tailscaled or tsnet · colocated
Go · server
ConfigFS server

Answers each filesystem call, authorised by the Tailscale identity behind it.

SQLite
One database file

Every path and every value, in a single file that is easy to back up and easy to reason about.

DF
Dave Finster
Platform engineering, storage, and the occasional musing.
More writing