Yandex Cloud
Search
Contact UsGet started
  • Blog
  • Pricing
  • Documentation
  • All Services
  • System Status
    • Featured
    • Infrastructure & Network
    • Data Platform
    • Containers
    • Developer tools
    • Serverless
    • Security
    • Monitoring & Resources
    • ML & AI
    • Business tools
  • All Solutions
    • By industry
    • By use case
    • Economics and Pricing
    • Security
    • Technical Support
    • Customer Stories
    • Start testing with double trial credits
    • Cloud credits to scale your IT product
    • Gateway to Russia
    • Cloud for Startups
    • Education and Science
    • Yandex Cloud Partner program
  • Blog
  • Pricing
  • Documentation
© 2025 Direct Cursus Technology L.L.C.
Yandex Managed Service for PostgreSQL
  • Getting started
    • All tutorials
    • Creating a PostgreSQL cluster for 1C
    • Creating a cluster of 1C:Enterprise Linux servers with a Managed Service for PostgreSQL cluster
    • Exporting a database to Yandex Data Processing
    • Searching for cluster performance issues
    • Performance analysis and tuning
    • Setting up a connection from a Serverless Containers container
    • Delivering data to Yandex Managed Service for Apache Kafka® using Yandex Data Transfer
    • Delivering data to Yandex Managed Service for YDB using Yandex Data Transfer
    • Delivering data to Yandex Managed Service for Apache Kafka® using Debezium
    • PostgreSQL change data capture and delivery to YDS
    • Delivering data from Yandex Managed Service for Apache Kafka® using Yandex Data Transfer
    • Transferring data from Yandex Object Storage using Yandex Data Transfer
    • Configuring a fault-tolerant architecture in Yandex Cloud
      • Overview
      • Management console
      • Terraform
    • Status monitoring of geographically distributed devices
    • Writing load balancer logs to PostgreSQL
    • Creating an MLFlow server for logging experiments and artifacts
    • Working with data using Query
    • Federated data queries using Query
    • Fixing string sorting issues after upgrading _glibc_
    • Writing data from a device into a database
  • Access management
  • Terraform reference
  • Monitoring metrics
  • Audit Trails events
  • Public materials
  • Release notes

In this article:

  • Get your cloud ready
  • Required paid resources
  • Create an infrastructure
  • Set up your VM environment
  • Configure Joomla
  • Test the website
  • How to delete the resources you created
  1. Tutorials
  2. Creating a Joomla website with a PostgreSQL database
  3. Terraform

Creating a Joomla website with a PostgreSQL database using Terraform

Written by
Yandex Cloud
Updated at May 7, 2025
  • Get your cloud ready
    • Required paid resources
  • Create an infrastructure
  • Set up your VM environment
  • Configure Joomla
  • Test the website
  • How to delete the resources you created

To create an infrastructure for your Joomla website with a PostgreSQL database using Terraform:

  1. Get your cloud ready.
  2. Create your infrastructure.
  3. Set up your VM environment.
  4. Configure Joomla.
  5. Test the website.

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

Get your cloud readyGet your cloud ready

Sign up in Yandex Cloud and create a billing account:

  1. Navigate to the management console and log in to Yandex Cloud or register 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 to operate in.

Learn more about clouds and folders.

Required paid resourcesRequired paid resources

The cost of hosting a Joomla-powered website includes:

  • Fee for a continuously running VM (see Yandex Compute Cloud pricing).
  • Fee for using a public IP address (see Yandex Virtual Private Cloud pricing).
  • Fee for a PostgreSQL DB cluster (see Yandex Managed Service for PostgreSQL pricing).
  • Fee for outbound traffic from Yandex Cloud to the internet (see Yandex Compute Cloud pricing).
  • Fee for public DNS queries and DNS zones (see Yandex Cloud DNS pricing).

Create an infrastructureCreate an infrastructure

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 documentation on the Terraform website or mirror website.

