Release notes#
Self Hosted
Each section lists what is in that version, newest first. The same notes are published on the GitHub releases page.
v0.9.1 — 1 November 2026#
Ingest stores what a device sends#
Numeric values are stored as received. There are no range checks and no clamps, before or after a unit conversion.
A request is rejected with 422 only when the body cannot be parsed, a required primary value is missing, a number is not finite, or a unit is not an allowed value. Unit letter case is ignored.
An absent pressure unit means kPa and an absent temperature unit means C.
An optional field the device did not send is stored empty instead of 0. Fields that are accepted but not stored are ignored whatever they contain.
Chamber readings no longer fail on a temperature, rssi or battery outside the manual-entry bounds.
The dispatch endpoint reads a bare
temperaturekey as the beer temperature.
Devices#
KegMon: a volume above the vessel’s capacity raises the capacity to that volume. A negative volume or max volume is rejected with 422 and logged with the field name.
Battery voltage and battery percent are stored and shown separately; neither is calculated from the other.
KegMon: the beer lookup returns the name of the batch on the tap, not the name of the keg.
KegMon: a beer lookup with an unknown token is recorded in the ingestion log.
Pressure#
Negative pressure readings are accepted (-3000 to 3000 in the device unit).
Pressure statistics no longer clip at the old seed values.
Web#
Readings without a battery, angle, velocity or rssi show no value instead of zero: the battery chart skips them and the gravity and pressure lists show a dash.
Fixes#
Gravity and pressure ingest no longer raises when a batch has a UUID id and a log line is written.
v0.9.0 — 26 October 2026#
First public release of BrewGraph, a self-hosted homebrewing telemetry platform. It collects readings from fermentation and keg sensors on your own network and tracks each batch from fermenting through conditioning to kegged or bottled. It runs with Docker Compose and needs no cloud account.
Its still early in the development so please report any issues.
BrewGraph is the successor to BrewLogger and uses a new data model. BrewLogger backups can be imported through Backup and Restore.
Its also available as a hosted version on www.brewgraph.com if you don’t want to run your own.
Fermentation tracking#
Batch lifecycle: fermenting, packaged, archived.
Per-batch fermentation steps, dry-hop additions and notes.
Gravity, pressure and temperature charts per batch, with list views of the raw readings.
Gravity comparison chart across batches.
Yeast strain library, selectable per batch.
Fermentation completion prediction from an ML model, shown per batch.
Chamber control for a batch: activate, deactivate and advance to the next fermentation step. It requires a chamber controller device on the batch and at least one fermentation step.
Live updates in the UI through server-sent events.
Devices and ingest#
Device |
Protocol |
Ingest endpoint |
|---|---|---|
iSpindel |
HTTP |
|
GravityMon |
HTTP / BLE |
|
GravityMon Gateway |
HTTP |
|
PressureMon |
HTTP / BLE |
|
KegMon |
HTTP |
server only; the firmware adds |
ChamberCtl |
HTTP / BLE |
|
KegMon and ChamberCtl: the ingest endpoints are in place, but there is no released firmware for them yet, so they have not been verified against real devices.
Ingest endpoints take no API key. Each device authenticates with its own token, which can be regenerated from the device page. Ingest is rate limited per IP and throttled per device.
Optional sidecars: BLE ingestion and mDNS device discovery (both Linux only), and a log collector for device serial logs.
Device pages show configuration, readings and device logs.
Gravity and formulas#
Per-device gravity formula editor, opened from the device page. A formula and its calibration data can only be saved on gravity devices (GravityMon, iSpindel); the API rejects them for other device types.
The formula is written in terms of
tilt(degrees) andtemp(degrees C), with numbers,+ - * /, parentheses and integer powers^1to^6.Formulas are validated when saved, by the API and by the editor, without executing code: maximum 200 characters and 128 tokens, only the variables
tiltandtemp, numeric literals up to 1,000,000, and exponent notation (for example8.1e-7) limited to -30 to 30 and stored as the equal plain decimal. A sign directly before a power (-tilt^2) is rejected as ambiguous; write(-tilt)^2or-(tilt^2). An empty formula means no formula.Formula unit: SG or Plato. When not set, it defaults to SG, except for iSpindel devices whose name does not start with
[SG], which default to Plato.Calibration points (angle and gravity, up to 20, distinct angles) can be entered in the editor. It fits polynomial formulas of degree 1 to 4 for you to choose from, plots the points, and has a test calculator for an angle and temperature.
Formula profiles can be exported to and imported from a JSON file, and the formula text can be copied.
Storage vessels, kegs and bottles#
Storage vessels track the beer you have packaged: what is in each keg or batch of bottles, how much is left, where it is, and what is on tap.
Two vessel types: keg and bottles. The type is chosen when the vessel is created and cannot be changed afterwards.
Each vessel has a name, an optional vessel number, fill date, location and notes.
Status is clean, filled or serving.
Kegs track total volume and volume remaining. Bottles track bottle size, bottle count and bottles remaining; if you give count and size, total and remaining volume default to their product. Remaining can never exceed total.
Volumes are entered and shown in your chosen volume format (metric, US or UK) and stored in litres.
Link a vessel to a batch. In the batch editor you can add a new keg, assign an empty keg, empty a keg (which unlinks it, sets it to clean and resets its remaining volume to zero), or add a set of bottles.
Linking a fermenting batch to a vessel marks the batch as packaged, with the vessel’s fill date as its package date. This is the same whether you assign an existing keg or add bottles. One batch can have several vessels. Archived or deleted batches cannot be linked to a new vessel.
Vessel list with columns for number, name, type, status, remaining volume (a bar for kegs, bottles remaining out of count for bottles) and pour count. It is sortable by number and name, paginated, and can be filtered by status and by batch. Each row links to edit the vessel, delete it, open its batch and show its pours.
Tap assignment: a vessel is put on a tap from the tap page (“Vessel on tap”). A tap holds one vessel, and assigning a vessel to a tap that is in use releases the previous vessel.
Pour tracking: record a pour (an amount in litres, shown in your volume format) on a keg that is on a tap, or a number of bottles consumed on a bottle vessel that is on a tap. Each pour reduces the remaining volume or bottle count. The pour list for a vessel shows date, amount, volume remaining and entry type, and lets you exclude a pour.
Pours can also arrive from a KegMon device through the tap’s ingest endpoint (see the KegMon note under Devices and ingest).
A pressure device or chamber controller can be paired to a vessel from its page, for example while a keg sits in cold storage with no active batch. Pressure and temperature readings from them are stored against the vessel, including when the vessel has no batch.
Deleted vessels are soft-deleted and can be restored through the API.
Backup and restore includes vessels with their pour events and their temperature and pressure history, and taps.
Taps#
Tap list with number, name, location, linked batch and volume remaining, and a “Cleaning due” badge when a tap line has not been cleaned for more than 14 days (counted from the tap’s creation if it has never been cleaned).
A daily scheduled reminder writes the same 14-day cleaning notice to the system log. There is no separate notification or inbox.
Each tap has a glass size, location, notes and its own device token, which can be regenerated.
Dashboard shows what is on tap.
Public tap board and bottle list#
The separate display service serves a tap board and a bottle list, intended for a wall display or TV. They show beer name, style, ABV, IBU and colour, and refresh every 60 seconds.
The tap board shows the volume remaining on each tap. The bottle list shows packaged bottle vessels that have bottles remaining, with the bottle size.
The display endpoints (
/d,/t,/b) are anonymous (no API key), rate limited and briefly cached, so they are readable by anyone who can reach the display service.
Import and export#
BeerXML recipe import into a batch.
Brewfather batch and recipe import and linking (needs your Brewfather user and API key).
Batch export: gravity CSV, pressure CSV and batch JSON.
Backup and restore of all data, including BrewLogger backups.
Integrations: forward measurements to an iSpindel-style endpoint, to Brewfather, or to a custom endpoint with a template. Gravity supports all three; pressure and temperature support Brewfather custom stream and custom; pours support custom only.
Operations and self-hosting#
Docker Compose deployment with pre-built images (
mpse2/brewgraph-*) or a build from source.Services: API, PostgreSQL 17, Redis, web UI (Nginx), display, and optional log, mDNS and BLE sidecars.
Database migrations run automatically when the API container starts.
Optional HTTPS: place
server.crtandserver.keyinweb/certs/and enable the port mapping in the compose file.System log, ingestion error log and a self-test.
Settings: temperature (C/F), gravity (SG/Plato), pressure (kPa/psi/bar) and volume (metric/US/UK) formats, plus light and dark theme.
REST API with interactive OpenAPI docs on the API port (blocked at the Nginx proxy).
The web UI is built for desktop browsers. The UI is in English only.
Security#
BrewGraph is designed for a trusted LAN and a single operator. Do not expose it to the public internet; use a VPN or a reverse proxy with its own authentication for remote access.
One shared API key (
API_KEY) protects the web UI and management API. There are no user accounts or roles.Failed authentication attempts are blocked per IP, and ingest rate limits apply. Both need Redis and do nothing without it.
See the README section “Security model & accepted tradeoffs” for the full list.
Requirements and upgrade notes#
Docker Engine 24 or newer and Docker Compose v2, on Linux, macOS or Windows (WSL2).
BLE ingestion and mDNS discovery need a Linux host (host networking; BLE also needs Bluetooth hardware and BlueZ).
PostgreSQL is the supported database. SQLite is for development and tests only.
Run Redis if you use Integrations. Without it, readings are still saved but nothing is forwarded, and no error is shown.
API_KEYandPOSTGRES_PASSWORDmust be set in.envbefore first start.Upgrade with
docker compose pull && docker compose up -d(orgit pull,docker compose build,docker compose up -dwhen building from source). Migrations apply on startup.License: GNU General Public License v3.0 for open source use. Use without source disclosure requires a separate Commercial License, as described in LICENSE.