Docs Blog Apps Pricing

Getting Started

1. Install the CLI 2. Login 3. Build and Push 4. Boot on GCP 5. Boot on Bare Metal

Guides

Authentication Pushing and Pulling Images Configuring Images Working with Hosts Working with GCP Working with Bare Metal latitude.sh OVHcloud Working with AWS Backups Tips and Tricks

CLI Reference

kheeper auth kheeper authorizations kheeper bots kheeper clouds kheeper contexts kheeper hosts kheeper images kheeper orgs kheeper push kheeper releases kheeper status

Boot on AWS

This guide walks through booting your first Kheeper-managed host on Amazon Web Services.

Prerequisites

Set the variables in your shell needed for the remaining steps.

ORG=$(kheeper orgs list | grep 'user-[0-9a-f]' | awk '{ print $1 }')
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
AWS_REGION=us-east-2

Note the us-east-2 region is currently the only region that has the Kheeper API so instances must be launched in that region.

Step 1 — Create an IAM role for EC2

The instance needs an IAM role so it can call STS GetCallerIdentity during auto-registration. Create a minimal role:

aws iam create-role \
  --role-name kheeper-autoregister \
  --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Principal": {"Service": "ec2.amazonaws.com"},
      "Action": "sts:AssumeRole"
    }]
  }'

aws iam create-instance-profile \
  --instance-profile-name kheeper-autoregister

aws iam add-role-to-instance-profile \
  --instance-profile-name kheeper-autoregister \
  --role-name kheeper-autoregister

Or, equivalently, with Terraform:

resource "aws_iam_role" "kheeper_autoregister" {
  name = "kheeper-autoregister"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { Service = "ec2.amazonaws.com" }
      Action    = "sts:AssumeRole"
    }]
  })
}

resource "aws_iam_instance_profile" "kheeper_autoregister" {
  name = "kheeper-autoregister"
  role = aws_iam_role.kheeper_autoregister.name
}

No additional permissions are needed — GetCallerIdentity requires no IAM permissions.

Step 2 — Connect your AWS account

Link your AWS account to your Kheeper org so that AWS instances can auto-register as Kheeper hosts.

kheeper clouds create ${ORG}/my-aws --provider aws --account-id ${ACCOUNT_ID}

This will allow new instances created from Kheeper AMIs to register as new hosts in the region shown by kheeper status. Kheeper accounts are region-scoped. If the same AWS account is linked to multiple Kheeper regions, instances will fail to register unless a region is configured with metadata:

aws ec2 run-instances --user-data 'kheeper-region=us.kheeper.com'

Step 3 — Create an EC2 instance

Since this guide uses the postgres image, create a security group that will allow your instance to get a TLS certificate from Lets Encrypt (port 80) and listen for incoming connections to postgres (port 5432). Additionally ssh (port 22) allows for accessing the instance for sysadmin work.

VPC_ID=$(aws ec2 describe-vpcs --filters "Name=isDefault,Values=true" \
  --query 'Vpcs[0].VpcId' --output text --region ${AWS_REGION})

SG_ID=$(aws ec2 create-security-group \
  --group-name kheeper-http-postgres \
  --description "Allow HTTP and Postgres" \
  --vpc-id ${VPC_ID} \
  --region ${AWS_REGION} \
  --query 'GroupId' --output text)

aws ec2 authorize-security-group-ingress \
  --group-id ${SG_ID} \
  --protocol tcp --port 80 --cidr 0.0.0.0/0 \
  --region ${AWS_REGION}

aws ec2 authorize-security-group-ingress \
  --group-id ${SG_ID} \
  --protocol tcp --port 5432 --cidr 0.0.0.0/0 \
  --region ${AWS_REGION}

aws ec2 authorize-security-group-ingress \
  --group-id ${SG_ID} \
  --protocol tcp --port 22 --cidr 0.0.0.0/0 \
  --region ${AWS_REGION}

Then launch an instance using the public Kheeper AMI. This is a Fedora bootc image that automatically connects to the Kheeper registry on first boot.

AMI_ID=$(aws ec2 describe-images \
  --owners 223249276674 \
  --filters "Name=name,Values=kheeper-aws-*" "Name=state,Values=available" \
  --query 'sort_by(Images, &CreationDate)[-1].ImageId' \
  --output text --region ${AWS_REGION})

