Skip to main content

Deploying a Web Server on UpCloud using Terraform Modules

In my earlier post, I shared an example of deploying UpCloud infrastructure using Terraform from scratch. In this post, I want to share how to deploy the infrastructure using available Terraform modules to speed up the set-up process, especially for common use cases like preparing a web server.

For instance, our need is to deploy a website with some conditions as follows.

  • The website can be accessed through HTTPS. If the request is HTTP, it will be redirected to HTTPS.
  • There are 2 domains, web1.yourdomain.com and web2.yourdomain.com. But, users should be redirected to "web2" if they are visiting "web1".

There are 4 main modules that we need to set up the environment.

  1. Private network. It allows the load balancer to connect with the server and pass the traffic.
  2. Server. It is used to host the website.
  3. Load balancer. It includes backend and frontend configuration.
  4. Dynamic certificate. It is required to allow an HTTPS connection.

Before we configure the main modules. We should set some variables used in the configuration in the variables.tf file. Then, we create a terraform.tfvars file that contains the values for those variables.

# variables.tf
variable "upcloud_username" {
  description = "UpCloud username"
  type = string
}

variable "upcloud_password" {
  description = "UpCloud password"
  type = string
}

variable "zone" {
  description = "UpCloud zone"
  type = string
  default = "sg-sin1"
}

variable "public_keys" {
    description = "List of public keys for server access"
    type = list(string)
}

# terraform.tfvars
upcloud_username = "xxx"
upcloud_password = "xxx"
zone = "sg-sin1"
public_keys = [ 
    "ssh-ed25519 AAAAxxx",
    "ssh-ed25519 AAAAxxx"
]

Firstly, we set up the private network as the code below.

# main.tf
provider "upcloud" {
  username = var.upcloud_username
  password = var.upcloud_password
}

module "private_network" {
  source  = "lukibsubekti/network-private/upcloud"
  version = "1.0.2"

  router_name = "my-router"
  network_name = "my-network"
  zone = var.zone
  network = {
    subnet = "10.0.10.0/24"
    is_dhcp = true
    family = "IPv4"
    is_dhcp_default_route = false
    gateway_address = "10.0.10.1"
  }
}

Next, we set up the web server. In this example, we just run an Nginx server which will host a default HTML page on port 80. The login method uses public keys.

# main.tf
module "web_server" {
  source  = "lukibsubekti/web-server/upcloud"
  version = "1.0.1"

  zone = var.zone
  hostname = "my-web-server"
  plan = "DEV-1xCPU-2GB"
  os = "ubuntu-22.04"
  private_network = {
    network_id = module.private_network.network_id
    ip_address = "10.0.10.123"
  }
  login = {
    send_password = "none"
    keys = var.public_keys
  }
  user_data = <<-EOF
    #!/bin/bash
    sudo apt-get update
    sudo apt-get install -y nginx
    EOF
}

Now, we configure the load balancer. We define a single backend server and several frontend rules to direct or serve requests based on conditions we set.

# main.tf
locals {
  web1 = "web1.yourdomain.com"
  web2 = "web2.yourdomain.com"
}

module "loadbalancer" {
  source  = "lukibsubekti/loadbalancer-static/upcloud"
  version = "1.0.2"

  zone = var.zone
  name = "my-loadbalancer"
  private_network = {
    name = "private-net"
    id = module.private_network.network_id
  }

  backends = {
    "my-website" = [
      {
        ip = module.web_server.networks.private.ip_address
        port = 80
      }
    ]
  }

  frontends = {
    "my-http" = {
      mode = "http"
      port = 80
      default_backend = "my-website"
    }
    "my-https" = {
      mode = "http"
      port = 443
      default_backend = "my-website"
    }
  }

