Skip to content

Your cloud

Your Hardware. Your Cloud.

A cloud is not a mysterious computer somewhere else. It is infrastructure, automation and control. Start with one machine and add layers only when they solve a real problem.

Saphira Linux dragon mascot

Four ways to run your workloads

Virtual machines

QEMU/KVM and libvirt

Complete guest operating systems with separate kernels, storage and networking. Choose this for isolation, independent operating systems and conventional server workloads.

Application containers

Docker

Application images and containers on one host. Choose this for individual services, development environments and reproducible deployments.

Container orchestration

Kubernetes

Desired state and scheduling across nodes. Choose this when the operational need justifies operating a cluster.

Infrastructure management

OpenStack

Virtual machines, networks, images, projects and storage through a control plane. Choose this for repeatable multi-user infrastructure and self-service APIs.

These layers can work together, but they are not interchangeable. Docker can run on a VM; Kubernetes can schedule Docker-style container workloads; OpenStack can supply the VMs beneath them. Complexity is not proof of maturity.

One Saphira, two service choices

Saphira and SaphiraD use the same packages and the same service names. Saphira uses OpenRC and its /etc/init.d/ service scripts; SaphiraD uses systemd and its /usr/lib/systemd/system/ units. The package contains both. Choose the commands for the system you booted—never run both sets.

Saphira · OpenRC

rc-update add SERVICE default
rc-service SERVICE start
rc-service SERVICE status

SaphiraD · systemd

systemctl enable --now SERVICE.service
systemctl status SERVICE.service

Installing an APK does not silently enable a service on either edition. That makes testing calmer: install the parts, review the configuration, then deliberately choose when a service should start now and at the next boot.

Start with the explanation you need

Docker: containers on your own terms

Docker 29.9.2 is published as separate engine, client, Compose and Buildx packages. The engine uses containerd; package installation does not enable the daemon.

apk update
apk add docker-engine docker-cli docker-compose docker-buildx

# Saphira / OpenRC
rc-update add dockerd default
rc-service dockerd start

# Saphira-D / systemd
systemctl enable --now dockerd.service

docker run --rm hello-world

The verified service is dockerd on both init systems. Images, writable layers and volumes live under /var/lib/docker; protect persistent volumes in backups, collect docker logs before deleting a failed container, and restart the daemon only with awareness that running containers can be affected.

Docker depends on the packaged containerd service. OpenRC expresses that dependency in dockerd’s init script and systemd expresses it in dockerd.service; enable and start containerd explicitly too when preparing a host from scratch.

Docker networking changes host firewall behaviour. Treat Docker-daemon access as root-equivalent, keep registry credentials out of images and compose files, review published ports, and use named volumes rather than assuming a container filesystem is durable.

There is not yet a Saphira Docker deployment helper. Install and operate the packages deliberately on each host, keep the daemon disabled until required, and record the volumes, networks, published ports and restart policy that each application needs. Docker’s package split is useful precisely because a host need not carry every Docker component.

Docker upstream documentation explains Docker itself; it is not evidence that every workload has been tested on Saphira.

Kubernetes: published components, deliberate clusters

Saphira publishes kubernetes-1.37.1-r4, saphira-kubernetes-0.1-r9 and kubectl-0.37.1-r1. The Kubernetes package contains kubelet, kubeadm and kube-proxy; the verified service name is kubelet. Installing binaries is not creating a control plane, joining workers, or proving a cluster.

apk add kubernetes kubectl saphira-kubernetes

# Enable kubelet only after kubeadm has supplied its configuration.
# OpenRC: rc-update add kubelet default && rc-service kubelet start
# systemd: systemctl enable --now kubelet.service

kubeadm version
kubectl version --client

Plan node IPv4/IPv6 ranges before selecting a CNI. containerd is the runtime boundary; CRI connects kubelet to it, while CNI provides pod networking. Service networking, persistent storage, registry credentials, certificates, node joins, upgrades and recovery are separate operator jobs.

Use the Saphira Kubernetes helper to plan and prove a cluster

saphira-kubernetes is a host-authorised, declarative cluster helper. It reads /etc/saphira-kubernetes/hosts, cluster files in /etc/saphira-kubernetes/clusters/ and one node file per member in the matching .d/ directory. A host absent from hosts is refused before an SSH connection is attempted; SSH is key-only and host keys are never accepted automatically.