To create an infrastructure using Terraform:

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

  2. Prepare the infrastructure description file:

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

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

      • joomla-postgresql-terraform.tf: New infrastructure configuration.
      • joomla-postgresql-terraform.auto.tfvars: User data file.
    1. Create a folder for the infrastructure description file.

    2. In this folder, create the joomla-postgresql-terraform.tf configuration file:

      joomla-postgresql-terraform.tf
      # Declaring variables for custom parameters
      
      variable "folder_id" {
        type = string
      }
      
      variable "ssh_key_path" {
        type = string
      }
      
      variable "db_password" {
        type      = string
        sensitive = true
      }
      
      variable "domain_name" {
        type = string
      }
      
      # Adding other variables
      
      locals {
        network_name       = "joomla-network"
        subnet_name1       = "joomla-subnet-a"
        subnet_name2       = "joomla-subnet-b"
        subnet_name3       = "joomla-subnet-d"
        subnet_cidr1       = "192.168.2.0/24"
        subnet_cidr2       = "192.168.1.0/24"
        subnet_cidr3       = "192.168.3.0/24" 
        sg_vm_name         = "joomla-sg"
        sg_pgsql_name      = "postgresql-sg"
        vm_name            = "joomla-web-server"
        cluster_name       = "joomla-pg-cluster"
        db_name            = "joomla_db"
        dns_zone_name      = "joomla-zone"
        vm_user            = "yc-user"
        db_user            = "joomla"
        cert_name          = "joomla-cert"
      }
      
      # 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" "joomla-pg-network" {
        name = local.network_name
      }
      
      # Creating a subnet in the ru-central1-a availability zone
      
      resource "yandex_vpc_subnet" "joomla-pg-network-subnet-a" {
        name           = local.subnet_name1
        zone           = "ru-central1-a"
        v4_cidr_blocks = [local.subnet_cidr1]
        network_id     = yandex_vpc_network.joomla-pg-network.id
      }
      
      # Creating a subnet in the ru-central1-b availability zone
      
      resource "yandex_vpc_subnet" "joomla-pg-network-subnet-b" {
        name           = local.subnet_name2
        zone           = "ru-central1-b"
        v4_cidr_blocks = [local.subnet_cidr2]
        network_id     = yandex_vpc_network.joomla-pg-network.id
      }
      
      # Creating a subnet in the ru-central1-d availability zone
      
      resource "yandex_vpc_subnet" "joomla-pg-network-subnet-d" {
        name           = local.subnet_name3
        zone           = "ru-central1-d"
        v4_cidr_blocks = [local.subnet_cidr3]
        network_id     = yandex_vpc_network.joomla-pg-network.id
      }
      
      # Creating a security group for a PostgreSQL database cluster
      
      resource "yandex_vpc_security_group" "pgsql-sg" {
        name       = local.sg_pgsql_name
        network_id = yandex_vpc_network.joomla-pg-network.id
      
        ingress {
          description    = "port-6432"
          port           = 6432
          protocol       = "TCP"
          v4_cidr_blocks = [local.subnet_cidr2]
        }
      
        ingress {
          description       = "self"
          protocol          = "ANY"
          from_port         = 0
          to_port           = 65535
          predefined_target = "self_security_group"
        }
      
        egress {
          description    = "any"
          protocol       = "ANY"
          v4_cidr_blocks = ["0.0.0.0/0"]
          from_port      = 0
          to_port        = 65535
        }
      
      }
      
      # Creating a security group for a VM
      
      resource "yandex_vpc_security_group" "vm-sg" {
        name       = local.sg_vm_name
        network_id = yandex_vpc_network.joomla-pg-network.id
      
        egress {
          description    = "any"
          protocol       = "ANY"
          v4_cidr_blocks = ["0.0.0.0/0"]
          from_port      = 0
          to_port        = 65535
        }
      
        ingress {
          description    = "http"
          protocol       = "TCP"
          v4_cidr_blocks = ["0.0.0.0/0"]
          port           = 80
        }
      
        ingress {
          description    = "https"
          protocol       = "TCP"
          v4_cidr_blocks = ["0.0.0.0/0"]
          port           = 443
        }
      
        ingress {
          description    = "ssh"
          protocol       = "ANY"
          v4_cidr_blocks = ["0.0.0.0/0"]
          port           = 22
        }
      
        ingress {
          description       = "self"
          protocol          = "ANY"
          from_port         = 0
          to_port           = 65535
          predefined_target = "self_security_group"
        }
      }
      
      # Reserving a public IP address
      
      resource "yandex_vpc_address" "addr" {
        name = "joomla-address"
      
        external_ipv4_address {
          zone_id = "ru-central1-b"
        }
      }
      
      
      # Adding a prebuilt VM image
      
      resource "yandex_compute_image" "joomla-pg-vm-image" {
        source_family = "ubuntu-2404-lts-oslogin"
      }
      
      resource "yandex_compute_disk" "boot-disk" {
        name     = "bootvmdisk"
        type     = "network-hdd"
        zone     = "ru-central1-b"
        size     = "10"
        image_id = yandex_compute_image.joomla-pg-vm-image.id
      }
      
      # Creating a VM instance
      
      resource "yandex_compute_instance" "joomla-pg-vm" {
        name               = local.vm_name
        platform_id        = "standard-v3"
        zone               = "ru-central1-b"
      
        resources {
          cores         = 2
          memory        = 4
        }
      
        boot_disk {
          disk_id = yandex_compute_disk.boot-disk.id
        }
      
        network_interface {
          subnet_id          = yandex_vpc_subnet.joomla-pg-network-subnet-b.id
          nat                = true
          nat_ip_address     = yandex_vpc_address.addr.external_ipv4_address[0].address
          security_group_ids = [ yandex_vpc_security_group.vm-sg.id ]
        }
      
        metadata = {
          user-data = "#cloud-config\nusers:\n  - name: ${local.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 PostgreSQL database cluster
      
      resource "yandex_mdb_postgresql_cluster" "joomla-pg-cluster" {
        name                = local.cluster_name
        environment         = "PRODUCTION"
        network_id          = yandex_vpc_network.joomla-pg-network.id
        security_group_ids  = [ yandex_vpc_security_group.pgsql-sg.id ]
      
        config {
          version = "17"
          resources {
            resource_preset_id = "b2.medium"
            disk_type_id       = "network-ssd"
            disk_size          = 10
          }
        }
      
        host {
          zone      = "ru-central1-a"
          subnet_id = yandex_vpc_subnet.joomla-pg-network-subnet-a.id
        }
      
        host {
          zone      = "ru-central1-b"
          subnet_id = yandex_vpc_subnet.joomla-pg-network-subnet-b.id
        }
      
        host {
          zone      = "ru-central1-d"
          subnet_id = yandex_vpc_subnet.joomla-pg-network-subnet-d.id
        }
      }
      
      # Creating a database
      
      resource "yandex_mdb_postgresql_database" "joomla-pg-tutorial-db" {
        cluster_id = yandex_mdb_postgresql_cluster.joomla-pg-cluster.id
        name       = local.db_name
        owner      = local.db_user
      }
      
      # Creating a database user
      
      resource "yandex_mdb_postgresql_user" "joomla-user" {
        cluster_id = yandex_mdb_postgresql_cluster.joomla-pg-cluster.id
        name       = local.db_user
        password   = var.db_password
      }
      
      # Creating a DNS zone
      
      resource "yandex_dns_zone" "joomla-pg" {
        name    = local.dns_zone_name
        zone    = "${var.domain_name}."
        public  = true
      }
      
      # Adding a Let's Encrypt certificate
      
      resource "yandex_cm_certificate" "le-certificate" {
        name    = local.cert_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.le-certificate.managed[0].challenge_count
        zone_id = yandex_dns_zone.joomla-pg.id
        name    = yandex_cm_certificate.le-certificate.challenges[count.index].dns_name
        type    = yandex_cm_certificate.le-certificate.challenges[count.index].dns_type
        ttl     = 600
        data    = [yandex_cm_certificate.le-certificate.challenges[count.index].dns_value]
      }
      
      # Creating a type A resource record
      
      resource "yandex_dns_recordset" "joomla-pg-a" {
        zone_id = yandex_dns_zone.joomla-pg.id
        name    = "${yandex_dns_zone.joomla-pg.zone}"
        type    = "A"
        ttl     = 600
        data    = [ yandex_compute_instance.joomla-pg-vm.network_interface.0.nat_ip_address ]
      }
      
    3. Create the joomla-postgresql-terraform.auto.tfvars user data file:

      joomla-postgresql-terraform.auto.tfvars
      folder_id          = "<folder_ID>"
      ssh_key_path       = "<path_to_public_SSH_key>"
      db_password        = "<DB_password>"
      domain_name        = "<domain_name>"
      

    For more information about the properties of Terraform resources, see the relevant Terraform guides:

    • Network: yandex_vpc_network.
    • Subnets: yandex_vpc_subnet.
    • Security groups: yandex_vpc_security_group.
    • VM image: yandex_compute_image.
    • Disk: yandex_compute_disk.
    • VM instance: yandex_compute_instance.
    • PostgreSQL cluster: yandex_mdb_postgresql_cluster.
    • PostgreSQL database: yandex_mdb_postgresql_database.
    • Database user: yandex_mdb_postgresql_user.
    • DNS zone: yandex_dns_zone.
    • DNS resource record: yandex_dns_recordset.
    • TLS certificate: yandex_cm_certificate.
  3. In the joomla-postgresql-terraform.auto.tfvars file, set the following user-defined properties:

    • folder_id: Folder ID.

    • ssh_key_path: Path to the public SSH key required to authenticate the user on the VM. For more information, see Creating an SSH key pair.

    • db_password: DB password (8 to 128 characters).

    • domain_name: Domain name. Specify your registered domain name delegated to Yandex Cloud DNS, e.g., example.com.

      To get access to public zone domain names, you need to delegate the domain. Specify the addresses of the ns1.yandexcloud.net and ns2.yandexcloud.net servers in your account on your domain name registrar's website.

  4. Create the resources:

    1. In the terminal, change to the folder where you edited the configuration file.

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

      terraform validate
      

      If the configuration is correct, the following message is returned:

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

      terraform plan
      

      The terminal will display a list of resources with parameters. No changes are made at this step. If the configuration contains errors, Terraform will point them out.

    4. Apply the configuration changes:

      terraform apply
      
    5. Confirm the changes: type yes in the terminal and press Enter.

After creating the infrastructure, install Joomla.

Set up your VM environmentSet up your VM environment

At this step, you will prepare the VM environment to deploy and set up Joomla.

  1. Export the joomla-cert TLS certificate to your local computer:

    Management console
    1. In the management console, select the folder to create your infrastructure in.
    2. In the list of services, select Certificate Manager and choose joomla-cert.
    3. In the top panel, click Export certificate, select Certificate without private key, and click Download certificate. A file with the certificate.pem certificate will be saved to your computer.
    4. Repeat the previous step and download the private key by selecting Private key only. Rename the downloaded private key file to private_key.pem.
    5. Save the downloaded certificate.pem and private_key.pem files: you will need them to configure the web server.
  2. Copy the certificate and private key to the VM:

    scp ./certificate.pem yc-user@<VM_IP_address>:certificate.pem \
      && scp ./private_key.pem yc-user@<VM_IP_address>:private_key.pem
    

    Where <VM_IP_address> is the public IP address of the previously created joomla-web-server VM.

    You can find the VM IP address in the management console on the VM page under Network.

    If this is your first time connecting to the VM, you will get this unknown host warning:

    The authenticity of host '51.250.**.*** (51.250.**.***)' can't be established.
    ED25519 key fingerprint is SHA256:PpcKdcT09gjU045pkEIwIU8lAXXLpwJ6bKC********.
    This key is not known by any other names
    Are you sure you want to continue connecting (yes/no/[fingerprint])?
    

    Type yes into the terminal and press Enter.

  3. Connect to the VM over SSH:

    ssh yc-user@<VM_IP_address>
    
  4. Create a directory for the certificate and move the copied files there:

    sudo mkdir /etc/ssl-certificates
    sudo mv certificate.pem /etc/ssl-certificates/
    sudo mv private_key.pem /etc/ssl-certificates/
    
  5. Upgrade the versions of the packages installed on the VM:

    sudo apt update && sudo apt upgrade -y
    
  6. Install and run the Apache HTTP server:

    sudo apt install apache2
    sudo systemctl start apache2 && sudo systemctl enable apache2
    
  7. Install PHP with the required libraries:

    sudo apt install php libapache2-mod-php php-common php-pgsql php-xml php-mbstring php-curl php-zip php-intl php-json unzip
    
  8. Download and unpack the Joomla package:

    Note

    This example uses a link to Joomla 5.2.4, the latest version at the time of writing this guide. To check for a newer version and get the download link, visit the project website.

    wget https://downloads.joomla.org/cms/joomla5/5-2-4/Joomla_5-2-4-Stable-Full_Package.zip -O Joomla.zip
    sudo rm /var/www/html/index.html
    sudo unzip Joomla.zip -d /var/www/html
    rm Joomla.zip
    
  9. Set up access permissions for the website directory:

    sudo chown -R www-data:www-data /var/www/html
    sudo chmod -R 755 /var/www/html
    
  10. Change the number of the default port used by Joomla to access PostgreSQL databases: Yandex Managed Service for PostgreSQL uses port 6432.

    1. Open the Joomla database access driver configuration file:

      sudo nano /var/www/html/libraries/vendor/joomla/database/src/Pdo/PdoDriver.php
      
    2. In the file, find the section with PostgreSQL database settings and change the port number from 5432 to 6432:

      ...
      case 'pgsql':
      $this->options['port'] = $this->options['port'] ?? 6432;
      ...
      

      Make sure to save your changes.

  11. Configure a virtual host for your website:

    1. Create a virtual host configuration file:

      sudo nano /etc/apache2/sites-available/joomla.conf
      
    2. Add the following configuration into the file:

      <VirtualHost *:80>
          ServerAdmin admin@localhost
          DocumentRoot /var/www/html
          ServerName <domain_name>
      
          <Directory /var/www/html>
              Options FollowSymLinks
              AllowOverride All
              Require all granted
          </Directory>
      
          ErrorLog ${APACHE_LOG_DIR}/joomla_http_error.log
          CustomLog ${APACHE_LOG_DIR}/joomla_http_access.log combined
      </VirtualHost>
      
      <VirtualHost *:443>
          ServerAdmin admin@localhost
          DocumentRoot /var/www/html
          ServerName <domain_name>
      
          ErrorLog ${APACHE_LOG_DIR}/joomla_ssl_error.log
          CustomLog ${APACHE_LOG_DIR}/joomla_ssl_access.log combined
      
          SSLEngine on
          SSLCertificateFile /etc/ssl-certificates/certificate.pem
          SSLCertificateChainFile /etc/ssl-certificates/certificate.pem
          SSLCertificateKeyFile /etc/ssl-certificates/private_key.pem
      </VirtualHost>
      

      Where <domain_name> is the domain name of your website, e.g., example.com.

  12. Activate the virtual host and restart the web server:

    sudo a2ensite joomla.conf
    sudo a2enmod rewrite
    sudo a2enmod ssl
    sudo systemctl restart apache2
    

Configure JoomlaConfigure Joomla

  1. Get the Managed Service for PostgreSQL cluster host names (you will need them when installing Joomla):

    Management console
    1. In the management console, select the folder with the cluster. From the list of services, select Managed Service for PostgreSQL.
    2. Select the joomla-pg-cluster cluster and open the Hosts tab.
    3. Hover over the Host FQDN field in the row with each host and click to copy the host FQDN. Save the values you copied, as you will need them later.
  2. Install and configure Joomla:

    1. Open the Joomla setup wizard in your browser. At this step, you can access it using any of these addresses:

      • http://<VM_public_IP_address>
      • http://<your_domain_name>
      • https://<your_domain_name>
    2. When configuring database parameters, fill in the following fields:

      • Database type: PostgreSQL (PDO).

      • Host name:

        <host_1_name>,<host_2_name>,<host_3_name>
        

        Where <host_1_name>, <host_2_name>, and <host_3_name> are the Managed Service for PostgreSQL cluster host FQDNs you copied at the previous step.

      • Database username: joomla.

      • Database user password: DB user password set when creating the PostgreSQL cluster.

      • Database name: joomla_db.

      • Connection encryption: Keep the default value.

    3. Joomla may prompt you to create or delete a specific test file in the product installation directory on the VM for security purposes. Navigate to the /var/www/html/installation/ directory and create or delete the specified file there:

      You are trying to connect to a database host that is not available on 
      your local server. You need to verify ownership of the hosting 
      account. Read the information provided on the **Secure 
      installation procedure** page.
      
      To verify your ownership of the website, delete 
      `_JoomlazUZKusLnD2jXi********.txt` from the `installation` directory and click 
      **Install Joomla** to continue.
      
  3. After installation is complete, delete the installation directory from the VM. This is a Joomla security requirement:

    sudo rm -rf /var/www/html/installation
    

If you encounter any issues while installing Joomla, use this guide on the project website.

Test the websiteTest the website

After Joomla installation is complete, enter your website’s IP address or domain name in the browser to test the site:

  • http://<VM_public_IP_address>
  • http://example.com
  • https://example.com

Now you can further configure your website and add content using the Joomla admin interface and tools.

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

To shut down the website and stop paying for the resources you created:

  1. Open the joomla-postgresql-terraform.tf configuration file and delete your infrastructure description from it.

  2. Apply the changes:

    1. In the terminal, change to the folder where you edited the configuration file.

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

      terraform validate
      

      If the configuration is correct, the following message is returned:

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

      terraform plan
      

      The terminal will display a list of resources with parameters. No changes are made at this step. If the configuration contains errors, Terraform will point them out.

    4. Apply the configuration changes:

      terraform apply
      
    5. Confirm the changes: type yes in the terminal and press Enter.

See alsoSee also

  • Creating a Joomla website with a PostgreSQL database using the management console

Was the article helpful?

Previous
Management console
Next
Status monitoring of geographically distributed devices
© 2025 Direct Cursus Technology L.L.C.