  rules = {
    # redirect HTTP traffic to HTTPS
    "my-rule1" = {
      frontend = "my-http"
      priority = 100
      matching_condition = "or"
      matchers = {
        request_header = [
          {
            method = "starts"
            name = "Host"
            value = local.web1
            ignore_case = true
          },
          {
            method = "starts"
            name = "Host"
            value = local.web2
            ignore_case = true
          }
        ]
      }
      actions = {
        http_redirect = {
            scheme = "https"
        }
        set_forwarded_headers = {
          active = true
        }
      }
    }

    # redirect HTTPS traffic from web1 to web2
    "my-rule2" = {
      frontend = "my-https"
      priority = 90
      matchers = {
        request_header = [
          {
            method = "starts"
            name = "Host"
            value = local.web1
            ignore_case = true
          }
        ]
      }
      actions = {
        http_redirect = {
            location = "https://${local.web2}"
        }
        set_forwarded_headers = {
          active = true
        }
      }
    }

    # handle HTTPS traffic for web2
    "my-rule3" = {
      frontend = "my-https"
      priority = 80
      matchers = {
        request_header = [
          {
            method = "starts"
            name = "Host"
            value = local.web2
            ignore_case = true
          }
        ]
      }
      actions = {
        use_backend = {
            backend_name = "my-website"
        }
        set_forwarded_headers = {
          active = true
        }
      }
    }
  }
}

We also need to output some values including the server IP address and the load balancer DNS name. We set it in output.tf file.

# output.tf
output "server_networks" {
  value = module.web_server.networks
  description = "Server networks"
}

output "loadbalancer_networks" {
  value = module.loadbalancer.networks_map
  description = "Load balancer networks"
}

Before we can configure the dynamic certificate, we should apply the current configuration to get the load balancer DNS name which will be added to our DNS record. It is necessary so that the certificate can be verified and generated by the certificate provider.

Initialize the module and apply the configuration.

terraform init
terraform apply

The server IP address

The public DNS name of the load balancer

Updated DNS record for our domain

After the DNS record is updated. We can apply the dynamic certificate configuration.

# main.tf
module "certs" {
    source = "lukibsubekti/certs-dynamic/upcloud"
    version = "1.0.0"

    name = "my-certs"
    hostnames = [
        local.web1,
        local.web2
    ]
    frontend_id = module.loadbalancer.frontends_map["my-https"].id
}

Reinitialize the module and apply the updated configuration.

terraform init
terraform apply

The certificate is verified

Lastly, we can verify the result by visiting http://web1.yourdomain.com that will be redirected to https://web2.yourdomain.com.

