Skip to content

Getting Started with Riptides

This guide walks you through connecting your first daemon and assigning a workload identity. Choose the installation method that matches your infrastructure:

Both methods share the same control plane and use JoinToken authentication to register daemons.

Before you begin, make sure you have:

  • kubectl installed and configured to communicate with the Riptides-hosted control plane (provided after signup)
  • The oidc-login kubectl plugin (also distributed as kubelogin) installed on your machine — this is required because the Riptides control plane authenticates human users via OIDC. Without it, kubectl commands will fail with an authentication error.

If you already use krew, install the plugin with:

Terminal window
kubectl krew install oidc-login

If kubectl krew is not available, install krew first using the official instructions:

Then install and verify:

Terminal window
kubectl krew install oidc-login
kubectl oidc-login --version

If you prefer a package manager, the same plugin is also distributed as kubelogin.

The daemon must reach the control plane on the following ports. Open these in your firewall, security group, or egress policy before proceeding:

PortProtocolPurpose
8443HTTPSPrimary API — kubectl commands and daemon registration
9443gRPC/TLSDaemon attestation and certificate signing
8001TCPPersistent tunnel for daemons behind NAT or strict firewalls

Tip: Port 8001 is most important for VMs and bare-metal nodes behind NAT. Kubernetes daemons typically only need 8443 and 9443.

Step 1: Connect to the Hosted Control Plane

Section titled “Step 1: Connect to the Hosted Control Plane”

The Riptides control plane is hosted and operated by Riptides. Log in to the control plane web UI at the URL provided in your access details email.

Configure kubectl to use the Riptides API server with the kubeconfig downloaded from the UI:

Terminal window
export KUBECONFIG=~/.riptides/kubeconfig

When you run your first kubectl command, the oidc-login plugin will open a browser window for authentication. After authenticating, the token is cached and subsequent commands will not require re-authentication until the token expires.

Verify connectivity:

Terminal window
riptides-cli ctl get namespaces

Note: See the Control Plane page for more details on the hosted control plane architecture.

A Verifier tells the control plane which authentication methods it should accept from daemons. Start with the joinToken verifier for a simple token-based flow. This step applies to both Kubernetes and VM/bare metal daemons:

verifier-jointoken.yaml
apiVersion: auth.riptides.io/v1alpha1
kind: Verifier
metadata:
name: jointoken
namespace: riptides-system
spec:
joinToken: {}

Apply it:

Terminal window
riptides-cli ctl apply -f verifier-jointoken.yaml

Confirm the Verifier is available:

Terminal window
riptides-cli ctl get verifiers

Expected output:

NAME STATE
jointoken Available

Create a JoinToken resource that the daemon will present during registration. Set token to a strong, unique value and give the token a workloadID and an expiration time:

jointoken.yaml
apiVersion: auth.riptides.io/v1alpha1
kind: JoinToken
metadata:
name: my-first-daemon-token
namespace: riptides-system
spec:
token: "my-secure-join-token"
workloadID: "riptides/daemon/my-first-node"
expireAt: "2026-12-31T23:59:59Z"

Apply it:

Terminal window
riptides-cli ctl apply -f jointoken.yaml

Tip: Rotate join tokens regularly and set short expiration windows in production environments.

The installer detects your distribution and kernel version, downloads the right packages, writes the daemon configuration, and starts the systemd service.

Terminal window
curl -fsSL https://docs.riptides.io/install.sh | sudo bash -s -- \
--controlplane-url https://<your-env-id>.console.riptides.io \
--join-token "<your-join-token>"

On EC2, the script auto-detects the instance and authenticates using the AWS Instance Identity Document — no join token required:

Terminal window
curl -fsSL https://docs.riptides.io/install.sh | sudo bash -s -- \
--controlplane-url https://<your-env-id>.console.riptides.io

Pass --awsiid explicitly if auto-detection does not trigger (e.g. when IMDSv2 is restricted).

On Azure, the script auto-detects the instance and authenticates using the Azure Instance Metadata Service — no join token required. The VM must have a managed identity attached:

Terminal window
curl -fsSL https://docs.riptides.io/install.sh | sudo bash -s -- \
--controlplane-url https://<your-env-id>.console.riptides.io

