BEC OS

How I run the business

A business is a product, and it deserves the same foundation you would give a product: a few pieces I built, many more I borrowed, and a substrate underneath that lets any of them be replaced.

The substrate

Common features

Everything below sits on these. They are the reason the stack has stayed small and the reason I can swap any part of it without a migration project.

Plain text, in Git

Time logs, accounting, invoices, documents, hardware designs, and this website are all plain files under version control. One backup story, one audit trail, one search. It also means every tool above the substrate reads and writes files, so none of them is a place my data can get stuck.

Borrowed processes, not just borrowed code

hledger, Gitea, Discourse, and Zola each come with maintainers, review, CI, and a security response I do not have to staff. Choosing them is choosing their process. That is the whole reason to prefer a healthy project over something I could write in a weekend.

Self hosting where it makes sense

The business runs on a couple of modest Linux servers, deployed with Ansible from a Git repository. I can read the entire configuration, and rebuild all of it from scratch in an afternoon if a provider disappears. Self-hosting also provides unlimitted accounts, so there is no cost to adding another user.

Money and time

Business workflow

Based in Git and easy to automate tools, scripts, and Claude.

borrowed · timedot

hledger

Plain-text, double-entry accounting. The books are a file I can diff, grep, and commit, and every report is a command I can rerun. Time is logged in hledger's timedot format as the day goes, in the same editor I write code in.

built · go

kairos

Frictionless time tracking for a team, and beautiful invoices out the other end. It turns timedot files into finished HTML: rates are per user and per account, the templates are mine, and the output is committed alongside the time log it came from. Every invoice I have sent is reproducible from the repository.

borrowed · documents

Typst

What I use in place of Word or LibreOffice. Proposals, contracts, and statements of work are Markdown content plus a Typst template holding the layout and typography, so every document that goes to a client comes out looking the same and rebuilds from one command. They live in Git with everything else, which means a contract has a history.

The workshop

Hosting work

Source, issues, CI, deploys, and the servers underneath.

borrowed · git hosting

Gitea

Self-hosted Git, issues, and CI on one modest server. It is also where I collaborate with customers: an account on my Gitea puts them next to the repository, the issues, and the builds, so a project runs visibly to everyone working on it rather than through status emails. The repositories stay private to the team.

built · ansible

Ansible roles

Every service on this page is installed and updated by a role in a Git repository. Gitea, Caddy, Grafana, and the rest are published, because the infrastructure a small team needs is much the same everywhere. Ansible allows me to rebuild a server in an hour, rather than remember a bunch of handtweaked changes.

borrowed · web server

Caddy

Sits in front of everything, with automatic HTTPS and a configuration file short enough to read at a glance. One fewer thing to think about, permanently.

borrowed · hosting

Linode and DigitalOcean

Plain Linux servers at predictable prices, sized for one person. Running on two providers keeps either one from becoming a dependency, and the Ansible repository turns a move between them into an afternoon's deploy.

borrowed · notifications

ntfy

Push notifications from scripts and servers to my phone with an HTTP request. Backups, build failures, and anything else worth interrupting me for arrive the same way.

built · go

Simple IoT

The same platform I build customer systems on also watches my own. It polls the servers and the things around the shop, keeps the current state, and forwards every measurement downstream. Running the business on it means I meet the rough edges before a customer does.

borrowed · metrics

VictoriaMetrics

Where the measurements land and stay. A time-series database that holds years of history on a small server without asking for attention, which is the right shape for infrastructure that is supposed to fade into the background.

borrowed · dashboards

Grafana

The view onto all of it: disk, memory, backups, certificates, and build times on dashboards I can scan in a few seconds. Anything worth waking me up for leaves Grafana as an alert and arrives through ntfy.

borrowed · ai

Claude Code

An agent that reads and writes the same open file formats I do. Because the substrate is plain text in Git, it can work across the whole business: code, documents, accounting, and hardware designs.

Publishing

Getting the thinking out

A daily post, a blog, a podcast, and a newsletter. One pipeline: everything starts as Markdown in a repository and ends as a static site.

borrowed · static sites

Zola

A single fast binary that builds this site, the daily, and several others. No package tree to maintain, and a build that finishes before I have finished reaching for the browser.

built · zola theme

simplepod

A Zola theme for podcasts. It generates an iTunes-compatible feed and a web player, and it does one job: a podcast, not an entire site. The TMPDIR podcast runs on it.

built · audio

soundrig

The audio side of podcast production: the processing and assembly steps that turn raw recordings into a published episode, scripted so that every episode goes through the same path.

borrowed · notes

Obsidian

The front end to a directory of Markdown files. Business planning, strategy, meeting notes, and drafts live in one vault that is also a Git repository, so the notes travel with everything else.

borrowed · email

Thunderbird

Mail stored locally, searchable, and mine. Paired with a plugin I wrote for composing in Markdown, so a reply with a code block or a list does not have to fight a rich-text editor.

borrowed · newsletter

Kit

One hosted service I am glad to pay for. Delivering email to inboxes is a reputation problem rather than a software problem, and it is not one I want to own.

People

Conversations, hosted

Consulting is a conversation business. Both halves of that run on software I can point at.

borrowed · forum

Discourse

Runs the TMPDIR community: a friendly place by engineers for engineers, and a home for the questions that do not fit in a bug tracker. Private categories are used for day-to-day collaboration with customer teams, where the discussion stays with the project instead of scattering across inboxes.

borrowed · messaging

Signal

The quick channel: a question between meetings, a photo of a board on the bench, a heads-up that a build is ready. End-to-end encrypted and run by a nonprofit. Perfect for team messaging.

built · jitsi

jaas-app

A small application in front of Jitsi that gives me hosted-quality video meetings without handing the recordings and the calendar to someone else. Client calls, podcast recordings, and working sessions all run through it.

The cadence

The tools are the easy half

Release first says that shipping is a sustained capability rather than an event. That applies to a business as much as to a product. These are the loops the stack exists to keep turning.

Write most weekdays

A short post on the daily site, thinking out loud about how we build. It compounds: the good ideas get found by writing them down badly first, and the best of them grow into articles here.

Log time as it happens

A line in a timedot file, in the editor already open. Time recorded at the end of the week is a guess, and a guess is a poor thing to bill from or to learn from.

Invoice on the first working day

A fixed date on the calendar, not a reminder to get to it someday. The pipeline from time log to sent invoice is short enough that there is never a reason to postpone it.

Commit everything

Books, documents, configuration, and content all land in Git the same day. The history is the record, and the record is what makes it possible to hand any of this to someone else, including an AI agent.

Deploy from the repository

No server holds state that only exists on that server. Every service is described by a role, so recovering from a lost machine is a run of Ansible rather than an archaeology project.

Would this work for your team?

The same thinking that produced this stack works on a product: decide what to build, what to borrow, and how the pieces fit. If you would like help with that, I would enjoy the conversation. Most of what is above is on GitHub, and the product side of the picture is on the technology page.