Comments

  1. Everyone knows Matty Boy as the guy who laughs the loudest at his own jokes, but somehow, that’s what makes them funny. His energy is contagious.

    ReplyDelete
  2. Born from a passion for clean lines and confident energy, Kroen represents a new generation of fashion that values both comfort and identity.

    ReplyDelete
  3. HMDD collects and organizes experimental data from scientific publications, making it easier to explore verified miRNA–disease associations. This helps bridge the gap between molecular biology and clinical research.

    ReplyDelete
  4. Fondée il y a plusieurs décennies, Davril a commencé comme un petit atelier familial. Au fil des ans, la marque a su évoluer tout en conservant ses méthodes traditionnelles de fabrication. Aujourd’hui, Davril est présente dans de nombreux pays et continue d’innover dans le domaine de la chaussure haut de gamme.

    ReplyDelete
  5. The design philosophy behind Akimbo hoodies revolves around versatility and self-expression. Unlike standard hoodies, Akimbo pieces often incorporate oversized fits, asymmetric cuts, and unexpected details like contrasting panels, zippers, or graphic prints. This approach allows wearers to make a statement while remaining comfortable, aligning with the modern trend of functional fashion that’s also visually striking.

    ReplyDelete
  6. In Islamic cosmology, the Seven Heavens are described as seven layers above the earthly realm, each inhabited by angels and sacred beings. The Qur’an mentions these heavens as part of God’s creation, with each level having unique characteristics. Similarly, in Judaic tradition, references to seven heavens appear in mystical texts such as the Talmud and Kabbalah, portraying ascending levels of spiritual experience.

    ReplyDelete
  7. Their mission is to offer luxury fragrances that blend traditional Arabian scents with modern appeal, making them accessible to a global audience.

    ReplyDelete
  8. One of the defining characteristics of Chrome Hearts hoodies is their use of high-quality fabrics. Most hoodies are crafted from heavyweight cotton or cotton-blend materials, ensuring durability, comfort, and a luxurious feel.

    ReplyDelete
  9. At the core of every Pokémon Center is the Pokémon Healing Machine, typically operated by the nurses, most famously Nurse Joy.

    ReplyDelete
  10. Mr. Winston exhibited a fascination with the metaphysical. Growing up surrounded by books on philosophy, religion, and ancient wisdom, he quickly developed an intuition for mystical traditions across cultures.

    ReplyDelete
  11. No visit to London is complete without seeing its famous landmarks. The historic Tower of London, the majestic Buckingham Palace, and the striking Big Ben clock tower are essential stops. Modern icons like The Shard and the London Eye offer panoramic views of the city, combining historical significance with contemporary architecture. These landmarks are not just tourist attractions—they reflect the city’s rich cultural heritage and dynamic evolution.

    ReplyDelete
  12. The black hue lends the piece versatility, allowing it to pair seamlessly with a range of outfits—from distressed jeans to tailored trousers. Its aesthetic is simultaneously raw and refined, appealing to those who seek an edge in everyday fashion.

    ReplyDelete
  13. Nazwa „Stone Island” ‒ kamienna wyspa ‒ zostaÅ‚a zaczerpniÄ™ta przez Ostiego od literatury Josepha Conrada, której motywy – morza, statków, żywiołów morskich – mocno wpÅ‚ynęły na estetykÄ™ marki.

    ReplyDelete
  14. Beyond just a visual motif, the spider imagery symbolizes connection, creativity, and the interwoven nature of culture, music, and community.

    ReplyDelete
  15. Comme des Garçons began to gain a strong cult following in Japan, especially among young consumers who were drawn to its deconstructed, monochrome, and sometimes “anti-fashion” aesthetic.

    ReplyDelete
  16. Murakami has extended his artistic vision into the realm of fashion through various collaborations and his own clothing lines, creating an intersection between art and wearability.

    ReplyDelete
  17. Honestly, the quality of Trapstar pieces has surprised me—in a good way. I thought it might be just hype at first, but the materials, stitching, and fit are actually on point. I bought one of their jackets last winter, and it's still in top condition after tons of wear. Definitely worth the investment if you care about durability and style.

    ReplyDelete
  18. Honestly, I like some of the designs, but the price point can be a bit much. I understand the exclusivity aspect and the brand value that Kanye brings, but it feels like a stretch to pay over $100 for a basic tee with a logo. That said, the resell value is wild, so it’s hard to argue with the hype.

    ReplyDelete
  19. I love how the God Speed Hoodie merges comfort and creativity. The fabric is soft and warm, ideal for any season, while the artwork and logo placement feel intentional and meaningful.

    ReplyDelete
  20. Kapital’s aesthetic is definitely not for everyone, but that’s what makes it special. It’s rebellious, raw, and unapologetically different.

    ReplyDelete
  21. Honestly, I never thought a hat could be this versatile until I tried the Lover Boy Hat. Whether you’re dressing up for a casual day out or aiming for a more polished look, this hat fits seamlessly into so many different styles.

    ReplyDelete
  22. Trapstar hoodies are more than just fashion they represent a movement and culture. The designs are bold yet minimal, and that iconic "It's a Secret" branding just hits different.

    ReplyDelete
  23. What makes Civil Regime stand out to me is the emotion behind their collections. The mix of luxury fashion elements with underground street culture gives their clothes a very distinct personality. You can tell there’s thought behind every design, and that’s why their fans connect with the brand on a deeper level.

    ReplyDelete
  24. Lattafa has quickly risen to become synonymous with luxury, elegance, and affordability. Based in the United Arab Emirates, Lattafa Perfumes has carved a niche for itself by offering high-quality, long-lasting fragrances that rival some of the most expensive designer brands

    ReplyDelete
  25. In the realm of underground hip-hop, few labels have carved out a niche as distinctive and dedicated as G59 Records (short for GREY59). Co-founded by the New Orleans-based rap duo $uicideboy$, the label has become a cultural force in both music and fashion.

    ReplyDelete
  26. Takashi Murakami, the acclaimed Japanese contemporary artist, has captivated the world not only with his vibrant, anime-inspired artworks but also with his foray into fashion. Known for blending traditional Japanese art techniques with bold pop culture imagery, Murakami has become a major force in the fashion world, pushing the boundaries of wearable art.

    ReplyDelete
  27. In a world increasingly shaped by fast fashion and mass production, Ensemble Vrunk emerges as a radical departure — a movement that challenges conventions and embraces bold, eclectic aesthetics. Combining the disciplines of fashion, art, and sustainability, Ensemble Vrunk has quickly carved a niche for itself in the modern sartorial landscape.

    ReplyDelete
  28. The Sp5der Store is now a go-to destination for fans of bold fashion statements, mixing high-end streetwear aesthetics with underground influence.

    ReplyDelete
  29. Eme Studios is a contemporary streetwear brand based in Madrid, Spain, known for fusing minimal aesthetics with deeper conceptual messages. Founded in 2018, the brand positions itself as more than just fashion: it strives to create wearable art that tells stories, challenges norms, and builds a community around values.

    ReplyDelete
  30. Cough syrups typically contain two active ingredients: dextromethorphan (DXM), a cough suppressant, and promethazine with codeine, an opioid, in some prescription formulations. When used as directed, these ingredients can effectively reduce coughing and aid sleep. However, in high doses, both can produce psychoactive effects.

    ReplyDelete
  31. In the modern streetwear scene, few brands have generated as much mystique and buzz as Corteiz (often stylized as CRTZ or misspelled as “Cortiez”). What began as a small, underground label has grown into a cultural phenomenon

    ReplyDelete
  32. In the rapidly evolving world of fashion, few brands have created as much buzz and loyal following in such a short span as Corteiz (often stylized as “Crtz”). Emerging from the streets of London, this underground label has grown into a cultural force, thanks to its authenticity, exclusivity, and a strong connection with youth culture.

    ReplyDelete
  33. Kanye West, a name synonymous with innovation and controversy in both music and fashion, has consistently pushed the boundaries of style. Among his many iconic fashion pieces, the Kanye West pullover has emerged as a quiet yet powerful symbol of modern streetwear.

    ReplyDelete

