[Yandex Cloud documentation](../../../index.md) > [Yandex Compute Cloud](../../index.md) > [Tutorials](../index.md) > [Single-node file server](index.md) > Terraform

# Creating a single-node file server using Terraform

To create an infrastructure for a [single-node file server](index.md) using Terraform:

1. [Get your cloud ready](#before-begin).
1. [Create an infrastructure](#deploy).
1. [Configure Samba and NFS](#setup-samba-nfs).
1. [Test your file server](#test-file-server).

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 cost for hosting a single node file server includes:
* Fee for a continuously running [VM](../../concepts/vm.md) (see [Yandex Compute Cloud pricing](../../pricing.md)).
* Fee for a dynamic or static [public IP address](../../../vpc/concepts/address.md#public-adresses) (see [Yandex Virtual Private Cloud pricing](../../../vpc/pricing.md)).
* Fee for outgoing traffic (see [Yandex Virtual Private Cloud pricing](../../../vpc/pricing.md#prices-traffic)).

## Create an 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 your infrastructure via Terraform:
1. [Install Terraform](../../../tutorials/infrastructure-management/terraform-quickstart.md#install-terraform), [get authentication credentials](../../../tutorials/infrastructure-management/terraform-quickstart.md#get-credentials), and specify the source for installing the Yandex Cloud provider. For details, see [Configure your provider](../../../tutorials/infrastructure-management/terraform-quickstart.md#configure-provider), step 1.
1. Prepare the infrastructure description files:

   {% list tabs group=infrastructure_description %}

   - Ready-made archive {#ready}

     1. Create a directory for the files.
     1. Download the [archive](https://storage.yandexcloud.net/doc-files/single-node-file-server.zip) (1 KB).
     1. Unpack the archive to the directory. This will add the `single-node-file-server.tf` configuration file to this directory.

   - Manually {#manual}

     1. Create a directory for the files.
     1. In the directory, create a configuration file named `single-node-file-server.tf`:

        {% cut "single-node-file-server.tf" %}

        ```hcl
        terraform {
          required_providers {
            yandex = {
              source  = "yandex-cloud/yandex"
              version = ">= 0.47.0"
            }
          }
        }
        
        provider "yandex" {
          zone = "ru-central1-a"
        }
        
        resource "yandex_vpc_network" "network-1" {
          name = "network1"
        }
        
        resource "yandex_vpc_subnet" "subnet-1" {
          name           = "subnet1"
          zone           = "ru-central1-a"
          network_id     = yandex_vpc_network.network-1.id
          v4_cidr_blocks = ["192.168.1.0/24"]
        }
        
        resource "yandex_vpc_security_group" "fileserver-tutorial-sg" {
          name       = "fileserver-tutorial-sg"
          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-ssh"
            v4_cidr_blocks = ["0.0.0.0/0"]
            port           = 22
          }
        
          ingress {
            protocol       = "TCP"
            description    = "ext-https"
            v4_cidr_blocks = ["0.0.0.0/0"]
            port           = 443
          }
        
          ingress {
            protocol       = "TCP"
            description    = "ext-msql"
            v4_cidr_blocks = ["0.0.0.0/0"]
            port           = 3306
          }
        
          ingress {
            protocol       = "TCP"
            description    = "nfs"
            v4_cidr_blocks = ["0.0.0.0/0"]
            port           = 2049
          }
        }
        
        resource "yandex_compute_image" "ubuntu-1804-lts" {
          source_family = "ubuntu-1804-lts"
        }
        
        resource "yandex_compute_disk" "boot-disk-ubuntu" {
          name     = "fileserver-tutorial-disk"
          type     = "network-ssd"
          zone     = "ru-central1-a"
          size     = "100"
          image_id = yandex_compute_image.ubuntu-1804-lts.id
        }
        
        resource "yandex_compute_instance" "fileserver-tutorial" {
          name        = "fileserver-tutorial"
          platform_id = "standard-v3"
          zone        = "ru-central1-a"
        
          resources {
            core_fraction = 100
            cores         = 8
            memory        = 56
          }
        
          boot_disk {
            disk_id = yandex_compute_disk.boot-disk-ubuntu.id
          }
        
          network_interface {
            subnet_id          = yandex_vpc_subnet.subnet-1.id
            security_group_ids = [yandex_vpc_security_group.fileserver-tutorial-sg.id]
            nat                = true
          }
        
          metadata = {
            user-data = "#cloud-config\nusers:\n  - name: <username>\n    groups: sudo\n    shell: /bin/bash\n    sudo: 'ALL=(ALL) NOPASSWD:ALL'\n    ssh_authorized_keys:\n      - ${file("<path_to_public_SSH_key>")}"
          }
        }
        ```

        {% endcut %}

   {% endlist %}

   For more on the properties of resources used in Terraform, see these 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 image](../../concepts/image.md): [yandex_compute_image](../../../terraform/resources/compute_image.md)
   * [Disk](../../concepts/disk.md): [yandex_compute_disk](../../../terraform/resources/compute_disk.md)
   * [VM](../../concepts/vm.md): [yandex_compute_instance](../../../terraform/resources/compute_instance.md)

1. Under `metadata`, enter your username and the SSH key contents. For more information, see [VM metadata](../../concepts/vm-metadata.md).
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, [configure Samba and NFS](#setup-samba-nfs).

## Configure Samba and NFS {#setup-samba-nfs}

After the `fileserver-tutorial` VM enters the `RUNNING` status, run:

1. On the VM page of the [management console](https://console.yandex.cloud), under **Network**, find the VM's public IP address.

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

   We recommend using a key pair when authenticating over SSH. Make sure to set up the created key pair so that the private key matches the public key sent to the VM.

1. Configure Samba and NFS:

   {% list tabs group=operating_system %}

   - Ubuntu {#ubuntu}

     1. Download and install Samba:

        ```bash
        sudo apt-get update
        sudo apt-get install nfs-kernel-server samba
        ```

     1. Prepare and mount the file system on the disk:

        ```bash
        sudo mkfs -t ext4 -L data /dev/vdb
        ```

     1. Prepare and mount a folder named `my_folder` for data storage on the disk:

        ```bash
        sudo mkdir /my_folder
        echo "LABEL=data /my_folder ext4 defaults 0 0" | sudo tee -a /etc/fstab
        sudo mount /my_folder
        ```

     1. Set the NFS configuration in the `/etc/exports` file. You can edit the file using `nano`:

        ```bash
        sudo nano /etc/exports
        ```

        Add the following lines to the file:

        ```bash
        /my_folder <IP_address>(rw,no_subtree_check,fsid=100)
        /my_folder 127.0.0.1(rw,no_subtree_check,fsid=100)
        ```

        Where `<IP_address>` is the IP address of the computer you are going to connect the network data disk to via NFS.

     1. Set the Samba configuration in the `/etc/samba/smb.conf` file. You can edit the file using `nano`:

        ```bash
        sudo nano /etc/samba/smb.conf
        ```

        Edit the file as follows:

        ```bash
        [global]
           workgroup = WORKGROUP
           server string = %h server (Samba)
           dns proxy = no
           log file = /var/log/samba/log.%m
           max log size = 1000
           syslog = 0
           panic action = /usr/share/samba/panic-action %d
           server role = standalone server
           passdb backend = tdbsam
           obey pam restrictions = yes
           unix password sync = yes
           passwd program = /usr/bin/passwd %u
           passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .
           pam password change = yes
           map to guest = bad user
           usershare allow guests = yes
        [printers]
           comment = All Printers
           browseable = no
           path = /var/spool/samba
           printable = yes
           guest ok = no
           read only = yes
           create mask = 0700
        [print$]
           comment = Printer Drivers
           path = /var/lib/samba/printers
           browseable = yes
           read only = yes
           guest ok = no
        [data]
           comment = /my_folder
           path = /my_folder
           browseable = yes
           read only = no
           writable = yes
           guest ok = yes
           hosts allow = <IP_address> 127.0.0.1
           hosts deny = 0.0.0.0/0
        ```

        Where `<IP_address>` in the `[data]` section is the IP address of the computer you are going to connect the network data disk to via NFS.

     1. Restart Samba and NFS:

        ```bash
        sudo service nfs-kernel-server restart
        sudo service smbd restart
        ```

   {% endlist %}

## Test your file server {#test-file-server}

1. Install ACL on the `fileserver-tutorial` VM and create a directory named `remote` and a file named `test.txt`.

   {% list tabs group=operating_system %}

   - Ubuntu {#ubuntu}

     ```bash
     sudo apt-get install acl
     sudo mkdir /my_folder/remote
     sudo setfacl -m u:<your_username>:rwx /my_folder/remote
     echo "Hello world!" > /my_folder/remote/test.txt
     ```

   {% endlist %}

1. Connect the network disk to your computer via NFS and check if the test file is available:

   {% list tabs group=operating_system %}

   - Linux/macOS {#linux-macos}

     If needed, install the network disk utility:

     ```bash
     sudo apt-get install nfs-common
     ```

     Create a mount point:

     ```bash
     sudo mkdir /remote-test-dir
     ```

     Attach a network disk:

     ```bash
     sudo mount -t nfs <VM_public_IP_address>:/my_folder /remote-test-dir
     ```

     As as result, the test directory and the file should become available at the mount point.

   - Windows {#windows}

     {% note info %}

     You may need to configure Windows security policies for access to the file server.

     {% endnote %}

     1. Run the **cmd.exe** utility. To do this, use the **Windows** + **R** keyboard shortcut and run the `cmd` command.
     1. From the command line, run:

        ```bash
        net use x: \\<VM_public_IP_address>\data
        ```

     This will create a disk **X** with the test directory and file.

   {% endlist %}

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

To stop paying for the resources you created:

1. Open the `single-node-file-server.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 a single-node file server using the management console](console.md).