Pass --azureimds explicitly if auto-detection does not trigger. See Connect Azure VMs for the required Verifier setup.

DistributionPackage
Ubuntu, Debian.deb
RHEL, CentOS, Rocky Linux, AlmaLinux.rpm
Amazon Linux 2023.rpm
Fedora.rpm

Packages are built for amd64 and arm64. The installer picks the right one automatically.

FlagDefaultDescription
--controlplane-url URLControl plane URL (required)
--join-token TOKENJoin token for daemon authentication
--awsiidauto-detected on EC2Use AWS Instance Identity Document auth
--azureimdsauto-detected on AzureUse Azure Instance Metadata Service auth
--version VERSIONlatestDaemon version to install (e.g. v0.5.12)
--driver-version VERSIONlatestDriver version to install (e.g. v0.5.15)
--data-dir DIR/var/lib/riptidesDirectory for daemon state and certificates
Terminal window
curl -fsSL https://docs.riptides.io/install.sh | sudo bash -s -- \
--controlplane-url https://<your-env-id>.console.riptides.io \
--join-token "<your-join-token>" \
--version v0.5.12 \
--driver-version v0.5.15

The daemon and driver are versioned independently. Omit either flag to use the latest release of that component.

  1. If Riptides is already installed and the driver is present, starts the daemon service if it is not running and prints a status summary. No reinstallation is performed.
  2. Detects your distribution (Debian/Ubuntu → .deb, RHEL/Amazon Linux/Fedora → .rpm), architecture, and running kernel version.
  3. Downloads and installs the kernel driver loader from riptides-packages/driver-loader. The loader downloads the pre-built driver package for your kernel and loads it via the riptides-modules systemd unit. If no pre-built package exists for your kernel, the loader queues a remote build and the script streams its output while waiting — this can take up to 30 minutes.
  4. Downloads and installs the daemon package from riptides-packages/daemon.
  5. Writes /etc/riptides/config.yaml (mode 0600, owned by root) with the control plane URL, trust domain, and auth plugin configuration.
  6. Enables and starts the riptides systemd service. The daemon authenticates to the control plane on first start using the configured join token, AWSIID, or AzureIMDS.

Once the daemon is running, confirm it has registered with the control plane:

Terminal window
riptides-cli ctl get daemons

You should see your VM daemon listed with its workload ID:

NAME WORKLOAD ID
e2140516-678a-419d-9a4c-156e971583ae riptides/daemon/my-first-node

The WORKLOAD ID will match the workloadID specified in the JoinToken.

Follow this section to install the Riptides daemon as a Helm chart on an existing Kubernetes cluster.

Additional prerequisites for Kubernetes:

  • Kubernetes cluster v1.26 or later
  • Helm v3.12 or later

Install the Riptides daemon using Helm. The daemon connects back to the control plane using the join token you created.

Terminal window
helm install daemon oci://ghcr.io/riptides-packages/helm/daemon \
--namespace riptides-system \
--create-namespace \
--set config.daemon.controlPlane.enabled=true \
--set config.daemon.controlPlane.url=https://<your-env-id>.console.riptides.io \
--set config.daemon.controlPlane.authPlugin.type=joinToken \
--set config.daemon.controlPlane.authPlugin.config.token=my-secure-join-token

Alternatively, create a values.yaml file for the daemon:

daemon-values.yaml
config:
daemon:
controlPlane:
enabled: true
url: https://<your-env-id>.console.riptides.io
authPlugin:
type: joinToken
config:
token: my-secure-join-token
dataDir: /data/riptides

Then install with:

Terminal window
helm install daemon oci://ghcr.io/riptides-packages/helm/daemon \
--namespace riptides-system \
--create-namespace \
-f daemon-values.yaml

Once the daemon pod is running, check that it has registered with the control plane:

Terminal window
riptides-cli ctl get daemons

You should see your daemon listed with its workload ID:

NAME WORKLOAD ID
e2140516-678a-419d-9a4c-156e971583ae riptides/daemon/my-first-node

The WORKLOAD ID will match the workloadID specified in the JoinToken. If the daemon does not appear, check the daemon pod logs for connection errors.

Step 1: Create Your First WorkloadIdentity