Post a Comment

Popular posts from this blog

Rangkaian Sensor Infrared dengan Photo Dioda

Keunggulan photodioda dibandingkan LDR adalah photodioda lebih tidak rentan terhadap noise karena hanya menerima sinar infrared, sedangkan LDR menerima seluruh cahaya yang ada termasuk infrared. Rangkaian yang akan kita gunakan adalah seperti gambar di bawah ini. Pada saat intensitas Infrared yang diterima Photodiode besar maka tahanan Photodiode menjadi kecil, sedangkan jika intensitas Infrared yang diterima Photodiode kecil maka tahanan yang dimiliki photodiode besar. Jika  tahanan photodiode kecil  maka tegangan  V- akan kecil . Misal tahanan photodiode mengecil menjadi 10kOhm. Maka dengan teorema pembagi tegangan: V- = Rrx/(Rrx + R2) x Vcc V- = 10 / (10+10) x Vcc V- = (1/2) x 5 Volt V- = 2.5 Volt Sedangkan jika  tahanan photodiode besar  maka tegangan  V- akan besar  (mendekati nilai Vcc). Misal tahanan photodiode menjadi 150kOhm. Maka dengan teorema pembagi tegangan: V- = Rrx/(Rrx + R2) x Vcc V- = 150 / (1...

What's Good About Strapi, a Headless CMS

Recently, I've been revisiting Strapi as a solution for building backend systems. I still think this headless CMS can be quite useful in certain cases, especially for faster prototyping or creating common websites like company profiles or e-commerce platforms. It might even have the potential to handle more complex systems. With the release of version 5, I'm curious to know what updates it brings. Strapi has launched a new documentation page, and it already feels like an improvement in navigation and content structure compared to the previous version. That said, there's still room for improvement, particularly when it comes to use cases and best practices for working with Strapi. In my opinion, Strapi stands out with some compelling features that could catch developers' attention. I believe three key aspects of Strapi offer notable advantages. First, the content-type builder feature lets us design the data structure of an entity or database model, including field ...

Configuring Swap Memory on Ubuntu Using Ansible

If we maintain a Linux machine with a low memory capacity while we are required to run an application with high memory consumption, enabling swap memory is an option. Ansible can be utilized as a helper tool to automate the creation of swap memory. A swap file can be allocated in the available storage of the machine. The swap file then can be assigned as a swap memory. Firstly, we should prepare the inventory file. The following snippet is an example, you must provide your own configuration. [server] 192.168.1.2 [server:vars] ansible_user=root ansible_ssh_private_key_file=~/.ssh/id_rsa Secondly, we need to prepare the task file that contains not only the tasks but also some variables and connection information. For instance, we set /swapfile  as the name of our swap file. We also set the swap memory size to 2GB and the swappiness level to 60. - hosts: server become: true vars: swap_vars: size: 2G swappiness: 60 For simplicity, we only check the...

Free Cloud Services from UpCloud

Although I typically deploy my development environment or experimental services on UpCloud , I do not always stay updated on its announcements. Recently, I discovered that UpCloud has introduced a new plan called the Essentials plan, which enables certain cloud services to be deployed at no cost. The complimentary services are generally associated with network components or serve as the foundation for other cloud services. This feature is particularly useful when retaining foundational services, such as a load balancer, is necessary, while tearing down all services and reconfiguring the DNS and other application settings each time we temporarily clean up infrastructure to reduce costs is undesirable.  When reviewing the service specifications of the cloud services in the Essentials plan, they appear to be very similar to those in the Development plan. The difference in service levels is unclear, but it could be related to hardware or resource allocation. For instance, the loa...

Increase of Malicious Activities and Implementation of reCaptcha

In recent time, I've seen the increase of malicious activities such as login attempts or phishing emails to some accounts I manage. Let me list some of them and the actions taken. SSH Access Attempts This happened on a server that host a Gitlab server. Because of this case, I started to limit the incoming traffic to the server using internal and cloud firewall provided by the cloud provider. I limit the exposed ports, connected network interfaces, and allowed protocols. Phishing Attempts This typically happened through email and messaging platform such as Whatsapp and Facebook Page messaging. The malicious actors tried to share a suspicious link lured as invoice, support ticket, or something else. Malicious links shared Spammy Bot The actors leverage one of public endpoint on my website to send emails. Actually, the emails won't be forwarded anywhere except to my own email so this just full my inbox. This bot is quite active, but I'm still not sure what...

Deliver SaaS According Twelve-Factor App

If you haven't heard of  the twelve-factor app , it gives us a recommendation or a methodology for developing SaaS or web apps structured into twelve items. The recommendation has some connections with microservice architecture and cloud-native environments which become more popular today. We can learn the details on its website . In this post, we will do a quick review of the twelve points. One Codebase Multiple Deployment We should maintain only one codebase for our application even though the application may be deployed into multiple environments like development, staging, and production. Having multiple codebases will lead to any kinds of complicated issues. Explicitly State Dependencies All the dependencies for running our application should be stated in the project itself. Many programming languages have a kind of file that maintains a list of the dependencies like package.json in Node.js. We should also be aware of the dependencies related to the pla...