Yandex Cloud
Search
Contact UsGet started
  • Pricing
  • Customer Stories
  • Documentation
  • Blog
  • All Services
  • System Status
    • Featured
    • Infrastructure & Network
    • Data Platform
    • Containers
    • Developer tools
    • Serverless
    • Security
    • Monitoring & Resources
    • AI for business
    • Business tools
  • All Solutions
    • By industry
    • By use case
    • Economics and Pricing
    • Security
    • Technical Support
    • Start testing with double trial credits
    • Cloud credits to scale your IT product
    • Gateway to Russia
    • Cloud for Startups
    • Center for Technologies and Society
    • Yandex Cloud Partner program
  • Pricing
  • Customer Stories
  • Documentation
  • Blog
© 2025 Direct Cursus Technology L.L.C.
Yandex Application Load Balancer
  • Getting started
    • All tutorials
    • Setting up virtual hosting
    • Creating an L7 load balancer with a Smart Web Security profile through an Application Load Balancer ingress controller
    • Integrating an L7 load balancer with CDN and Object Storage
    • Blue-green and canary deployment of service versions
    • Writing load balancer logs to PostgreSQL
    • Deploying and load testing a scalable gRPC service in Yandex Managed Service for Kubernetes
    • Setting up the Gateway API in Yandex Managed Service for Kubernetes
    • Configuring an L7 Application Load Balancer using an ingress controller
    • Configuring L7 Application Load Balancer logging via an ingress controller
    • Health checking applications in a Managed Service for Kubernetes cluster via an L7 Application Load Balancer
    • Implementing a secure high-availability network infrastructure with a dedicated DMZ using the next-generation firewall
      • Overview
      • Deploying Nextcloud on a VM from a Container Optimized Image
      • Manually deploying Nextcloud on a VM or VM group
      • Deploying Nextcloud on a VM or VM group using Terraform
    • Deploying a web application on BareMetal servers with an L7 load balancer and Smart Web Security protection
  • Access management
  • Pricing policy
  • Terraform reference
  • Monitoring metrics
  • Audit Trails events
  • L7 load balancer logs
  • Release notes

In this article:

  • Getting started
  • Required paid resources
  • Deploy Nextcloud in a basic configuration
  • Create an infrastructure for the basic configuration
  • Install and configure Nextcloud on the VM
  • Test the solution in the basic configuration
  • Deploy Nextcloud in a fault-tolerant configuration
  • Complete Nextcloud setup
  • Scale the infrastructure for the fault-tolerant configuration
  • Test the solution in the fault-tolerant configuration
  • How to delete the resources you created
  1. Tutorials
  2. Deploying Nextcloud integrated with Object Storage
  3. Deploying Nextcloud on a VM or VM group using Terraform

Deploying Nextcloud integrated with Yandex Object Storage on a Yandex Compute Cloud VM or VM group with the help of Terraform

Written by
Yandex Cloud
Updated at November 27, 2025
  • Getting started
    • Required paid resources
  • Deploy Nextcloud in a basic configuration
    • Create an infrastructure for the basic configuration
    • Install and configure Nextcloud on the VM
    • Test the solution in the basic configuration
  • Deploy Nextcloud in a fault-tolerant configuration
    • Complete Nextcloud setup
    • Scale the infrastructure for the fault-tolerant configuration
    • Test the solution in the fault-tolerant configuration
  • How to delete the resources you created

In this tutorial, you will connect an Object Storage bucket to a Nextcloud solution deployed on a Compute Cloud VM instance with a database in a Yandex Managed Service for MySQL® cluster. To ensure fault tolerance and redundancy of your Nextcloud infrastructure, you will scale Nextcloud across an instance group and implement L7 load balancing with Yandex Application Load Balancer. In the fault-tolerant configuration, Nextcloud will be available via a domain name, for which a TLS certificate will be issued in Yandex Certificate Manager.

Note

To implement a fault-tolerant Nextcloud configuration, you will need a domain for the L7 load balancer.

Fault-tolerant solution diagram:

Where:

  • example.com: Your domain for which a certificate is issued in Yandex Certificate Manager, connected to the L7 load balancer.
  • nextcloud-alb: L7 load balancer to evenly distribute incoming user traffic across instance group hosts.
  • nextcloud-instance-group: Instance group with hosts the Nextcloud solution is deployed on.
  • nextcloud-db-cluster: Yandex Managed Service for MySQL® cluster with the Nextcloud service database.
  • my-nextcloud-bucket: Yandex Object Storage bucket connected to the Nextcloud solution.

To deploy Nextcloud in Yandex Cloud and connect an Object Storage bucket:

  1. Get your cloud ready.
  2. Deploy Nextcloud in a basic configuration:
    1. Create an infrastructure for the basic configuration.
    2. Install and configure Nextcloud on the VM.
    3. Test the solution in the basic configuration.
  3. Deploy Nextcloud in a fault-tolerant configuration:
    1. Complete Nextcloud setup.
    2. Scale the infrastructure for the fault-tolerant configuration.
    3. Test the solution in the fault-tolerant configuration.

If you no longer need the resources you created, delete them.

Getting startedGetting started

Sign up for Yandex Cloud and create a billing account:

  1. Navigate to the management console and log in to Yandex Cloud or create a new account.
  2. On the Yandex Cloud Billing page, make sure you have a billing account linked and it has the ACTIVE or TRIAL_ACTIVE status. If you do not have a billing account, create one and link a cloud to it.