Section titled “Step 1: Create Your First WorkloadIdentity”

A WorkloadIdentity assigns a SPIFFE identity to processes that match a set of selectors. The following example assigns an identity to an Nginx process running in a specific Kubernetes namespace. The same resource type is used regardless of whether the daemon is running on Kubernetes or a VM.

workload-identity.yaml
apiVersion: core.riptides.io/v1alpha1
kind: WorkloadIdentity
metadata:
name: nginx-web
namespace: riptides-system
spec:
workloadID: my-app/web/nginx
selectors:
- process:name: nginx
k8s:pod:namespace: my-app
k8s:label:app: nginx
connection:
tls:
mode: PERMISSIVE

Apply it:

Terminal window
riptides-cli ctl apply -f workload-identity.yaml

This WorkloadIdentity will issue the SPIFFE ID spiffe://example.com/my-app/web/nginx to any process named nginx in a pod labeled app: nginx within the my-app namespace.

Selector Reference

Selectors identify which processes receive the identity. Common selector keys include:

SelectorDescription
process:nameName of the running process binary
k8s:pod:namespaceKubernetes namespace the pod runs in
k8s:label:<key>Value of a Kubernetes pod label
k8s:container:nameName of the Kubernetes container

For the full list of available selectors, see the WorkloadIdentity reference.

TLS Modes

The connection.tls.mode field controls how TLS is enforced for the workload:

ModeDescription
SIMPLEOne-way TLS — the workload presents its certificate to clients
MUTUALMutual TLS — both sides present and verify certificates
PERMISSIVEAccepts both plaintext and mTLS connections (useful during migration)

After applying the WorkloadIdentity, verify that the control plane has matched it against running workloads:

Terminal window
riptides-cli ctl get workloadidentities

You should see the nginx-web identity listed. If the daemon is running on a node where an Nginx process matches the selectors, the identity will be assigned and a SPIFFE ID issued.

The daemon logs will show the reason. Common causes:

  • Join token expired or not applied — confirm riptides-cli ctl get jointokens shows the token and that expireAt has not passed. Generate a new one and update /etc/riptides/config.yaml (VM) or your Helm values (Kubernetes), then restart the daemon:
    Terminal window
    sudo systemctl restart riptides
  • Wrong control plane URL — verify it matches exactly what was provided after signup.
  • Outbound connectivity blocked — the daemon needs access to the control plane on ports 8443 and 9443:
    Terminal window
    curl -v https://<your-env-id>.console.riptides.io:8443/healthz
Terminal window
sudo systemctl status riptides
sudo journalctl -u riptides -n 50 --no-pager

Common causes:

  • YAML syntax error in /etc/riptides/config.yaml:
    Terminal window
    python3 -c "import yaml; yaml.safe_load(open('/etc/riptides/config.yaml'))"
  • Kernel module not loaded — check lsmod | grep riptides and sudo systemctl status riptides-modules.
  • Port blocked — the daemon needs outbound access to the control plane on ports 8443 and 9443.

Daemon pod in CrashLoopBackOff (Kubernetes)

Section titled “Daemon pod in CrashLoopBackOff (Kubernetes)”

Check the pod logs for the root cause:

Terminal window
kubectl logs -n riptides-system -l app.kubernetes.io/name=daemon --previous

Common causes:

  • Image pull failure — the regcred pull secret may be missing or the GHCR token has expired. Re-create it and restart the pod.
  • Wrong control plane URL — double-check the URL matches exactly what was provided after signup.

Daemon does not appear in riptides-cli ctl get daemons

Section titled “Daemon does not appear in riptides-cli ctl get daemons”

The pod may be running but failing to register with the control plane. Check live logs:

Terminal window
kubectl logs -n riptides-system -l app.kubernetes.io/name=daemon -f

Common causes:

  • JoinToken expired or not applied — confirm riptides-cli ctl get jointokens shows the token and that expireAt has not passed.
  • Port 8443 or 9443 blocked — verify the daemon node can reach the control plane on both ports.

The OIDC login flow requires a desktop browser. On headless servers, the plugin will print a URL to open manually. If your environment blocks outbound OAuth redirects, check the console.riptides.io dashboard for alternative authentication options.