Skip to main content

Primary links

  • Home
  • AI
  • Kubernetes
  • Incus
  • Ansible
  • Terraform
  • OpenStack
  • Virtualization
  • Linux
  • SmartHome
  • HowTo

Misc

  • Linux
  • Hardware
  • Programming
  • Databases
  • Multimedia
  • Windows

Cloud

  • OpenStack
  • cloud-config
  • nextcloud

Virtualization

  • Virtualization
  • Incus
  • Docker
  • KVM
  • Kubernetes
  • LXC
  • LXD
  • QEMU
  • VMware
  • VirtualBox
  • multipass
  • podman
  • vagrant
  • XEN

Network

  • DNS
  • Firewall
  • Linux
  • OpenvSwitch
  • SSL
  • VLAN
  • VPN
  • iPXE
  • namespaces
  • nmcli
  • tcpdump

Storage

  • CEPH
  • DRBD
  • LVM
  • S3
  • ZFS
  • btrfs

Automation / CI/CD

  • Install
  • Ansible
  • GitLab
  • LLM
  • Preseed
  • Puppet
  • Terraform
  • Ubuntu autoinstall

Monitoring / Visualisation

  • Grafana
  • Icinga
  • Prometheus
  • Monitoring
  • ELK
  • mermaid

Incus Terraform

Enable Incus remote API authentication
http://www.panticz.de/incus

Terraform main.tf

terraform {
  required_providers {
    incus = {
      source = "lxc/incus"
    }
  }
}

provider "incus" {
  # generate_client_certificates = true
  # accept_remote_certificate    = true

  remote {
    name    = "10.0.1.104"
    scheme  = "https"
    address = "10.0.1.104"
    token   = "xxxxxxxxxxxxxxxxxxxxxxxxxx"
    default = true
  }
}

