Skip to content

Daemon Deployment on Bare Metal and VMs

This guide covers installing the Riptides daemon and kernel module on bare-metal Linux servers and virtual machines. This approach works for any Linux-based environment outside of Kubernetes, including EC2 instances, GCP VMs, Azure VMs, on-premises hardware, local development VMs (e.g., Lima), and Windows hosts via WSL2.

  • Linux kernel 5.15+ (x86_64 or ARM64), including the WSL2 kernel on Windows hosts
  • Root access
  • Network connectivity to the control plane’s API, gRPC, and tunnel endpoints (HTTPS/TLS on port 443)

The Riptides kernel module provides transparent in-kernel TLS/mTLS termination for TCP sockets.

The recommended way to install it is via the driver-loader package, which automatically detects your kernel version and architecture and downloads and installs the correct driver package. Download the appropriate package from the driver-loader releases page and install it:

Debian / Ubuntu:

Terminal window
sudo dpkg -i riptides-driver-loader_<version>_<arch>.deb
# or
sudo apt install ./riptides-driver-loader_<version>_<arch>.deb

CentOS / Fedora / Amazon Linux:

Terminal window
sudo rpm -i riptides-driver-loader-<version>.<arch>.rpm
# or
sudo dnf install ./riptides-driver-loader-<version>.<arch>.rpm

Alternatively, download the driver package directly from the driver releases page. Select the driver version and the package matching your kernel version and architecture, then install it manually:

Terminal window
# Debian / Ubuntu
sudo dpkg -i riptides-driver-<distro>-<kernel-version>_<driver-version>_<arch>.deb
# e.g. riptides-driver-ubuntu-6.14.0-37-generic_v0.5.15_arm64.deb
# CentOS / Fedora / Amazon Linux
sudo rpm -i riptides-driver-<distro>-<kernel-version>_<driver-version>.<arch>.rpm

Confirm the kernel module loaded successfully:

Terminal window
# Check kernel messages
sudo dmesg -T | grep riptides
# Verify the module is loaded
lsmod | grep riptides
# Check driver health
cat /proc/riptides/health

The health endpoint will report “waiting for daemon” until the daemon connects and pushes configuration. This is expected.

Install the daemon from the package repository:

Debian / Ubuntu:

Terminal window
sudo apt install riptides-daemon

RHEL / Fedora / Amazon Linux:

Terminal window
sudo dnf install riptides-daemon

Alternatively, build from source (requires a GitHub account with access to the daemon repository):

Terminal window
git clone https://github.com/riptideslabs/daemon.git
cd daemon
GOOS=linux make build
# The binary is at ./build/riptides
sudo cp ./build/riptides /usr/local/bin/riptides

Create the configuration directories:

Terminal window
sudo mkdir -p /etc/riptides/identities
sudo mkdir -p /etc/riptides/services
sudo mkdir -p /etc/riptides/credentials

Create a configuration file at /etc/riptides/config.yaml:

daemon:
trustDomain: example.com
defaultCertTTL: 2h
dataDir: /var/lib/riptides
metadataCollectors:
procfs:
enabled: true
extractEnvs: false
linuxos:
enabled: true
sysfsdmi:
enabled: true
ec2:
enabled: false # Set to true on AWS EC2
gcp:
enabled: false # Set to true on GCP
azure:
enabled: false # Set to true on Azure
kubernetes:
enabled: false # Disable on bare metal
docker:
enabled: false
controlPlane:
enabled: true
url: https://cp.example.com
grpcServerAddress: grpc.example.com:443
tokenBrokerBaseURL: https://cp.example.com/token-broker
authPlugin:
type: joinToken
config:
token: "your-join-token-here"
tunnelServer:
address: tunnel.example.com:443

Enable the cloud metadata collectors relevant to your environment:

  • AWS EC2: Set ec2.enabled: true and use authPlugin.type: AWSIID for automatic attestation
  • GCP: Set gcp.enabled: true and use authPlugin.type: GCPIIT
  • Azure: Set azure.enabled: true and use authPlugin.type: AzureIMDS
  • On-premises / local VMs: Use authPlugin.type: joinToken with a pre-shared token

Run the daemon manually:

Terminal window
sudo riptides daemon \
--identities-path /etc/riptides/identities \
--services-path /etc/riptides/services \
--credentials-path /etc/riptides/credentials

Create a systemd unit file at /etc/systemd/system/riptides-daemon.service:

[Unit]
Description=Riptides Daemon
After=network-online.target
Wants=network-online.target
ConditionPathExists=/dev/riptides
[Service]
Type=simple
ExecStart=/usr/local/bin/riptides daemon \
--identities-path /etc/riptides/identities \
--services-path /etc/riptides/services \
--credentials-path /etc/riptides/credentials
Restart=always
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target

Enable and start the service:

Terminal window
sudo systemctl daemon-reload
sudo systemctl enable riptides-daemon
sudo systemctl start riptides-daemon
sudo systemctl status riptides-daemon

Once the daemon is running, the driver health should report OK:

Terminal window
cat /proc/riptides/health

Check daemon logs:

Terminal window
# If running as a systemd service
sudo journalctl -u riptides-daemon -f
# If running manually, logs go to stdout/stderr

