Open-source project
sysadminsmedia/homebox avatar
sysadminsmedia/homebox

sysadminsmedia/homebox: the pepper file, port 7745, and a Dockerfile condition that excludes nothing

A continuation of HomeBox the inventory and organization system built for the Home User.

7,871 stars622 forksGoAGPL-3.0

At a glance

What is it?
Homebox keeps a household inventory in SQLite behind an embedded web UI, shipped as one Go container. Getting it running means generating an auth pepper first, mapping 3100 to 7745, and picking between three image variants that differ by privilege model. The Dockerfile also carries an architecture condition that excludes nothing.
Who is it for?
Homebox suits a household that wants one container, one SQLite file, and an inventory it can read from a phone, and it accepts that upgrades arrive as tagged releases you apply yourself. It does not suit a shared or audited deployment, since AGPL-3.0 and a hand-rolled pepper are the only controls on record.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • sysadminsmedia/homebox7,871 ★ · +1,268
Star history
Repository2026-07-312026-11-14
sysadminsmedia/homebox6.6k7.9k

1,268 Stars in the last 106 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The pepper file has to exist before the container does

The quick start opens with a file nobody would guess from the feature list. A 48 byte random value is written to `hbox.pepper`, the file is locked to mode 400, and its contents are handed to the container through an environment variable at every start:

bash
# Save pepper to local file
openssl rand -base64 48 > hbox.pepper
chmod 400 hbox.pepper
# If using the rootless or hardened image, ensure data
# folder has correct permissions
mkdir -p /path/to/data/folder
chown 65532:65532 -R /path/to/data/folder
docker run -d \
  --name homebox \
  --restart unless-stopped \
  --publish 3100:7745 \
  --env TZ=Europe/Bucharest \
  --env HBOX_AUTH_API_KEY_PEPPER=$(cat hbox.pepper) \
  --volume /path/to/data/folder/:/data \
  ghcr.io/sysadminsmedia/homebox:latest

The value is read with `cat` on every launch, so the file has to outlive the container rather than be a build argument. Three details in that command block are easy to skip and hard to notice afterwards. The restart policy is `unless-stopped`, so the container comes back by itself after a host reboot. The timezone is passed as `TZ`, which is a host concern rather than a database one. And the pepper sits in an environment variable, which means it is visible in the process environment of a running container, something to weigh before treating the deployment as private. Set `HBOX_LOG_LEVEL=-1` and the compose file's own pepper value, spelled `dev-only-pepper-not-for-production-use-32b+`, show what the project counts as a throwaway configuration.

One published port, one volume, and no database service

The deployment shape is deliberately small. A single port is published, 3100 on the host to 7745 in the container, and one directory is mounted at `/data`. There is no Postgres in the compose file, no reverse proxy, and no separate frontend container, because the choice is SQLite plus an embedded web UI. The readme credits Go for idle memory under 50MB for the whole container, and SQLite plus the embedded web UI for making it easy to deploy, use and back up. The compose file is a development build: an image built from the local Dockerfile, two build arguments pinned to `COMMIT=head` and `BUILD_TIME=0001-01-01T00:00:00Z`, and the same 3100 to 7745 mapping. Port 7745 is the service inside the image, so anything expecting the default web port has to be told otherwise, and nothing in the compose file publishes 7745 directly.

Three images, three privilege models, one shared data directory

The repository holds `Dockerfile`, `Dockerfile.rootless` and `Dockerfile.hardened`, and the quick start ends with the two alternative tags sitting in comments beside the default one, `ghcr.io/sysadminsmedia/homebox:latest-rootless` and `ghcr.io/sysadminsmedia/homebox:latest-h`. That choice propagates into the filesystem. The `chown 65532:65532 -R` line is there because the non-root and hardened images cannot own a data directory created by your user, and the comment says so directly. Create the folder and fix its ownership before the first launch, not after a save fails, because the same directory holds every attachment and document uploaded through the interface. The comment in the quick start ties the ownership fix to those two images specifically, which leaves the reading that the default image copes with a directory owned by your own user. Nothing in the readme explains what the hardened variant tightens beyond the user id, so choosing it means reading the file rather than a table.

The image library condition excludes nothing