data "template_file" "user_data" {
  template = <

<strong>Deploy</strong>
<code>
terraform init
terraform apply -auto-approve

Links
https://registry.terraform.io/providers/lxc/incus/latest/docs
https://github.com/lxc/terraform-provider-incus
https://discuss.linuxcontainers.org/t/issues-with-private-network-and-cloud-init-using-tf-incus-and-images-debian-12-cloud/19196/3

Run Ansible from Terraform

Prerequisites
- Terraform instalation
- Ansible instalation
- OpenStack application credentials (~/.config/openstack/clouds.yaml)
- OpenStack security group with allow ingress traffic to TCP 22 (SSH) from terraform node

main.tf

terraform {
  required_providers {
    openstack = {
      source = "terraform-provider-openstack/openstack"
    }

    ansible = {
      source = "ansible/ansible"
    }
  }
}

provider "openstack" {
  cloud = "test-application-credentials"
}

data "openstack_compute_keypair_v2" "keypair_1" {
  name = "test-keypair"
}

data "openstack_networking_network_v2" "network_1" {
  name = "test-network"
}

data "openstack_networking_secgroup_v2" "secgroup_1" {
  # Ensure that the security group allow ingress to TCP 22 (SSH) from terraform node
  name = "test-secgroup" 
}

data "openstack_networking_port_v2" "port_1" {
  device_id  = openstack_compute_instance_v2.instance_1.id
  network_id = openstack_compute_instance_v2.instance_1.network.0.uuid
}

# data "template_file" "user_data" {
#   template = <

<strong>test-playbook.yml</strong>
<code>
---
- name: Deploy webserver(s)
  hosts: www
  # remote_user: ubuntu
  gather_facts: no
  become: true
  pre_tasks:
    - name: Wait util host is reachable by SSH
      wait_for_connection:
        timeout: 300

    - name: Gether facts
      setup:
  tasks:
    - name: Install nginx
      apt:
        update_cache: yes
        name:
          - nginx

Deploy

terraform init
terraform apply -auto-approve

Ansible Provider
https://github.com/ansible/terraform-provider-ansible
https://registry.terraform.io/providers/ansible/ansible/latest/docs

Links
https://www.redhat.com/en/blog/providing-terraform-with-that-ansible-magic

Terraform: OpenStack

OpenStack Providery
https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs

# Configure the OpenStack Provider
provider "openstack" {
  user_name   = "admin"
  tenant_name = "admin"
  password    = "pwd"
  auth_url    = "http://myauthurl:5000/v2.0"
  region      = "RegionOne"
}

# cloud.yaml
provider "openstack" {
  cloud      = "dev-foo"
}

Router
https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/resources/networking_router_v2

resource "openstack_networking_router_v2" "router_1" {
  name       = "foo-router"
  external_network_id = "88934cac-8d55-40d5-8ff9-bde65011741d"
}

resource "openstack_networking_router_interface_v2" "terraform" {
  router_id = openstack_networking_router_v2.router_1.id
  subnet_id = openstack_networking_subnet_v2.subnet_1.id
}

Compute
https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/resources/compute_instance_v2

resource "openstack_compute_instance_v2" "basic" {
  name            = "basic"
  image_id        = "ad091b52-742f-469e-8f3c-fd81cadf0743"
  flavor_id       = "3"
  key_pair        = "my_key_pair_name"
  security_groups = ["default"]

  metadata = {
    this = "that"
  }

  network {
    name = "my_network"
  }
}

Image

data "openstack_images_image_v2" "image_ubuntu_2204" {
  name = "Ubuntu 22.04"
  most_recent = true
}

Floating IP
# network
https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/resources/networking_floatingip_v2
# compute
https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/resources/compute_floatingip_v2

resource "openstack_networking_floatingip_v2" "fip_1" {
  pool = "public"
}

resource "openstack_compute_floatingip_associate_v2" "fip_1" {
  floating_ip = openstack_networking_floatingip_v2.fip_1.address
  instance_id = openstack_compute_instance_v2.bastion.id
}

openstack-check.tf

Deploy LXD container with terraform

Docs
https://registry.terraform.io/providers/terraform-lxd/lxd/latest/docs
https://registry.terraform.io/providers/terraform-lxd/lxd/latest/docs/resources/container

Create LXD container

# terraform init
# terraform apply -auto-approve
# terraform destroy -auto-approve


terraform {
  required_providers {
    lxd = {
      source = "terraform-lxd/lxd"
    }
  }
}

provider "lxd" {
  generate_client_certificates = true
  accept_remote_certificate    = true
}

resource "lxd_container" "lxd_container_u2004" {
  name  = "u2004"
  image = "ubuntu:20.04"

  config = {
    "boot.autostart" = true
  }

  limits = {
    cpu = 2
  }
}

resource "lxd_container" "lxd_container_u2110" {
  name = "u2110"
  image = "ubuntu:21.10"
  # image = "images:ubuntu-minimal:21.10" # fixme

  config = {
    "boot.autostart" = true
  }

  limits = {
    cpu = 2
  }
}

Links
https://dev.to/smashse/snap-lxd-terraform-3f0p

Create OpenStack VPNaaS with Terraform

terraform.tfvars

os_user = "foo"
psk = "pass1234"
fritzbox_wan_ip = "1.2.3.4"
fritzbox_cidr = "192.168.178.0/24"

terraform.tf

variable "os_user" {
  type = string
}

variable "psk" {
  type = string
}

variable "fritzbox_wan_ip" {
  type = string
}

variable "fritzbox_cidr" {
  type = string
}

data "openstack_networking_network_v2" "networking_network_1" {
  name = "${var.os_user}-net"
}

data "openstack_networking_subnet_v2" "networking_subnet_1" {
  name = "${var.os_user}-subnet"
  network_id = data.openstack_networking_network_v2.networking_network_1.id
}

data "openstack_networking_router_v2" "router_1" {
  name = "${var.os_user}-router"
}

resource "openstack_vpnaas_ike_policy_v2" "vpnaas_ike_policy_1" {
  name = "${var.os_user}-ike-aes256-sha512"
  encryption_algorithm = "aes-256"
  auth_algorithm = "sha512"
  pfs = "group2"
}

resource "openstack_vpnaas_ipsec_policy_v2" "vpnaas_ipsec_policy_1" {
  name = "${var.os_user}-ipsec-aes256-sha512"
  encryption_algorithm = "aes-256"
  auth_algorithm = "sha512"
  pfs = "group2"  
}

resource "openstack_vpnaas_service_v2" "vpnaas_service_1" {
  name = "${var.os_user}-vpn-service1"
  router_id = data.openstack_networking_router_v2.router_1.id
}

resource "openstack_vpnaas_endpoint_group_v2" "vpnaas_endpoint_group_subnet_1" {
  name = "${var.os_user}-vpn-ep-subnet"
  type = "subnet"
  endpoints = toset([data.openstack_networking_subnet_v2.networking_subnet_1.id])
}

resource "openstack_vpnaas_endpoint_group_v2" "vpnaas_endpoint_group_cidr_1" {
  name = "${var.os_user}-vpn-ep-cidr"
  type = "cidr"
  endpoints = toset([var.fritzbox_cidr])
}

resource "openstack_vpnaas_site_connection_v2" "vpnaas_site_connection" {
  name = "${var.os_user}-vpn-conn1"
  ikepolicy_id = openstack_vpnaas_ike_policy_v2.vpnaas_ike_policy_1.id
  ipsecpolicy_id = openstack_vpnaas_ipsec_policy_v2.vpnaas_ipsec_policy_1.id
  vpnservice_id = openstack_vpnaas_service_v2.vpnaas_service_1.id
  psk = var.psk
  peer_address = var.fritzbox_wan_ip
  peer_id = var.fritzbox_wan_ip
  local_ep_group_id = openstack_vpnaas_endpoint_group_v2.vpnaas_endpoint_group_subnet_1.id
  peer_ep_group_id  = openstack_vpnaas_endpoint_group_v2.vpnaas_endpoint_group_cidr_1.id
}

data "openstack_networking_secgroup_v2" "networking_secgroup_1" {
  name = "${var.os_user}-sec"
}

resource "openstack_networking_secgroup_rule_v2" "networking_secgroup_rule_1" {
  direction = "ingress"
  ethertype = "IPv4"
  protocol = "tcp"
  port_range_min = 22
  port_range_max = 22
  remote_ip_prefix = var.fritzbox_cidr
  security_group_id = data.openstack_networking_secgroup_v2.networking_secgroup_1.id
}

output "vpnaas_service_external_v4_ip" {
  value = openstack_vpnaas_service_v2.vpnaas_service_1.external_v4_ip
}

Configure connnection

terraform 0.13upgrade -yes .
terraform init
terraform plan
terraform apply -auto-approve

Fix / import already existing security group rule

Terraform: Create LoadBalancer in OpenStack

provider "openstack" {
  cloud = "lab-admin"
  use_octavia = true
}

# data "template_file" "user_data" {
#   template = file("user-data.txt")
# }

data "template_file" "user_data" {
  template = < /tmp/debug
EOF
}

variable "http_instance_names" {
  type = set(string)
  default = ["www1", "www2"]
}

resource "openstack_compute_instance_v2" "http" {
  for_each    = var.http_instance_names
  name        = each.key
 #name = "www${count.index + 1}"
 #count = 2
 image_name = "Ubuntu 20.04 minimal"
 flavor_name = "m1.small"
 key_pair = "lab-key"
 security_groups = ["default"]
 user_data = data.template_file.user_data.rendered

 network {
   name = "demo-net"
 }
}

data "openstack_networking_network_v2" "network_1" {
  name = "demo-net"
}

data "openstack_networking_subnet_v2" "subnet_1" {
  name = "demo-subnet"
  network_id = data.openstack_networking_network_v2.network_1.id
}

# Create loadbalancer
resource "openstack_lb_loadbalancer_v2" "http" {
  name          = "demo-lb1"
  vip_subnet_id = data.openstack_networking_subnet_v2.subnet_1.id
}

# Create listener
resource "openstack_lb_listener_v2" "http" {
  name            = "demo-lb1-http-listener"
  protocol        = "TCP"
  protocol_port   = 80
  loadbalancer_id = openstack_lb_loadbalancer_v2.http.id
  #depends_on      = [openstack_lb_loadbalancer_v2.http]

  insert_headers = {
    X-Forwarded-For = "true"
    X-Forwarded-Proto = "true"
  }
}

# Create pool
resource "openstack_lb_pool_v2" "http" {
  name        = "demo-lb1-http-pool1"
  protocol    = "TCP"
  lb_method   = "ROUND_ROBIN"
  listener_id = openstack_lb_listener_v2.http.id
  #depends_on  = [openstack_lb_listener_v2.http]
}

# Add member to pool
resource "openstack_lb_member_v2" "http1" {
  for_each      = var.http_instance_names
  address       = openstack_compute_instance_v2.http[each.key].access_ip_v4
  protocol_port = 80
  pool_id       = openstack_lb_pool_v2.http.id
  subnet_id     = data.openstack_networking_subnet_v2.subnet_1.id
  #depends_on    = [openstack_lb_pool_v2.http]
}

# Get floating IP
resource "openstack_networking_floatingip_v2" "floatingip_1" {
  pool = "public"
}

# Associate floating IP to LoadBalancer
resource "openstack_networking_floatingip_associate_v2" "floatip_1" {
  floating_ip = openstack_networking_floatingip_v2.floatingip_1.address
  port_id = openstack_lb_loadbalancer_v2.http.vip_port_id
}

output "LoadBalancer_IP" {
  value = "http://${openstack_networking_floatingip_v2.floatingip_1.address}"
}

TERMINATED_HTTPS loadbalancer

Kubernetes the hard way

Links
https://github.com/kelseyhightower/kubernetes-the-hard-way

Configure OpenStack application credentials

mkdir -p ~/.config/openstack

cat < ~/.config/openstack/clouds.yaml
clouds:
  dev-foo:
    auth_type: "v3applicationcredential"
    auth:
      auth_url: https://keystone.service.dev.example.com/v3
      application_credential_id: "YOUR_CREDENTIAL_ID"
      application_credential_secret: "YOUR_CREDENTIAL_PASS"
EOF

Install Terraform

cat < /tmp/install-terraform.yml 
---
- hosts: localhost
  tasks:
    - name: Get latest Terraform version
      uri:
        url: https://checkpoint-api.hashicorp.com/v1/check/terraform
      register: response

    - set_fact:
        terraform_download_url: "{{ response.json.current_download_url }}"
        terraform_version: "{{ response.json.current_version }}"

    - name: Download Terraform {{ terraform_version }}
      unarchive:
        src: "{{ terraform_download_url }}terraform_{{ terraform_version }}_{{ ansible_system | lower }}_amd64.zip"
        remote_src: yes
        dest: ~/bin
        creates: ~/bin/terraform
        mode: 0550
EOF

ansible-playbook /tmp/install-terraform.yml

Create test env on OpenStack

Terraform snippets

local-exec:

data "template_file" "user_data" {
  template = < /tmp/debug"
      ]

    connection {
      type        = "ssh"
      host        = openstack_networking_floatingip_v2.floatingip_1.address
      user        = "ubuntu"
      private_key = file(pathexpand("~/.ssh/id_rsa"))
    }
  }

  provisioner "local-exec" {
    command = "TF_STATE=terraform.tfstate ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i inventory install-nginx.yml"
  }

  depends_on = [openstack_networking_floatingip_v2.floatingip_1]        
}