You can run Riptides in a local Lima VM for development and testing. This is useful for testing workload identity assignment and credential injection locally before deploying to production infrastructure.

One command with the Riptides Lima template

Section titled “One command with the Riptides Lima template”

The riptideslabs/lima-templates repo ships a ready-made template (requires Lima 2.0 or later) that boots the latest Ubuntu, installs the daemon and kernel driver, and joins your control plane - all from a single limactl start. Generate a join token first (Daemons → Attach Daemon in the UI, or a JoinToken resource), then:

Terminal window
limactl start --name=riptides \
--param controlplaneUrl="https://<your-env-id>.console.riptides.io" \
--param token="<your-join-token>" \
github:riptideslabs/lima-templates/templates/riptides

Tip: You don’t have to fill this in by hand - the control plane UI generates a ready-to-use command with your control plane URL and a fresh join token already inserted. Go to Daemons → Attach Daemon and open the Lima tab, then copy the command.

Lima’s github: scheme fetches the template straight from the repo’s default branch - no cloning required. Append @<tag-or-commit> to pin a specific version. Once the VM is up, verify the daemon:

Terminal window
limactl shell riptides -- systemctl status riptides

The join is idempotent across reboots, so a single-use token is not re-consumed. The first boot is slower because the driver is compiled against the VM’s kernel.

Alternatively, install the kernel module and daemon inside any Lima VM using the same installer steps as above, and connect it to the hosted control plane using a JoinToken.

On a Windows host the workload runs inside WSL2, and Riptides installs into the WSL2 distribution exactly as it does on any other Linux machine. The examples below assume Ubuntu, the default WSL distribution; any Debian-family distribution installs the same way, and rpm-based ones take the .rpm packages instead.

WSL2 boots Microsoft’s own kernel rather than the distribution’s, so uname -r reports something like 6.6.123.2-microsoft-standard-WSL2. The driver is built per kernel version, so the package has to match that kernel. The driver-loader keys on the kernel release rather than on /etc/os-release for exactly this reason - every WSL distribution on a machine shares the one Microsoft kernel, so one driver package serves all of them.

Three things are specific to WSL2:

systemd is required, and Ubuntu enables it by default. The driver-loader and the daemon both run as systemd services. In WSL2 systemd is a per-distribution setting rather than a platform default, but Ubuntu’s WSL image enables it out of the box, so on Ubuntu there is nothing to do. Check inside the distribution:

Terminal window
ps -p 1 -o comm= # systemd, or init/wsl-init if it is not running

If it is not systemd, add it to /etc/wsl.conf and restart the VM from Windows:

[boot]
systemd=true
Terminal window
wsl --shutdown

Running without systemd is planned but not implemented yet. Until it lands, a distribution that cannot enable systemd needs the container route: the daemon runs in a container (Docker, or Kubernetes with the Helm chart) while the kernel module is still loaded into the WSL2 kernel from the distribution itself. The native installer deliberately refuses to run inside a container.

Reinstall the driver after a WSL update. wsl --update replaces the WSL2 kernel, and a module built for the previous version will no longer load. Re-run the driver-loader after updating WSL to pick up the driver for the new kernel.

The Riptides kernel module exposes several diagnostic endpoints for troubleshooting.

PathDescription
/proc/riptides/healthDriver health status
/proc/riptides/certificatesCurrently loaded certificates
/proc/riptides/connectionsActive connection state
/proc/riptides/trust_anchorsTrust anchor chain
/sys/module/riptides/credentials/Credential files loaded by the daemon

Example - dump certificates directly:

Terminal window
cat /proc/riptides/certificates | python3 -m json.tool

Example - enable kernel dynamic debug for the module:

Terminal window
echo -n '-p; module riptides +pftl' | sudo tee /proc/dynamic_debug/control > /dev/null
Terminal window
sudo systemctl stop riptides-daemon
sudo systemctl disable riptides-daemon
sudo rm /etc/systemd/system/riptides-daemon.service
sudo systemctl daemon-reload

If installed via package:

Terminal window
sudo apt remove riptides-daemon # Debian/Ubuntu
sudo dnf remove riptides-daemon # RHEL/Fedora
Terminal window
# Unload the module
sudo modprobe -r riptides
# Remove the package
sudo apt remove riptides-driver # Debian/Ubuntu
sudo dnf remove riptides-driver # RHEL/Fedora

A complete configuration for an EC2 instance that attests using the instance identity document:

daemon:
trustDomain: example.com
defaultCertTTL: 2h
dataDir: /var/lib/riptides
metadataCollectors:
procfs:
enabled: true
extractEnvs: false
linuxos:
enabled: true
sysfsdmi:
enabled: true
ec2:
enabled: true
gcp:
enabled: false
azure:
enabled: false
kubernetes:
enabled: false
docker:
enabled: false
controlPlane:
enabled: true
url: https://cp.example.com
grpcServerAddress: grpc.example.com:443
tokenBrokerBaseURL: https://cp.example.com/token-broker
authPlugin:
type: AWSIID
tunnelServer:
address: tunnel.example.com:443

No shared secrets are needed - the daemon uses the EC2 instance identity document signed by AWS for attestation with the control plane.