The Go builder stage adds four image libraries behind a guard meant to skip them on platforms that lack them:

bash
    if [ "$TARGETARCH" != "arm" ] || [ "$TARGETARCH" != "riscv64" ]; then apk --no-cache add libwebp libavif libheif libjxl; fi

The operator is an or, and no build target is both arm and riscv64 at once, so the first comparison is true on its own for every architecture except the one named first. On 32 bit arm the condition still holds on the riscv64 half and the libraries install anyway. The stage otherwise installs `git build-base gcc g++`, which is what the Go cross compile needs, and takes its targets from the `TARGETOS` and `TARGETARCH` build arguments rather than from the host.

The compose build ships three architectures, the Dockerfile reasons about two

The bake metadata in the compose file names `linux/amd64`, `linux/arm64` and `linux/arm`, while the builder stage's conditional mentions arm and riscv64. Those are two different views of the same matrix: the first is the set of platforms the compose bake targets, the second is the set of exceptions the build believes exist, and riscv64 appears only in the second. For a self-hosted home user the practical effect is small, since the published `:latest` tag on the usual desktop and server architectures covers the common case, and a custom multi-architecture bake is something you would assemble yourself from this file rather than pull from the registry.

Fixed fields plus custom fields is the whole data model

What gets stored is an item with a home rather than a spreadsheet row. Items are organised into categories, locations, and tags, and a custom field mechanism sits on top for anything the fixed fields miss. Alongside identity, the tracked values are purchase dates, prices, maintenance schedules, documents and warranties, plus uploaded images that make items easy to identify. Search is the retrieval path, and the interface is described as working on desktops, tablets, and smartphones, which is a claim about the embedded web UI rather than about native clients. In practice the interesting constraint is that all of it lives under `/data`, so a lost volume means losing custom fields, warranty documents, and photographs together, and a partial copy means an inventory that opens but no longer lists the items whose files never arrived.

Release tags lag behind the work, and a nightly demo shows the gap

The version picture is uneven. The newest release is v0.27.1 from 2026-10-23, following v0.27.0 on 2026-10-17 and the release candidate v0.27.0-rc.1 on 2026-09-28, and the last push was on 2026-10-31. Two hosted instances make that visible: a demo instance and a nightly one. This repository is a continuation of the original project by hay-kot, with the logo by lakotelman, licensed AGPL-3.0, with translations handled through a Weblate instance and financial contributions invited from people who cannot code or translate. Contributor plumbing is spread across several systems at once: `Taskfile.yml`, `flake.nix` with its lock, a `.gitlab-ci.yml` beside the `.github/` directory, and a `docs/` folder, while the quick start links to homebox.software for configuration detail.

Editorial conclusion

Homebox suits a household that wants one container, one SQLite file, and an inventory it can read from a phone, and it accepts that upgrades arrive as tagged releases you apply yourself. It does not suit a shared or audited deployment, since AGPL-3.0 and a hand-rolled pepper are the only controls on record. Before the first run, generate the pepper, decide which of the three images matches your privilege tolerance, and read the quick start page rather than the readme for configuration detail.

Frequently asked questions

what is homebox

An inventory and organization system for the home, written in Go, using SQLite with an embedded web UI. This repository is a continuation of the original project by hay-kot and is licensed AGPL-3.0.

how to install homebox

Run the published image and map one port. The quick start generates a 48 byte pepper with `openssl rand -base64 48 > hbox.pepper`, sets it to mode 400, and passes it as `HBOX_AUTH_API_KEY_PEPPER` while publishing 3100 to 7745.

how to set up homebox

Create the data folder first and mount it at `/data`. For the rootless or hardened images it must be owned by 65532:65532, otherwise the container cannot write to the directory that holds your items and uploads.

how to use homebox

Organise items into categories, locations, and tags, then add custom fields, purchase dates, prices, maintenance schedules, documents, warranties, and images. Everything lands in the mounted `/data` folder.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/sysadminsmedia-homebox.svg)](https://hysenlabs.com/projects/sysadminsmedia-homebox)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/sysadminsmedia-homebox.svg)](https://hysenlabs.com/projects/sysadminsmedia-homebox)

Was this useful?