[Yandex Cloud documentation](../../../index.md) > [Tutorials](../../index.md) > Application solutions > Creating a website > [Website based on LAMP or LEMP stack](index.md) > Terraform

# Website based on LAMP or LEMP stack using Terraform

To create an infrastructure for a [website on the LAMP or LEMP stack](index.md) using Terraform:

1. [Get your cloud ready](#before-you-begin).
1. [Create your infrastructure](#deploy).
1. [Upload the website files](#upload-files).
1. [Test the website](#test-site).

We will use the `example.com` domain name as an example.

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

## Get your cloud ready {#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 costs for a website include:
* Fee for a continuously running [VM](../../../compute/concepts/vm.md) (see [Yandex Compute Cloud pricing](../../../compute/pricing.md)).
* Fee for using a [public IP address](../../../vpc/concepts/address.md#public-addresses) (see [Yandex Virtual Private Cloud pricing](../../../vpc/pricing.md)).
* Fee for public DNS queries and [DNS zones](../../../dns/concepts/dns-zone.md) if using [Yandex Cloud DNS](../../../dns/index.md) (see [Cloud DNS pricing](../../../dns/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 relevant documentation on the [Terraform](https://www.terraform.io/docs/providers/yandex/index.html) website or [its mirror](../../../terraform/index.md).

To create an infrastructure using Terraform:
1. [Install Terraform](../../infrastructure-management/terraform-quickstart.md#install-terraform) and [get the authentication data](../../infrastructure-management/terraform-quickstart.md#get-credentials).
1. Specify the source for installing the Yandex Cloud provider (see [Configure your provider](../../infrastructure-management/terraform-quickstart.md#configure-provider), step 1).
1. Set up your infrastructure description files:

    {% list tabs group=infrastructure_description %}

    - Ready-made archive {#ready}

      1. Create a directory.
      1. Download the [archive](https://storage.yandexcloud.net/doc-files/lamp-lemp.zip) (1 KB).
      1. Unpack the archive to the directory. As a result, it should contain the `lamp-lemp.tf` configuration file and the `lamp-lemp.auto.tfvars` user data file.

    - Manually {#manual}

      1. Create a folder for the infrastructure description file.
      1. In the directory, create a configuration file named `lamp-lemp.tf`:

          {% cut "lamp-lemp.tf" %}

          ```hcl
          # Declaring variables for custom parameters
          
          variable "zone" {
            type = string
          }
          
          variable "folder_id" {
            type = string
          }
          
          variable "vm_image_family" {
            type = string
          }
          
          variable "vm_user" {
            type = string
          }
          
          variable "ssh_key_path" {
            type = string
          }
          
          variable "dns_zone" {
            type = string
          }
          
          # Adding other variables
          
          locals {
            network_name       = "web-network"
            subnet_name        = "subnet1"
            sg_vm_name         = "sg-web"
            vm_name            = "lamp-vm"
            dns_zone_name      = "example-zone"
          }
          
          # Configuring a provider
          
          terraform {
            required_providers {
              yandex    = {
                source  = "yandex-cloud/yandex"
                version = ">= 0.47.0"
              }
            }
          }
          
          provider "yandex" {
            folder_id = var.folder_id
          }
          
          # Creating a cloud network
          
          resource "yandex_vpc_network" "network-1" {
            name = local.network_name
          }
          
          # Creating a subnet
          
          resource "yandex_vpc_subnet" "subnet-1" {
            name           = local.subnet_name
            v4_cidr_blocks = ["192.168.1.0/24"]
            zone           = var.zone
            network_id     = yandex_vpc_network.network-1.id
          }
          
          # Creating a security group
          
          resource "yandex_vpc_security_group" "sg-1" {
            name        = local.sg_vm_name
            network_id  = yandex_vpc_network.network-1.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
            }
          }
          
          # Adding a prebuilt VM image
          
          resource "yandex_compute_image" "lamp-vm-image" {
            source_family = var.vm_image_family
          }
          
          resource "yandex_compute_disk" "boot-disk" {
            name     = "bootvmdisk"
            type     = "network-hdd"
            zone     = "ru-central1-a"
            size     = "20"
            image_id = yandex_compute_image.lamp-vm-image.id
          }
          
          # Creating a VM instance
          
          resource "yandex_compute_instance" "vm-lamp" {
            name        = local.vm_name
            platform_id = "standard-v3"
            zone        = var.zone
            resources {
              core_fraction = 20
              cores         = 2
              memory        = 1
            }
            boot_disk {
              disk_id = yandex_compute_disk.boot-disk.id
            }
            network_interface {
              subnet_id          = yandex_vpc_subnet.subnet-1.id
              nat                = true
              security_group_ids = [yandex_vpc_security_group.sg-1.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}")}"
            }
          }
          
          # Creating a DNS zone
          
          resource "yandex_dns_zone" "zone1" {
            name    = local.dns_zone_name
            zone    = var.dns_zone
            public  = true
          }
          
          # Creating a type A resource record
          
          resource "yandex_dns_recordset" "rs-a" {
            zone_id = yandex_dns_zone.zone1.id
            name    = var.dns_zone
            type    = "A"
            ttl     = 600
            data    = [ yandex_compute_instance.vm-lamp.network_interface.0.nat_ip_address ]
          }
          
          # Creating a CNAME resource record
          
          resource "yandex_dns_recordset" "rs-cname" {
            zone_id = yandex_dns_zone.zone1.id
            name    = "www"
            type    = "CNAME"
            ttl     = 600
            data    = [ var.dns_zone ]
          }
          ```

          {% endcut %}

      1. In the directory, create a user data file named `lamp-lemp.auto.tfvars`:

          {% cut "lamp-lemp.auto.tfvars" %}

          ```hcl
          zone               = "<availability_zone>"
          folder_id          = "<folder_ID>"
          vm_image_family    = "<VM_image_family>"
          vm_user            = "<VM_username>"
          ssh_key_path       = "<path_to_public_SSH_key>"
          dns_zone           = "<DNS_zone>"
          ```

          {% endcut %}

    {% endlist %}

    Learn more about the properties of Terraform resources in the relevant provider guides:
    * [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).
    * [VM](../../../compute/concepts/vm.md): [yandex_compute_instance](../../../terraform/resources/compute_instance.md).
    * [DNS zone](../../../dns/concepts/dns-zone.md): [yandex_dns_zone](../../../terraform/resources/dns_zone.md).
    * [DNS resource record](../../../dns/concepts/resource-record.md): [yandex_dns_recordset](../../../terraform/resources/dns_recordset.md).

  1. In the `lamp-lemp.auto.tfvars` file, set the following user parameters:
      * `zone`: [Availability zone](../../../overview/concepts/geo-scope.md) the VM will reside in.
      * `folder_id`: [Folder ID](../../../resource-manager/operations/folder/get-id.md).
      * `family_id`: Specify the family of a VM [image](../../../compute/concepts/image.md) with the required components:
        * `lamp`: [LAMP](https://yandex.cloud/en/marketplace/products/yc/lamp) (Linux, Apache, MySQL®, and PHP).
        * `lemp`: [LEMP](https://yandex.cloud/en/marketplace/products/yc/lemp) (Linux, Nginx, MySQL®, and PHP).
      * `vm_user`: VM user name.
      * `ssh_key_path`: Path to the file with a 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).
      * `dns_zone`: [DNS zone](../../../dns/concepts/dns-zone.md). Specify your registered domain with a period at the end, e.g., `example.com.`.
          To use domain names in the public DNS zone, you need to delegate it to authoritative name servers. Specify `ns1.yandexcloud.net` and `ns2.yandexcloud.net` server addresses in your registrar's account settings.

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.

1. [Get the VM public IP address](../../../compute/operations/vm-info/get-info.md): you will need it later to [upload the website files](#upload-files).

After creating the infrastructure, [upload the website files](#upload-files).

## Upload the website files {#upload-files}

To test the web server, upload the `index.html` file to the VM. You can use a [test file](https://storage.yandexcloud.net/doc-files/index.html.zip). Download and unpack the archive.
1. Find the VM public IP address under **Network** on the VM page in the [management console](https://console.yandex.cloud).
1. [Connect](../../../compute/operations/vm-connect/ssh.md) to the VM via SSH.
1. Grant your user write permissions for the `/var/www/html` directory:

    ```bash
    sudo chown -R "$USER":www-data /var/www/html
    ```

1. Upload the website files to the VM via [SCP](https://en.wikipedia.org/wiki/Secure_copy_protocol).

    {% list tabs group=operating_system %}

    - Linux/macOS {#linux-macos}

      Use the `scp` command line utility:

      ```bash
      scp -r <path_to_directory_with_files> <VM_user_name>@<VM_IP_address>:/var/www/html
      ```

    - Windows {#windows}

      Use [WinSCP](https://winscp.net/eng/download.php) to copy the local file directory to `/var/www/html` on the VM.

    {% endlist %}

After uploading the files, [test the website](#test-files).

## Test the website {#test-site}

To test the site, enter its IP or domain name in your browser:
* `http://<public_IP_of_VM>`
* `http://www.example.com`

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

To stop paying for the resources you created:

1. Open the `lamp-lemp.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.

#### See also {#see-also}

* [Website on a LAMP or LEMP stack using the management console](console.md).