Blog post – Implementation

This blog post shows the first steps I took to spinning up a secure virtual machine instance, which will be used to host a secure web form. This isn’t the full end-to-end implementation, but just my journey on what I am learning along the way. The form itself will be running a self-hosted version of Formbricks, behind a Traefik reverse proxy, and running on a free-tier Google Cloud e2-micro virtual machine.

Setup of the VM on Google Cloud

I kept getting a “billing account not found” error that was blocking me from setting up a Google Cloud virtual machine instance. This was because the VM required that I create and link a billing account to the project. After adding a credit card, I was now allowed to provision a virtual machine for the project.

The instance was named instance-20260615-005936, and I chose an e2-micro machine (2 vCPU shared core, 1 GB RAM), as opposed to the default e2-medium, so that it would remain free. The region chosen was us-central1 (Iowa) region, which is also eligible for the free-tier.

The OS chosen was Debian GNU/Linux 12 (bookworm). I also set the boot disk type to Standard persistent disk to keep costs low, and increased the HDD size to 30 GB (which was still within free limits). I also removed the default snapshot schedule as well (lowering cost).

For networking, I selected both HTTP and HTTPS options to allow for redirecting HTTP requests to HTTPS via Traefik.

I opted to not install the Ops Agent to avoid further charges.

I also changed the settings so that the external IP became static as opposed to ephemeral. This is because by default, Google cloud VMS reserve ephemeral external IP addresses, meaning it can change if you ever stop and restart the VM machine. That’s a problem, because for the reverse proxy to work, I need to have a DNS record pointing to the IP address of the instance, and if this were to change periodically, the DNS record would point to nothing. Reserving the external IP address to static makes it permanent to this project, even if the VM were to restart or stop. For a public facing form, this step is necessary.

Installing Docker

These are the commands I ran on the fresh VM, with an explanation of what each one does.

First, I updated existing packages:

  • sudo apt update && sudo apt upgrade -y

This refreshes Debian’s list of available packages and updates the installed ones. These two scripts are standard whenever you want to make a change to a linux system. These two scripts downloads the latest versions of installed packages, and installs these newer versions. Important for things such as fetching security patches.

Next, I installed the prerequisites:

  • sudo apt install -y ca-certificates curl

This installs two prerequisites for the Docker

I then added the script to allow official and verified downloads from Docker

  • sudo install -m 0755 -d /etc/apt/keyrings
  • sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
  • sudo chmod a+r /etc/apt/keyrings/docker.asc

I added Docker’s official repository to the list of places to install software from. This also uses the signing key we created above.

  • sudo tee /etc/apt/sources.list.d/docker.sources <<EOF Types: deb URIs: https://download.docker.com/linux/debian Suites: $(. /etc/os-release && echo “$VERSION_CODENAME”) Components: stable Architectures: $(dpkg –print-architecture) Signed-By: /etc/apt/keyrings/docker.asc EOF

Then I installed Docker itself

  • sudo apt update
  • sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

After Docker, I added swap memory:

  • sudo fallocate -l 2G /swapfile
  • sudo chmod 600 /swapfile
  • sudo mkswap /swapfile
  • sudo swapon /swapfile
  • echo ‘/swapfile none swap sw 0 0’ | sudo tee -a /etc/fstab

The free tier only has 1 GB of RAM, so I enabled 2 GB of swap to use the disk as backup memory in case Formbricks needs more. For context, formbricks requires 2GB ram, and our free cloud virtual machine has just 1. Hopefully 2GB swap will be enough for our needs of serving a static secure form.

Finally, I set up a public DNS hostname via DuckDNS which will point to the VM’s static IP. This is required for our reverse proxy Traefik.

The next steps will be installing and configuring the reverse proxy, and Formbricks instance, and verify that it works.

 

 

References

 

[1] Docker, “Install Docker Engine on Debian,” Docker Inc. [Online]. Available: https://docs.docker.com/engine/install/debian/. [Accessed: Jun. 6, 2026].

[2] Google Cloud, “Create and start a Compute Engine instance,” Google. [Online]. Available: https://docs.cloud.google.com/compute/docs/instances/create-start-instance. [Accessed: Jun. 6, 2026].

[3] Formbricks, “Self-hosting overview,” Formbricks. [Online]. Available: https://formbricks.com/docs/self-hosting/overview. [Accessed: Jun. 10, 2026].

[4] L. Tesar, “Create a Linux swap file,” Linuxize. [Online]. Available: https://linuxize.com/post/create-a-linux-swap-file/. [Accessed: Jun. 11, 2026].

[5] Formbricks, “Docker setup,” Formbricks. [Online]. Available: https://formbricks.com/docs/self-hosting/setup/docker. [Accessed: Jun. 13, 2026].

 

Leave a Reply

Your email address will not be published. Required fields are marked *