$linuxjunkies
>

Install k3s on a Single Linux Node

Install k3s on a single Linux node in minutes: covers the curl installer, kubeconfig setup, built-in Traefik ingress, and essential kubectl commands.

IntermediateUbuntuDebianFedoraArch9 min readUpdated June 7, 2026

Before you start

  • Root or passwordless sudo access on the target node
  • curl installed (sudo apt install curl / sudo dnf install curl)
  • Ports 6443, 80, and 443 available and not blocked by a host firewall

k3s is a lightweight, certified Kubernetes distribution from Rancher that packages everything into a single binary under 100 MB. It strips out legacy drivers, uses containerd as the container runtime, and replaces etcd with SQLite by default — making it a practical choice for home labs, edge nodes, and CI environments where a full kubeadm cluster is overkill. This guide gets you from a bare Linux node to a running cluster with Traefik ingress in about fifteen minutes.

Prerequisites and System Requirements

k3s officially supports x86_64, ARM64, and ARMv7. You need:

  • A 64-bit Linux node with at least 512 MB RAM (1 GB recommended)
  • curl installed
  • Root or passwordless sudo access
  • Ports 6443 (API server) and 10250 (kubelet) not already in use

Step 1 — Run the Installer

The official installer script handles binary placement, a systemd unit, and kubeconfig generation in one shot. Run it as root or with sudo:

curl -sfL https://get.k3s.io | sh -

The script detects your architecture, downloads the correct binary to /usr/local/bin/k3s, writes /etc/systemd/system/k3s.service, and starts the service. On a fresh node this typically completes in under two minutes, network speed aside.

If you want to pin a specific version — always a good idea in production — set the INSTALL_K3S_VERSION environment variable:

curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION="v1.30.2+k3s1" sh -

Check the k3s releases page for the current stable tag.

Step 2 — Verify the Service

k3s registers itself as a systemd unit. Confirm it started cleanly:

sudo systemctl status k3s

You should see Active: active (running). If it is still initializing, wait 20–30 seconds and check again. For a live stream of startup logs:

sudo journalctl -u k3s -f

Watch for the line Node controller sync successful — that confirms the control plane is ready.

Step 3 — Configure kubectl Access

k3s writes its kubeconfig to /etc/rancher/k3s/k3s.yaml, readable only by root by default. You have two options.

Option A — Use the k3s kubectl wrapper (quickest)

k3s ships its own kubectl alias. No extra configuration needed:

sudo k3s kubectl get nodes

Option B — Use your system kubectl as a non-root user

This is the better long-term setup. Copy the kubeconfig to your home directory and fix the permissions:

mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
chmod 600 ~/.kube/config

The file references 127.0.0.1:6443 as the server address. If you intend to manage this cluster from another machine, replace that address with the node's actual IP or hostname before copying the file off the node.

kubectl get nodes

Expected output (will vary by hostname and k3s version):

# NAME        STATUS   ROLES                  AGE   VERSION
# mynode      Ready    control-plane,master   2m    v1.30.2+k3s1

Step 4 — Understand What Traefik Gives You

k3s bundles Traefik v2 as its default Ingress controller, deployed automatically into the kube-system namespace. It also installs a ServiceLB (formerly klipper-lb) that binds host ports 80 and 443 directly on the node — no external load balancer required. Verify both are running:

kubectl get pods -n kube-system -l app.kubernetes.io/name=traefik
kubectl get svc -n kube-system traefik

The traefik Service will show EXTERNAL-IP as the node's primary interface IP once ServiceLB is ready. If you see <pending>, wait another minute for ServiceLB to reconcile.

Step 5 — Deploy a Test Application with Ingress

Deploy a minimal nginx workload and expose it through Traefik to prove the full path works.

Create the Deployment and Service

kubectl create deployment demo --image=nginx:alpine --port=80
kubectl expose deployment demo --port=80

Create an Ingress resource

kubectl apply -f - <<'EOF'
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo
  annotations:
    traefik.ingress.kubernetes.io/router.entrypoints: web
