# smartbotic-automation: Debian 13 packaging + upstream DB migration **Date:** 2026-05-09 **Status:** Design — pending user approval **Owner:** Ferenc Szontagh ## 1. Goal Ship the contents of `/data/smartbotic` as a single Debian 13 (`trixie`) `.deb` package named `smartbotic-automation`, distributed through the SmartBotics APT repository at `https://repository.smartbotics.ai`. As part of this work, drop the in-repo `src/database/` service entirely and have our remaining services (`smartbotic-webserver`, `smartbotic-runner`, `smartbotic-migrate-nodes`) talk to the standalone upstream `smartbotic-database` daemon via its `libsmartbotic-db-client` library (upstream repo: , current version `1.7.5`). Packaging style follows `/data/shadowman-cpp/packaging/` and `/tmp/smartbotic-database-upstream/packaging/` — Docker-based two-stage build targeting Debian 13, with `build.sh --sync` integration into `/data/smartbotics-deb-repo/`. ## 2. Identity & metadata | Field | Value | | --- | --- | | Package name | `smartbotic-automation` | | Version source | `/data/smartbotic/VERSION` (new file, initial value `1.0.0` — matches `project(SmartBotic VERSION 1.0.0 …)` in `CMakeLists.txt`) | | Architecture | `amd64` | | Maintainer | `Ferenc Szontagh ` | | Section | `contrib/utils` | | Priority | `optional` | | License | proprietary (`Proprietary software by SmartBotics Kft.`) | | Homepage | `https://smartbotics.ai` | | Target distro | Debian 13 (`trixie`) | ## 3. Code migration: drop internal DB, adopt upstream client ### 3.1 Removals - `src/database/` (entire directory: `database_service.{cpp,hpp}`, `memory_store.{cpp,hpp}`, `document.hpp`, `main.cpp`, `persistence/{wal,snapshot}.{cpp,hpp}`) - `proto/storage.proto` (replaced by upstream's `database.proto`, which we do not need to ship — upstream client hides gRPC behind PIMPL) - The `smartbotic-database` CMake executable target (currently at `CMakeLists.txt:152`) - The current `lib/storage/storage_client.{cpp,hpp}` implementations (file paths kept; contents replaced — see §3.2) ### 3.2 `lib/storage/` adapter Keep the existing public interface so that the 10 caller files do not need to change: - `src/webserver/webserver_service.{hpp,cpp}` - `src/webserver/runners/runner_registry.{hpp,cpp}` - `src/webserver/nodes/node_store.{hpp,cpp}` - `src/webserver/api/database_controller.cpp` - `src/webserver/api/workflow_group_controller.cpp` - `src/webserver/api/webhook_controller.{hpp,cpp}` Internally, `lib/storage/storage_client.cpp` becomes a thin adapter over `smartbotic::database::Client` (`` from `libsmartbotic-db-client-dev`): | Adapter API (kept stable) | Upstream call | | --- | --- | | `Result get(coll, id)` | wraps `std::optional Client::get(...)` | | `Result insert(coll, data, id, ttl_ms)` | `Client::insert(...)` (note: upstream takes `ttlSeconds` — we convert) | | `Result update(coll, id, data, expected_version, partial)` | dispatch by flags: `partial=false, expected_version=0` → `Client::update`; `partial=false, expected_version!=0` → `Client::updateIfVersion`; `partial=true` → `Client::patch` | | `Result remove(coll, id, expected_version)` | `Client::remove` / `Client::removeIfVersion` | | `QueryResult query(coll, options)` | `Client::find(...)` (translate filter/sort enums) | Translation rules: - TTL: caller passes ms; upstream takes seconds. Adapter divides by 1000, rounding up; documents the loss-of-precision in a one-line comment. - Connection address: adapter `StorageClientConfig::address` default changes from `localhost:9001` to `localhost:9004` (upstream default), and is config-overridable through `webserver.json` / `runner.json`. - Versioning options (`VersioningOptions`, `DocumentVersionInfo`, `VersionListResult`) map directly onto upstream's version-history API. If a method on our existing surface has no upstream equivalent (none expected on a quick read of `client.hpp`), it gets removed and any caller adapted at the same time. ### 3.3 CMake changes - Remove `src/database/*` source list and the `add_executable(smartbotic-database ...)` block. - Replace internal `proto/storage.proto` references in `lib/storage/`'s target with a `find_package(libsmartbotic-db-client REQUIRED)` (or `pkg_check_modules` fallback). `target_link_libraries(smartbotic_storage PUBLIC smartbotic::database::client)` (exact target name to be confirmed when reading the installed CMake config). - `proto/credentials.proto`, `proto/runner.proto`, `proto/workflow.proto`, `proto/common.proto` remain — they are between webserver and runner, not the DB. ### 3.4 `smartbotic-migrate-nodes` Verify (in implementation phase) that this binary only talks to the webserver via HTTP `/api/v1/nodes/migrate` and has no direct DB dependency. If it does have a direct DB dependency, port it to the new client at the same time. ## 4. Installed file layout (system-wide) ``` /usr/bin/smartbotic-webserver /usr/bin/smartbotic-runner /usr/bin/smartbotic-migrate-nodes /usr/share/smartbotic-automation/webui/ # built React app (`webui/dist/`) /usr/share/smartbotic-automation/nodes/ # default workflow node JS modules /etc/smartbotic-automation/webserver.json # conffile /etc/smartbotic-automation/runner.json # conffile /etc/smartbotic-automation/env # optional EnvironmentFile (empty default, conffile) /var/lib/smartbotic-automation/ # mode 0750, owned smartbotic-automation:smartbotic-automation /var/log/smartbotic-automation/ # mode 0750, owned smartbotic-automation:smartbotic-automation /lib/systemd/system/smartbotic-automation-webserver.service /lib/systemd/system/smartbotic-automation-runner.service ``` Both default config files point `database.address` at `localhost:9004`. Admin overrides per-deployment. ### 4.1 systemd units `smartbotic-automation-webserver.service`: ```ini [Unit] Description=SmartBotic Automation — Webserver (HTTP/WS API) After=network.target smartbotic-database.service Wants=smartbotic-database.service [Service] Type=simple User=smartbotic-automation Group=smartbotic-automation ExecStart=/usr/bin/smartbotic-webserver --config /etc/smartbotic-automation/webserver.json WorkingDirectory=/var/lib/smartbotic-automation EnvironmentFile=-/etc/smartbotic-automation/env Restart=on-failure RestartSec=5 TimeoutStopSec=15 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target ``` `smartbotic-automation-runner.service` is structurally identical, with `ExecStart=/usr/bin/smartbotic-runner --config /etc/smartbotic-automation/runner.json` and `After=network.target smartbotic-automation-webserver.service`. The unit *Wants* `smartbotic-database.service` — that upstream daemon is a `Depends:` of our package. The admin is responsible for ensuring it listens on the port `webserver.json` points at (default `9004`; in test environments where the host already has another `smartbotic-database` instance, run ours on an alternate port and override). ## 5. Dependencies ``` Depends: smartbotic-database (>= 1.7.5), libsmartbotic-db-client (>= 1.7.5), libssl3t64, libprotobuf32t64, libgrpc++1.51t64, libspdlog1.15, libfmt10, libuuid1, zlib1g, nodejs Build-Depends: libsmartbotic-db-client-dev (>= 1.7.5), libgrpc++-dev, libprotobuf-dev, protobuf-compiler, protobuf-compiler-grpc, libssl-dev, libspdlog-dev, libfmt-dev, libuuid-dev, nlohmann-json3-dev, nodejs, npm, cmake (>= 3.20), ninja-build, g++ (>= 12) ``` (The exact versioned names match Debian 13 / `trixie` package names — the `t64` suffix is the time64 transition. We mirror ShadowMan's list and trim to what we actually link.) ## 6. Maintainer scripts ### 6.1 `preinst` No-op for `install` and `upgrade` (mirrors ShadowMan). ### 6.2 `postinst configure` 1. Create system group + user (idempotent), home `/home/smartbotic-automation`, shell `/usr/sbin/nologin`. 2. `install -d -o smartbotic-automation -g smartbotic-automation -m 0750` on: - `/home/smartbotic-automation` - `/var/lib/smartbotic-automation` - `/var/log/smartbotic-automation` - `/etc/smartbotic-automation` (only if missing) 3. `systemctl daemon-reload` 4. **First install:** `deb-systemd-helper enable smartbotic-automation-webserver.service smartbotic-automation-runner.service` — **but do not start them.** Reason: the operator must first verify that `smartbotic-database` is reachable at the configured port (default `9004`) before starting our services. A `NEWS.Debian` or echo at install time will tell the admin to run `systemctl start smartbotic-automation-webserver smartbotic-automation-runner` once the DB is ready. 5. **Upgrade:** `deb-systemd-invoke try-restart` for any unit that was already active. ### 6.3 `prerm remove` / `prerm upgrade` `deb-systemd-invoke stop` both units. On `prerm remove`: also `deb-systemd-helper disable` them. ### 6.4 `postrm purge` - `deluser --system smartbotic-automation` (idempotent) - `delgroup --system smartbotic-automation` (idempotent) - `rm -rf /var/lib/smartbotic-automation /var/log/smartbotic-automation` - Leave `/etc/smartbotic-automation/` to dpkg's normal conffile handling. ## 7. `packaging/` directory layout (added to `/data/smartbotic`) ``` packaging/ Dockerfile.base # Debian 13 + build deps + libsmartbotic-db-client-dev Dockerfile.build # COPY source, build C++ + npm run build, dpkg-deb assembly build.sh # orchestrator smartbotics-repo.gpg # public APT key (copied from /data/smartbotics-deb-repo/) deb/ templates/ control.smartbotic-automation scripts/ preinst postinst prerm postrm systemd/ smartbotic-automation-webserver.service smartbotic-automation-runner.service config/ webserver.json runner.json env ``` ### 7.1 `Dockerfile.base` Mirrors ShadowMan's `Dockerfile.base`: - `FROM debian:trixie` - Configure SmartBotics APT repo with `REPO_USER` / `REPO_PASS` build args (used to install `libsmartbotic-db-client-dev`) - Install build toolchain: `build-essential cmake ninja-build git pkg-config ccache libssl-dev libprotobuf-dev libgrpc++-dev protobuf-compiler-grpc nlohmann-json3-dev libspdlog-dev libfmt-dev libuuid-dev zlib1g-dev nodejs npm libsmartbotic-db-client-dev` Image tag: `smartbotic-automation-build-base:debian13`. ### 7.2 `Dockerfile.build` - `FROM smartbotic-automation-build-base:debian13` - Mount source as `/src`, build dir `/build`, output dir `/out` - `cmake -G Ninja -B /build -S /src -DCMAKE_BUILD_TYPE=Release` - `cmake --build /build -j${BUILD_JOBS}` - `npm --prefix /src/webui ci && npm --prefix /src/webui run build` - `bash /src/packaging/scripts/assemble-deb.sh /build /src/webui/dist /out` — writes the `DEBIAN/` payload tree, runs `dpkg-deb --build` - Final `.deb` lands in `/out/` ### 7.3 `build.sh` flag surface (matches ShadowMan + upstream) ``` [VERSION] --rebuild-base --no-cache --deb-revision N (default 1) --repo (run /data/smartbotics-deb-repo/scripts/{add-packages,create-repo --suite}) --suite NAME (default trixie) --sync (--repo + sync-repo.sh) --help / -h ``` Env: `BUILD_JOBS` (default `nproc`), `DEB_REPO_DIR` (default `/data/smartbotics-deb-repo`). Outputs land in `/data/smartbotic/dist/debian13/smartbotic-automation_-_amd64.deb`. ## 8. APT repository deployment `build.sh --sync --suite trixie` chains: 1. `${DEB_REPO_DIR}/scripts/add-packages.sh dist/debian13/` 2. `${DEB_REPO_DIR}/scripts/create-repo.sh --suite trixie` 3. `${DEB_REPO_DIR}/scripts/sync-repo.sh` End state: `apt install smartbotic-automation` works on a `trixie` host that has the SmartBotics repo configured. ## 9. Local-instance cleanup (this host) Confirmed during exploration: - Nothing built from `/data/smartbotic` is currently running as a service or process. - The system service `smartbotic-database.service` running `/usr/bin/smartbotic-database` (installed package `smartbotic-database 1.7.1-1`) belongs to a different project — left intact per user direction. No cleanup action needed on this host. Testing of the new package will happen on a separate VM or with a side-by-side smartbotic-database instance running on an alternate port. ## 10. Decisions explicitly approved by user 1. **DB strategy:** delete `src/database/`, depend on upstream `smartbotic-database` package, talk to it via `libsmartbotic-db-client`. 2. **Package layout:** single `smartbotic-automation` package (no split). 3. **Install prefix:** system-wide (`/usr/bin/`, `/usr/share/smartbotic-automation/`, `/etc/smartbotic-automation/`). 4. **Local instance:** leave the unrelated `smartbotic-database 1.7.1-1` system service alone. 5. **Auto-start policy on first install:** `enable` units, but **do not start** — admin must point config at a reachable `smartbotic-database` and start manually (the upstream DB port is deployment-specific). ## 11. Out of scope - Repackaging the upstream `smartbotic-database` itself. - Any frontend / `webui/` feature work beyond `npm run build`. - Cross-distro builds (only `trixie` is targeted). - Migrating the existing `/data/smartbotic` `smartbotic-database` *data* (WAL, snapshots) — operators run a fresh upstream instance for their deployment. ## 12. Implementation phases (for the plan) 1. **Phase A — code migration**: remove `src/database/`, rewrite `lib/storage/`, fix CMake, ensure native build (`cmake --build build`) succeeds. 2. **Phase B — packaging skeleton**: add `packaging/` directory, write `Dockerfile.base`, `Dockerfile.build`, `build.sh`, control template, maintainer scripts, systemd units, default configs, `VERSION` file. Confirm Docker build produces a `.deb`. 3. **Phase C — install / smoke test**: install the `.deb` in a throwaway container or VM, start the upstream `smartbotic-database` on the configured port, start `smartbotic-automation-webserver`, hit `/api/v1/healthz`, confirm node migration and basic workflow works. 4. **Phase D — repo publish**: `build.sh --sync --suite trixie`. Verify `apt update && apt install smartbotic-automation` works from a clean `trixie` host.