Production Install Flags with INSTALL_K3S_EXEC
Bake your permanent server flags into INSTALL_K3S_EXEC so the systemd unit always starts k3s exactly how you want it.
There are two ways to pass options to the install script, and mixing them up is a classic gotcha. Flags placed after sh -s - go to k3s only for that one run. To make flags stick in the generated systemd unit, put them in the INSTALL_K3S_EXEC environment variable instead.
What belongs here
- The role and long-lived server flags:
--disable,--tls-san,--node-taint,--write-kubeconfig-mode. - Anything you want to survive a service restart or a re-run of the installer.
Prefer the config file for anything long-lived
Once you have more than a handful of flags, graduate to /etc/rancher/k3s/config.yaml. It version-controls cleanly and keeps the unit file readable. A good production pattern is a tiny INSTALL_K3S_EXEC that only names the role, with everything else in the config file.
To confirm what actually launched, read the rendered environment file the installer writes at /etc/systemd/system/k3s.service.env and the exec line in the unit itself.
Example
# Permanent server flags baked into the systemd unit
curl -sfL https://get.k3s.io | \
INSTALL_K3S_VERSION=v1.30.6+k3s1 \
INSTALL_K3S_EXEC="server --tls-san k3s.example.com --write-kubeconfig-mode 0644 --node-taint node-role.kubernetes.io/control-plane=true:NoSchedule" \
sh -
# Verify what systemd will actually run
sudo systemctl cat k3s | grep ExecStart
cat /etc/systemd/system/k3s.service.envWhen to use it
- An operator embeds TLS SANs, cluster CIDR, and disabled add-ons in INSTALL_K3S_EXEC so every server restart uses the same production flags.
- A provisioning script exports INSTALL_K3S_EXEC with node labels and taints before calling the install script, so nodes are ready for workloads immediately.
- A team documents INSTALL_K3S_EXEC in a Makefile target so any engineer can reproduce the exact cluster configuration without reading the systemd unit file.
More examples
Install with production flags baked in
Passes all persistent server flags via INSTALL_K3S_EXEC so they are baked into the systemd unit and survive reboots.
curl -sfL https://get.k3s.io | \
INSTALL_K3S_EXEC='
--tls-san k3s.prod.example.com
--tls-san 10.0.1.5
--disable traefik
--disable servicelb
--cluster-cidr 10.42.0.0/16
--service-cidr 10.43.0.0/16
' sh -Verify flags in systemd unit
Reads the generated systemd unit to confirm INSTALL_K3S_EXEC flags are recorded in the ExecStart line.
systemctl cat k3s | grep ExecStart
# ExecStart=/usr/local/bin/k3s server --tls-san ... --disable traefikCombine EXEC flags with config file
Shows that INSTALL_K3S_EXEC flags merge with config.yaml so you can override individual settings per-node at install time.
# /etc/rancher/k3s/config.yaml handles most options;
# override one flag at install time via EXEC:
curl -sfL https://get.k3s.io | \
INSTALL_K3S_EXEC='--node-name prod-server-01' sh -
kubectl get node prod-server-01
Discussion