If you have an active billing account, you can navigate to the cloud page to create or select a folder for your infrastructure.

Learn more about clouds and folders here.

Required paid resourcesRequired paid resources

The cost of the proposed solution includes:

  • Fee for disks, disk snapshots, and continuously running VMs (see Yandex Compute Cloud pricing).
  • Fee for using public IP addresses and NAT gateways (see Yandex Virtual Private Cloud pricing).
  • Fee for data storage in Object Storage and data operations (see Yandex Object Storage pricing).
  • Fee for using a MySQL® managed DB (see Managed Service for MySQL® pricing).
  • If using Yandex Cloud DNS, fee for DNS zones and public DNS queries (see Cloud DNS pricing).
  • If using a load balancer, fee for the number of L7 load balancer resource units (see Yandex Application Load Balancer pricing).
  • If using a log group for load balancer logging, fee for data logging and storage (see Yandex Cloud Logging pricing).

Deploy Nextcloud in a basic configurationDeploy Nextcloud in a basic configuration

You will deploy the basic Nextcloud configuration on a single VM with the Nextcloud service database created in a single-host Managed Service for MySQL® cluster.

Create an infrastructure for the basic configurationCreate an infrastructure for the basic configuration

With Terraform, 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. The Yandex Cloud provider for Terraform is distributed under the MPL-2.0 license.

For more information about the provider resources, see the relevant documentation on the Terraform website or its mirror.