apk add containerd cni-plugins kubectl kubernetes saphira-kubernetes

# Create your own hosts and cluster/node configuration first.
# Use the installed schema and example; addresses and Pod networks are never guessed.
sed -n '1,240p' /usr/share/doc/saphira-kubernetes/CONFIG.md
sed -n '1,160p' /usr/share/doc/saphira-kubernetes/example-cluster.conf

# Read-only checks and a reproducible plan.
saphira-kubernetes inventory --host local --host worker1
saphira-kubernetes plan --cluster production

# Preview first. apply requires an explicit confirmation and, for workers,
# names the control-plane member that mints the short-lived join token.
saphira-kubernetes --dry-run apply --cluster production --control-plane cp --confirm
saphira-kubernetes apply --cluster production --control-plane cp --confirm
saphira-kubernetes verify --cluster production --deep

A cluster file explicitly chooses ipv4, ipv6 or dual, its Pod and Service ranges, and its pinned Kubernetes line. Node files name each member’s role, authorised host and control-plane advertise address. After joining, the helper writes each node’s assigned PodCIDRs back into that node’s configuration; re-apply then renders the matching CNI configuration. Join tokens are minted at apply time and are not stored in these files.

Check every member before a live apply: forwarding enabled, swap off, overlay and br_netfilter available, bridge netfilter sysctls set, containerd usingSystemdCgroup=true, and CNI plugins available under /opt/cni/bin. The helper inventories and plans against those requirements; the successful result is still verify passing, not merely a package installation.

The helper can also add optional tools for installing, inspecting or viewing a cluster. They are not applications for your users and they are not installed by default. The Kubernetes setup guide explains what Helm, crictl, k9s and Headlamp are for before asking anyone to enable them. Its drain and removal actions are confirmation-gated; drain warns when it would destroy unmanaged bare Pods.

Use kubeadm to initialise a chosen control plane and its join command to add workers, then prove scheduling, networking and storage with a real workload. No HA claim is made here. Restrict API access, rotate credentials, back up control-plane state, and test recovery before depending on a cluster.

Kubernetes upstream documentation is the reference for Kubernetes behaviour; the published packages do not by themselves prove a finished cluster design.

OpenStack: build your own cloud

OpenStack adds Keystone identity, Glance images, Nova compute, Neutron networking, Placement scheduling, Horizon administration and Cinder volumes above QEMU/KVM, libvirt and Linux. Saphira publishes the role packages saphira-openstack-0.1-r3, controller, compute, storage and documentation.

The existing guides remain the source of operational detail: architecture, controller, compute, storage and troubleshooting.

Keep their boundaries: Cinder still requires end-to-end lifecycle proof, and the controller/Horizon path has documented asset prerequisites. Back up credentials, databases and configuration; never treat a package install as a cloud deployment.

Design and validate the OpenStack inventory first

The saphira-openstack helper is the shared planning foundation for the OpenStack role packages. It can inspect local interfaces, Open vSwitch, VLANs, ZFS, routes and the init system as suggestions, but it never chooses, formats, adopts or modifies them on its own. Its inventory declares controller and compute roles, independent IPv4/IPv6 addressing, networks, storage, service placement and operations.

apk add saphira-openstack

# Interactive design: writes an inventory only after explicit confirmation.
saphira-openstack init

# Review an existing inventory and prove that it is valid.
saphira-openstack inventory
saphira-openstack inventory --check
saphira-openstack plan

# The shipped examples are illustrations, not defaults.
ls /usr/share/saphira/openstack/examples

init writes /etc/saphira-openstack/inventory.ini only after confirmation. inventory and plan are read-only apart from an explicitly requested plan output directory. This helper does not install, configure or start OpenStack services: it gives the administrator a reproducible design and an honest package-readiness plan before they follow the controller, compute and storage guides.

Choose deliberately

Choose a VM when the guest needs its own operating system boundary. Choose Docker for a self-contained application on a host you administer. Choose Kubernetes when several machines need coordinated container scheduling. Choose OpenStack when several people need repeatable virtual infrastructure, APIs and project boundaries.

For every layer, plan host networking and firewall rules, persistent storage, credentials, logs, updates, backups and recovery first. The first successful operation is a small, observable workload—not a production promise.