Realm - Simple container orchestration service
Realm is a extendable, embeddable and simple orchestration service for different type of loads such as native processes or OCI containers.
It's simple because it is just one executable to command the cluster where Realm runs as daemon on each one of the cluster nodes. It's also extendable because it uses a driver systems to extend it with custom loads or node drivers. Managing the cluster can be commanded from command-line interface or using the REST API that each daemon exposes. It's embeddable because Realm provides a C API to interface with clusters.
Development setup
Recommended setup is Debian 12 or Windows 11 Pro with Go >=1.24 installed.
Windows 11 Pro setup
We recommend to use only Powershell and check that you don't use msys2 or have another unix shell installed, make can conflicts with these shells.
Install building dependencies (required for CGO):
choco install mingw
Install golang: https://go.dev/doc/install
Install containerd:
Enable-WindowsOptionalFeature -Online -FeatureName containers -All
mkdir "c:\Program Files\containerd"
cd "c:\Program Files\containerd"
curl.exe -L https://github.com/containerd/containerd/releases/download/v2.2.1/containerd-2.2.1-windows-amd64.tar.gz -o containerd-windows-amd64.tar.gz
tar.exe xvf .\containerd-windows-amd64.tar.gz -C "c:\Program Files\containerd"
$Path = [Environment]::GetEnvironmentVariable("PATH", "Machine") + [IO.Path]::PathSeparator + "$Env:ProgramFiles\containerd\bin"
[Environment]::SetEnvironmentVariable("Path", $Path, "Machine")
containerd.exe config default | Out-File "c:\Program Files\containerd\config.toml" -Encoding ascii
containerd --register-service
net start containerd
Debian 12 setup
Install ansible:
apt update
apt install ansible -y
Building with ZFS support (optional)
ZFS volume support is optional and enabled at build time with the zfs build tag. To build with ZFS, you will need to install the ZFS development libraries from Debian Bookworm Backports.
Install backports as follows:
cat > /etc/apt/sources.list.d/bookworm-backports.list << EOF
deb http://deb.debian.org/debian bookworm-backports main contrib non-free-firmware
EOF
Now install the ZFS development dependencies:
apt update
apt install zfsutils-linux libzfslinux-dev -y
Then build with:
make TAGS=zfs
Before starting the daemon with ZFS support, create the ZFS pool:
sudo zpool create realm_volumes /dev/sdX # Replace /dev/sdX with your device
Without the zfs tag, Realm uses directory-based volumes which work on all platforms with no extra dependencies.
Configuration
Realm can be configured using a YAML configuration file (config.yaml) or environment variables.
Etcd configuration
Realm always starts a etcd client but it can also start an embedded etcd server. Basically a Realm cluster always expect at least one realm daemon with the embedded etcd server running.
A typical scenario is setting up a single-node cluster as follows:
- A selected realm daemon shall start as etcd server. For example:
daemon:
etcd_listen_client_urL: http://192.168.105.2:2379
etcd_listen_peer_url: http://192.168.105.2:2380
In this configuration, embedded etcd will listen for client requests on http://192.168.105.2:2379 and will listen for other etcd cluster peers on http://192.168.105.2:2380. It's important to notice that these URLs are also the ones advertise to the rest of the cluster. Have in mind also that another cluster peers can join later to the formation, that's why we need to set etcd_listen_peer_url even in a single-node formation.
- Others realm daemons will be configured as etcd clients. Following the example:
daemon:
data_path: ./realm_data
etcd_mode: client
etcd_listen_client_url: http://192.168.105.3:2379
etcd_endpoints: ["http://192.168.105.2:2379"]
etcd_endpoints is a list of client URLs of etcd members and it works as a bootstrap list.
You can use etcdctl to list the member states. Following the example:
etcdctl --write-out=table --endpoints=192.168.105.2:2379 member list
Daemon Configuration
The daemon section configures the realm daemon behavior. All fields are optional and have default values:
daemon:
data_path: /var/lib/realm # Path to store daemon data (ID and etcd) (default: /var/lib/realm on Linux)
cni_path: /usr/lib/cni # Path to CNI plugins (default: /usr/lib/cni on Linux)
volumes_pool: realm_volumes # Name of the volumes pool (ZFS pool name or directory name) (default: realm_volumes)
listen_address: 127.0.0.1 # Address to bind the daemon API (default: 127.0.0.1)
listen_port: 9000 # Port to bind the daemon API (default: 9000)
logs_path: /var/log/realm # Path to store daemon logs (default: /var/log/realm on Linux)
log_format: text # Log format: "text" or "json" (default: text)
containers_log_path: /var/log/realm/containers # Path to store container logs (default: platform-specific)
proxy_enabled: false # Enable/disable the proxy (default: false)
local_caddy_url: localhost:2019 # Local Caddy admin URL (default: localhost:2019)
master_caddy_url: localhost:2019 # Master Caddy admin URL (default: localhost:2019)
github_registry_token: "" # Token for GitHub registry (default: empty)
containerd_sock: /run/containerd/containerd.sock # Containerd socket path (default: platform-specific)
containerd_namespace: realm # Containerd namespace (default: realm)
etcd_name: "" # etcd member name (default: empty)
etcd_listen_client_url: http://192.168.1.100:2379 # etcd client URL (default: auto-detected from main network interface)
etcd_listen_peer_url: http://192.168.1.100:2380 # etcd peer URL (default: auto-detected from main network interface)
etcd_initial_cluster: "" # etcd initial cluster configuration (default: empty)
etcd_cluster_state: new # etcd cluster state: "new" or "existing" (default: new)
Environment Variables
Configuration values can be overridden using environment variables with the REALM_ prefix and underscores for nested values:
REALM_DAEMON_LOG_FORMAT=json
REALM_DAEMON_LISTEN_PORT=9001
Security
All containers shall not have any capabilities. For example we don't set NET_ADMIN (https://man7.org/linux/man-pages/man7/capabilities.7.html) to prevent containers modifying routing tables what could allow them to have access to other containers outside of its internal network.
Contributing
Please follow the guidelines below to ensure code quality and consistency.
Code Style and Conventions
This project follows standard Go conventions as outlined in Effective Go and the Go Code Review Comments.
Naming
- Use MixedCaps or mixedCaps rather than underscores for multi-word names
- Acronyms should be all capitals (e.g.,
URL, HTTP, API)
- Interfaces with a single method should be named with the method name plus the
-er suffix (e.g., Reader, Writer)
- Package names should be short, concise, lowercase, and without underscores or mixedCaps
- All exported functions, types, constants, and variables must have doc comments
- Doc comments should be complete sentences starting with the name of the element
- Package comments should be included above the package declaration
- Use
// style comments; avoid /* */ except for package comments
Example:
// LoadDriver manages the lifecycle of container loads.
// It provides methods to create, start, stop, and remove loads.
type LoadDriver interface {
// Create creates a new load with the given configuration.
Create(ctx context.Context, config *LoadConfig) error
// Start starts the specified load by ID.
Start(ctx context.Context, loadID string) error
}
Code Organization
- Organize imports into groups: standard library, third-party, local packages
- Use
make verify-fmt to format all code before committing
- Run
make vet to catch common mistakes
Error Handling
- Always check errors; don't use
_ to discard errors unless you have a good reason
- Provide context when returning errors using
fmt.Errorf with %w for wrapping
- Use meaningful error messages that help debugging
Example:
if err := daemon.Start(ctx); err != nil {
return fmt.Errorf("failed to start daemon: %w", err)
}
Project Structure
realm/
├── cmd/ # Command-line interface
│ ├── main.go # Application entry point
│ ├── daemon.go # Daemon commands
│ ├── containers.go # Container management commands
│ ├── images.go # Image management commands
│ ├── network.go # Network commands
│ ├── nodes.go # Node management commands
│ ├── proxy.go # Proxy commands
│ └── loads.go # Load management commands
├── daemon/ # Daemon implementation
├── drivers/ # Standard drivers
├── internal/ # Private application code
│ ├── dto/ # Data Transfer Objects
│ └── runtime/ # Runtime abstractions
├── config/ # Configuration management
│ └── logs/ # Logging configuration
├── dev/ # Development tools and scripts
│ └── ansible/ # Ansible playbooks for deployment
└── docs/ # Documentation
Development Workflow
- Fork and clone the repository
- Create a feature branch from
main:
git checkout -b feature/my-feature
- Make your changes following the code style guidelines
- Write tests for new functionality
- Run tests to ensure everything passes:
make test
- Format your code:
gofmt -w .
- Commit your changes with clear, descriptive commit messages
- Push to your fork and submit a pull request
Testing
- Place tests in
*_test.go files in the same package
- Run tests before submitting pull requests:
make test
Documentation
- Add doc comments to all exported types, functions, constants, and variables
- Keep comments up-to-date when changing code
- Use examples in doc comments where helpful
Pull Request Guidelines
- Keep pull requests focused on a single feature or bug fix
- Reference any related issues in the PR description
- Ensure all tests pass and code is formatted before submitting
- Be responsive to review feedback
- Squash commits if requested before merging
License
Realm is dual-licensed:
Open Source License: AGPL-3.0
The open-source version of Realm is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
Commercial License
If you cannot comply with AGPL-3.0 requirements, we offer commercial licenses that allow you to:
- 🔓 Use Realm in proprietary/closed-source applications
- 🔓 Embed Realm via the C API without open-sourcing your code
- 🔓 Offer Realm-based services without releasing your source code
- 🎯 Receive enterprise support and SLA guarantees
- 🎯 Access professional services and custom development
Commercial licenses include:
- Freedom from AGPL-3.0 requirements
- Enterprise support with SLA
- Professional services options
- Legal indemnification
For commercial licensing options and pricing, contact licensing@bitomia.com.
Copyright (C) 2024-2025 Bitomia Software SLU. All rights reserved.