To create an infrastructure using Terraform:

  1. Install Terraform, get the credentials, and specify the source for installing Yandex Cloud (see Configure your provider, step 1).

  2. Prepare your infrastructure description files:

    Ready-made configuration
    Manually
    1. Clone the repository with configuration files.

      git clone https://github.com/yandex-cloud-examples/yc-nextcloud-s3.git
      
    2. Navigate to the repository directory. Make sure it contains the following files and folders:

      • nextcloud-integrate-storage-basic-config.tf: Configuration file of the new basic infrastructure.
      • nextcloud-integrate-storage.auto.tfvars: File with the values of user-defined variables.
      • failsafe: Folder containing the fault-tolerant configuration:
        • nextcloud-integrate-storage-failsafe-config.tf: Configuration file of the new infrastructure in the fault-tolerant version.
    1. Create a folder for configuration files.

    2. In the folder, create:

      1. nextcloud-integrate-storage-basic-config.tf configuration file:

        nextcloud-integrate-storage-basic-config.tf
        # Declaring variables
        
        variable "folder_id" {
          type = string
        }
        
        variable "bucket_name" {
          type = string
        }
        
        variable "ssh_key_path" {
          type = string
        }
        
        variable "db_password" {
          type = string
          sensitive  = true
        }
        
        variable "domain_name" {
          type = string
        }
        
        locals {
          sa_name             = "nextcloud-sa"
          network_name        = "nextcloud-network"
          subnet_a_name       = "nextcloud-subnet-ru-central1-a"
          subnet-a-cidr       = "192.168.11.0/24"
          sg_name             = "nextcloud-sg"
          gw_name             = "nextcloud-gateway"
          vm_name             = "nextcloud-vm"
          vm_image_id         = "fd8vsghfu10ev5gdatkh"
          ig_name             = "nexcloud-ig"
          cluster_name        = "nextcloud-db-cluster"
          db_name             = "nextcloud"
          db_username         = "user"
        }
        
        # Configuring the provider
        
        terraform {
          required_providers {
            yandex = {
              source = "yandex-cloud/yandex"
            }
          }
          required_version = ">= 0.13"
        }
        
        provider "yandex" {
          folder_id = var.folder_id
        }
        
        # Creating a network
        
        resource "yandex_vpc_network" "nextcloud-network" {
          name = local.network_name
        }
        
        # Creating a NAT gateway
        
        resource "yandex_vpc_gateway" "nextcloud-gw" {
          name = local.gw_name
          shared_egress_gateway {}
        }
        
        # Creating a routing table
        
        resource "yandex_vpc_route_table" "nextcloud-rt-table" {
          network_id  = yandex_vpc_network.nextcloud-network.id
        
          static_route {
            destination_prefix = "0.0.0.0/0"
            gateway_id         = yandex_vpc_gateway.nextcloud-gw.id
          }
        }
        
        # Creating a subnet
        
        resource "yandex_vpc_subnet" "nextcloud-subnet-a" {
          name           = local.subnet_a_name
          zone           = "ru-central1-a"
          network_id     = yandex_vpc_network.nextcloud-network.id
          v4_cidr_blocks = [local.subnet-a-cidr]
          route_table_id = yandex_vpc_route_table.nextcloud-rt-table.id
        }
        
        # Creating a security group
        
        resource "yandex_vpc_security_group" "nextcloud-sg" {
          name        = local.sg_name
          network_id  = yandex_vpc_network.nextcloud-network.id
        
          ingress {
            protocol       = "TCP"
            description    = "http"
            v4_cidr_blocks = ["0.0.0.0/0"]
            port           = 80
          }
        
          ingress {
            protocol       = "TCP"
            description    = "https"
            v4_cidr_blocks = ["0.0.0.0/0"]
            port           = 443
          }
        
          ingress {
            protocol       = "TCP"
            description    = "ssh"
            v4_cidr_blocks = ["0.0.0.0/0"]
            port           = 22
          }
        
          ingress {
            protocol       = "ANY"
            description    = "self"
            predefined_target = "self_security_group"
            from_port      = 0
            to_port        = 65535
          }
        
          ingress {
            protocol       = "ANY"
            description    = "healthchecks"
            predefined_target = "loadbalancer_healthchecks"
            from_port      = 0
            to_port        = 65535
          }
        
          egress {
            protocol       = "ANY"
            description    = "any"
            v4_cidr_blocks = ["0.0.0.0/0"]
            from_port      = 0
            to_port        = 65535
          }
        }
        
        # Creating a service account
        
        resource "yandex_iam_service_account" "nextcloud-sa" {
          name = local.sa_name
        }
        
        # Assigning roles to a service account
        
        resource "yandex_resourcemanager_folder_iam_member" "editor" {
          folder_id = var.folder_id
          role      = "editor"
          member    = "serviceAccount:${yandex_iam_service_account.nextcloud-sa.id}"
        }
        
        # Creating a static access key for CA
        
        resource "yandex_iam_service_account_static_access_key" "sa-static-key" {
          service_account_id = yandex_iam_service_account.nextcloud-sa.id
        }
        
        # Creating a bucket
        
        resource "yandex_storage_bucket" "nextcloud-bucket" {
          access_key = yandex_iam_service_account_static_access_key.sa-static-key.access_key
          secret_key = yandex_iam_service_account_static_access_key.sa-static-key.secret_key
          bucket     = var.bucket_name
        }
        
        # Creating a boot disk for the VM
        
        resource "yandex_compute_disk" "boot-disk" {
          type     = "network-ssd"
          zone     = "ru-central1-a"
          size     = "24"
          image_id = local.vm_image_id
        }
        
        # Creating a VM
        
        resource "yandex_compute_instance" "nextcloud-vm" {
          name        = local.vm_name
          platform_id = "standard-v2"
          zone        = "ru-central1-a"
        
          resources {
            cores  = "2"
            memory = "4"
          }
        
          boot_disk {
            disk_id = yandex_compute_disk.boot-disk.id
          }
        
          network_interface {
            subnet_id          = yandex_vpc_subnet.nextcloud-subnet-a.id
            nat                = true
            security_group_ids = [yandex_vpc_security_group.nextcloud-sg.id]
          }
        
          metadata = {
            user-data = "#cloud-config\nusers:\n  - name: yc-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 MySQL cluster
        
        resource "yandex_mdb_mysql_cluster" "nextcloud-cluster" {
          name        = local.cluster_name
          environment = "PRODUCTION"
          network_id  = yandex_vpc_network.nextcloud-network.id
          version     = "8.0"
          security_group_ids = [yandex_vpc_security_group.nextcloud-sg.id]
        
          resources {
            resource_preset_id = "s2.micro"
            disk_type_id       = "network-ssd"
            disk_size          = 10
          }
        
          host {
            zone      = "ru-central1-a"
            subnet_id = yandex_vpc_subnet.nextcloud-subnet-a.id
          }
        
          mysql_config = {
            sql_mode             = "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
            character_set_server = "utf8mb4"
            collation_server     = "utf8mb4_general_ci"
          }
        }
        
        # Creating a database in the MySQL cluster
        
        resource "yandex_mdb_mysql_database" "nextcloud-db" {
          cluster_id = yandex_mdb_mysql_cluster.nextcloud-cluster.id
          name       = local.db_name
        }
        
        # Creating a database user in the MySQL cluster
        
        resource "yandex_mdb_mysql_user" "my_user" {
          cluster_id = yandex_mdb_mysql_cluster.nextcloud-cluster.id
          name       = local.db_username
          password   = var.db_password
        
          permission {
            database_name = yandex_mdb_mysql_database.nextcloud-db.name
            roles         = ["ALL"]
          }
        }
        
        # Displaying static access key data on the screen
        
        output "Access_key" {
          value = yandex_iam_service_account_static_access_key.sa-static-key.access_key
        }
        
        output "Secret_key" {
          value = yandex_iam_service_account_static_access_key.sa-static-key.secret_key
          sensitive = true
        }
        
      2. nextcloud-integrate-storage.auto.tfvars user data file:

        nextcloud-integrate-storage.auto.tfvars
        folder_id     = "<folder_ID>"
        ssh_key_path  = "<public_SSH_key_path>"
        bucket_name   = "<bucket_name>"
        db_password   = "<database_user_password>"
        domain_name   = "<domain_name>"
        

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

    • Network: yandex_vpc_network.
    • NAT gateway: yandex_vpc_gateway.
    • Route table: yandex_vpc_route_table.
    • Subnet: yandex_vpc_subnet.
    • Security group: yandex_vpc_security_group.
    • Service account: yandex_iam_service_account.
    • Role: yandex_resourcemanager_folder_iam_member
    • Static access key: yandex_iam_service_account_static_access_key.
    • Bucket: yandex_storage_bucket.
    • VM disk: yandex_compute_disk.
    • VM instance: yandex_compute_instance.
    • Managed Service for MySQL® cluster: yandex_mdb_mysql_cluster.
    • MySQL® database: yandex_mdb_mysql_database.
    • MySQL® database user: yandex_mdb_mysql_user.
  3. In the nextcloud-integrate-storage.auto.tfvars file, set the values of the user-defined variables:

    • folder_id: Folder ID.

    • ssh_key_path: Path to the public SSH key file. For more information, see Creating an SSH key pair.

    • bucket_name: Bucket name consistent with the following naming conventions.

    • db_password: MySQL® database user password.

    • domain_name: Name of the domain to host the Nextcloud instance.

      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.

      Note

      If you only plan to create a basic Nextcloud instance without deploying a fault-tolerant solution, you do not have to change the value of the domain_name variable.

  4. Create the resources:

    1. In the terminal, go to the directory where you edited the configuration file.

    2. Make sure the configuration file is correct using this command:

      terraform validate
      

      If the configuration is correct, you will get this message:

      Success! The configuration is valid.
      
    3. Run this command:

      terraform plan
      

      You will see a detailed list of resources. No changes will be made at this step. If the configuration contains any errors, Terraform will show them.

    4. Apply the changes:

      terraform apply
      
    5. Type yes and press Enter to confirm the changes.

This will create all the infrastructure you need to deploy Nextcloud in a basic configuration in the selected folder.

Terraform will display the ID of the created static access key. You will need this value later when setting up Nextcloud integration with Object Storage. You will also need a secret key. To get it, run the following command in the terminal:

terraform output Secret_key

Once you have the secret key value, proceed to configuring Nextcloud on your VM.

Install and configure Nextcloud on the VMInstall and configure Nextcloud on the VM

  1. Install Nextcloud on nextcloud-vm:

    1. Connect to nextcloud-vm over SSH.

      To do this, run this command in the VM terminal, specifying the public IP address of the VM:

      ssh yc-user@<VM_IP_address>
      

      You can look up the VM's public IP address in the management console by checking the Network section's Public IPv4 address field on the VM information page.

    2. Upgrade the versions of the packages installed on the VM:

      sudo apt update && sudo apt upgrade
      
    3. Install the required software packages and dependencies:

      sudo apt install \
        apache2 mariadb-server libapache2-mod-php php-gd php-mysql php-curl php-mbstring \
        php-intl php-gmp php-bcmath php-xml php-imagick php-zip php-fpm unzip
      
    4. Download the archive with the latest Nextcloud version:

      wget https://download.nextcloud.com/server/releases/latest.zip
      
    5. Unpack the archive to the /var/www directory:

      sudo unzip latest.zip -d /var/www
      
    6. Edit access permissions for the Nextcloud directory:

      sudo chown -R www-data:www-data /var/www/nextcloud
      sudo chmod -R 755 /var/www/nextcloud/
      
    7. Configure the default virtual host:

      1. Open the configuration file of the default virtual host:

        sudo nano /etc/apache2/sites-available/000-default.conf
        
      2. Replace the contents of 000-default.conf with the following:

        <VirtualHost *:80>
            DocumentRoot /var/www/nextcloud/
        
            <Directory /var/www/nextcloud/>
            Require all granted
            AllowOverride All
            Options FollowSymLinks MultiViews
        
            <IfModule mod_dav.c>
            Dav off
            </IfModule>
            </Directory>
            </VirtualHost>
        
    8. Enable the required Apache web server modules:

      sudo a2enmod rewrite
      sudo a2enmod headers
      a2enmod env
      a2enmod dir
      a2enmod mime
      
    9. Increase the amount of RAM available to the PHP interpreter for processing requests to Nextcloud to 512 MB.

      1. Open the .htaccess file in the Nextcloud installation directory:

        sudo nano /var/www/nextcloud/.htaccess
        
      2. Add the following line to the end of the file:

        php_value memory_limit 512M
        

        Make sure to save your changes.

    10. Restart the web server:

      sudo systemctl restart apache2
      
  2. Configure Nextcloud in the GUI:

    1. Open your local computer browser and enter the following in the address bar:

      http://<VM_public_IP_address>
      

      You can look up the VM's public IP address in the management console by checking the Network section's Public IPv4 address field on the VM information page.

    2. In the Create an admin account form that opens:

      1. In the New admin account name and New admin password fields, set the Nextcloud administrator credentials you will use to log in to the system.

      2. In the Database account field, specify user, which is the name of the database user created in the MySQL® cluster.

      3. In the Database password field, enter the database user password you specified in the nextcloud-integrate-storage.auto.tfvars file.

      4. In the Database name field, specify nextcloud, which is the name of the database created in the MySQL® cluster.

      5. In the Database host field, specify the FQDN of the MySQL® cluster’s current master host and port in this format:

        c-<cluster_ID>.rw.mdb.yandexcloud.net:3306
        

        You can look up the cluster ID in the management console by checking the ID field on the cluster information page.

      6. Click Install.

        This will start the deployment of the Nextcloud database in the MySQL® cluster. Wait for this process to complete.

    3. After the installation is over, you will see a window with recommended apps. Click Skip. You can get back to installing the applications you need at a later time.

    4. Close the window with information on updates in the current Nextcloud version.

    5. Open the application management menu. To do this, click the user icon in the top-right corner of the screen and select Apps from the context menu.

    6. In the window that opens, select Your apps in the left-hand panel.

    7. In the list that opens, find the External storage support application and click Enable in the row with it.

      If needed, enter your Nextcloud administrator password in the pop-up window to confirm the operation.

    8. Open the main settings menu. To do this, click the user icon in the top-right corner of the screen and select Administration settings from the context menu.

    9. In the window that opens, select External storage in the left-hand panel under Administration and specify the Object Storage integration settings under External storage in the window that opens:

      1. In the External storage section, select Amazon S3.

      2. In the Authentication section, select Access key.

      3. In the Configuration section:

        • In the Bucket field, enter the name of the bucket you created earlier, e.g., my-nextcloud-bucket.
        • In the Hostname field, specify storage.yandexcloud.net.
        • In the Port field, specify 443.
        • In the Access key field, paste the static access key ID you got earlier.
        • In the Secret key field, paste the static access key's secret key you got earlier.
      4. Under Available for, enable All people.

      5. On the right side of the section you are editing, click the icon to save your changes.

        Enter your Nextcloud administrator password in the pop-up window to confirm the operation.

Test the solution in the basic configurationTest the solution in the basic configuration

To test Yandex Object Storage integration with Nextcloud on a single host:

  1. Open your local computer browser and enter the public IPv4 address of the Nextcloud VM in the address bar:

    http://<VM_public_IP_address>
    
  2. Get authenticated in Nextcloud using the login and password created when configuring the solution in the previous step.

  3. In the left pane of the top menu, select Files.

  4. In the left-hand menu, select External storage and then AmazonS3.

  5. Click New and select Upload files to upload a file from your local computer to the storage.

  6. Select a file on your local computer and upload it to the storage.

    The uploaded file will now appear in the Nextcloud storage named AmazonS3.

  7. In Yandex Object Storage, make sure the file was uploaded to the bucket.

The deployment of the Nextcloud basic configuration is now complete. You can now proceed to deploy the fault-tolerant configuration.

Deploy Nextcloud in a fault-tolerant configurationDeploy Nextcloud in a fault-tolerant configuration

You will deploy a fault-tolerant Nextcloud configuration in a group of three VMs, the load on Nextcloud hosts distributed with the help of an L7 Yandex Application Load Balancer. The service database will reside in a three-host MySQL® cluster. Hosts of the instance group, load balancer, and MySQL® cluster will be evenly distributed across three availability zones. Nextcloud will be available via the domain name, for which a TLS certificate will be issued in Certificate Manager.

Complete Nextcloud setupComplete Nextcloud setup

Before you begin deploying a fault-tolerant configuration, add your domain to Nextcloud's list of trusted addresses and domains:

  1. Connect to nextcloud-vm over SSH.

  2. Add your domain to the array of trusted addresses and Nextcloud domains:

    1. In the VM terminal, open the Nextcloud configuration file:

      sudo nano /var/www/nextcloud/config/config.php
      
    2. In the trusted_domains array, replace the host IP address with your domain name.

      Here is an example:

      'trusted_domains' =>
      array (
        0 => 'example.com',
      ),
      

      The trusted_domains array allows you to restrict the range of IP addresses and/or domains you can use to access Nextcloud and ensures additional protection from unauthorized access. You can specify multiple addresses and/or domains, and you can also reduce or remove this restriction using wildcard characters:

      Example 1
      Example 2
      'trusted_domains' =>
      array (
        0 => '*.example.com',
        1 => '198.168.*.*',
      ),
      

      In this example, access is allowed from any subdomains of the example.com domain and the IP addresses of the 192.168.0.0 - 192.168.255.255 range.

      'trusted_domains' =>
      array (
        0 => '*',
      ),
      

      In this example, access is allowed from any domains and IP addresses.

    3. Delete the 'overwrite.cli.url' => 'http://<VM_IP_address>', line.

    4. Save the changes and close the nano editor.

  3. Stop the nextcloud-vm virtual machine.

Scale the infrastructure for the fault-tolerant configurationScale the infrastructure for the fault-tolerant configuration

  1. Set up your infrastructure description files:

    Ready-made configuration
    Manually
    1. In the folder with the downloaded repository, delete the nextcloud-integrate-storage-basic-config.tf file.
    2. From the failsafe folder, move the nextcloud-integrate-storage-failsafe-config.tf file to the repository’s root folder, i.e., the one you just deleted the file from.
    1. In the previously created folder for configuration files, delete the nextcloud-integrate-storage-basic-config.tf file.

    2. Create a new nextcloud-integrate-storage-failsafe-config.tf configuration file in this folder:

      nextcloud-integrate-storage-failsafe-config.tf
      # Declaring variables
      
      variable "folder_id" {
        type = string
      }
      
      variable "bucket_name" {
        type = string
      }
      
      variable "ssh_key_path" {
        type = string
      }
      
      variable "db_password" {
        type = string
        sensitive  = true
      }
      
      variable "domain_name" {
        type = string
      }
      
      locals {
        sa_name             = "nextcloud-sa"
        network_name        = "nextcloud-network"
        subnet_a_name       = "nextcloud-subnet-ru-central1-a"
        subnet_b_name       = "nextcloud-subnet-ru-central1-b"
        subnet_d_name       = "nextcloud-subnet-ru-central1-d"
        subnet-a-cidr       = "192.168.11.0/24"
        subnet-b-cidr       = "192.168.12.0/24"
        subnet-d-cidr       = "192.168.13.0/24"
        sg_name             = "nextcloud-sg"
        gw_name             = "nextcloud-gateway"
        vm_name             = "nextcloud-vm"
        vm_image_id         = "fd8vsghfu10ev5gdatkh"
        ig_name             = "nextcloud-instance-group"
        cluster_name        = "nextcloud-db-cluster"
        db_name             = "nextcloud"
        db_username         = "user"
        domain_zone_name    = "nexcloud-domain-zone"
        certificate_name    = "mymanagedcert"
        snapshot_name       = "nextcloud-vm-snapshot"
        tg_name             = "nextcloud-target-group"
        backend_name        = "nextcloud-backend"
        bg_name             = "nextcloud-bg"
        http_router_name    = "nextcloud-router"
        vh_name             = "nextcloud-vh"
        route_name          = "nextcloud-route"
        alb_name            = "nextcloud-alb"
        listener_name       = "nextcloud-listener"
      }
      
      # Configuring the provider
      
      terraform {
        required_providers {
          yandex = {
            source = "yandex-cloud/yandex"
          }
        }
        required_version = ">= 0.13"
      }
      
      provider "yandex" {
        folder_id = var.folder_id
      }
      
      # Create network
      
      resource "yandex_vpc_network" "nextcloud-network" {
        name = local.network_name
      }
      
      # Creating a NAT gateway
      
      resource "yandex_vpc_gateway" "nextcloud-gw" {
        name = local.gw_name
        shared_egress_gateway {}
      }
      
      # Creating a routing table
      
      resource "yandex_vpc_route_table" "nextcloud-rt-table" {
        network_id  = yandex_vpc_network.nextcloud-network.id
      
        static_route {
          destination_prefix = "0.0.0.0/0"
          gateway_id         = yandex_vpc_gateway.nextcloud-gw.id
        }
      }
      
      # Creating subnets
      
      resource "yandex_vpc_subnet" "nextcloud-subnet-a" {
        name           = local.subnet_a_name
        zone           = "ru-central1-a"
        network_id     = yandex_vpc_network.nextcloud-network.id
        v4_cidr_blocks = [local.subnet-a-cidr]
        route_table_id = yandex_vpc_route_table.nextcloud-rt-table.id
      }
      
      resource "yandex_vpc_subnet" "nextcloud-subnet-b" {
        name           = local.subnet_b_name
        zone           = "ru-central1-b"
        network_id     = yandex_vpc_network.nextcloud-network.id
        v4_cidr_blocks = [local.subnet-b-cidr]
        route_table_id = yandex_vpc_route_table.nextcloud-rt-table.id
      }
      
      resource "yandex_vpc_subnet" "nextcloud-subnet-d" {
        name           = local.subnet_d_name
        zone           = "ru-central1-d"
        network_id     = yandex_vpc_network.nextcloud-network.id
        v4_cidr_blocks = [local.subnet-d-cidr]
        route_table_id = yandex_vpc_route_table.nextcloud-rt-table.id
      }
      
      # Creating a security group
      
      resource "yandex_vpc_security_group" "nextcloud-sg" {
        name        = local.sg_name
        network_id  = yandex_vpc_network.nextcloud-network.id
      
        ingress {
          protocol       = "TCP"
          description    = "http"
          v4_cidr_blocks = ["0.0.0.0/0"]
          port           = 80
        }
      
        ingress {
          protocol       = "TCP"
          description    = "https"
          v4_cidr_blocks = ["0.0.0.0/0"]
          port           = 443
        }
      
        ingress {
          protocol       = "TCP"
          description    = "ssh"
          v4_cidr_blocks = ["0.0.0.0/0"]
          port           = 22
        }
      
        ingress {
          protocol       = "ANY"
          description    = "self"
          predefined_target = "self_security_group"
          from_port      = 0
          to_port        = 65535
        }
      
        ingress {
          protocol       = "ANY"
          description    = "healthchecks"
          predefined_target = "loadbalancer_healthchecks"
          from_port      = 0
          to_port        = 65535
        }
      
        egress {
          protocol       = "ANY"
          description    = "any"
          v4_cidr_blocks = ["0.0.0.0/0"]
          from_port      = 0
          to_port        = 65535
        }
      }
      
      # Creating a service account
      
      resource "yandex_iam_service_account" "nextcloud-sa" {
        name = local.sa_name
      }
      
      # Assigning roles to a service account
      
      resource "yandex_resourcemanager_folder_iam_member" "editor" {
        folder_id = var.folder_id
        role      = "editor"
        member    = "serviceAccount:${yandex_iam_service_account.nextcloud-sa.id}"
      }
      
      # Creating a static access key for CA
      
      resource "yandex_iam_service_account_static_access_key" "sa-static-key" {
        service_account_id = yandex_iam_service_account.nextcloud-sa.id
      }
      
      # Creating a bucket
      
      resource "yandex_storage_bucket" "nextcloud-bucket" {
        access_key = yandex_iam_service_account_static_access_key.sa-static-key.access_key
        secret_key = yandex_iam_service_account_static_access_key.sa-static-key.secret_key
        bucket     = var.bucket_name
      }
      
      # Creating a boot disk for the VM
      
      resource "yandex_compute_disk" "boot-disk" {
        type     = "network-ssd"
        zone     = "ru-central1-a"
        size     = "24"
        image_id = local.vm_image_id
      }
      
      # Creating a VM
      
      resource "yandex_compute_instance" "nextcloud-vm" {
        name        = local.vm_name
        platform_id = "standard-v2"
        zone        = "ru-central1-a"
      
        resources {
          cores  = "2"
          memory = "4"
        }
      
        boot_disk {
          disk_id = yandex_compute_disk.boot-disk.id
        }
      
        network_interface {
          subnet_id          = yandex_vpc_subnet.nextcloud-subnet-a.id
          nat                = true
          security_group_ids = [yandex_vpc_security_group.nextcloud-sg.id]
        }
      
        metadata = {
          user-data = "#cloud-config\nusers:\n  - name: yc-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 MySQL cluster
      
      resource "yandex_mdb_mysql_cluster" "nextcloud-cluster" {
        name        = local.cluster_name
        environment = "PRODUCTION"
        network_id  = yandex_vpc_network.nextcloud-network.id
        version     = "8.0"
        security_group_ids = [yandex_vpc_security_group.nextcloud-sg.id]
      
        resources {
          resource_preset_id = "s2.micro"
          disk_type_id       = "network-ssd"
          disk_size          = 10
        }
      
        host {
          zone      = "ru-central1-a"
          subnet_id = yandex_vpc_subnet.nextcloud-subnet-a.id
        }
      
        host {
          zone      = "ru-central1-b"
          subnet_id = yandex_vpc_subnet.nextcloud-subnet-b.id
        }
      
        host {
          zone      = "ru-central1-d"
          subnet_id = yandex_vpc_subnet.nextcloud-subnet-d.id
        }
      
        mysql_config = {
          sql_mode             = "ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
          character_set_server = "utf8mb4"
          collation_server     = "utf8mb4_general_ci"
        }
      }
      
      # Creating a database in a MySQL cluster
      
      resource "yandex_mdb_mysql_database" "nextcloud-db" {
        cluster_id = yandex_mdb_mysql_cluster.nextcloud-cluster.id
        name       = local.db_name
      }
      
      # Creating a database user in a MySQL cluster
      
      resource "yandex_mdb_mysql_user" "my_user" {
        cluster_id = yandex_mdb_mysql_cluster.nextcloud-cluster.id
        name       = local.db_username
        password   = var.db_password
      
        permission {
          database_name = yandex_mdb_mysql_database.nextcloud-db.name
          roles         = ["ALL"]
        }
      }
      
      # Creating a disk snapshot
      
      resource "yandex_compute_snapshot" "nextcloud-snapshot" {
        name           = local.snapshot_name
        source_disk_id = yandex_compute_disk.boot-disk.id
      }
      
      # Creating a public DNS zone
      
      resource "yandex_dns_zone" "nextcloud-domain-zone" {
        name    = local.domain_zone_name
        zone    = "${var.domain_name}."
        public  = true
      }
      
      # Adding a Let's Encrypt certificate
      
      resource "yandex_cm_certificate" "nextcloud-certificate" {
        name    = local.certificate_name
        domains = [var.domain_name]
      
        managed {
        challenge_type = "DNS_CNAME"
        challenge_count = 1
        }
      }
      
      # Creating CNAME records for domain validation when issuing a certificate
      
      resource "yandex_dns_recordset" "validation-record" {
        count   = yandex_cm_certificate.nextcloud-certificate.managed[0].challenge_count
        zone_id = yandex_dns_zone.nextcloud-domain-zone.id
        name    = yandex_cm_certificate.nextcloud-certificate.challenges[count.index].dns_name
        type    = yandex_cm_certificate.nextcloud-certificate.challenges[count.index].dns_type
        ttl     = 600
        data    = [yandex_cm_certificate.nextcloud-certificate.challenges[count.index].dns_value]
      }
      
      # Waiting for domain validation and the issue of a Let's Encrypt certificate
      
      data "yandex_cm_certificate" "wait-nextcloud-certificate" {
        depends_on      = [yandex_dns_recordset.validation-record]
        certificate_id  = yandex_cm_certificate.nextcloud-certificate.id
        wait_validation = true
      }
      
      # Creating an instance group
      
      resource "yandex_compute_instance_group" "nextcloud-ig" {
        name                = local.ig_name
        service_account_id  = yandex_iam_service_account.nextcloud-sa.id
        instance_template {
          platform_id = "standard-v2"
          resources {
            memory = 4
            cores  = 2
          }
          boot_disk {
            mode = "READ_WRITE"
            initialize_params {
              snapshot_id = yandex_compute_snapshot.nextcloud-snapshot.id
              size     = 24
            }
          }
      
          network_interface {
            subnet_ids         = [yandex_vpc_subnet.nextcloud-subnet-a.id,yandex_vpc_subnet.nextcloud-subnet-b.id,yandex_vpc_subnet.nextcloud-subnet-d.id]
            security_group_ids = [yandex_vpc_security_group.nextcloud-sg.id]
          }
      
          metadata = {
            ssh-keys = "yc-user:${file(var.ssh_key_path)}"
          }
        }
      
        scale_policy {
          fixed_scale {
            size = 3
          }
        }
      
        allocation_policy {
          zones = ["ru-central1-a","ru-central1-b","ru-central1-d"]
        }
      
        deploy_policy {
          max_unavailable = 2
          max_expansion   = 1
        }
      
        application_load_balancer {
          target_group_name = local.tg_name
        }
      
        depends_on = [
          yandex_resourcemanager_folder_iam_member.editor
        ]
      }
      
      # Creating a backend group
      
      resource "yandex_alb_backend_group" "nextcloud-backend-group" {
        name = local.bg_name
      
        session_affinity {
          connection {
            source_ip = true
          }
        }
      
        http_backend {
          name             = local.backend_name
          weight           = 1
          port             = 80
          target_group_ids = [yandex_compute_instance_group.nextcloud-ig.application_load_balancer[0].target_group_id]
          load_balancing_config {
            mode = "MAGLEV_HASH"
          }
        }
      }
      
      # Creating an HTTP router
      
      resource "yandex_alb_http_router" "nextcloud-router" {
        name = local.http_router_name
      }
      
      # Creating a virtual host
      
      resource "yandex_alb_virtual_host" "nextcloud-vhost" {
        name           = local.vh_name
        http_router_id = yandex_alb_http_router.nextcloud-router.id
        route {
          name = local.route_name
          http_route {
            http_route_action {
              backend_group_id = yandex_alb_backend_group.nextcloud-backend-group.id
              timeout          = "60s"
            }
          }
        }
      }
      
      # Creating an L7 load balancer
      
      resource "yandex_alb_load_balancer" "nextcloud-alb" {
        name = local.alb_name
      
        network_id = yandex_vpc_network.nextcloud-network.id
      
        allocation_policy {
          location {
            zone_id   = "ru-central1-a"
            subnet_id = yandex_vpc_subnet.nextcloud-subnet-a.id
          }
          location {
            zone_id   = "ru-central1-b"
            subnet_id = yandex_vpc_subnet.nextcloud-subnet-b.id
          }
          location {
            zone_id   = "ru-central1-d"
            subnet_id = yandex_vpc_subnet.nextcloud-subnet-d.id
          }
        }
      
        security_group_ids = [yandex_vpc_security_group.nextcloud-sg.id]
      
        listener {
          name = local.listener_name
          endpoint {
            address {
              external_ipv4_address {
              }
            }
            ports = [443]
          }
      
          tls {
            default_handler {
              certificate_ids = [data.yandex_cm_certificate.wait-nextcloud-certificate.id]
              http_handler {
                http_router_id = yandex_alb_http_router.nextcloud-router.id
              }
            }
          }
        }
      }
      
      # Creating a type A resource record for the L7 load balancer
      
      resource "yandex_dns_recordset" "nextcloud-a-record" {
        zone_id = yandex_dns_zone.nextcloud-domain-zone.id
        name    = yandex_dns_zone.nextcloud-domain-zone.zone
        type    = "A"
        ttl     = 600
        data    = [yandex_alb_load_balancer.nextcloud-alb.listener[0].endpoint[0].address[0].external_ipv4_address[0].address]
      }
      

    For more information about the properties of resources added to Terraform, refer to the relevant provider guides:

    • Disk snapshot: yandex_compute_snapshot
    • DNS zone: yandex_dns_zone
    • TLS certificate: yandex_cm_certificate
    • DNS resource record: yandex_dns_recordset
    • Instance group: yandex_compute_instance_group
    • Backend group: yandex_alb_backend_group
    • HTTP router: yandex_alb_http_router
    • Virtual host: yandex_alb_virtual_host
    • L7 load balancer: yandex_alb_load_balancer
  2. Create the resources:

    1. In the terminal, go to the directory where you edited the configuration file.

    2. Make sure the configuration file is correct using this command:

      terraform validate
      

      If the configuration is correct, you will get this message:

      Success! The configuration is valid.
      
    3. Run this command:

      terraform plan
      

      You will see a detailed list of resources. No changes will be made at this step. If the configuration contains any errors, Terraform will show them.

    4. Apply the changes:

      terraform apply
      
    5. Type yes and press Enter to confirm the changes.

As a result, a fault-tolerant Nextcloud solution will be deployed in the selected folder.

Test the solution in the fault-tolerant configurationTest the solution in the fault-tolerant configuration

To test Yandex Object Storage integration with Nextcloud in a fault-tolerant configuration:

  1. Open your local computer browser and enter your domain name in the address bar, e.g.:

    https://example.com
    
  2. Get authenticated in Nextcloud using the login and password created when configuring the solution.

  3. In the left pane of the top menu, select Files.

  4. In the left-hand menu, select External storage and then AmazonS3.

  5. Make sure you see the file uploaded in the previous step.

  6. Download the file you uploaded earlier. Do this by clicking and selecting Download in the line with the filename.

  7. Delete the file. Do this by clicking and selecting Delete file in the line with the filename.

  8. In Yandex Object Storage, make sure the file was deleted from the bucket.

How to delete the resources you createdHow to delete the resources you created

Warning

Before deleting the infrastructure, delete all objects in the created bucket.

To stop paying for the resources you created:

  1. Open the nextcloud-integrate-storage-failsafe-config.tf file and delete your infrastructure description from it.

  2. Apply the changes:

    1. In the terminal, go to the directory where you edited the configuration file.

    2. Make sure the configuration file is correct using this command:

      terraform validate
      

      If the configuration is correct, you will get this message:

      Success! The configuration is valid.
      
    3. Run this command:

      terraform plan
      

      You will see a detailed list of resources. No changes will be made at this step. If the configuration contains any errors, Terraform will show them.

    4. Apply the changes:

      terraform apply
      
    5. Type yes and press Enter to confirm the changes.

See alsoSee also

  • Deploying Nextcloud on a Yandex Compute Cloud VM from a Container Optimized Image image, integrated with Yandex Object Storage
  • Manually deploying Nextcloud on a Yandex Compute Cloud VM or in a VM group, integrated with Yandex Object Storage

Was the article helpful?

Previous
Manually deploying Nextcloud on a VM or VM group
Next
Deploying a web application on BareMetal servers with an L7 load balancer and Smart Web Security protection
© 2025 Direct Cursus Technology L.L.C.