Alfalfa is an open source web application forged in the melting pot of Building Energy Modeling (BEM), Building Controls, and Software Engineering domain expertise. Alfalfa transforms Building Energy Models (BEMs) into virtual buildings by providing industry standard building control interfaces for interacting with models as they run. From a software engineering perspective, Alfalfa leverages widely adopted open source products and is architected according to best practices for a robust, modular, and scalable architecture.
Documentation resides in the GitHub wiki!
We are currently working on increasing our developer documentation. See how to run the tests on the GitHub wiki. For releasing, see the wiki's release instructions.
Alfalfa runs as a Docker Compose stack (web, worker, MongoDB, Redis, and MinIO). Configuration is read from the .env file in the repository root. Requires Docker with the Compose plugin.
Note for Apple Silicon (M1/M2/M3+) users: Modelica FMUs typically only ship x86_64 (binaries/linux64) shared libraries, so a native arm64 worker will fail to load them with a misleading error such as:
pyfmi.fmi.InvalidBinaryException: The FMU could not be loaded. Error loading the binary.
Could not load the FMU binary: .../binaries/linux64/<Model>.so: cannot open shared object file: No such file or directory
This is an architecture mismatch, not a missing file. docker-compose.yml does not pin platform: linux/amd64 on the worker service (running everything under amd64 emulation by default would make the worker significantly slower for the common case, and most Apple Silicon users don't need FMU support). If you need to run Modelica FMUs on Apple Silicon, force amd64 yourself with export DOCKER_DEFAULT_PLATFORM=linux/amd64 (or an explicit --platform linux/amd64) before running docker compose up, whether the worker image is pulled prebuilt from GHCR or built locally with --build.
Builds the optimized web bundle and runs the web service with node build/index.js:
docker compose up --buildThe web application is served at http://localhost/ and the API docs at http://localhost/docs. MinIO is available at http://localhost:9000.
Mounts alfalfa_web and alfalfa_worker into the containers and runs them in watch mode so code changes reload automatically (webpack watch for the web, watchmedo for the worker):
docker compose -f docker-compose.yml -f docker-compose.dev.yml up --buildHISTORIAN_ENABLE=true docker compose -f docker-compose.yml -f docker-compose.historian.yml up --buildGrafana is served at http://localhost:3000.
docker compose down # or: docker compose down -v to also remove volumesThe Alfalfa docker images are published to the GitHub Container Registry (GHCR) under the natlabrockies org for easy deployment via Helm or other docker services. The images include:
- Alfalfa Web —
ghcr.io/natlabrockies/alfalfa/web - Alfalfa Worker —
ghcr.io/natlabrockies/alfalfa/worker - Alfalfa Grafana —
ghcr.io/natlabrockies/alfalfa/grafana
Pull an image with:
docker pull ghcr.io/natlabrockies/alfalfa/web:latestIf the packages are private, authenticate first with a GitHub personal access token that has the read:packages scope:
echo "$GHCR_TOKEN" | docker login ghcr.io -u <github-username> --password-stdinThe alfalfa_worker Docker image is built FROM a base image published by the separate alfalfa-dependencies repository (ghcr.io/natlabrockies/alfalfa-dependencies). That repo owns the slow-to-compile, infrequently-changing native/scientific dependencies the worker needs — EnergyPlus, OpenStudio, and Modelica/FMU support (Assimulo, PyFMI, and SUNDIALS, including the legacy SUNDIALS 5.x runtime compatibility libraries some FMUs require) — so they're built once as a shared image rather than recompiled on every alfalfa_worker build.
The two repos are independent git repositories (no submodule/subtree link) connected only through the image tag referenced by FROM in alfalfa_worker/Dockerfile, currently main (alfalfa-dependencies' default branch, rebuilt and republished by its CI on every push). During development that tag is sometimes a work-in-progress branch name from alfalfa-dependencies' CI instead; once merged to main (or a tagged release), alfalfa_worker/Dockerfile should be bumped back to main or the corresponding release tag. If a worker build/runtime issue looks like it belongs to EnergyPlus, OpenStudio, Assimulo/PyFMI, or SUNDIALS rather than alfalfa's own code, it likely needs to be fixed in alfalfa-dependencies instead.
An Alfalfa Python Notebook repository contains examples on how to interact with Alfalfa.
The Alfalfa Client is a Python library for making API calls to Alfalfa easier. The source code is available on GitHub and the package is released through PyPi.