Blog » Linux » How to Install K3s on Linux: Lightweight Kubernetes for Your Homelab
› how-to-install-k3s-on-linux Linux terminal showing kubectl get nodes output with K3s cluster nodes in Ready status on a homelab desk setup

How to Install K3s on Linux: Lightweight Kubernetes for Your Homelab

Table of Contents

The first time I tried to install full Kubernetes on a spare homelab box, I lost 2 GB of RAM before a single pod deployed. My poor little ThinkCentre wheezed like it was running Windows Vista on a netbook. That night, I learned how to install K3s on Linux — and I never looked back. K3s is a single binary, under 70 MB, that gives you a real, CNCF-certified Kubernetes cluster in under two minutes.

Linux terminal showing kubectl get nodes output with K3s cluster nodes in Ready status on a homelab desk setup

This matters more than ever. According to the CNCF 2025 Annual Cloud Native Survey, 82% of container users now run Kubernetes in production. A huge slice of those folks started on K3s — it’s the friendliest on-ramp I’ve ever recommended. If you’re still mapping the broader landscape, my roundup of the best Linux container management tools puts K3s in context next to its peers.

Quick answer: Run curl -sfL https://get.k3s.io | sh - on a Linux server with 2 GB of RAM. K3s installs as a systemd service, starts immediately, and you’ll have a working single-node Kubernetes cluster ready for kubectl get nodes within ninety seconds. Worker nodes join with a token from /var/lib/rancher/k3s/server/node-token.

What Is K3s (And Why I Run It Instead of Full Kubernetes)

K3s is a CNCF-certified Kubernetes distribution packaged as a single binary under 70 MB. It is not a fork. It passes the same conformance tests as the upstream project. Darren Shepherd at Rancher Labs built it because spinning up full Kubernetes for every test run was painfully slow, and Rancher donated it to the CNCF in June 2020.

RackNerd Mobile Leaderboard Banner

Get a VPS from as low as $11/year! WOW!

If you’ve already got your container fundamentals down with Docker basics and graduated to Docker Compose for multi-container apps, K3s is the next natural step. It’s the bridge from “I run a few containers” to “I orchestrate a real cluster.” There’s a fun detail about K3s networking I’ll come back to — it ships with three things most people forget to install on day one.

K3s vs Standard Kubernetes: What’s Actually Different

The headline difference is resource usage. A K3s server node sits around 400 MB RAM. Standard Kubernetes wants closer to 1.8 GB per node before you’ve done anything useful. That’s the entire reason it fits on a Raspberry Pi.

K3s swaps a few defaults to get there. It replaces etcd with SQLite for the datastore (you can swap back to etcd or external Postgres for HA). It removes legacy alpha features and cloud-provider integrations you’ll never use in a homelab. It still uses containerd as the runtime, so if you’ve explored Podman as a daemonless container runtime, the mental model is similar.

What K3s Bundles Out of the Box

  • containerd: the same runtime that powers most production Kubernetes clusters.
  • Flannel CNI: pod networking that just works without configuration.
  • Traefik ingress controller: reverse proxy and TLS termination ready on first boot.
  • Klipper service load balancer: turns NodePort services into something usable from your LAN.
  • Local-path storage provisioner: dynamic PersistentVolumes backed by host paths.

From the official documentation: “K3s is a highly available, certified Kubernetes distribution designed for production workloads in unattended, resource-constrained, remote locations or inside IoT appliances.” That’s not marketing fluff — I’ve run K3s on a Pi 4 in a closet for eighteen months without a single restart.

Before You Install: System Requirements and Prep

K3s is forgiving, but five minutes of prep saves an hour of debugging. The full K3s official system requirements live in the docs, but here’s the short version.

Hardware Minimums

  • Server node: 2 vCPU, 2 GB RAM.
  • Agent node: 1 vCPU, 512 MB RAM.
  • Supported OS: Ubuntu 20.04+, Debian 11+, Fedora 36+, RHEL/Rocky 8+, openSUSE Leap 15.4+.

I run my K3s cluster on Debian — boring, stable, and patched for years. If you’re still picking an OS, my guide on the best Linux distribution for your server walks through the tradeoffs. One small mercy: K3s handles swap natively, so you do not need to disable it the way standard Kubernetes used to demand.

Ports to Open

These three ports matter for almost every cluster:

  • 6443/TCP: the Kubernetes API server. Agents and kubectl both need this.
  • 8472/UDP: Flannel VXLAN traffic between nodes. Skip this and pods can’t talk across hosts.
  • 10250/TCP: kubelet metrics endpoint.

On Ubuntu and Debian, my walkthrough on how to configure UFW to allow K3s traffic covers it. On Fedora, Rocky, or RHEL, you’ll want to open the required ports with firewalld instead. I learned this the hard way after spending forty minutes debugging a “node NotReady” issue that turned out to be a default firewalld zone blocking 8472.

Set a Static IP on Each Node

Your nodes need stable IP addresses. DHCP leases that rotate will eventually break cluster networking and confuse certificate SANs. Take ten minutes to set a static IP on each node before you install anything.

Also: two nodes cannot share the same hostname. Set unique ones with sudo hostnamectl set-hostname k3s-server (or k3s-agent-01, etc.) before running the installer. K3s registers nodes by hostname, and collisions will silently corrupt your cluster.

Install K3s on Your Server Node (Single Command)

This is the part that still feels like magic to me. The whole install is one line.

Run the Installer

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

That’s it. The script detects your init system, drops a systemd unit called k3s, downloads the binary to /usr/local/bin/k3s, and starts the service. The whole thing takes about ninety seconds on a decent connection.