spec:
  rules:
  - host: demo.example.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: demo
            port:
              number: 80
EOF

Test it with curl, faking the Host header so you do not need DNS:

curl -H "Host: demo.example.local" http://127.0.0.1/

You should receive the default nginx welcome page HTML. If you get a 404 from Traefik, give the Ingress a few seconds to sync and retry.

Step 6 — Essential Day-One Commands

A short reference for common k3s operations on a single node:

TaskCommand
List all pods, all namespaceskubectl get pods -A
Watch pod events in real timekubectl get events -A --watch
Tail container logskubectl logs -f deploy/demo
Check node resource usagekubectl top node (metrics-server is built in)
Restart k3s servicesudo systemctl restart k3s
Stop and uninstall k3s completelysudo /usr/local/bin/k3s-uninstall.sh

Firewall Configuration

If the node runs a firewall, open the API server port so external kubectl clients can reach it. The exact command depends on your firewall manager.

ufw (Debian/Ubuntu)

sudo ufw allow 6443/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

firewalld (Fedora/RHEL/Rocky)

sudo firewall-cmd --permanent --add-port=6443/tcp
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

k3s also needs the CNI flannel network to communicate between pods on the same node. Flannel uses UDP 8472 (VXLAN) internally; this matters if you later add worker nodes.

Troubleshooting

  • Node stuck in NotReady: Check sudo journalctl -u k3s --since "5 min ago" for CNI plugin errors. If flannel cannot write to /run/flannel, ensure SELinux is either in permissive mode or the k3s SELinux policy RPM is installed (sudo dnf install k3s-selinux on Fedora/RHEL).
  • Port 6443 already in use: Another process (often a stale k3s or a local kubeadm install) is holding the port. Find it with sudo ss -tlnp | grep 6443 and stop the conflicting service before reinstalling.
  • curl to Ingress returns connection refused: ServiceLB may not have bound the host port yet. Confirm with sudo ss -tlnp | grep ':80' — you should see k3s server or containerd listed. If nothing is listening, check the svclb-traefik pod logs: kubectl logs -n kube-system -l app=svclb-traefik.
  • Metrics-server pod CrashLooping: On nodes without a properly configured hostname in DNS, metrics-server TLS verification fails. Add --kubelet-insecure-tls to the metrics-server deployment args, or set a valid hostname with hostnamectl set-hostname mynode and restart k3s.
tested on:Ubuntu 24.04Debian 12Fedora 40Rocky 9

Frequently asked questions

Is k3s production-ready?
Yes. k3s is a CNCF Sandbox project and holds full Kubernetes conformance certification. It is used in production at edge sites and in embedded environments. For high-availability production use, run k3s with an external datastore (PostgreSQL or MySQL) and at least three server nodes.
Can I disable Traefik and use a different Ingress controller?
Yes. Pass --disable traefik to the install script: curl -sfL https://get.k3s.io | sh -s - --disable traefik. You can then install nginx-ingress or any other controller via Helm.
How do I add worker nodes to this single-node install?
Retrieve the node token from /var/lib/rancher/k3s/server/node-token on the server, then run the installer on each worker with K3S_URL and K3S_TOKEN set: curl -sfL https://get.k3s.io | K3S_URL=https://<server-ip>:6443 K3S_TOKEN=<token> sh -
Does k3s work on Raspberry Pi?
Yes, k3s supports ARM64 (Pi 4/5) and ARMv7 (Pi 3). On Raspberry Pi OS you must add cgroup_memory=1 cgroup_enable=memory to /boot/cmdline.txt and reboot before installing, otherwise k3s will start but pods will not schedule.
What is the difference between k3s and k0s or minikube?
All three are lightweight Kubernetes distributions, but they target slightly different use cases. minikube is for local development only. k0s is similar to k3s in scope but uses a different CNI default and packaging approach. k3s is the most mature of the lightweight options and has the largest edge-deployment community.

Related guides