resource "local_file" "hosts_cfg" {
  content = templatefile("inventory.tmpl",
    {
      ubuntu_hosts = openstack_networking_floatingip_v2.floatingip_1.*.address
    }
  )
  filename = "inventory"
  depends_on = [openstack_networking_floatingip_associate_v2.instance_fip_association]
}

Links
https://github.com/knetsolutions/learn-terraform-with-openstack/blob/master/provisioner/README.md
https://www.digitalocean.com/community/tutorials/how-to-use-ansible-with-terraform-for-configuration-management

subnetpool

# DEV only
# resource "openstack_networking_subnetpool_v2" "subnetpool_1" {
#   # count = var.env == "dev" ? 1 : 0

#   name = "subnetpool_1"
#   # prefixes = ["10.0.0.0/16"]
#   prefixes = [var.test_subnet_cidr]
#   # address_scope_id = "1a68b969-b6d1-43ba-8bd0-4c6b770e3012" # DEV only
# }

resource "openstack_networking_subnet_v2" "subnet_1" {
  network_id = openstack_networking_network_v2.network_1.id
  name       = var.test_subnet
  cidr       = var.test_subnet_cidr

  # DEV only
  # subnetpool_id = openstack_networking_subnetpool_v2.subnetpool_1.id

  # depends_on = [openstack_networking_subnetpool_v2.subnetpool_1]  
}

# show sensitive variable
terraform output -raw my_password

# run specific task
terraform apply -auto-approve -replace=terraform_data.foo_api_key

DNS loockup

data "dns_a_record_set" "google" {
  host = "google.com"
}

output "google_addrs" {
  value = join(",", data.dns_a_record_set.google.addrs)
}

terraform
Profiles GitHub StackOverflow LinkedIn Xing
Contact Imprint
© panticz 2026

Cookie-Einstellungen

Diese Website nutzt eingebettete Inhalte von Drittanbietern (z.B. YouTube, SoundCloud). Beim Laden dieser Inhalte werden Daten an die jeweiligen Anbieter übermittelt. Datenverarbeitungserklärung