If you’re planning a multi-node cluster, set a custom token at install time so you don’t have to dig the auto-generated one out later:

curl -sfL https://get.k3s.io | sudo K3S_TOKEN='MyClusterToken123' sh -

Verify the Install

Run sudo kubectl get nodes. You should see your server with STATUS showing Ready within thirty seconds. If it sits at NotReady, give it another minute — Flannel needs a moment to come up.

To double-check the API is actually listening, my guide on how to confirm port 6443 is listening shows the ss incantation I use. Quick version: sudo ss -tlnp | grep 6443.

Set Up kubectl Access

K3s drops the kubeconfig at /etc/rancher/k3s/k3s.yaml, but it’s mode 600 and owned by root. Every K3s tutorial I read as a beginner skipped this step, and it tripped me up for an embarrassing amount of time.

Copy it to your user’s config directory so you can run kubectl without sudo:

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

Now kubectl get nodes works as your regular user. Good. That’s the foundation done.

Add Worker Nodes to Your K3s Cluster

Single-node K3s is great for testing. For real workloads, you’ll want at least one agent node so pods aren’t all crammed onto the control plane.

Get Your Node Token from the Server

On the server, grab the token:

sudo cat /var/lib/rancher/k3s/server/node-token

Copy that string. If you set a custom token at install time with K3S_TOKEN, you already know it — use that instead.

Install the K3s Agent on Worker Nodes

SSH into your agent node and run:

curl -sfL https://get.k3s.io | K3S_URL=https://<server-ip>:6443 K3S_TOKEN=<token> sh -

The presence of K3S_URL tells the installer “this is an agent, not a server.” K3s installs a separate systemd unit called k3s-agent that handles joining. If you’d rather set these persistently for your shell, my notes on how to set environment variables in Linux walk through the options.

Confirm Nodes Joined

Back on the server, run kubectl get nodes. Within thirty seconds your agent should appear with STATUS Ready. If it’s stuck at NotReady or doesn’t show up at all, that’s almost always a firewall problem — go back and verify 6443/TCP and 8472/UDP between the nodes.

Deploy Your First Workload on K3s

Time for the satisfying part. Let’s deploy nginx and prove the cluster actually works.

kubectl create deployment nginx --image=nginx --replicas=2
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get svc nginx

The output of the last command shows a NodePort like 80:31572/TCP. That second number (31572 in my example, yours will differ) is a port mapped on every node in the cluster. Curl any node IP at that port:

curl http://<node-ip>:31572

You should get the nginx welcome HTML back. I still smile every time. To see which nodes the pods landed on, run kubectl get pods -o wide.

Managing K3s Day-to-Day

K3s runs as a normal systemd service, which means everything you already know carries over.

Essential systemctl Commands

If you’re new to service management, my use systemctl to manage the K3s service guide covers the basics. The day-to-day commands are predictable:

  • Start/stop/restart: sudo systemctl start k3s / stop k3s / restart k3s.
  • Status: sudo systemctl status k3s.
  • Follow logs: sudo journalctl -u k3s -f.

Updating K3s

Re-run the install script. That’s it. The installer detects an existing install and upgrades in place, then restarts the service. I’ve done this on a production cluster while traffic was flowing and never had a workload interruption — though I still keep snapshots on hand because I learned discipline the hard way after running sudo rm -rf in the wrong directory on Ubuntu 8.04 back in college.

Uninstalling K3s

The installer drops uninstall scripts that clean up everything:

  • Server: /usr/local/bin/k3s-uninstall.sh.
  • Agent: /usr/local/bin/k3s-agent-uninstall.sh.

Common K3s Problems (And How to Fix Them)

Almost every K3s headache I’ve debugged falls into one of five buckets. Here they are, in rough order of how often I see them.

Agent node not joining the cluster: Check the firewall between the agent and the server. Port 6443/TCP must be reachable from the agent host to the server IP. Run nc -zv <server-ip> 6443 from the agent to verify.

kubectl: permission denied on k3s.yaml: The kubeconfig at /etc/rancher/k3s/k3s.yaml is root-owned. Copy it to ~/.kube/config and chown it to your user, as shown in the install section.

k3s service fails to start: Run sudo journalctl -u k3s -n 50. Nine times out of ten it’s a hostname collision (two nodes with the same name) or a port conflict on 6443.

Nodes stuck in NotReady: Flannel VXLAN on UDP/8472 is blocked. Verify with sudo ss -ulnp | grep 8472 and open the port in your firewall.

Pods pending forever: Run kubectl describe node <name> and look for resource pressure. On low-RAM homelab boxes, pods get evicted before they can schedule.

For deeper edge cases, the official K3s documentation is excellent — better than most upstream Kubernetes docs in my opinion.

Where to Go From Here

You’ve got a working K3s cluster. The fun part is everything you can layer on top. My personal next-step ritual: spin up monitoring before I deploy anything I actually care about. Walk through how to set up Prometheus and Grafana to monitor your cluster and you’ll never deploy blind again.

From there, the path forks based on what you want to build. If you’re still firming up container fundamentals, loop back to Docker basics or the broader Linux container ecosystem. Either way — welcome to running real Kubernetes at home. It’s a rabbit hole, in the best way.

author avatar
Alexa Velinxs
I'm Alexa Velinxs, a cryptocurrency trading expert passionate about demystifying digital assets for both beginners and seasoned investors. Through my writing, I share actionable strategies, market insights, and practical tips to help you navigate the crypto landscape with confidence. Let's explore the future of finance together.
Related Posts