Skip to content

Architecture

Kittynode is a control center for world computer operators. The codebase is architected to be tiny, extensible, and secure.

The least important goal is speed, but Kittynode is also blazing fast. We care deeply about code quality and thorough testing.

Kittynode is split into four crates. These boundaries let us reason clearly about security per module, reuse code, and refactor fearlessly.

CrateWhat it does
kittynode-coreRust library that defines the APIs, Docker integration, manifests, and persistence shared by every surface
kittynode-cliThin wrapper that forwards subcommands to kittynode-core and can spin up kittynode-web
kittynode-tauriTauri desktop/mobile shell that communicates with kittynode-core over IPC or HTTP
kittynode-webAxum HTTP service that exposes the core API for remote management and automation
  • Consumers import from kittynode_core::api and kittynode_core::api::types only.
  • Internal layers (application, domain, infra, manifests) remain crate-internal to allow for refactors without breaking consumers.

Inside kittynode-core the folders map directly to responsibilities:

  • application orchestrates use cases such as installing packages, updating configuration, and managing capabilities.
  • domain defines the data types that move between layers as plain structs and enums.
  • infra talks to Docker through Bollard, manages files under ~/.config/kittynode, and persists configuration.
  • manifests holds package definitions. Each manifest describes the containers, networks, and volumes needed for a stack like Ethereum.

This split keeps privileged logic small and makes it straightforward to add new behaviours without touching every consumer.

Kittynode has three user facing apps:

  • A command line interface.
  • A desktop app.
  • A mobile app.

Every app uses the same core library, and the desktop/mobile app uses the same frontend code. By re-using components, Kittynode is smaller, easier to audit, and more secure.

The Tauri app switches between a local IPC client and an HTTP client (kittynode-web) based on the configured server URL. This allows us to manage a remote node without changing any UI code.

Remote mode disables sensitive flows like key generation on the controlling device, but still surfaces live status from the node. The kittynode-web process is invoked from the CLI app. When operators execute the kittynode-web command, a background process spawns and runs the HTTP web server.

There are several capabilities you can add to your Kittynode which augment the threat model. We default to minimizing the capabilities of the Kittynode, while giving enough features to get started.

Here are a few example capabilities related to remote access:

  • Read only (default): Kittynode is a read-only monitoring application.
  • Local only: Kittynode can update local node infrastructure from the host machine.
  • Private onchain requests: Kittynode can update local node infrastructure via listening to private requests submitted onchain.
  • Local HTTPS server: Kittynode can update local node infrastructure via requests that come from the same Wireguard network (but a different machine, such as a phone); these requests are authenticated by a passkey or JWT token.

Capabilities and general configuration are stored under ~/.config/kittynode/config.toml.

Kittynode supports a package ecosystem. Ethereum nodes are simply packages which are executed and managed by Kittynode. Developers can create their own packages easily with Kittynode’s package API. Kittynode supports Docker images but also supports direct binary executables. Kittynode may also support other languages and executable scripts in the future.

The design goals of the package ecosystem are to ensure installs are:

  • Secure: Packages are securely isolated from each other.
  • Consistent: Packages behave the same on all systems.
  • Atomic: Package installs and uninstalls are atomic, without polluting the system.

The system checker is a utility within Kittynode that checks the system prerequisites for running a node, along with other system checks. A short list of some checks are:

  • System resources: Checking the available storage, CPU, and RAM.
  • Network settings: Checking the firewall and internet connectivity.
  • Security settings: Checking file permissions and other system security settings.

The system checker is important in several areas of Kittynode. For example, when applying configuration changes it ensures networking and file permissions meet our security expectations.

Kittynode supports remote access. This means you can setup and monitor your node from a phone or desktop. This is currently done via a secure connection over Wireguard, which allows users to monitor their node from trusted devices. This also allows users to easily upgrade their nodes from anywhere, which is important for voting.

Package installs are declarative:

  1. A manifest returns a Package with default configuration and container definitions.
  2. infra::package::install_package creates the Docker network, pulls images, and starts the containers.
  3. infra::package::delete_package stops containers, removes Docker resources, and cleans any files that were mounted.

Because the manifests are normal Rust code, adding a new stack mainly means writing one manifest and any matching UI strings.

kittynode-core reports mode, Docker health, and diagnostics through get_operational_state. If Docker is not running and auto-start is enabled, start_docker_if_needed will try to launch Docker once and return a status so the UI can inform the operator. Hardware, storage, and OS details come from get_system_info and feed into the same status views.


Kittynode is free software released under the MIT License.