Terraform module for deploying a single-node K3s Kubernetes cluster on AWS using the official Digitalis K3s Marketplace AMI — a ready-to-use development and testing environment.
This module is designed for developers, QA teams, and anyone needing a lightweight, single-node Kubernetes cluster for testing and development.
Quick Start · Examples · Inputs · Outputs · Getting Your Kubeconfig
K3s is a lightweight, certified Kubernetes distribution built for production workloads in resource-constrained environments. Packaged as a single binary under 100MB, K3s is perfect for edge computing, IoT, CI/CD pipelines, and development environments. It includes all the essential Kubernetes components while removing legacy and optional features to reduce complexity.
- Single-Node Cluster — Deploys a complete K3s Kubernetes cluster on a single EC2 instance
- Multi-Architecture — Supports both AMD64 (x86_64) and ARM64 (Graviton) instance types
- Multiple Deployments — Deploy multiple clusters in the same environment with unique names
- Security Hardened — Enforces IMDSv2, uses encrypted gp3 volumes, and restricts network access by default
- Static IP Option — Optionally assign an Elastic IP for a persistent public address
- Fully Configurable — Customize instance type, volume size, network rules, and tags
- Developer Focused — Clear outputs and instructions for retrieving your kubeconfig
module "k3s" {
source = "github.com/digitalis-io/terraform-aws-dev-k3s"
# Required: Unique name for this deployment
name = "my-cluster"
# Required: Network configuration
vpc_id = "vpc-xxxxxxxxx"
subnet_id = "subnet-xxxxxxxx"
# Required: SSH key for access
key_name = "my-ssh-key"
}That's it. This deploys a K3s cluster with sensible defaults: t3.medium instance, 30GB encrypted volume, IMDSv2 enforced, and SSH access enabled.
After applying, see the Getting Your Kubeconfig section for instructions on connecting.
| Example | Description |
|---|---|
| simple | Single instance with defaults — dev/test |
| with-eip | Instance with Elastic IP for static public address |
| arm64 | ARM64 (Graviton) instance for cost savings |
module "k3s" {
source = "github.com/digitalis-io/terraform-aws-dev-k3s"
# Required: Unique name for this deployment
name = "platform-cluster"
# Network
vpc_id = "vpc-xxxxxxxxx"
subnet_id = "subnet-xxxxxxxx"
# Instance configuration
key_name = "my-ssh-key"
instance_type = "t3.large"
architecture = "amd64"
# Static IP for consistent access
enable_eip = true
# Prevent accidental deletion
enable_termination_protection = true
# Restrict access to your IP
api_allowed_cidr_blocks = ["203.0.113.0/24"]
ssh_allowed_cidr_blocks = ["203.0.113.0/24"]
# Resource naming
project_name = "myproject"
environment = "dev"
tags = {
Team = "platform"
Owner = "devops"
}
}After terraform apply, K3s is running, but you need the kubeconfig file to connect with kubectl. The AMI includes a setup wizard for downloading your kubeconfig and credentials.
Open the setup wizard URL in your browser:
terraform output -raw setup_wizard_url
# Example: https://54.123.45.67:9443The wizard uses a self-signed certificate — accept the browser warning to proceed.
From the wizard, download and save:
- kubeconfig — Kubernetes cluster access configuration
- config.yml — Complete configuration with all credentials
Important: Save your credentials before locking the wizard. Once locked, you cannot retrieve them again through the wizard.
export KUBECONFIG=~/Downloads/kubeconfig
kubectl get nodesYou should see your K3s node in Ready status.
| Name | Description | Type |
|---|---|---|
name |
Unique name for this K3s deployment (3-32 chars, lowercase alphanumeric with hyphens) | string |
vpc_id |
VPC ID where the security group will be created | string |
subnet_id |
Subnet ID where the K3s instance will be launched | string |
key_name |
Name of an existing EC2 key pair for SSH access | string |
| Name | Description | Type | Default |
|---|---|---|---|
instance_type |
EC2 instance type. Use t3/m5/c5 for amd64 or t4g/m6g/c6g for arm64 | string |
"t3.medium" |
architecture |
CPU architecture: amd64 (x86_64) or arm64 (Graviton) |
string |
"amd64" |
root_volume_size |
Size of the root EBS volume in GB | number |
30 |
associate_public_ip_address |
Associate a public IP address with the instance | bool |
true |
| Name | Description | Type | Default |
|---|---|---|---|
api_allowed_cidr_blocks |
CIDRs allowed to access K8s API and wizard (443, 6443, 9443) | list(string) |
["0.0.0.0/0"] |
ssh_allowed_cidr_blocks |
CIDRs allowed SSH access (port 22) | list(string) |
["0.0.0.0/0"] |
enable_ssh_access |
Enable SSH access in the security group | bool |
true |
enable_termination_protection |
Prevent accidental instance termination | bool |
false |
enable_eip |
Assign an Elastic IP for a static public address | bool |
false |
| Name | Description | Type | Default |
|---|---|---|---|
project_name |
Project name for resource naming prefix | string |
"digitalis" |
environment |
Environment name (dev, staging, prod) | string |
"dev" |
tags |
Additional tags for all resources | map(string) |
{} |
| Name | Description |
|---|---|
name |
Name of this K3s deployment |
name_prefix |
Resource name prefix used for all resources |
instance_id |
EC2 instance ID |
instance_arn |
EC2 instance ARN |
instance_public_ip |
Public IP (EIP if enabled, otherwise auto-assigned) |
instance_private_ip |
Private IP address |
security_group_id |
Security group ID |
security_group_arn |
Security group ARN |
ami_id |
Marketplace AMI ID used |
ami_name |
Marketplace AMI name |
ami_architecture |
AMI architecture (x86_64 or arm64) |
setup_wizard_url |
URL to access the setup wizard (HTTPS on port 9443) |
ssh_command |
Ready-to-use SSH command |
kubernetes_api_url |
Kubernetes API server URL |
next_steps |
Post-deployment instructions |
| Name | Version |
|---|---|
| terraform | >= 1.0 |
| aws | ~> 5.0 |
The IAM principal running Terraform needs permissions for:
| Service | Always | Conditional |
|---|---|---|
| EC2 (instances, security groups, AMIs) | Yes | — |
| EC2 Elastic IPs | — | enable_eip = true |
This module follows security best practices out of the box:
- IMDSv2 Enforced — Instance metadata access requires tokens (
http_tokens = "required") - Encrypted EBS — Root volume uses gp3 with encryption enabled
- Minimal Ports — Security group only exposes Kubernetes API and SSH (optional)
- SSH Configurable — SSH access can be disabled entirely via
enable_ssh_access = false
- Community support — Open a GitHub Issue for bug reports, feature requests, and questions
- Professional support — Contact Digitalis.io for commercial support, consulting, and managed services
This module is maintained by Digitalis.io, a cloud-native consultancy specialising in open-source infrastructure, platform engineering, and DevOps. We help organisations design, build, and operate secure, scalable systems using tools like Kubernetes, Terraform, and OpenBao.
- Website: digitalis.io
- GitHub: github.com/digitalis-io
K3s is a lightweight Kubernetes distribution that removes legacy, alpha, and cloud-provider-specific features to deliver a smaller, faster, and simpler Kubernetes experience. It's ideal for:
- Development environments — Quick cluster setup for local testing
- CI/CD pipelines — Ephemeral clusters for integration tests
- Edge computing — Resource-constrained environments
- Learning — Lower barrier to entry for Kubernetes education
This Terraform module makes it straightforward to deploy K3s on AWS with production-ready defaults — encrypted volumes, IMDSv2 enforcement, and configurable network access.
Contributions are welcome. Please see CONTRIBUTING.md for details.
Apache 2.0 — see LICENSE for details.