From zero to a fully functional data server with REST API and web frontend. Estimated time: under 10 minutes on a prepared Linux system. Hive is built as a C++23 binary — no runtime interpreter, no container required.
GCC 14 is the tested and recommended compiler. Clang with C++23 support (clang-18+) should also work but is not the primary target.
gcc --version
# gcc (GCC) 14.x.x
# Debian/Ubuntu install:
sudo apt install gcc-14 g++-14
OpenSSL is a required dependency — used for SHA-256 in migration integrity checking (chain hash), and for token hashing. The development headers must be present.
# Debian/Ubuntu
sudo apt install libssl-dev
# Fedora/RHEL
sudo dnf install openssl-devel
# Verify
openssl version
pkg-config --modversion openssl
CMake for the build system. Ninja is the recommended generator — it is significantly faster than Make for incremental builds of the ~68k LOC codebase (~45k lines of C++).
cmake --version # 3.20+
ninja --version # any recent
# Debian/Ubuntu
sudo apt install cmake ninja-build
Required for cloning the repository. All C++ third-party libraries (Crow, SQLiteCpp, nlohmann/json, GoogleTest) are vendored as Git submodules in thirdparty/.
git --version # any recent version
# Debian/Ubuntu
sudo apt install git
sudo apt install build-essential gcc-14 g++-14 cmake ninja-build \
git libssl-dev
| Library | Path | Purpose |
|---|---|---|
| Crow | thirdparty/Crow | C++ HTTP/WebSocket server framework — all REST endpoints |
| SQLiteCpp | thirdparty/SQLiteCpp | C++ SQLite wrapper — all database operations |
| nlohmann/json | thirdparty/nlohmann_json | JSON serialisation/deserialisation |
| GoogleTest | thirdparty/googletest | Unit and integration testing framework |
Clone Hive and initialise all vendored dependencies. This will populate thirdparty/ with Crow, SQLiteCpp, nlohmann/json, and GoogleTest.
git clone https://github.com/openeggbert/hive.git
cd hive
git submodule update --init --recursive
The recursive flag is important — some submodules themselves have nested submodules (e.g., Crow's Asio dependency).
Configure the build directory. Hive uses Ninja for speed. The example below shows a production Release build with all performance flags enabled.
cmake -S . -B build \
-G Ninja \
-DCMAKE_BUILD_TYPE=Debug
cmake -S . -B build \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-O3" \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
-DCMAKE_UNITY_BUILD=ON
| Flag | Value | Effect |
|---|---|---|
CMAKE_BUILD_TYPE | Release / Debug | Optimisation level and debug symbols |
CMAKE_CXX_FLAGS | -O3 | Maximum optimisation — important for production performance |
CMAKE_INTERPROCEDURAL_OPTIMIZATION | ON | Link-Time Optimisation (LTO) — enables cross-translation-unit inlining |
CMAKE_UNITY_BUILD | ON | Unity (jumbo) build — combines multiple .cpp files to reduce compilation time and improve LTO quality |
ENABLE_TESTS | ON (default) | Build the GoogleTest test suite (Tests target) |
MINDNET_ENABLE_DICTIONARY_PLUGIN | ON (default) | Build the Dictionary plugin |
ALLOW_LEGACY_PLUGINS | OFF (default) | Enable the legacy plugin set — unlocks MINDNET_ENABLE_SLIPBOX_PLUGIN (ON) and MINDNET_ENABLE_REPETITION_PLUGIN (OFF) |
MINDNET_ENABLE_HISTORY | ON (default) | Compile in the history audit subsystem |
MINDNET_ENABLE_API_LOG | OFF (default) | Compile in per-request api_log persistence |
CMake detects OpenSSL automatically via find_package(OpenSSL REQUIRED). If OpenSSL is in a non-standard path, set -DOPENSSL_ROOT_DIR=/path/to/openssl.
Compile the hive_app target. First build takes a few minutes (all vendored dependencies compile from source). Subsequent incremental builds are fast with Ninja.
cmake --build build --target hive_app
# Or with explicit parallelism (adjust to your CPU core count)
cmake --build build --target hive_app -- -j8
The compiled binary is placed at build/src/hive-app/hive_app.
Alternatively, the repository ships a build.sh script that performs a clean Release build and assembles a timestamped distribution directory containing the binary, configuration/, and frontend/.
Start Hive with the frontend directory, port, and host settings. The -s flag points to the static frontend files.
./build/src/hive-app/hive_app start \
--port 9000 \
--frontend-port 9000 \
--host http://localhost \
-s ./frontend
On startup Hive loads configuration/hive.properties, resolves plugin dependency order, applies pending migrations (verifying SHA-256 checksums and chain hashes), builds the model/validator/trigger/job/query registries, generates all HTTP routes, starts the cron scheduler (4 worker threads), and begins accepting connections on the configured port.
All start options (parsed in Main.cpp): -p/--port, -f/--frontend-port, -h/--host, -s/--static-directory.
http://localhost:9000/web/
The Hive web frontend loads, reads /api/v1/model_definition, and builds navigation from all registered plugin models.
# Full metadata contract (drives frontend)
http://localhost:9000/api/v1/model_definition
# Health probe — returns 200 OK with server uptime
http://localhost:9000/health
# Runtime info — name, version, build_time, environment,
# host/ports, access_mode, registration_mode, default_user_role
http://localhost:9000/info
http://localhost:9000/web/app_slip_box.html
http://localhost:9000/web/app_dictionary.html
http://localhost:9000/web/app_repetition.html
On the very first start, if no users exist in the database, Hive auto-generates a random administrator password and writes it to pw.txt in the working directory.
pw.txt and copy the admin username and password securely (password manager).pw.txt immediately — it contains plaintext credentials.POST /api/v1/auth/change_password or the auth UI.access_mode and registration_mode in configuration/hive.properties for your deployment needs.# Login
curl -s -X POST http://localhost:9000/api/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"YOUR_PW"}' | jq
# Use the returned access_token
TOKEN="3f9c2a..."
curl -s http://localhost:9000/api/v1/dictionary_term \
-H "Authorization: Bearer $TOKEN" | jq
Hive reads configuration/hive.properties on startup. Command-line flags override configuration file values. The actual default configuration shipped with the repository:
# === configuration/hive.properties (real shipped example) ===
#Identification
name=Robert Vokac
description=Zettelkasten system for Robert Vokac
environment=Development
dev_mode=false
#
#host=
#port=
#frontend_port=
database_type=SQLite
#Access
access_mode=PublicFullAccess
registration_mode=Free
default_user_role=Reader
#Other
max_log_level=ERROR
allowed_plugins=slip_box, repetition, dictionary
access_token_expires_in=15 # minutes
refresh_token_expires_in=43200 # minutes (= 30 days)
refresh_token_rotation_threshold_in=10080 # minutes (= 7 days)
| Key | Values | Description |
|---|---|---|
access_mode | MaintenanceMode, AdminsReadOnly, AdminsReadWrite, AuthenticatedReadOnly, AuthenticatedReadWrite, AuthenticatedFullAccess, PublicReadOnlyAuthenticatedReadOnly, PublicReadOnlyAuthenticatedReadWrite, PublicFullAccess | Global API access gate (see access matrix on the home page) |
registration_mode | Free / RequiresAdminApproval / AdminAddsUsers | Who may create accounts |
default_user_role | Guest, Reader, Editor, Reviewer, Admin, SuperAdmin | Role assigned to newly registered users |
database_type | SQLite (default) / PostgreSQL (groundwork) | Persistence backend; PostgreSQL adds db_host, db_port, db_name, db_user, db_password |
allowed_plugins | comma-separated names | Domain plugins allowed to load (core is always loaded) |
max_log_level | log level name | Logging verbosity ceiling |
access_token_expires_in | minutes (validated 5 min – 30 days) | Access token lifetime |
refresh_token_expires_in | minutes (validated 1 day – ~300 days) | Refresh token lifetime |
read_cache_capacity_size / read_cache_capacity_bytes | integer | ModelCache capacity limits |
dev_mode / environment | bool / label | Development toggles and environment name shown in /info |
Configuration can also be edited at runtime by a SuperAdmin via the built-in web form at /api/v1/superadmin/configure — fields requiring a restart (host, ports, database, allowed plugins) are marked, with an optional scheduled restart.
start command)| Flag | Example | Description |
|---|---|---|
-p, --port <n> | 9000 | HTTP server port |
-f, --frontend-port <n> | 9000 (or 443 behind TLS proxy) | Port the frontend uses for API calls (relevant behind a reverse proxy) |
-h, --host <url> | http://localhost | Host URL base (used for absolute URL generation) |
-s, --static-directory <path> | ./frontend | Path to frontend static files directory |
Command-line flags override the corresponding hive.properties values. Everything else (tokens, access mode, plugins, cache) is configured via the properties file or the SuperAdmin configure UI.
| Deployment | Recommended access_mode | Reasoning |
|---|---|---|
| Local development | PublicFullAccess (8) | No auth friction during development |
| Private personal server | AuthenticatedFullAccess (5) or AuthenticatedReadWrite (4) | All users must log in; write access per role |
| Small team / internal | AuthenticatedReadWrite (4) | Login required; roles control writes; validators add per-model rules |
| Public read / private write | PublicReadOnlyAuthenticatedReadWrite (7) | Guests read; authenticated users write according to roles |
| Maintenance window | MaintenanceMode (0) | All requests rejected — migration or upgrade in progress |
Hive ships with a hive.service systemd unit file for running as a Linux daemon. Edit paths to match your installation before enabling.
# hive.service — real template shipped in the repository
# (replace the {PLACEHOLDER} values with your paths)
[Unit]
Description=Hive (C++ REST backend)
After=network.target
[Service]
Type=simple
User={USER}
Group={USER}
WorkingDirectory={WORKING DIRECTORY}
ExecStart={PATH}/hive start --port 9000 --frontend-port 443 \
--host {HOST} -s {PATH TO frontend}
Restart=on-failure
RestartSec=5s
Environment=USER={USER} HOME={HOME}
StandardOutput=append:/var/log/hive.log
StandardError=append:/var/log/hive.err
# kill settings — graceful shutdown
KillSignal=SIGINT
TimeoutStopSec=10
[Install]
WantedBy=multi-user.target
Note the template's --frontend-port 443: when a TLS reverse proxy terminates HTTPS on 443, the frontend must call the API through the proxy port, not Hive's internal port.
# Install and enable
sudo cp hive.service /etc/systemd/system/
sudo nano /etc/systemd/system/hive.service # edit paths
# Enable and start
sudo systemctl daemon-reload
sudo systemctl enable hive
sudo systemctl start hive
# Status and logs
sudo systemctl status hive
sudo journalctl -u hive -f # live log tail
sudo journalctl -u hive --since "1 hour ago" # last hour
hive user — no root required.access_mode=AuthenticatedFullAccess (or stricter) in hive.properties.registration_mode=AdminAddsUsers if the server is not intended for public registration.configuration/hive.properties and hive.db are readable only by the hive user.hive.db regularly — this SQLite file contains all your data.Hive ships a GoogleTest/GoogleMock test suite under tests/, built as the Tests target (enabled by default via ENABLE_TESTS=ON) and registered with CTest through gtest_discover_tests().
# Configure with tests (ON by default)
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DENABLE_TESTS=ON
cmake --build build --target Tests
# Run all tests via CTest
cd build && ctest --output-on-failure
# Run a specific test filter
ctest -R "PluginRegistry" --output-on-failure
# Run directly with GoogleTest output
./build/tests/Tests --gtest_filter="AccessMode*"
tests/hive/)| Test file / area | What is verified |
|---|---|
UtilsTests.cpp | Shared utility functions (string/time helpers, hashing) |
AccessModeTests.cpp | All 9 access mode enum values and the AccessMode × UserRole × CRUDL permission matrix |
api/PluginRegistryTests.cpp | Topological sort correctness, CyclicDependencyException and MissingDependencyException detection |
api/cronq/ | Cron expression parsing and scheduling logic of the cronq scheduler |
| Symptom | Likely cause | Fix |
|---|---|---|
CMake error: Could not find OpenSSL |
OpenSSL development headers not installed | sudo apt install libssl-dev (Debian/Ubuntu) or set -DOPENSSL_ROOT_DIR=... |
Compiler error: feature not supported with this compiler |
GCC version too old for C++23 | Install GCC 14: sudo apt install gcc-14 g++-14; set -DCMAKE_CXX_COMPILER=g++-14 |
Server starts but /web/ returns 404 |
Wrong frontend path in -s flag |
Verify -s ./frontend points to the directory containing index.html |
| Migration integrity error on startup | An already-applied embedded migration script was modified (checksum or chain-hash mismatch) | Revert the migration script to its original content, or delete the database and restart (data loss — dev only) |
MissingDependencyException on startup |
A plugin listed in allowed_plugins does not exist or its dependency is not enabled |
Check allowed_plugins in hive.properties; ensure all dependency plugins are listed |
| Frontend shows no models / empty navigation | /api/v1/model_definition returns empty or CORS issue |
Check server logs; verify allowed_plugins has correct plugin names; try curl http://localhost:9000/api/v1/model_definition |
| Login returns 403 even with correct credentials | access_mode=MaintenanceMode or user status is Pending/Banned |
Check access_mode in config; check user record status in user table |