diff --git a/docs/README.md b/docs/README.md index e45e71f61..6f0a60d3a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -102,10 +102,13 @@ product documentation, organized as follows: - [swift/](../swift/apple): macOS / iOS clients. - [kotlin/](../kotlin/android): Android / ChromeOS clients. - [website/](../website): Marketing website and product documentation. -- [terraform/](../terraform): Terraform files for our cloud infrastructure: +- [terraform/](../terraform): Terraform files for various example deployments. + - [terraform/examples/gcp/nat_gateway](../terraform/examples/gcp/nat_gateway): + Example Terraform configurations for deploying a cluster of Firezone + gateways behind a NAT gateway on GCP with single egress IP. - [terraform/modules/gateway-google-cloud-compute](../terraform/modules/gateway-google-cloud-compute): - Example Terraform module for deploying a Gateway to a Google Compute - Regional Instance Group. + Production-ready Terraform module for deploying regional Firezone gateways + to Google Cloud Compute. ## Quickstart diff --git a/terraform/.gitignore b/terraform/.gitignore index 71d78fdda..c091d9e6c 100644 --- a/terraform/.gitignore +++ b/terraform/.gitignore @@ -1,7 +1,8 @@ # Ignore Terraform state and temporary files -.terraform -*.tfstate.backup -terraform.tfstate.d +**/.terraform +**/*.tfstate.backup +**/terraform.tfstate.d +**/terraform.tfvars out.plan # Don't ever commit these files to git diff --git a/terraform/examples/README.md b/terraform/examples/README.md new file mode 100644 index 000000000..c4327532b --- /dev/null +++ b/terraform/examples/README.md @@ -0,0 +1,16 @@ +# Terraform Examples + +This directory contains examples of how to use Terraform to deploy Firezone +Gateways to your infrastructure. + +## Examples + +Each example below is self-contained and includes a `README.md` with +instructions on how to deploy the example. + +### Google Cloud Platform (GCP) + +- [NAT Gateway](./gcp/nat_gateway): This example shows how to deploy one or more + Firezone Gateways in a single GCP VPC that is configured with a Cloud NAT for + egress. Read this if you're looking to deploy Firezone Gateways behind a + single, shared static IP address on GCP. diff --git a/terraform/examples/gcp/nat_gateway/README.md b/terraform/examples/gcp/nat_gateway/README.md new file mode 100644 index 000000000..c74a65fe3 --- /dev/null +++ b/terraform/examples/gcp/nat_gateway/README.md @@ -0,0 +1,102 @@ +# GCP NAT Gateway Example + +In this example, we will deploy one or more Firezone Gateways in a single VPC on +Google Cloud Platform (GCP) that are configured to egress traffic through a +single Cloud NAT that is assigned a single static IP address. + +## Common use cases + +Use this guide to give your Firezone Clients a static public IP address for +egress traffic to particular Resource(s). Here are some common use cases for +this example: + +- Use IP whitelisting to access a third-party or partner application such as a + client's DB or third-party API. +- Use IP whitelisting with your identity provider to lock down access to a + public application. +- Enabling a team of remote contractors access to a regionally-locked + application or service. + +## High availability + +All Firezone Gateways deployed in this example will automatically failover and +load balance for each other. No other configuration is necessary. To perform +upgrades with minimal downtime, see +[minimal downtime upgrades](#minimal-downtime-upgrades). + +## Prerequisites + +1. [Terraform](https://www.terraform.io/downloads.html) +1. [Google Cloud Platform (GCP) account](https://cloud.google.com/) +1. [Google Cloud SDK](https://cloud.google.com/sdk/docs/install) +1. [Enable the Compute Engine API](https://console.cloud.google.com/flows/enableapi?apiid=compute.googleapis.com) +1. A [Firezone Site](https://www.firezone.dev/kb/deploy/sites) dedicated to use + for this example. This Site should contain **only** the Firezone Gateway(s) + deployed in this example and any associated Resources. +1. A Firezone Gateway token. See + [Multiple Gateways](https://www.firezone.dev/kb/deploy/gateways#deploy-multiple-gateways) + for instructions on how to obtain a Firezone Gateway token that can be used + across multiple instances. + +## Sizing + +Simply update the number of replicas to deploy more or fewer Firezone Gateways. +There's no limit to the number of Firezone Gateways you can deploy in a single +VPC. + +We've tested with `f1-micro` instances which still work quite well for most +applications. However, you may want to consider a larger instance type if you +have a high volume of traffic or lots of concurrent connections. + +## Deployment + +1. Configure the necessary Terraform + [variables](https://developer.hashicorp.com/terraform/language/values/variables). + Here's an example `terraform.tfvars` you can use as a starting point: + + ```hcl + project_id = "my-gcp-project" + region = "us-west1" + zone = "us-west1-a" + token = "" + replicas = 3 + machine_type = "f1-micro" + log_level = "info" + ``` + +1. Run `terraform init` to initialize the working directory and download the + required providers. +1. Run `terraform apply` to deploy the Firezone Gateway(s) into your GCP + project. + +You can see the static IP address assigned to the Cloud NAT in the Terraform +output. This is the IP address that your Firezone Gateway(s) will use to egress +traffic. + +You can verify all Firezone Gateways are using this IP by viewing the Site in +the Firezone admin portal, where you should now see the Firezone Gateway(s) +listed as `Online`. + +
+ +![Online Gateways](./online-gateways.png) + +
+ +## Upgrading + +To upgrade the Firezone Gateway(s) to the latest version, simply update the +`token` and issue a `terraform apply` which will trigger a redeployment of the +Firezone Gateway(s). + +This will incur about a minute or two of downtime as Terraform destroys the +existing Firezone Gateway(s) and deploys new ones in their place. + +## Future improvements + +- Minimal downtime upgrades using a regional instance manager. +- Expose the ability to select an existing subnetwork instead of auto-creating a + new one. +- Expose the ability to select an existing + [regional external IP address](https://cloud.google.com/nat/docs/ports-and-addresses) + instead of auto-creating a new one. diff --git a/terraform/examples/gcp/nat_gateway/main.tf b/terraform/examples/gcp/nat_gateway/main.tf new file mode 100644 index 000000000..50296c102 --- /dev/null +++ b/terraform/examples/gcp/nat_gateway/main.tf @@ -0,0 +1,112 @@ +terraform { + required_providers { + google = { + source = "hashicorp/google" + version = "5.19.0" + } + } +} + +provider "google" { + project = var.project_id + region = var.region + zone = var.zone +} + +resource "google_project_service" "compute-api" { + project = var.project_id + service = "compute.googleapis.com" +} + +resource "google_service_account" "firezone" { + account_id = "firezone-gateway" + display_name = "Firezone Gateway Service Account" +} + +resource "google_compute_network" "firezone" { + name = "firezone-gateway" + auto_create_subnetworks = true + depends_on = [google_project_service.compute-api] +} + +resource "google_compute_router" "firezone" { + name = "firezone-gateway-router" + network = google_compute_network.firezone.id +} + +resource "google_compute_router_nat" "firezone" { + name = "firezone-gateway-nat" + router = google_compute_router.firezone.name + nat_ip_allocate_option = "AUTO_ONLY" + source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_IP_RANGES" +} + +resource "google_compute_instance_template" "gateway" { + name = "gateway-template" + description = "Instance template for the Firezone Gateway" + instance_description = "Firezone Gateway" + machine_type = var.machine_type + tags = ["firezone-gateway"] + can_ip_forward = true + + scheduling { + automatic_restart = true + on_host_maintenance = "MIGRATE" + } + + disk { + source_image = "debian-cloud/debian-12" + auto_delete = true + boot = true + } + + network_interface { + network = google_compute_network.firezone.id + } + + service_account { + email = google_service_account.firezone.email + scopes = ["cloud-platform"] + } + +} + +// Allow SSH access to the gateways. This is optional but helpful for debugging +// and administration of the gateways. Since they're not publicly accessible, +// you need to tunnel through IAP: +// +// gcloud compute ssh --tunnel-through-iap --project --zone gateway-0 +resource "google_compute_firewall" "ssh-rule" { + name = "allow-ssh" + network = google_compute_network.firezone.name + + allow { + protocol = "tcp" + ports = ["22"] + } + + target_tags = ["gateway"] + source_ranges = ["0.0.0.0/0"] +} + +resource "google_compute_instance_from_template" "gateway" { + name = "gateway-${count.index}" + count = var.replicas + source_instance_template = google_compute_instance_template.gateway.self_link_unique + + # Script is defined here to set instance-specific metadata + metadata_startup_script = <<-SCRIPT + #!/usr/bin/env bash + set -euo pipefail + + # Install dependencies + sudo apt-get update + sudo apt-get install -y iptables curl + + # Set necessary environment variables and run installer + FIREZONE_ID="gateway-${google_compute_instance_template.gateway.id}-${count.index}" \ + FIREZONE_TOKEN="${var.token}" \ + bash <(curl -fsSL https://raw.githubusercontent.com/firezone/firezone/main/scripts/gateway-systemd-install.sh) + + SCRIPT +} diff --git a/terraform/examples/gcp/nat_gateway/online-gateways.png b/terraform/examples/gcp/nat_gateway/online-gateways.png new file mode 100644 index 000000000..21c149993 Binary files /dev/null and b/terraform/examples/gcp/nat_gateway/online-gateways.png differ diff --git a/terraform/examples/gcp/nat_gateway/variables.tf b/terraform/examples/gcp/nat_gateway/variables.tf new file mode 100644 index 000000000..e1bfb4070 --- /dev/null +++ b/terraform/examples/gcp/nat_gateway/variables.tf @@ -0,0 +1,54 @@ +################################################################################ +## Google Cloud Project +################################################################################ + +variable "project_id" { + type = string + description = "Google Cloud Project ID" +} + +################################################################################ +## Compute +################################################################################ + +variable "region" { + type = string + description = "Region to deploy the Gateway(s) in." +} + +variable "zone" { + type = string + description = "Availability to deploy the Gateway(s) in." +} + +variable "replicas" { + type = number + description = "Number of Gateway replicas to deploy in the availability zone." + default = 3 +} + +variable "machine_type" { + type = string + default = "n1-standard-1" +} + +################################################################################ +## Observability +################################################################################ + +variable "log_level" { + type = string + nullable = false + default = "info" + + description = "Sets RUST_LOG environment variable to configure the Gateway's log level. Default: 'info'." +} + +################################################################################ +## Firezone +################################################################################ + +variable "token" { + type = string + description = "Gateway token to use for authentication." +} diff --git a/website/src/app/kb/deploy/gateways/readme.mdx b/website/src/app/kb/deploy/gateways/readme.mdx index 47b1e1334..1ccb61437 100644 --- a/website/src/app/kb/deploy/gateways/readme.mdx +++ b/website/src/app/kb/deploy/gateways/readme.mdx @@ -68,13 +68,21 @@ A single Client connection to a single Gateway can typically reach speeds of **1 Gbps** or more. This scales linearly with each Client connection up to the number of CPU cores available to the Gateway. -Use the table below as a rough guide for sizing your Gateway deployments: +In our tests, we've found that even a single `f1.micro` instance on Google Cloud +Platform, equipped with a single shared vCPU core, can effortlessly handle up to +1 Gbps of tunneled traffic. This performance is attributed to the efficiency of +the WireGuard® protocol and the Rust programming language. -| Gateway size | Users served | CPU cores | Memory | Network link | -| ------------ | ------------ | --------- | ------ | ------------ | -| Small | 100 | 2 | 2 GB | 1 Gbps | -| Medium | 1,000 | 8 | 8 GB | 10 Gbps | -| Large | 10,000 | 32 | 32 GB | 40 Gbps | +Use the table below as a rough guide for sizing your Gateway deployments. These +are general recommendations and may not be accurate for your specific use case. +If you're unsure, start with a smaller Gateway and scale up as needed. + +| Gateway size | Users served | CPU cores | Memory | Network link | +| ------------ | -------------- | --------- | ------ | ------------ | +| Micro | 10 - 100 | 1 | 512 MB | 1 Gbps | +| Small | 100 - 250 | 2 | 1 GB | 1 Gbps | +| Medium | 250 - 1,000 | 4 | 4 GB | 10 Gbps | +| Large | 1,000 - 10,000 | 16 | 16 GB | 25 Gbps | To go beyond the table above, you can deploy additional Gateways and use Firezone's [automatic load balancing](#load-balancing) to distribute Client