[Yandex Cloud documentation](../../../index.md) > [Yandex Smart Web Security](../../index.md) > [Tutorials](../index.md) > [Creating an L7 load balancer with DDoS protection at OSI L3-L4](index.md) > Terraform

# Creating an L7 load balancer with DDoS protection using Terraform


To create an L7 load balancer with DDoS protection using Terraform:

1. [Get your cloud ready](#before-begin).
1. [Create your infrastructure](#deploy).
1. [Test the load balancer](#test).

If you no longer need the resources you created, [delete them](#clear-out).


## Get your cloud ready {#before-begin}

Sign up for Yandex Cloud and create a [billing account](../../../billing/concepts/billing-account.md):
1. Navigate to the [management console](https://console.yandex.cloud) and log in to Yandex Cloud or create a new account.
1. On the **[Yandex Cloud Billing](https://center.yandex.cloud/billing/accounts)** page, make sure you have a billing account linked and it has the `ACTIVE` or `TRIAL_ACTIVE` [status](../../../billing/concepts/billing-account-statuses.md). If you do not have a billing account, [create one](../../../billing/quickstart/index.md) and [link](../../../billing/operations/pin-cloud.md) a cloud to it.

If you have an active billing account, you can create or select a [folder](../../../resource-manager/concepts/resources-hierarchy.md#folder) for your infrastructure on the [cloud page](https://console.yandex.cloud/cloud).

[Learn more about clouds and folders here](../../../resource-manager/concepts/resources-hierarchy.md).


### Required paid resources {#paid-resources}

The infrastructure support cost for a DDoS-protected load balancer includes:

* Fee for continuously running [VMs](../../../compute/concepts/vm.md) (see [Yandex Compute Cloud pricing](../../../compute/pricing.md)).
* Fee for using a [public static IP address](../../../vpc/concepts/address.md#public-addresses) (see [Yandex Virtual Private Cloud pricing](../../../vpc/pricing.md)).
* Fee for filtering incoming traffic to a public IP address with [DDoS protection](../../../vpc/ddos-protection/index.md) (see [Yandex Virtual Private Cloud pricing](../../../vpc/pricing.md#prices-ddos-protection)).
* Fee for using computing resources of the [L7 load balancer](../../../application-load-balancer/concepts/index.md) (see [Application Load Balancer pricing](../../../application-load-balancer/pricing.md)).


## Create your infrastructure {#deploy}

With [Terraform](https://www.terraform.io/), you can quickly create a cloud infrastructure in Yandex Cloud and manage it using configuration files. These files store the infrastructure description written in HashiCorp Configuration Language (HCL). If you change the configuration files, Terraform automatically detects which part of your configuration is already deployed, and what should be added or removed.

Terraform is distributed under the [Business Source License](https://github.com/hashicorp/terraform/blob/main/LICENSE). The [Yandex Cloud provider for Terraform](https://github.com/yandex-cloud/terraform-provider-yandex) is distributed under the [MPL-2.0](https://www.mozilla.org/en-US/MPL/2.0/) license.

For more information about the provider resources, see the guides on the [Terraform](https://www.terraform.io/docs/providers/yandex/index.html) website or [its mirror](../../../terraform/index.md).

To create an infrastructure with Terraform:

1. [Install Terraform](../../../tutorials/infrastructure-management/terraform-quickstart.md#install-terraform), [get the authentication credentials](../../../tutorials/infrastructure-management/terraform-quickstart.md#get-credentials), and specify the Yandex Cloud provider source (see [Configure your provider](../../../tutorials/infrastructure-management/terraform-quickstart.md#configure-provider), Step 1).
1. Set up your infrastructure description file:

   {% list tabs group=infrastructure_description %}

   - Ready-made configuration {#ready}

     1. Clone the repository with configuration files:

        ```bash
        git clone https://github.com/yandex-cloud-examples/yc-alb-ddos-protection.git
        ```

     1. Navigate to the repository directory. It should now contain the following files:
        * `alb-with-ddos-protection.tf`: New infrastructure configuration.
        * `alb-with-ddos-protection.auto.tfvars`: User data.

   - Manually {#manual}

     1. Create a folder for the infrastructure description file.
     1. In the folder, create a configuration file named `alb-with-ddos-protection.tf`:

        {% cut "alb-with-ddos-protection.tf" %}

        ```hcl
        variable "folder_id" {
          type = string
        }
        
        variable "vm_user" {
          type = string
        }
        
        variable "ssh_key_path" {
          type = string
        }
        
        locals {
          network_name     = "ddos-network"
          subnet_name1     = "subnet-1"
          subnet_name2     = "subnet-2"
          sa_name          = "ig-sa"
          sg_balancer_name = "ddos-sg-balancer"
          sg_vm_name       = "ddos-sg-vms"
          vm_name          = "ddos-group"
          tg_name          = "tg-ddos"
          address_name     = "ddos-addr"
          abg_name         = "ddos-backend-group"
          backend_name     = "backend-1"
          router_name      = "ddos-router"
          vh_name          = "ddos-host"
          authority_domain = ["alb-with-ddos.com"]
          route_name       = "route-1"
          alb_name         = "ddos-protect-alb"
          listener_name    = "ddos-listener"
        }
        
        terraform {
          required_providers {
            yandex = {
              source  = "yandex-cloud/yandex"
              version = ">= 0.47.0"
            }
          }
        }
        
        provider "yandex" {
          folder_id = var.folder_id
        }
        
        resource "yandex_iam_service_account" "ig-sa" {
          name = local.sa_name
        }
        
        resource "yandex_resourcemanager_folder_iam_member" "editor" {
          folder_id = var.folder_id
          role      = "editor"
          member    = "serviceAccount:${yandex_iam_service_account.ig-sa.id}"
        }
        
        resource "yandex_vpc_network" "ddos-network" {
          name = local.network_name
        }
        
        resource "yandex_vpc_subnet" "subnet-1" {
          name           = local.subnet_name1
          zone           = "ru-central1-a"
          network_id     = yandex_vpc_network.ddos-network.id
          v4_cidr_blocks = ["192.168.1.0/24"]
        }
        
        resource "yandex_vpc_subnet" "subnet-2" {
          name           = local.subnet_name2
          zone           = "ru-central1-b"
          network_id     = yandex_vpc_network.ddos-network.id
          v4_cidr_blocks = ["192.168.2.0/24"]
        }
        
        resource "yandex_vpc_security_group" "ddos-sg-balancer" {
          name       = local.sg_balancer_name
          network_id = yandex_vpc_network.ddos-network.id
        
          egress {
            protocol       = "ANY"
            description    = "any"
            v4_cidr_blocks = ["0.0.0.0/0"]
          }
        
          ingress {
            protocol       = "TCP"
            description    = "ext-http"
            v4_cidr_blocks = ["0.0.0.0/0"]
            port           = 80
          }
        
          ingress {
            protocol       = "TCP"
            description    = "ext-https"
            v4_cidr_blocks = ["0.0.0.0/0"]
            port           = 443
          }
        
          ingress {
            protocol          = "TCP"
            description       = "healthchecks"
            predefined_target = "loadbalancer_healthchecks"
            port              = 30080
          }
        }
        
        resource "yandex_vpc_security_group" "ddos-sg-vms" {
          name       = local.sg_vm_name
          network_id = yandex_vpc_network.ddos-network.id
        
          ingress {
            protocol          = "TCP"
            description       = "balancer"
            security_group_id = yandex_vpc_security_group.ddos-sg-balancer.id
            port              = 80
          }
        
          ingress {
            protocol       = "TCP"
            description    = "ssh"
            v4_cidr_blocks = ["0.0.0.0/0"]
            port           = 22
          }
        }
        
        resource "yandex_compute_image" "lemp" {
          source_family = "lemp"
        }
        
        resource "yandex_compute_instance_group" "ddos-group" {
          name               = local.vm_name
          folder_id          = var.folder_id
          service_account_id = yandex_iam_service_account.ig-sa.id
          instance_template {
            platform_id        = "standard-v2"
            service_account_id = yandex_iam_service_account.ig-sa.id
            resources {
              core_fraction = 5
              memory        = 1
              cores         = 2
            }
        
            boot_disk {
              mode = "READ_WRITE"
              initialize_params {
                image_id = yandex_compute_image.lemp.id
                type     = "network-hdd"
                size     = 3
              }
            }
        
            network_interface {
              network_id         = yandex_vpc_network.ddos-network.id
              subnet_ids         = [yandex_vpc_subnet.subnet-1.id,yandex_vpc_subnet.subnet-2.id]
              nat                = true
              security_group_ids = [yandex_vpc_security_group.ddos-sg-vms.id]
            }
        
            metadata = {
              user-data = "#cloud-config\nusers:\n  - name: ${var.vm_user}\n    groups: sudo\n    shell: /bin/bash\n    sudo: 'ALL=(ALL) NOPASSWD:ALL'\n    ssh_authorized_keys:\n      - ${file("${var.ssh_key_path}")}"
            }
          }
        
          scale_policy {
            fixed_scale {
              size = 2
            }
          }
        
          allocation_policy {
            zones = ["ru-central1-a", "ru-central1-b"]
          }
        
          deploy_policy {
            max_unavailable = 1
            max_expansion   = 0
          }
        
          application_load_balancer {
            target_group_name = local.tg_name
          }
        }
        
        resource "yandex_vpc_address" "ddos-addr" {
          name = local.address_name
        
          external_ipv4_address {
            zone_id                  = "ru-central1-a"
            ddos_protection_provider = "qrator"
          }
        }
        
        resource "yandex_alb_backend_group" "ddos-backend-group" {
          name = local.abg_name
        
          http_backend {
            name             = local.backend_name
            port             = 80
            target_group_ids = [yandex_compute_instance_group.ddos-group.application_load_balancer.0.target_group_id]
            healthcheck {
              timeout          = "10s"
              interval         = "2s"
              healthcheck_port = 80
              http_healthcheck {
                path = "/"
              }
            }
          }
        }
        
        resource "yandex_alb_http_router" "ddos-router" {
          name   = local.router_name
        }
        
        resource "yandex_alb_virtual_host" "ddos-host" {
          name           = local.vh_name
          http_router_id = yandex_alb_http_router.ddos-router.id
          authority      = local.authority_domain
          route {
            name = local.route_name
            http_route {
              http_route_action {
                backend_group_id = yandex_alb_backend_group.ddos-backend-group.id
              }
            }
          }
        }
        
        resource "yandex_alb_load_balancer" "ddos-protect-alb" {
          name               = local.alb_name
          network_id         = yandex_vpc_network.ddos-network.id
          security_group_ids = [yandex_vpc_security_group.ddos-sg-balancer.id]
        
          allocation_policy {
            location {
              zone_id   = "ru-central1-a"
              subnet_id = yandex_vpc_subnet.subnet-1.id
            }
        
            location {
              zone_id   = "ru-central1-b"
              subnet_id = yandex_vpc_subnet.subnet-2.id
            }
          }
        
          listener {
            name = local.listener_name
            endpoint {
              address {
                external_ipv4_address {
                  address = yandex_vpc_address.ddos-addr.external_ipv4_address[0].address
                }
              }
              ports = [ 80 ]
            }
            http {
              handler {
                http_router_id = yandex_alb_http_router.ddos-router.id
              }
            }
          }
        }
        ```

        {% endcut %}

     1. In the folder, create a user data file named `alb-with-ddos-protection.auto.tfvars`:

        {% cut "alb-with-ddos-protection.auto.tfvars" %}

        ```hcl
        folder_id    = "<folder_ID>"
        vm_user      = "<VM_username>"
        ssh_key_path = "<path_to_public_SSH_key>"
        ```

        {% endcut %}

   {% endlist %}

   Learn more about the properties of Terraform resources in the relevant Terraform guides:

   * [Service account](../../../iam/concepts/users/service-accounts.md): [yandex_iam_service_account](../../../terraform/resources/iam_service_account.md).
   * [Role](../../../iam/concepts/access-control/roles.md): [yandex_resourcemanager_folder_iam_member](../../../terraform/resources/resourcemanager_folder_iam_member.md).
   * [Network](../../../vpc/concepts/network.md#network): [yandex_vpc_network](../../../terraform/resources/vpc_network.md).
   * [Subnets](../../../vpc/concepts/network.md#subnet): [yandex_vpc_subnet](../../../terraform/resources/vpc_subnet.md).
   * [Security groups](../../../vpc/concepts/security-groups.md): [yandex_vpc_security_group](../../../terraform/resources/vpc_security_group.md).
   * [Image](../../../compute/concepts/image.md): [yandex_compute_image](../../../terraform/resources/compute_image.md).
   * [Instance group](../../../compute/concepts/instance-groups/index.md): [yandex_compute_instance_group](../../../terraform/resources/compute_instance_group.md).
   * [Static public IP address](../../../vpc/concepts/address.md#public-addresses): [yandex_vpc_address](../../../terraform/resources/vpc_address.md).
   * [Backend group](../../../application-load-balancer/concepts/backend-group.md): [yandex_alb_backend_group](../../../terraform/resources/alb_backend_group.md).
   * [HTTP router](../../../application-load-balancer/concepts/http-router.md): [yandex_alb_http_router](../../../terraform/resources/alb_http_router.md).
   * [Virtual host](../../../application-load-balancer/concepts/http-router.md#virtual-host): [yandex_alb_virtual_host](../../../terraform/resources/alb_virtual_host.md).
   * [L7 load balancer](../../../application-load-balancer/concepts/application-load-balancer.md): [yandex_alb_load_balancer](../../../terraform/resources/alb_load_balancer.md).

1. In the `alb-with-ddos-protection.auto.tfvars` file, set the following user-defined properties:

    * `folder_id`: [Folder ID](../../../resource-manager/operations/folder/get-id.md).
    * `vm_user`: VM user name.
    * `ssh_key_path`: Path to the public SSH key to authenticate the user on the VM. For more information, see [Creating an SSH key pair](../../../compute/operations/vm-connect/ssh.md#creating-ssh-keys).

1. Create the resources:

   1. In the terminal, navigate to the configuration file directory.
   1. Make sure the configuration is correct using this command:
   
      ```bash
      terraform validate
      ```
   
      If the configuration is valid, you will get this message:
   
      ```bash
      Success! The configuration is valid.
      ```
   
   1. Run this command:
   
      ```bash
      terraform plan
      ```
   
      You will see a list of resources and their properties. No changes will be made at this step. Terraform will show any errors in the configuration.
   1. Apply the configuration changes:
   
      ```bash
      terraform apply
      ```
   
   1. Type `yes` and press **Enter** to confirm the changes.

After creating the infrastructure, [test](#test) it.

## Test the load balancer {#test}

Check that the service is available on the `alb-with-ddos.com` host. To do this, run the following command:

```bash
curl \
  --header "Host: alb-with-ddos.com" \
  http://<L7_load_balancer_IP_address>
```

Result:

```html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
  body {
    width: 35em;
    margin: 0 auto;
    font-family: Tahoma, Verdana, Arial, sans-serif;
  }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
```


## How to delete the resources you created {#clear-out}

To stop paying for the resources you created:

1. Open the `alb-with-ddos-protection.tf` file and delete your infrastructure description from it.
1. Apply the changes:

    1. In the terminal, navigate to the configuration file directory.
    1. Make sure the configuration is correct using this command:
    
       ```bash
       terraform validate
       ```
    
       If the configuration is valid, you will get this message:
    
       ```bash
       Success! The configuration is valid.
       ```
    
    1. Run this command:
    
       ```bash
       terraform plan
       ```
    
       You will see a list of resources and their properties. No changes will be made at this step. Terraform will show any errors in the configuration.
    1. Apply the configuration changes:
    
       ```bash
       terraform apply
       ```
    
    1. Type `yes` and press **Enter** to confirm the changes.

#### Useful links {#see-also}

* [Creating an L7 load balancer with DDoS protection using the management console or CLI](console.md)