INSTANCE_ID=$(aws ec2 run-instances \
  --image-id ${AMI_ID} \
  --instance-type m7i.large \
  --block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":40}}]' \
  --iam-instance-profile Name=kheeper-autoregister \
  --security-group-ids ${SG_ID} \
  --user-data 'kheeper-region=us.kheeper.com' \
  --region ${AWS_REGION} \
  --query 'Instances[0].InstanceId' --output text)

echo "Launched ${INSTANCE_ID}"

Or, equivalently, with Terraform (the region comes from your aws provider block):

data "aws_vpc" "default" {
  default = true
}

resource "aws_security_group" "kheeper_http_postgres" {
  name        = "kheeper-http-postgres"
  description = "Allow HTTP and Postgres"
  vpc_id      = data.aws_vpc.default.id
}

resource "aws_vpc_security_group_ingress_rule" "http" {
  security_group_id = aws_security_group.kheeper_http_postgres.id
  ip_protocol       = "tcp"
  from_port         = 80
  to_port           = 80
  cidr_ipv4         = "0.0.0.0/0"
}

resource "aws_vpc_security_group_ingress_rule" "postgres" {
  security_group_id = aws_security_group.kheeper_http_postgres.id
  ip_protocol       = "tcp"
  from_port         = 5432
  to_port           = 5432
  cidr_ipv4         = "0.0.0.0/0"
}

resource "aws_vpc_security_group_ingress_rule" "ssh" {
  security_group_id = aws_security_group.kheeper_http_postgres.id
  ip_protocol       = "tcp"
  from_port         = 22
  to_port           = 22
  cidr_ipv4         = "0.0.0.0/0"
}

data "aws_ami" "kheeper" {
  owners      = ["223249276674"]
  most_recent = true

  filter {
    name   = "name"
    values = ["kheeper-aws-*"]
  }

  filter {
    name   = "state"
    values = ["available"]
  }
}

resource "aws_instance" "kheeper" {
  ami                    = data.aws_ami.kheeper.id
  instance_type          = "m7i.large"
  iam_instance_profile   = aws_iam_instance_profile.kheeper_autoregister.name
  vpc_security_group_ids = [aws_security_group.kheeper_http_postgres.id]
  user_data              = "kheeper-region=us.kheeper.com"

  root_block_device {
    volume_size = 40
  }
}

Step 4 — Verify Host Registration

The instance will boot and auto-register within a few minutes. Check that the host appeared:

kheeper hosts list --org ${ORG}

You should see a host whose instance name matches the instance ID you launched.

Step 5 — Author the config

Generate a starter config from the image's schema and edit it to fit your host. Here we are using the public postgres image: You can use the DNS name from kheeper hosts list where the config requests a domain.

kheeper releases start config.json --image us.kheeper.com/public/postgres:v0.2.0

Here's an example for a config with a single ssh public key that creates a database named kheeper and a database user named kheeper.

{
  "base": {
    "admin_authorized_keys": "ssh-ed25519 AAAAC3NzaC1lZDI1NET5AAAAINFEt8Q1O8VSKe+GVOsHMqjXdyukUkM38VI/edNs0ur8"
  },
  "database": {
    "name": "kheeper",
    "users": [{"name": "kheeper", "password": "changeme1234567890"}]
  },
  "postgres": {
    "domain_name": "i-0a35818c9f09bada3.user-12345678.us.kheeper.app"
  }
}

Step 6 — Create a release

Create and activate a release that pairs the image with your config:

kheeper releases create ${ORG}/${INSTANCE_ID}:v1 \
  --image us.kheeper.com/public/postgres:v0.2.0 \
  --config-file config.json \
  --activate

Step 7 — Verify Postgres

The host will pick up the release within a minute, pull and reboot.

You can now connect to your Postgres server with psql.

HOST_DNS=$INSTANCE_ID.user-12345678.us.kheeper.app
USER=kheeper
export PGPASSWORD=changeme1234567890

psql "host=$HOST_DNS user=$USER sslmode=verify-full sslrootcert=system"

Troubleshooting

If an instance fails to autoregister as a new host or fails to reboot into a release after you activate it, you should inspect the console output:

aws ec2 get-console-output --instance-id ${INSTANCE_ID} --region ${AWS_REGION} --output text

Clean up

Terminate the EC2 instance and delete the Kheeper host when you're done:

aws ec2 terminate-instances --instance-ids ${INSTANCE_ID} --region ${AWS_REGION}
kheeper hosts delete ${ORG}/${INSTANCE_ID}