TJs Kubernetes Service: Terraform configs for Talos clusters on Proxmox VE
Enable enthusiasts and administrators alike to easily provision highly available and production-ready Kubernetes clusters on Proxmox VE.
At a glance
- What is it?
- TJ's Kubernetes Service, or TKS, is a set of Terraform configurations that deploy Talos Linux Kubernetes clusters onto Proxmox VE using the BPG Proxmox and Sidero Labs Talos providers, wrapped in a tks helper for tokens, config merging, CSR approval and health checks. It fits a homelab or small platform team that wants cluster lifecycle in Terraform, and it does not fit a cluster that needs a managed control plane.
- Who is it for?
- TKS fits a team that runs its own Proxmox VE hosts and wants Kubernetes clusters described as Terraform configuration, with a helper that merges kubeconfig and Talos config and approves kubelet CSRs. It does not fit a shared multi tenant platform where every tenant needs isolation that a shared Proxmox user cannot give, and the CNI gap is real: a cluster created with Flannel disabled is not functional until a CNI is installed.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly HCL, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Cluster lifecycle for Proxmox hosts described in HCL
TJ's Kubernetes Service, or TKS, is a collection of Terraform configurations that deploy Talos Linux Kubernetes clusters to Proxmox VE. The description of the project says it exists to let enthusiasts and administrators provision highly available, production ready Kubernetes clusters on Proxmox VE, and the mechanism it uses is infrastructure as code rather than a bespoke installer. That choice is the point for anyone who already runs Proxmox and wants the cluster to appear in the same plan, in the same state, and in the same audit trail as the virtual machines hosting it. The primary language of the repository is HCL, the configuration language Terraform uses, with the .tf files at the top level covering the cluster, the nodes and the outputs, plus modules for the reusable pieces. The audience is a homelab operator or a small platform team, not a managed Kubernetes reseller.
Two providers and two Terraform roots
The stack has two moving parts. Cluster machines are created by the BPG Proxmox provider, and the Talos machines themselves are configured by the Sidero Labs Talos provider, which is what writes the Talos configuration into a virtual machine. The repository is split into two Terraform roots, and the split is a security boundary rather than a cosmetic one. The bootstrap root exists to create Proxmox users, their roles and their API tokens, and it needs root credentials on the Proxmox side to do that. The cluster root then runs with the narrower credentials that the bootstrap step produced. The README states that the bootstrap root needs root credentials, and instructs you to export them in a separate shell used only for that step, which is a simple but effective way to keep superuser access out of the rest of the run. The example tfvars file also creates users for the Proxmox CSI Plugin and the Proxmox Cloud Controller Manager, so those two components can be enabled later without revisiting the root account.
The bootstrap step and the token it prints
If you do not already have a Proxmox API token, the bootstrap root creates the users listed in the bootstrap tfvars, each with its own role and token. The credentials are exported into a shell used only for that step, and the first line in the example unsets any existing token variable so the provider prefers what you set here over a password. The endpoint, the username and the password are then exported as environment variables that the provider reads:
export PROXMOX_VE_ENDPOINT="https://earth.sol.milkyway:8006"
export PROXMOX_VE_INSECURE="true"
export PROXMOX_VE_USERNAME="root@pam"
export PROXMOX_VE_PASSWORD="REPLACEME"After the bootstrap apply, the helper prints the token of the user you name, and the README explains the format, which is the id and the secret joined by an equals sign, the form the API token environment variable expects. The remaining commands in the same root create the users and then fetch the token for the tks@pve user:
cd bootstrap
terraform init
terraform apply -var-file=../vars/bootstrap.tfvars
cd ..
./bin/tks token tks@pveThe next step is to copy the config environment example to a config file, fill it in and source it, which is where the token goes:
source vars/config.envDescribing nodes, then applying the cluster
The cluster itself is described in a tfvars file, and every input is documented in the configuration document, with a complete example shipped in the test tfvars. Nodes are a map keyed by hostname, and each entry carries a static IP and a VMID, so the addressing of the cluster is explicit in the configuration rather than left to a DHCP server. That static addressing is what makes the Talos provider's job possible, and it is also what lets the CSR approver in the next step be strict about identity. Once the file is written, the cluster root is initialised and a workspace is created for it:
terraform init
terraform workspace new tks-testThe apply then creates the machines and their Talos configuration in one plan:
terraform apply --var-file="vars/test.tfvars"Workspaces are the organising unit for more than one cluster, and the README explains the naming convention used with HCP Terraform later, where a tks- prefix is recommended so that cluster workspaces and the bootstrap workspace can be told apart at a glance.
The tks helper: config merge, CSR approval, health check
Three helper commands carry the day to day work. The first merges the Talos and Kubernetes configuration files into ~/.talos/config and ~/.kube/config, and the merge behaviour is specified: entries belonging to other clusters are kept, entries from an earlier build of the same cluster are replaced, and the new cluster becomes the current context. That is the difference between a helper that appends to a kubeconfig and one you can run repeatedly without accumulating dead entries:
./bin/tks configThe second is the certificate step. Kubelet serving certificates need their certificate signing requests approved, and without an approver such as the Kubelet CSR Approver, the helper can do it. The README states the constraint that makes this acceptable: it only approves a CSR that comes from a node and names nothing but that node's hostname and IP, so a request claiming a different identity is refused:
./bin/tks approve-csrsThe third is a health check that reaches further than a status page. The doctor command checks the Proxmox API, each VM, each node's Talos and Kubernetes versions against the tfvars, etcd membership, GPU drivers, and talosctl health. Comparing the running versions against the tfvars is the part that catches a cluster that was edited on paper and never applied:
./bin/tks doctorState location, and the secrets that live inside it
Both Terraform roots keep state locally by default, and the README is direct about why that matters: state holds the cluster's secrets and, for the bootstrap root, the Proxmox API tokens, and a separate security guide covers keeping it safe. The alternative is HCP Terraform, and the setup is deliberately constrained. The Default Execution Mode in the HCP organization has to be set to Local, so plans run locally where Proxmox is reachable, which means the HCP account is used for state storage rather than for running the apply. You log in, then copy the cloud override example files to the real names in the root and in the bootstrap directory and set the organization in both. The bootstrap workspace is named tks-bootstrap, cluster workspaces are tagged tks-cluster, and because HCP uses the workspace name as is, a tks- prefix keeps them distinguishable. There is one wrinkle worth reading twice: the first terraform init in the repository root asks for a workspace name because no workspace carries the tag yet, and you should type the cluster workspace name there instead of running terraform workspace new. If a root already has local state, init offers to migrate it.
CNI, cloud controller manager and the GPU worker path
Three configuration options change how the cluster is wired, and each has a catch worth knowing before you apply. Talos uses Flannel by default, so a different CNI means setting cluster.disable_flannel to true at creation time, and the README warns that the cluster is not functional and nodes cannot be upgraded until a CNI is installed. In other words, the CNI is not a post-install add-on here. Setting cluster.external_cloud_provider to true hands node initialization and cleanup to a cloud controller manager such as the Proxmox CCM, which is the right shape for a Proxmox cluster because node identity and load balancer handling then belong to that component. The GPU worker path has the strictest requirement of the three: IOMMU has to be enabled on the host, with each GPU alone in its own IOMMU group, and the requirements table marks it as needed only for a GPU worker.
Pinned tooling and a busy release cadence
The repository runs its checks through a Makefile whose stated rule is that every check CI runs is a target, and each tool runs from a pinned container image so that a local run and a CI run use the same versions, with Docker and Make as the only local requirements. The pinned tools are Terraform 1.16.6, tflint, Trivy, actionlint and terraform-docs, and the versions are bumped by Renovate through annotations in the file, with a comment in the Makefile explaining that Docker Hub images come through Google's public mirror because GitHub's shared runners hit the anonymous pull limit. The cluster root requires Terraform 1.16 or newer, and the helper additionally needs kubectl, talosctl and openssl, the last of which is used to check kubelet certificate requests before approving them. The release cadence is fast: v4.0.9 on 2026-10-18, v4.0.8 on 2026-10-16 and v4.0.7 on 2026-10-16, with the last push on 2026-10-18. The licence is GPL-3.0, and the repository ships SECURITY.md and CONTRIBUTING.md alongside the code, with a trivy configuration for scanning images.
Editorial conclusion
TKS fits a team that runs its own Proxmox VE hosts and wants Kubernetes clusters described as Terraform configuration, with a helper that merges kubeconfig and Talos config and approves kubelet CSRs. It does not fit a shared multi tenant platform where every tenant needs isolation that a shared Proxmox user cannot give, and the CNI gap is real: a cluster created with Flannel disabled is not functional until a CNI is installed. Verify first that your Proxmox API token carries only the privileges the security guide lists, and decide where the Terraform state lives before the first init, because the state holds the cluster secrets and the Proxmox tokens.
Frequently asked questions
What does TJ's Kubernetes Service actually deploy?
TKS is a collection of Terraform configurations that deploy Talos Linux Kubernetes clusters to Proxmox VE, using the BPG Proxmox provider to create the machines and the Sidero Labs Talos provider to configure them. The repository is written in HCL.
How do I approve kubelet certificate requests in a TKS cluster?
Without an approver such as Kubelet CSR Approver, you can approve them with the helper. The README states that it only approves a CSR that comes from a node and names nothing but that node's hostname and IP. The helper needs openssl to check the requests.
Where should I store the Terraform state for a TKS cluster?
Both roots store state locally by default, and the state holds the cluster secrets and, for the bootstrap root, the Proxmox API tokens. To use HCP Terraform instead, set the Default Execution Mode to Local, run terraform login, and copy the cloud override example files to their real names with the organization set.
Can I use a CNI other than Flannel with TKS?
Yes, but the README states that cluster.disable_flannel must be set to true when the cluster is created, and that the cluster is not functional and nodes cannot be upgraded until a CNI is installed.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/zimmertr-tjs-kubernetes-service)Was this useful?