Hydro0x01: a full stack hydroponic controller for the ESP32
Secure, production-grade IoT hydroponic automation system with ESP32, MQTT telemetry, and real-time dashboard
At a glance
- What is it?
- HydroponicOne is an open source hydroponic monitoring and control system that spans an ESP32 firmware, a Fastify and Prisma backend, a React dashboard and a dual database setup, with MQTT over TLS between them and RSA signed over the air updates for the firmware. The project aims to sit between hobbyist setups and expensive industrial automation.
- Who is it for?
- Hydro0x01 suits a maker or a small farm who wants real sensor telemetry and closed loop control of pumps and lights rather than a timer, and the two database design and the calibration guide are what make it usable rather than a demo.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Five layers, and the boundary between them is MQTT
HydroponicOne is described as a modular and professional-grade hydroponic monitoring and control system, and it aims to bridge the gap between hobbyist DIY setups and expensive industrial automation.
The architecture table lists five layers, and it is the clearest summary of what the project actually is:
The frontend is React 19 with Vite, Tailwind CSS, Recharts, Zustand and Lucide Icons. The backend is Node.js with Fastify, Prisma ORM and Socket.io. The databases are PostgreSQL for relational data and InfluxDB for time series telemetry. The firmware is C++ on Arduino using PlatformIO with async MQTT. And the DevOps layer is Docker support, GitHub Actions and secure OTA deployment.
The interesting design decision is the split of responsibilities, and the two-database choice is the part that shows the author's assumptions. PostgreSQL holds persistent configuration state, which is the small amount of data that describes the system itself: what sensors exist, what the setpoints are, what the relays control. InfluxDB holds the time series, which is the high volume data: pH, EC, water level, temperature and humidity sampled continuously.
That is a deliberate separation rather than an accident of tooling. Configuration is relational and transactional and changes rarely. Telemetry is append-only, enormous and queried by time range. Putting both in one database means either the relational tables get a write path that is not really what they are for, or the time series data forces the schema design of the configuration into a shape that does not suit it.
The communication between the layers is MQTT, and it is the same protocol throughout, from the firmware to the broker to the backend and on to the dashboard. The backend exposes the dashboard over WebSockets with Socket.io, and the dashboard is described as an edge-first local React single page application talking in real time.
The feature list at the top of the README maps onto the same structure: real-time environment monitoring of pH, EC, water level, temperature and humidity, automated actuator control with smart relays for dosing pumps, main circulation, grow lights and ventilation, a secure architecture with async MQTT over TLS, offline operating modes and RSA-2048 signed OTA updates, and enterprise data management with the two databases.
The backend first, and the secret you have to generate before anything works
The quickstart is a four step sequence, and the first step is the code you already have.
git clone https://github.com/40rbidd3n/Hydro0x01.git
cd HydroponicOneThen the backend, where you configure the environment and seed the database:
cd backend
npm install
cp .env.example .env
# Edit .env with your DB credentials and set JWT_SECRET using: openssl rand -base64 32
npx prisma db push
npm run devThe JWT_SECRET requirement is specified tightly enough to be worth reading twice. It is required and must contain at least 32 characters, and the backend rejects missing, blank, short or previously published example secrets. You generate a secret once per installation and keep the same value across restarts, because changing it invalidates existing tokens.
That last check, rejecting a previously published example secret, is the kind of detail that separates a system meant for real use from a tutorial. A secret copied from a .env.example that ended up on the internet is a specific and common failure, and refusing it at startup is cheap.
The Prisma step is npx prisma db push, which pushes the schema to the database directly rather than running migrations, which is the right choice for a first run of a project where you are also seeding, and a choice you might revisit when the schema starts evolving.
The Docker path is separate and explicit. For Docker deployments you save the generated secret as JWT_SECRET in docker/.env, which is ignored by Git, and then run from the repository root:
docker compose -f docker/docker-compose.yml up -d --buildCompose requires a non-empty JWT_SECRET from docker/.env or from your shell, so a container start fails fast rather than coming up half-configured.
The frontend then follows the same pattern, with its own npm install, its own .env copy and its own dev server:
cd ../frontend
npm install
cp .env.example .env
npm run devThe prerequisites list is short and tells you what you need on the bench before you start: Node.js with v20 recommended, PostgreSQL v14 or newer, InfluxDB v2.0 or newer, an MQTT broker such as Mosquitto or HiveMQ, an ESP32 development board, and the PlatformIO IDE.
Firmware, and the configuration template you have to copy by hand
The firmware step is where a hardware project stops being a web project, and the README marks the one thing people forget.
cd ../firmware
# IMPORTANT: Clone the configuration template before compiling
cp include/config.example.h include/config.h
# Edit include/config.h with your network and MQTT details
# Edit platformio.ini to choose your hardware environment (e.g., env:esp32_dht_bmp)
pio run -t uploadThe configuration header is a template that has to be copied into place and filled in with your network and MQTT details before the code will compile or will find your broker. The comment in the README marks this as important, and it is the step a first-time builder is most likely to skip, because the example file is right there and the build failure appears much later as a connection problem rather than a compile error.
The PlatformIO configuration is where the hardware variant is chosen, with the environment named in the example being one for an ESP32 with a DHT sensor and a BMP barometer. That single word tells you the project is structured around a family of sensor combinations rather than one fixed rig, and the docs directory backs that up with a dedicated hardware setup guide, a firmware guide and a calibration guide.
The hardware side of the repository is worth noting as well. Alongside backend, frontend and firmware there is a pcb/ directory, a 3d_design/ directory and a tools/ directory, so the project covers circuit boards, printed enclosures and the tooling to work with them, not just the code. There is also an assets/ directory with the branding and the architecture diagrams, including a system overview image and a master architecture diagram.
The MQTT transport in the firmware is described as async, and the security guide covers the TLS side. The troubleshooting section for connectivity says to use mqtts:// if you are on port 8883, and to check your base topic, which is the detail that trips people up when a broker on 1883 with plain MQTT and a broker on 8883 with TLS are otherwise configured identically.
For sensor readings, the troubleshooting points at the I2C and ADC calibration solutions in the troubleshooting document, and there is a whole calibration guide in the docs list for sensor tuning procedures, which is the right way round: the hardware is cheap and the calibration is what makes the numbers right.
Nine documents, and the security work behind the OTA path
The documentation table is the index of the project, and the order of it is the order you would need things in.
The system overview explains how everything connects. The hardware setup guide has the wiring diagrams and assembly. The firmware guide covers configuration and flashing. The integration guide covers Home Assistant, Telegram and Discord, which is the part that turns a monitoring system into something you actually want running in your house. The calibration guide is the sensor tuning procedures. The troubleshooting guide covers the common issues. The API reference is the REST API documentation. The MQTT guide is topics and payload specifications. And the security and OTA guide is firmware signing and RSA keys.
That last one is the most interesting, because the security story in this project is not a bolt-on. The architecture list mentions RSA-2048 signed OTA updates as a feature of the secure architecture, and it has a whole guide of its own, alongside a SECURITY.md file at the repository root.
The design of it is the standard one for firmware distribution, and the reason it matters here is that an ESP32 update is code that runs with access to your grow room. A signed update means the device will only accept firmware that was signed with a key you hold, which closes the door on a compromised update server being able to push something onto your hardware.
The MQTT guide being separate from the API reference is also a deliberate separation, because the two serve different consumers. The REST API is for the dashboard and for integrations that speak HTTP. The MQTT topics and payloads are for anything that wants to subscribe to sensor readings or drive a relay without going through the backend at all, which is how you get the offline operating mode mentioned in the feature list.
The features also mention offline operating modes, which is the system continuing to work when the broker or the backend is unreachable. That is a hard requirement for a growing system, because a plant does not care that your network went down, and the MQTT guide and the integration guide are where you would look to understand how much local autonomy there is.
The integrations are worth singling out. Home Assistant is the obvious one for a home build, and Telegram and Discord are notification channels, which is the pattern for alerting on a tank level or a pH excursion without opening a dashboard.
Releases, the roadmap, and what is not built yet
The project says that all code modifications and versioning are strictly documented, with a CHANGELOG.md for version history and a GitHub Releases page for pre-compiled binaries and full production release notes.
That last part is worth noting. Pre-compiled firmware binaries in a release page means you can flash the device without a PlatformIO toolchain, which removes the largest barrier for someone who just wants the system running rather than developing it. The separate in-repository firmware build instructions are then for the developer path, and the docs list confirms the two audiences are meant to be served differently.
There are no GitHub releases in the repository listing available here, and the last push was on 2026-10-22, so the project is actively worked on even though the tagged history is not visible from the repository metadata.
The future roadmap is described as extensive, ranging from LoRa master and slave setups to AI diagnostics, with the full development roadmap in the docs directory. LoRa is the interesting one, because a greenhouse with an ESP32 on WiFi in one building and a sensor in another is exactly the case where the current architecture, which assumes a broker and a backend you can reach, stops working.
AI diagnostics is the other one, and it connects to the calibration guide. A system that measures pH and EC and has a history of it in InfluxDB has everything it needs to detect a failing sensor or a drifting nutrient balance, which is a more valuable use of machine learning here than trying to predict a harvest.
The repository also has a CONTRIBUTING.md and a CODE_OF_CONDUCT.md, and the project asks that you read both before submitting pull requests, which is the standard expectation.
The licence is MIT, and the closing line of the README says it was built with love for the future of sustainable farming.
Editorial conclusion
Hydro0x01 suits a maker or a small farm who wants real sensor telemetry and closed loop control of pumps and lights rather than a timer, and the two database design and the calibration guide are what make it usable rather than a demo. It does not suit you if you want a single binary to run, because the stack needs PostgreSQL, InfluxDB and an MQTT broker alongside the firmware, and it does not suit you if you are not comfortable with embedded C++ and a browser dashboard at the same time. Before you build it, read the hardware setup guide, because the sensor choice constrains the firmware build, and note that the firmware configuration template has to be copied into place before you compile, and that the backend will refuse to start without a JWT secret of at least 32 characters.
Frequently asked questions
What does the Hydro0x01 system consist of?
Five layers: a React 19 frontend with Vite, Tailwind, Recharts and Zustand, a Node.js backend with Fastify, Prisma and Socket.io, PostgreSQL for configuration state and InfluxDB for time series telemetry, C++ Arduino firmware on PlatformIO with async MQTT, and Docker plus GitHub Actions for deployment with signed OTA updates.
How do I set up the Hydro0x01 backend?
Clone the repository, change into the backend directory, run npm install, copy .env.example to .env, set your database credentials and a JWT_SECRET of at least 32 characters generated with openssl rand -base64 32, run npx prisma db push to push the schema, and start it with npm run dev. The backend rejects missing, blank, short or previously published example secrets.
How do I flash the ESP32 firmware for Hydro0x01?
Change into the firmware directory, copy include/config.example.h to include/config.h and edit it with your network and MQTT details, choose your hardware environment in platformio.ini, then run pio run -t upload. Copying the configuration template before compiling is marked as important in the documentation.
How does Hydro0x01 keep the firmware secure on the device?
Updates are signed, with RSA-2048 signed OTA updates as part of the secure architecture, and there is a dedicated security and OTA guide covering firmware signing and RSA keys alongside a SECURITY.md file in the repository root.
Official sources
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.
[](https://hysenlabs.com/projects/40rbidd3n-hydro0x01)Was this useful?