[Yandex Cloud documentation](../../index.md) > [Yandex Application Load Balancer](../index.md) > [Tutorials](index.md) > Deploying a web application on BareMetal servers with an L7 load balancer and Smart Web Security protection

# Deploying a web application on Yandex BareMetal servers with an L7 load balancer and Yandex Smart Web Security protection


In this tutorial, you will deploy a web application on Yandex BareMetal [servers](../../baremetal/concepts/servers.md). To evenly distribute load across the application hosts, you will configure an [L7 load balancer](../concepts/application-load-balancer.md) in Yandex Application Load Balancer. A Yandex Smart Web Security [profile](../../smartwebsecurity/concepts/profiles.md) will ensure protection of your web application from bots, DDoS, and web attacks. A Yandex Cloud Interconnect [routing instance](../../cloud-router/concepts/routing-instance.md) will provide a [private connection](../../interconnect/concepts/priv-con.md) between the Yandex Virtual Private Cloud [cloud network](../../vpc/concepts/network.md#network) and the Yandex BareMetal [private network](../../baremetal/concepts/private-network.md).

You can see the solution architecture in the diagram below:

![webapp-on-bms-behind-sws](../../_assets/tutorials/webapp-on-bms-behind-sws.svg)

Where:
* BareMetal infrastructure components:

    * Private subnet in the `ru-central1-m4` [server pool](../../baremetal/concepts/servers.md#server-pools): `subnet-m4`.
    * [Virtual network segment](../../baremetal/concepts/private-network.md#vrf-segment) (VRF), `my-vrf`.
    * Two BareMetal servers, `alb-back-0` and `alb-back-1`, hosting the deployed application in the `ru-central1-m4` server pool.
* Cloud Interconnect `Routing Instance` for connectivity between the Virtual Private Cloud and BareMetal networks.
* [Virtual Private Cloud](../../vpc/index.md) infrastructure components:

    * Cloud network, `sample-network`.
    * [Subnets](../../vpc/concepts/network.md#subnet) named `vpc-subnet-a` and `vpc-subnet-b` in the `ru-central1-a` and `ru-central1-b` [availability zones](../../overview/concepts/geo-scope.md), respectively.
    * L7 load balancer from Application Load Balancer , `demo-alb-bms`.
    * Smart Web Security profile, `sws-demo-profile`.
    * `vm-validator` [VM](../../compute/concepts/vm.md) for connectivity checks between the Virtual Private Cloud and BareMetal networks.

To deploy a web application on Yandex BareMetal servers with an L7 load balancer and Yandex Smart Web Security protection:

1. [Get your cloud ready](#before-you-begin).
1. [Set up your VPC environment](#setup-vpc).
1. [Create a routing instance](#create-routing-instance).
1. [Set up your BareMetal environment](#setup-baremetal).
1. [Configure an L7 load balancer](#setup-balancer).
1. [Set up protection against bots, DDoS, and web attacks](#setup-sws).

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

## Getting started {#before-you-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 deploying a web application on BareMetal servers with an L7 load balancer and Smart Web Security protection includes:

* Fee for using the VM [public IP address](../../vpc/concepts/address.md#public-addresses) (see [Yandex Virtual Private Cloud pricing](../../vpc/pricing.md)).
* Fee for [VM](../../compute/concepts/vm.md) computing resources and disks (see [Yandex Compute Cloud pricing](../../compute/pricing.md)).
* Fee for renting the BareMetal servers (see [Yandex BareMetal pricing](../../baremetal/pricing.md)).
* Fee for using the L7 load balancer’s computing resources (see [Yandex Application Load Balancer pricing](../pricing.md)).
* Fee for requests processed by security profile rules (see [Yandex Smart Web Security pricing](../../smartwebsecurity/pricing.md)).
* If using a [log group](../../logging/concepts/log-group.md) for load balancer logging, fee for data logging and storage (see [Yandex Cloud Logging pricing](../../logging/pricing.md)).

Traffic transmitted via [Yandex Cloud Interconnect](../../interconnect/index.md) between private Yandex BareMetal and Yandex Virtual Private Cloud addresses in either direction is not billable.

## Set up your VPC environment {#setup-vpc}

Configure the infrastructure on the Virtual Private Cloud side. In this step, you will create a [cloud network](../../vpc/concepts/network.md#network), [subnets](../../vpc/concepts/network.md#subnet), required [security groups](../../vpc/concepts/security-groups.md), and a [VM](../../compute/concepts/vm.md).

### Create a cloud network {#create-network}

{% list tabs group=instructions %}

- Management console {#console} 

  1. In the [management console](https://console.yandex.cloud), select the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) where you are going to create your infrastructure.
  1. Navigate to **Virtual Private Cloud**.
  1. At the top right, click **Create network**.
  1. In the **Name** field, specify `sample-network`.
  1. In the **Advanced** field, disable **Create subnets**.
  1. Click **Create network**.

{% endlist %}

### Create subnets {#create-subnets}

{% list tabs group=instructions %}

- Management console {#console} 

  1. In the [management console](https://console.yandex.cloud), select the folder where you are deploying your cloud infrastructure.
  1. Navigate to **Virtual Private Cloud**.
  1. In the left-hand panel, select ![subnets](../../_assets/console-icons/nodes-right.svg) **Subnets**.
  1. At the top right, click **Create subnet**.
  1. In the **Name** field, specify `vpc-subnet-a`.
  1. In the **Availability zone** field, select `ru-central1-a`.
  1. In the **Network** field, select `sample-network`.
  1. In the **CIDR** field, specify `192.168.6.0/24`.
  
      {% note warning %}
      
      To successfully configure network connectivity between BareMetal subnets and on-premise or VPC subnets, their CIDR address ranges must not match or overlap.
      
      {% endnote %}

  1. Click **Create subnet**.
  1. Similarly, in `sample-network`, create a subnet named `vpc-subnet-b` with CIDR `192.168.11.0/24` in the `ru-central1-b` availability zone.

{% endlist %}

### Create security groups {#create-sg}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you are deploying your cloud infrastructure.
  1. Navigate to **Virtual Private Cloud**.
  1. In the left-hand panel, select ![image](../../_assets/console-icons/shield.svg) **Security groups** and click **Create security group**.
  1. In the **Name** field, specify `vpc-ingress-sg`.
  1. In the **Network** field, select `sample-network` you created earlier.
  1. Under **Rules**, [create](../../vpc/operations/security-group-add-rule.md) the following traffic management rules:

      | Traffic<br/>direction | Description | Port range | Protocol | Source /<br/>Destination name | CIDR blocks /<br/>Security group |
      | --- | --- | --- | --- | --- | --- |
      | Inbound | `http`            | `80`   | `TCP`  | `CIDR` | `0.0.0.0/0` |
      | Inbound | `https`            | `443`   | `TCP`  | `CIDR` | `0.0.0.0/0` |
      | Inbound | `ssh`            | `22`   | `TCP`  | `CIDR` | `0.0.0.0/0` |
      | Egress | `any`           | `All` | `Any` | `CIDR` | `0.0.0.0/0` |
  1. Click **Create**.
  1. Similarly, in `sample-network`, create a [security group](../../vpc/concepts/security-groups.md) named `alb-sg` with the following rules:

      | Traffic<br/>direction | Description | Port range | Protocol | Source /<br/>Destination name | CIDR blocks /<br/>Security group |
      | --- | --- | --- | --- | --- | --- |
      | Inbound | `http`            | `80`   | `TCP`  | `CIDR` | `0.0.0.0/0` |
      | Inbound | `healthchecks`            | `30080`   | `TCP`  | `Load balancer healthchecks` | — |
      | Outbound | `any`           | `All` | `Any` | `CIDR` | `0.0.0.0/0` |

{% endlist %}

### Create a VM {#create-vm}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you are deploying your infrastructure.
  1. Navigate to **Compute Cloud**.
  1. In the left-hand panel, select ![image](../../_assets/console-icons/server.svg) **Virtual machines** and click **Create virtual machine**.
  1. Under **Boot disk image**, select the [Ubuntu 24.04](https://yandex.cloud/en/marketplace/products/yc/ubuntu-2404-lts-oslogin) image.
  1. Under **Location**, select the `ru-central1-a` [availability zone](../../overview/concepts/geo-scope.md).
  1. Under **Network settings**:

      * In the **Subnet** field, select the `vpc-subnet-a` subnet you created earlier.
      * In the **Public IP address** field, select `Auto`.
      * In the **Security groups** field, select `vpc-ingress-sg`.

  1. Under **Access**, select **SSH key** and specify the VM access credentials:

      * In the **Login** field, enter the username: `yc-user`.
      * In the **SSH key** field, select the SSH key saved in your [organization user](../../organization/concepts/membership.md) profile.
        
        If there are no SSH keys in your profile or you want to add a new key:
        
        1. Click **Add key**.
        1. Enter a name for the SSH key.
        1. Select one of the following:
        
            * `Enter manually`: Paste the contents of the public SSH key. You need to [create](../../compute/operations/vm-connect/ssh.md#creating-ssh-keys) an SSH key pair on your own.
            * `Load from file`: Upload the public part of the SSH key. You need to create an SSH key pair on your own.
            * `Generate key`: Automatically create an SSH key pair.
            
              When adding a new SSH key, an archive containing the key pair will be created and downloaded. In Linux or macOS-based operating systems, unpack the archive to the `/home/<user_name>/.ssh` directory. In Windows, unpack the archive to the `C:\Users\<user_name>/.ssh` directory. You do not need additionally enter the public key in the management console.
        
        1. Click **Add**.
        
        The system will add the SSH key to your organization user profile. If the organization has [disabled](../../organization/operations/os-login-access.md) the ability for users to add SSH keys to their profiles, the added public SSH key will only be saved in the user profile inside the newly created resource.

  1. Under **General information**, specify the VM name: `vm-validator`.
  1. Click **Create VM**.

{% endlist %}

## Create a routing instance {#create-routing-instance}

To set up network connectivity between BareMetal subnets and Virtual Private Cloud subnets, you need to create a [routing instance](../../cloud-router/concepts/routing-instance.md) resource. To create a `Routing Instance`, [contact](https://center.yandex.cloud/support/tickets/create) support.

If your folder already has [Cloud Interconnect](../../interconnect/index.md) network connectivity (VPC-to-On-Prem) configured, you can either use the existing `Routing Instance` or request a new additional `Routing Instance` to be created for standalone network connectivity.

### Make sure you have a routing instance in your folder {#check-for-ri}

1. If you do not have the Yandex Cloud CLI yet, [install and initialize it](../../cli/quickstart.md#install).

    The folder used by default is the one specified when [creating](../../cli/operations/profile/profile-create.md) the CLI profile. To change the default folder, use the `yc config set folder-id <folder_ID>` command. You can also specify a different folder for any command using `--folder-name` or `--folder-id`. If you access a resource by its name, the search will be limited to the default folder. If you access a resource by its ID, the search will be global, i.e., through all folders based on access permissions.

1. Make sure you have a routing instance in your default folder:
   
   {% list tabs group=instructions %}
   
   - CLI {#cli}
   
     Run this command:
   
     ```bash
     yc cloudrouter routing-instance list
     ```
   
     If your folder already contains a routing instance, the command will output something like this:
   
     ```text
     +----------------------+-------------------------------------------+--------+-----------------------+
     |          ID          |                    NAME                   | STATUS | PRIVATE CONNECTION ID |
     +----------------------+-------------------------------------------+--------+-----------------------+
     | cf35oot8f0eu******** | ajeol2afu1js********-enpcfncr6uld******** | ACTIVE | cf395uf8dg7h********  |
     +----------------------+-------------------------------------------+--------+-----------------------+
     ```
   
   {% endlist %}

1. If you already have a `Routing Instance`, you may skip the next step and [proceed](#setup-baremetal) to setting up your BareMetal environment.

    If you do not have a `Routing Instance` or you want to build additional dedicated network connectivity, [request](#request-ri) a new `Routing Instance`.

### Request a new routing instance {#request-ri}

[Contact](https://center.yandex.cloud/support/tickets/create) support to create a routing instance in your folder.

Fill out your request as follows:

```text
Subject: [CIC for BareMetal] Creating a routing instance.

Request text:
Please create a routing instance in the specified cloud folder with the following parameters:

folder_id: <folder_ID>

vpc:
  vpc_net_id: <network_ID>
    vpc_subnets:
      ru-central1-a: [CIDR_a1, CIDR_a2, ..., CIDR_an]
      ru-central1-b: [CIDR_b1, CIDR_b2, ..., CIDR_bn]
      ru-central1-d: [CIDR_d1, CIDR_d2, ..., CIDR_dn]
```

Where:
* `folder_id`: [Folder ID](../../resource-manager/operations/folder/get-id.md).
* `vpc_net_id`: Cloud network [ID](../../vpc/operations/network-get-info.md).
* `vpc_subnets`: List of [announced](../../interconnect/concepts/priv-con.md#prc-announce) address prefixes for each [availability zone](../../overview/concepts/geo-scope.md). For example, for the VPC subnet you created earlier, you will specify `ru-central1-b: [192.168.11.0/24]`.

    You may announce [aggregated](../../interconnect/concepts/priv-con.md#agg-subnets) address prefixes.

{% note info %}

It may take up to 24 hours for the support to create a routing instance. With that done, you will be able to get the ID of the new routing instance by running the `yc cloudrouter routing-instance list` [Yandex Cloud CLI](../../cli/index.md) command.

{% endnote %}

## Set up your BareMetal environment {#setup-baremetal}

Configure the BareMetal infrastructure. In this step, you will create a [virtual network segment (VRF)](../../baremetal/concepts/private-network.md#vrf-segment) and [private subnet](../../baremetal/concepts/private-network.md#private-subnet), configure a [private connection](../../baremetal/concepts/private-network.md#private-connection-to-vpc) to the cloud network, and lease two BareMetal [servers](../../baremetal/concepts/servers.md).

### Create a VRF segment and a private subnet {#setup-vrf}

Create a VRF segment and a private subnet in the `ru-central1-m4` [server pool](../../baremetal/concepts/servers.md#server-pools):

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you are deploying your infrastructure.
  1. Navigate to **BareMetal**.
  1. Create a virtual routing and forwarding segment:
        1. In the left-hand panel, select ![icon](../../_assets/console-icons/vector-square.svg) **VRF** and click **Create VRF**.
        1. In the **Name** field, name your VRF segment: `my-vrf`.
        1. Click **Create VRF**.
  1. Create a private subnet:
        1. In the left-hand panel, select ![icon](../../_assets/console-icons/nodes-right.svg) **Private subnets** and click **Create subnet**.
        1. In the **Pool** field, select the `ru-central1-m4` server pool.
        1. In the **Name** field, enter the subnet name: `subnet-m4`.
        1. Enable **IP addressing and routing**.
        1. In the **Virtual network segment (VRF)** field, select `my-vrf`.
        1. In the **CIDR** field, specify `172.28.4.0/24`.
        1. In the **Default gateway** field, keep the default value, `172.28.4.1`.
        1. Enable the **Assigning IP addresses via DHCP** option and in the **IP address range** field that appears, leave the default values, `172.28.4.1`-`172.28.4.254`.
        1. Click **Create subnet**.

{% endlist %}

### Configure a private connection to your cloud network {#connect-to-vpc}

Create a Cloud Interconnect [private connection](../../baremetal/concepts/private-network.md#private-connection-to-vpc) in BareMetal:

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the [folder](../../resource-manager/concepts/resources-hierarchy.md#folder) where you want to create your private connection.
  1. Navigate to **BareMetal**.
  1. In the left-hand panel, select ![icon](../../_assets/console-icons/vector-square.svg) **VRF** and then select the virtual network segment you need.
  1. Under **Private connection to cloud networks**, click **Configure connection**, and in the window that opens:

      1. In the **Setup method** field, select `Enter ID` and paste the `Routing Instance` private connection ID to the **Connection ID** field.

          You can also select the `Choose from folder` option. In this case, select the `Routing Instance` you need from the list that opens.

          As a result, you will see the CIDR blocks of Virtual Private Cloud subnets that will be [advertised](../../interconnect/concepts/priv-con.md#prc-announce) over Cloud Interconnect.

          {% note warning %}
          
          To successfully configure network connectivity between BareMetal subnets and on-premise or VPC subnets, their CIDR address ranges must not match or overlap.
          
          {% endnote %}
      1. To create a private connection for the specified CIDR subnets, click **Save**.

  As a result, the VRF information page will display the newly created connection ID and its status under **Private connection to cloud networks**.

- API {#api}

  To create a private connection with cloud networks, use the [PrivateCloudConnection.Create](../../baremetal/api-ref/PrivateCloudConnection/create.md) REST API method or the [PrivateCloudConnectionService/Create](../../baremetal/api-ref/grpc/PrivateCloudConnection/create.md) gRPC API call.

  Run this query:

  ```bash
  curl -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer <IAM_token>" \
    -d '{
      "routingInstanceId":"fokrf2in3c7********",
      "vrfId":"ly5uyq2gbxu2********"
      }' \
    "https://baremetal.api.cloud.yandex.net/baremetal/v1alpha/privateCloudConnections"
  ```

  Where:

  * `routingInstanceId`: [Routing instance](../../cloud-router/concepts/routing-instance.md) ID in Cloud Router.
  * `vrfId`: ID of the VRF you are connecting to the Routing Instance. To get the VRF ID, use the [VrfService.List](../../baremetal/api-ref/Vrf/list.md) method.

  Result:

  ```json
  {
    "done": false,
    "id": "arpas4mne3********",
    "description": "Create private cloud connection",
    "createdAt": "2024-01-01T12:00:00Z",
    "createdBy": "user-id",
    "modifiedAt": "2024-01-01T12:00:00Z",
    "metadata": {
      "privateCloudConnectionId": "kor4msi1aqq********"
    }
  }
  ```

  The operation of creating a private connection is performed asynchronously. Follow the status of the operation by the `done` field.

{% endlist %}

{% note info %}

Setting up a private connection may take up to two business days. During this period, the connection status will display as `Creating`. Once the connection is created, its status will change to `Ready`.

{% endnote %}

Private cloud netweork connections may show one of the following statuses:

* `CREATING`: Connection creation in progress.
* `READY`: Connection is up and ready to use.
* `ERROR`: Connection failure. Contact support.
* `DELETING`: Connection deletion in progress.
* `UPDATING`: Connection settings update in progress.

### Rent BareMetal servers {#rent-servers}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you are deploying your infrastructure.
  1. Navigate to **BareMetal**.
  1. Click **Lease server** and, in the window that opens, select `Stock configurations` and a suitable BareMetal server [configuration](../../baremetal/concepts/server-configurations.md) in the `ru-central1-m4` server pool.

      Do it by selecting the `ru-central1-m4` server pool in the filter on the right side of the window, under **Pool**.

      To select the suitable server configuration, click the section with its name in the central part of the screen.

      {% note tip %}
      
      You can reduce the cost of renting a server in some configurations by ordering server [assembly](../../baremetal/concepts/server-custom-configurations.md#assembly).
      
      To use the discount, hover over **Cheaper with assembly** ![circle-info.svg](../../_assets/console-icons/circle-info.svg) under the configuration at hand and click ![person-nut-hex.svg](../../_assets/console-icons/person-nut-hex.svg) **Go to assembly** in the pop-up window.
      
      When ordering a server with assembly, follow the steps below to configure the server properties. In this case, the server will not be available immediately, but only after the assembly is completed (within four calendar days), and at a lower price.
      
      {% endnote %}

  1. In the server configuration window that opens:

      1. In the **Lease duration** field, select your lease period: `1 day`.

          When this period expires, server lease will automatically be renewed for the same period. You cannot terminate the lease during the specified lease period, but you can [refuse](../../baremetal/operations/servers/server-lease-cancel.md) to extend the server lease further.

      1. Under **Image**, select the `Debian 11` image.
      1. Under **Network interfaces**:
          1. In the **Private subnet** field, select the `subnet-m3` subnet you created earlier.
          1. In the **Public address** field, select `From ephemeral subnet`.

      1. Under **Access**:

          1. In the **Password** field, select one of the following options to create a root password:
          
              * To generate a new root password, select `New password` and click **Generate**.
          
                  {% note warning %}
                  
                  This option requires you to maintain password security. Save the password you generated in a secure location. Yandex Cloud does not store it, and you will not be able to retrieve it once the server is deployed.
                  
                  {% endnote %}
          
              * To use the root password saved in a Yandex Lockbox [secret](../../lockbox/concepts/secret.md), select `Lockbox secret`.
          
                  In the **Name**, **Version**, and **Key** fields, select the secret containing your password, its version, and its key, respectively.
                  
                  If you do not have a Yandex Lockbox secret, click **Create** to create it.
          
                  Choose the `Custom` secret type to specify a custom password or `Generated` to generate password automatically.
          
          1. In the **Public SSH key** field, select the SSH key saved in your [organization user](../../organization/concepts/membership.md) profile.
          
              If there are no SSH keys in your profile or you want to add a new key:
              
              1. Click **Add key**.
              1. Enter a name for the SSH key.
              1. Select one of the following:
              
                  * `Enter manually`: Paste the contents of the public SSH key. You need to [create](../../compute/operations/vm-connect/ssh.md#creating-ssh-keys) an SSH key pair on your own.
                  * `Load from file`: Upload the public part of the SSH key. You need to create an SSH key pair on your own.
                  * `Generate key`: Automatically create an SSH key pair.
                  
                    When adding a new SSH key, an archive containing the key pair will be created and downloaded. In Linux or macOS-based operating systems, unpack the archive to the `/home/<user_name>/.ssh` directory. In Windows, unpack the archive to the `C:\Users\<user_name>/.ssh` directory. You do not need additionally enter the public key in the management console.
              
              1. Click **Add**.
              
              The system will add the SSH key to your organization user profile. If the organization has [disabled](../../organization/operations/os-login-access.md) the ability for users to add SSH keys to their profiles, the added public SSH key will only be saved in the user profile inside the newly created resource.

      1. Under **Server information**, in the **Name** field, enter the server name: `alb-back-0`.
      1. Click **Lease server**.
  1. Similarly, lease one more server, `alb-back-1`, in the `ru-central1-m4` server pool.

{% endlist %}

{% note info %}

Server setup and OS installation may take up to 45 minutes. The server will have the `Provisioning` status during this time. After OS installation is complete, the server status will change to `Ready`.

{% endnote %}

### Deploy your web application {#deploy-web-service}

In this step, you will deploy your web application on BareMetal servers. The web application will use the following server resources:
* `/opt/mygoapp`: Web server's working directory.
* `/opt/mygoapp/server`: Web server's executable.
* `/etc/systemd/system/mygoapp.service`: Configuration file to manage the web server via [systemd](https://en.wikipedia.org/wiki/Systemd).

To deploy your web application on the server:

1. [Connect](../../compute/operations/vm-connect/ssh.md) to the `alb-back-0` BareMetal server over SSH:

    ```bash
    ssh root@<server_public_IP_address>
    ```

    You can look up the server's public IP address in the [management console](https://console.yandex.cloud): see the BareMetal server info on the **Overview** page. You can find the address in the **Public address** field under **Network interfaces**.

    You will perform all further actions under this step in the server terminal.
1. Prepare your working directory:

    ```bash
    mkdir -p /opt/mygoapp && cd /opt/mygoapp
    ```
1. Download the web server's executable:

    ```bash
    wget https://storage.yandexcloud.net/yc-public-share/server
    ```
1. Set the execute permission for the file you downloaded:

    ```bash
    chmod +x server
    ```
1. Create a new service in `systemd`:

    1. Open the service configuration file:

        ```bash
        nano /etc/systemd/system/mygoapp.service
        ```
    1. Paste the following into the file you opened:

        ```
        [Unit]
        Description=Simple Web Server on Go
        After=network.target
        [Service]
        Type=simple
        WorkingDirectory=/opt/mygoapp
        ExecStart=/opt/mygoapp/server
        Restart=always
        RestartSec=5
        [Install]
        WantedBy=multi-user.target
        ```
    1. Save the changes and close the file.
1. Initialize the service you created:

    ```bash
    systemctl daemon-reload
    ```
1. Run the service:

    ```bash
    systemctl start mygoapp.service
    ```
1. Test your web application. To do this, on your local computer, paste the `alb-back-0` server's public IP address into the browser's address bar. 

    Your browser will open a page with the host name and information about the web server’s running time since startup.

    {% cut "Web application source code" %}

    ```go
    package main

    import (
      "context"
      "fmt"
      "net/http"
      "os"
      "os/signal"
      "syscall"
      "time"
      "github.com/gorilla/handlers"
    )

    var (
      hostname    string
      htmlContent []byte
    )

    const (
      serverTimeout  = 5 * time.Second
      cacheDuration  = 86400 * 30 // 30 days in seconds
      htmlTemplate = `
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <!-- Minified CSS -->
        <style>*{margin:0;padding:0;box-sizing:border-box;font-family:'Segoe UI',system-ui,sans-serif}body{min-height:100vh;display:flex;justify-content:center;align-items:center;background:linear-gradient(135deg,#1a1a1a,#2d2d2d);color:#fff;padding:20px}.container{background:rgba(255,255,255,0.1);backdrop-filter:blur(10px);border-radius:20px;padding:40px;box-shadow:0 8px 32px rgba(0,0,0,0.3);text-align:center;max-width:600px;width:100%%;transition:transform .3s ease}.server-name{font-size:1.8rem;margin-bottom:30px;color:#0f0;font-weight:600;text-shadow:0 0 10px rgba(0,255,136,0.3)}.datetime{font-size:2.5rem;letter-spacing:2px;margin-bottom:20px}.date{font-size:1.5rem;opacity:.8}@media (max-width:768px){.container{padding:25px;border-radius:15px}.server-name{font-size:1.4rem}.datetime{font-size:2rem}.date{font-size:1.2rem}}@media (max-width:480px){.datetime{font-size:1.6rem}}</style>
        <meta name="viewport" content="width=device-width,initial-scale=1">
        <title>Server Info & Time</title>
    </head>
    <body>
        <div class="container">
            <div class="server-name">Server Hostname: %s</div>
            <div class="datetime" id="datetime"></div>
            <div class="date" id="date"></div>
        </div>
        <script>
            // Minified JavaScript
            const e=()=>{const e=new Date;document.getElementById("datetime").textContent=e.toLocaleTimeString("en-US",{timeZone:"Europe/Moscow",hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit"}),document.getElementById("date").textContent=e.toLocaleDateString("en-US",{timeZone:"Europe/Moscow",weekday:"long",year:"numeric",month:"long",day:"numeric"})};e(),setInterval(e,1e3);
        </script>
    </body>
    </html>`
    )

    func init() {
      // Initializing the host at startup
      var err error
      if hostname, err = os.Hostname(); err != nil {
        hostname = "Unavailable"
      }
      
      // Pre-generating HTML
      htmlContent = []byte(fmt.Sprintf(htmlTemplate, hostname))
    }

    func main() {
      // Configuring handlers
      mux := http.NewServeMux()
      mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "text/html; charset=utf-8")
        w.Header().Set("Cache-Control", fmt.Sprintf("public, max-age=%d", cacheDuration))
        w.Write(htmlContent)
      })

      // Middleware
      chain := handlers.CompressHandler(
        handlers.CombinedLoggingHandler(os.Stdout, mux),
      )

      // Server configuration
      server := &http.Server{
        Addr:         ":80",
        Handler:      chain,
        ReadTimeout:  serverTimeout,
        WriteTimeout: serverTimeout,
        IdleTimeout:  serverTimeout * 2,
      }

      // Graceful shutdown
      ctx, stop := signal.NotifyContext(context.Background(), 
        os.Interrupt, syscall.SIGTERM)
      defer stop()

      go func() {
        <-ctx.Done()
        shutdownCtx, cancel := context.WithTimeout(
          context.Background(), 5*time.Second)
        defer cancel()
        server.Shutdown(shutdownCtx)
      }()

      fmt.Println("Server started")
      if err := server.ListenAndServe(); err != http.ErrServerClosed {
        fmt.Printf("Server error: %v\n", err)
      }
    }
    ```

    {% endcut %}

1. Similarly, deploy your web application on the `alb-back-1` server.

### Test network connectivity {#check-connectivity}

Make sure the [previously created](#connect-to-vpc) private connection to the cloud network is `Ready` and test network connectivity between the `vm-validator` VM in the Virtual Private Cloud network and servers in the BareMetal private subnet:

1. [Connect](../../compute/operations/vm-connect/ssh.md) to the `vm-validator` VM over SSH:

    ```bash
    ssh yc-user@<VM_public_IP_address>
    ```

    You can look up the VM's public IP address in the [management console](https://console.yandex.cloud): see the **Public IPv4 address** section's **Network** field on the VM information page.

    You will perform all further actions under this step in the VM terminal.
1. Ping the `alb-back-0` server by its private IP address:

    ```bash
    ping <server_private_IP_address> -s 1024 -c 3
    ```

    You can look up the server's private IP address in the [management console](https://console.yandex.cloud): see the BareMetal server info on the **Overview** page. You can find the address in the **Private IP address** field under **Network interfaces**.

    Result:

    ```text
    PING 172.28.4.11 (172.28.4.11) 1024(1052) bytes of data.
    1032 bytes from 172.28.4.11: icmp_seq=1 ttl=58 time=3.77 ms
    1032 bytes from 172.28.4.11: icmp_seq=2 ttl=58 time=3.83 ms
    1032 bytes from 172.28.4.11: icmp_seq=3 ttl=58 time=3.80 ms

    --- 172.28.4.11 ping statistics ---
    3 packets transmitted, 3 received, 0% packet loss, time 2004ms
    rtt min/avg/max/mdev = 3.767/3.800/3.830/0.025 ms
    ```
1. Similarly, `ping` the `alb-back-1` server by its private IP address.

Save the private IP addresses of the BareMetal servers as you will need them to configure an L7 load balancer.

## Configure an L7 load balancer {#setup-balancer}

After you create the Virtual Private Cloud and BareMetal infrastructure components and test network connectivity between them, configure an L7 load balancer to manage user traffic to your web application.

### Create a target group for the L7 load balancer {#create-tg}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you are deploying your infrastructure.
  1. Navigate to **Application Load Balancer**.
  1. In the left-hand panel, select ![image](../../_assets/console-icons/target.svg) **Target groups** and click **Create target group**.
  1. In the **Name** field, enter a name for the [target group](../concepts/target-group.md): `bms-target-group`.
  1. Under **Targets**:
  
      1. In the **IP address** field, enter the `alb-back-0` server's private IP address you saved earlier.
      1. In the IP address row, enable the **Outside VPC** option and click **Add target resource**.
      1. Repeat the previous two steps to add the `alb-back-1` server's private IP address to your target group.
  1. Click **Create**.

{% endlist %}

### Create a backend group {#create-backend-group}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you are deploying your infrastructure.
  1. Navigate to **Application Load Balancer**.
  1. In the left-hand panel, select ![image](../../_assets/console-icons/cubes-3-overlap.svg) **Backend groups** and click **Create backend group**.
  1. In the **Name** field, enter a name for the [backend group](../concepts/backend-group.md): `bms-backend-group`.
  1. In the **Type** field, select `HTTP`.
  1. Under **Backends**, click **Add** and do the following in the **New backend** form that opens:

      1. In the **Name** field, specify the [backend](../concepts/backend-group.md#types) name: `bms-backend`.
      1. In the **Target groups** field, select the `bms-target-group` target group you created earlier.
      1. In the **HTTP health check** section, do the following:

          1. Set the **Timeout, s** to `3`.
          1. Set the **Interval** to `10`.
          1. Under **Path**, specify the root path, `/`.
          1. In the **HTTP codes** field, select the `200` response code.

      Leave the other parameters unchanged.
  1. Click **Create**.

{% endlist %}

### Create an HTTP router {#create-http-router}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you are deploying your infrastructure.
  1. Navigate to **Application Load Balancer**.
  1. In the left-hand panel, select ![image](../../_assets/console-icons/route.svg) **HTTP routers** and click **Create HTTP router**.
  1. In the **Name** field, enter a name for the [HTTP router](../concepts/http-router.md): `http-80`.
  1. Under **Virtual hosts**, click **Add virtual host** and do the following in the **New virtual host** form that opens:

      1. In the **Name** field, enter `http-vh` for the [virtual host](../concepts/http-router.md#virtual-host)‘s name and click **Add route**.
      1. In the **New route** form that opens, enter `main-route-80` as the [route](../concepts/http-router.md#routes)'s name in the **Name** field.
      1. In the **HTTP methods** field, select `GET`.
      1. In the **Backend group** field, select the `bms-backend-group` backend group created in the previous step.
      1. Leave all other parameters unchanged and click **Create** at the bottom of the page.

{% endlist %}

### Create an L7 load balancer {#create-alb}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you are deploying your infrastructure.
  1. Navigate to **Application Load Balancer**.
  1. Click **Create L7 load balancer** and select **Manual**.
  1. In the **Name** field, enter a name for the load balancer: `demo-alb-bms`.
  1. In the **Network** field, select `sample-network`.
  1. In the **Security groups** field, select `From list` and then the `alb-sg` security group from the list that opens.
  1. Under **Allocation**, leave only the `ru-central1-a` and `ru-central1-b` availability zones with the `vpc-subnet-a` and `vpc-subnet-b` subnets, respectively.
  1. If you do not want load balancer logs saved to a [log group](../../logging/concepts/log-group.md), disable **Write logs**.
  1. In the **Listeners** section, click **Add listener** and do the following in the form that opens:

      1. In the **Name** field, enter a name for the [listener](../concepts/application-load-balancer.md#listener): `alb-bms-listener`.
      1. In the **HTTP router** field, select the `http-80` HTTP router you created earlier.
  1. Leave all other parameters unchanged and click **Create** at the bottom of the page.
  1. Wait for the load balancer status to change to `Active` and copy its public IP address from the **IP addresses** field.
  1. On your local computer, paste the load balancer's IP address into your browser's address bar. If everything is configured correctly, the browser will open your web application deployed on the BareMetal servers.

{% endlist %}

## Set up protection against bots, DDoS, and web attacks {#setup-sws}

Once you make sure your L7 load balancer works correctly, set up a Smart Web Security profile to protect your web application against bots, DDoS, and web attacks.

### Create an ARL profile {#create-arl-profile}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you are deploying your infrastructure.
  1. Navigate to **Smart Web Security**.
  1. In the left-hand panel, select ![arl](../../_assets/smartwebsecurity/arl.svg) **ARL profiles** and click **Create ARL profile**.
  1. In the **Name** field, specify the [ARL profile](../../smartwebsecurity/concepts/arl.md) name: `arl-profile-demo`.
  1. Click ![plus](../../_assets/console-icons/plus.svg) **Add rule** and in the window that opens:

      1. In the **Name** field, specify the rule name: `permit-50-rps-in`.
      1. Set the **Priority** to `10`.
      1. Set the **Request limit** to `50` requests in `1 second`.
      1. Leave all the other parameters unchanged and click **Save rule**.
  1. Click **Create**.

{% endlist %}

### Create a WAF profile {#create-waf-profile}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you are deploying your infrastructure.
  1. Navigate to **Smart Web Security**.
  1. In the left-hand panel, select ![waf](../../_assets/smartwebsecurity/waf.svg) **WAF profiles** and click **Create WAF profile**.
  1. In the **Name** field, specify the [WAF profile](../../smartwebsecurity/concepts/waf.md) name: `waf-profile-demo`.
  1. By default, the WAF profile uses the [OWASP Core Rule Set](https://coreruleset.org/). Click the row with the rule set to view the rules it includes.
  1. Click **Create**.

{% endlist %}

### Create a security profile {#create-security-profile}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you are deploying your infrastructure.
  1. Navigate to **Smart Web Security**.
  1. In the left-hand panel, select ![shield-check](../../_assets/console-icons/shield-check.svg) **Security profiles**.
  1. Click **Create profile** and select `From scratch`.
  1. In the **Name** field, specify the [security profile](../../smartwebsecurity/concepts/profiles.md) name: `sws-demo-profile`.
  1. In the **ARL profile** field, select the previously created profile, `arl-profile-demo`.
  1. Create a new `Web Application Firewall` [rule](../../smartwebsecurity/concepts/rules.md):
  
      1. Click ![plus](../../_assets/console-icons/plus.svg) **Add rule**.
      1. In the **Name** field, specify the rule name: `waf-rule`.
      1. Set the **Priority** to `200`.
      1. Under **Rule type**, select `Web Application Firewall`. In the list that opens, select the `waf-profile-demo` rule you created earlier.

          This will apply rules from the WAF profile to the new rule. The system will redirect suspicious requests to [Yandex SmartCaptcha](../../smartcaptcha/index.md).
      1. Click **Add**.

      The rule will appear in the list of rules under **Security rules**.
  1. Create a new `Smart Protection` rule:

      1. Click ![plus](../../_assets/console-icons/plus.svg) **Add rule** once again.
      1. In the **Name** field, specify the rule name: `smart-rule`.
      1. Set the **Priority** to `300`.
      1. Under **Rule type**, select `Smart Protection`.

          The new rule will send traffic for automatic processing by machine learning and behavioral analysis algorithms. The system will redirect suspicious requests to Yandex SmartCaptcha for additional verification.
      1. Click **Add**.
  
      The rule will appear in the list of rules under **Security rules**.
  1. Click **Create profile**.

{% endlist %}

### Apply protection to your hosts {#apply-protection-to-hosts}

{% list tabs group=instructions %}

- Management console {#console}

  1. In the [management console](https://console.yandex.cloud), select the folder where you are deploying your infrastructure.
  1. Navigate to **Smart Web Security**.
  1. In the left-hand panel, click ![shield-check](../../_assets/console-icons/shield-check.svg) **Security profiles** and select the `sws-demo-profile` you created earlier.
  1. In the top panel, click ![plug](../../_assets/console-icons/plug-connection.svg) **Connect to host**.
  1. In the window that opens, click **Add resource** and select **Virtual host**.
  1. Set field values in the following order:

      1. Select `demo-alb-bms`.
      1. Select `http-80` as the HTTP router.
      1. Select the `http-vh` virtual host.
      1. Click **Connect**.

      Information about the connected virtual host will appear in the ![cubes-3-overlap](../../_assets/console-icons/cubes-3-overlap.svg) **Connected resources** section of the Smart Web Security profile overview page.

{% endlist %}

You have deployed a web application on two BareMetal servers, configured distribution of user traffic with an L7 load balancer in Application Load Balancer, and implemented protection of your application by means of a Smart Web Security profile.

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

To stop paying for the resources you created:

1. [Delete](../../compute/operations/vm-control/vm-delete.md) the VM.
1. [Delete](../operations/application-load-balancer-delete.md) the L7 load balancer; then delete the [HTTP router](../operations/http-router-delete.md), [backend group](../operations/backend-group-delete.md), and the load balancer's [target group](../operations/target-group-delete.md) one by one.
1. [Delete](../../smartwebsecurity/operations/profile-delete.md) the Smart Web Security profile; then delete the [WAF profile](../../smartwebsecurity/operations/waf-profile-delete.md) and [ARL profile](../../smartwebsecurity/operations/arl-profile-delete.md).
1. You cannot delete BareMetal servers. Instead, [cancel](../../baremetal/operations/servers/server-lease-cancel.md) the renewal of their lease.
1. If the L7 load balancer logging feature was left on, [delete](../../logging/operations/delete-group.md) the log group.
1. Optionally, delete the [security groups](../../vpc/operations/security-group-delete.md), [subnets](../../vpc/operations/subnet-delete.md), and [cloud network](../../vpc/operations/network-delete.md) one by one.
1. Delete the private connection if you no longer need it:

    {% list tabs group=instructions %}

    - Management console {#console} 
    
      1. In the [management console](https://console.yandex.cloud), select the folder where you created the infrastructure.
      1. Navigate to **BareMetal**.
      1. In the left-hand panel, click ![icon](../../_assets/console-icons/vector-square.svg) **VRF** and select `my-vrf`.
      1. Under **Private connection to cloud networks**, click ![image](../../_assets/console-icons/ellipsis.svg) and select ![CircleXmark](../../_assets/console-icons/circle-xmark.svg) **Disable connection**.
      1. In the window that opens, confirm the deletion.

      The connection status will change to `Deleting`. Once all links are deleted, the connection will disappear from the list.

    {% endlist %}