From fc8d89ea733742542b3b40e38deea0a863dc6783 Mon Sep 17 00:00:00 2001 From: Jamil Date: Thu, 27 Jun 2024 21:05:38 -0700 Subject: [PATCH] docs: Add AWS NAT Gateway example (#5543) - Adds the AWS equivalent of our GCP scalable NAT Gateway. - Adds a new kb section `/kb/automate` that will contain various automation / IaaC recipes going forward. It's better to have these guides in the main docs with all the other info. ~~Will update the GCP example in another PR.~~ Portal helper docs in the gateway deploy page will come in another PR after this is merged. --- docs/README.md | 14 +- terraform/examples/.gitignore | 1 + terraform/examples/README.md | 9 +- terraform/examples/aws/nat-gateway/README.md | 4 + terraform/examples/aws/nat-gateway/main.tf | 168 ++++++++++++++ .../google-cloud/nat-gateway/README.md | 4 + .../examples/google-cloud/nat-gateway/main.tf | 212 ++++++++++++++++++ .../examples/google-cloud/nat_gateway/main.tf | 40 ---- .../google-cloud/nat_gateway/network.tf | 103 --------- .../google-cloud/nat_gateway/outputs.tf | 3 - .../google-cloud/nat_gateway/variables.tf | 55 ----- .../google-cloud/nat_gateway/versions.tf | 8 - .../modules/aws/firezone-gateway/main.tf | 54 +++++ .../modules/aws/firezone-gateway/variables.tf | 85 +++++++ .../public/images/kb/automate/aws-logo.svg | 38 ++++ .../public/images/kb/automate/gcp-logo.svg | 1 + .../images/kb/automate/terraform-logo.svg | 7 + .../terraform/gcp}/online-gateways.png | Bin website/src/app/kb/automate/_page.tsx | 6 + website/src/app/kb/automate/page.tsx | 17 ++ website/src/app/kb/automate/readme.mdx | 49 ++++ .../app/kb/automate/terraform/aws/_page.tsx | 6 + .../app/kb/automate/terraform/aws/page.tsx | 17 ++ .../app/kb/automate/terraform/aws/readme.mdx | 87 +++++++ .../app/kb/automate/terraform/gcp/_page.tsx | 6 + .../app/kb/automate/terraform/gcp/page.tsx | 18 ++ .../app/kb/automate/terraform/gcp/readme.mdx | 30 ++- website/src/app/kb/deploy/gateways/readme.mdx | 7 +- website/src/app/page.tsx | 144 ++++++------ website/src/components/DocCards/index.tsx | 0 website/src/components/KbCards/index.tsx | 35 +++ website/src/components/KbSidebar/index.tsx | 13 ++ 32 files changed, 943 insertions(+), 298 deletions(-) create mode 100644 terraform/examples/.gitignore create mode 100644 terraform/examples/aws/nat-gateway/README.md create mode 100644 terraform/examples/aws/nat-gateway/main.tf create mode 100644 terraform/examples/google-cloud/nat-gateway/README.md create mode 100644 terraform/examples/google-cloud/nat-gateway/main.tf delete mode 100644 terraform/examples/google-cloud/nat_gateway/main.tf delete mode 100644 terraform/examples/google-cloud/nat_gateway/network.tf delete mode 100644 terraform/examples/google-cloud/nat_gateway/outputs.tf delete mode 100644 terraform/examples/google-cloud/nat_gateway/variables.tf delete mode 100644 terraform/examples/google-cloud/nat_gateway/versions.tf create mode 100644 terraform/modules/aws/firezone-gateway/main.tf create mode 100644 terraform/modules/aws/firezone-gateway/variables.tf create mode 100644 website/public/images/kb/automate/aws-logo.svg create mode 100644 website/public/images/kb/automate/gcp-logo.svg create mode 100644 website/public/images/kb/automate/terraform-logo.svg rename {terraform/examples/google-cloud/nat_gateway => website/public/images/kb/automate/terraform/gcp}/online-gateways.png (100%) create mode 100644 website/src/app/kb/automate/_page.tsx create mode 100644 website/src/app/kb/automate/page.tsx create mode 100644 website/src/app/kb/automate/readme.mdx create mode 100644 website/src/app/kb/automate/terraform/aws/_page.tsx create mode 100644 website/src/app/kb/automate/terraform/aws/page.tsx create mode 100644 website/src/app/kb/automate/terraform/aws/readme.mdx create mode 100644 website/src/app/kb/automate/terraform/gcp/_page.tsx create mode 100644 website/src/app/kb/automate/terraform/gcp/page.tsx rename terraform/examples/google-cloud/nat_gateway/README.md => website/src/app/kb/automate/terraform/gcp/readme.mdx (80%) create mode 100644 website/src/components/DocCards/index.tsx create mode 100644 website/src/components/KbCards/index.tsx diff --git a/docs/README.md b/docs/README.md index db5be830c..87b6db57c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -103,12 +103,18 @@ product documentation, organized as follows: - [kotlin/](../kotlin/android): Android / ChromeOS clients. - [website/](../website): Marketing website and product documentation. - [terraform/](../terraform): Terraform files for various example deployments. - - [terraform/examples/google-cloud/nat_gateway](../terraform/examples/google-cloud/nat_gateway): - Example Terraform configurations for deploying a cluster of Firezone - gateways behind a NAT gateway on GCP with single egress IP. + - [terraform/examples/google-cloud/nat-gateway](../terraform/examples/google-cloud/nat-gateway): + Example Terraform configuration for deploying a cluster of Firezone Gateways + behind a NAT gateway on GCP with single egress IP. + - [terraform/examples/aws/nat-gateway](../terraform/examples/aws/nat-gateway): + Example Terraform configuration for deploying a cluster of Firezone Gateways + behind a NAT gateway on AWS with single egress IP. - [terraform/modules/google-cloud/apps/gateway-region-instance-group](../terraform/modules/google-cloud/apps/gateway-region-instance-group): - Production-ready Terraform module for deploying regional Firezone gateways + Production-ready Terraform module for deploying regional Firezone Gateways to Google Cloud Compute using Regional Instance Groups. + - [terraform/modules/aws/firezone-gateway](../terraform/modules/aws/firezone-gateway): + Production-ready Terraform module for deploying Firezone Gateways to AWS + using Auto Scaling Groups. ## Quickstart diff --git a/terraform/examples/.gitignore b/terraform/examples/.gitignore new file mode 100644 index 000000000..809648bda --- /dev/null +++ b/terraform/examples/.gitignore @@ -0,0 +1 @@ +**/.terraform.* diff --git a/terraform/examples/README.md b/terraform/examples/README.md index 8ca4e6b17..3e77a0bfd 100644 --- a/terraform/examples/README.md +++ b/terraform/examples/README.md @@ -8,9 +8,16 @@ Gateways to your infrastructure. Each example below is self-contained and includes a `README.md` with instructions on how to deploy the example. +### AWS + +- [NAT Gateway](./aws/nat-gateway): This example shows how to deploy one or more + Firezone Gateways in a single AWS VPC that is configured with a NAT Gateway + for egress. Read this if you're looking to deploy Firezone Gateways behind a + single, shared static IP address on AWS. + ### Google Cloud Platform (GCP) -- [NAT Gateway](./google-cloud/nat_gateway): This example shows how to deploy +- [NAT Gateway](./google-cloud/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/aws/nat-gateway/README.md b/terraform/examples/aws/nat-gateway/README.md new file mode 100644 index 000000000..3d99a80f0 --- /dev/null +++ b/terraform/examples/aws/nat-gateway/README.md @@ -0,0 +1,4 @@ +# Deploy Firezone on AWS with Terraform + +See [our docs for a detailed guide](/kb/automate/terraform/aws) on deploying +Firezone on AWS with Terraform using this example. diff --git a/terraform/examples/aws/nat-gateway/main.tf b/terraform/examples/aws/nat-gateway/main.tf new file mode 100644 index 000000000..551da8a91 --- /dev/null +++ b/terraform/examples/aws/nat-gateway/main.tf @@ -0,0 +1,168 @@ +module "gateway_aws_example" { + source = "github.com/firezone/firezone/terraform/modules/aws/firezone-gateway" + + ################### + # Required inputs # + ################### + + # Generate a token from the admin portal in Sites -> -> Deploy Gateway. + # Only one token is needed for the cluster. + firezone_token = "YOUR_FIREZONE_TOKEN" + + # Pick an AMI to use. We recommend Ubuntu LTS or Amazon Linux 2. + base_ami = data.aws_ami_ids.ubuntu.ids[0] + + # Attach the Gateways to your VPC and subnets. + vpc = aws_vpc.main.id + public_subnet = aws_subnet.public.id + private_subnet = aws_subnet.private.id + instance_security_groups = [ + aws_security_group.instance.id + ] + + ################### + # Optional inputs # + ################### + + # Deploy a specific version of the Gateway. Generally, we recommend using the latest version. + # firezone_version = "latest" + + # Override the default API URL. This should almost never be needed. + # firezone_api_url = "wss://api.firezone.dev" + + # Gateways are very lightweight. + # See https://www.firezone.dev/kb/deploy/gateways#sizing-recommendations. + # instance_type = "t3.nano" + + # We recommend a minimum of 3 instances for high availability. + # min_size = 3 + # max_size = 5 + # desired_capacity = 3 +} + +data "aws_ami_ids" "ubuntu" { + owners = ["099720109477"] # Canonical + + filter { + name = "name" + values = ["ubuntu/images/hvm-ssd/ubuntu-*-22.04-amd64-server-*"] + } +} + +provider "aws" { + # Change this to your desired region + region = "us-east-1" +} + +resource "aws_vpc" "main" { + cidr_block = "172.16.0.0/16" + enable_dns_support = true + enable_dns_hostnames = true +} + +resource "aws_subnet" "public" { + vpc_id = aws_vpc.main.id + cidr_block = "172.16.0.0/24" + map_public_ip_on_launch = true +} + +resource "aws_subnet" "private" { + vpc_id = aws_vpc.main.id + cidr_block = "172.16.1.0/24" +} + +resource "aws_internet_gateway" "gw" { + vpc_id = aws_vpc.main.id +} + +resource "aws_eip" "nat" { + domain = "vpc" +} + +resource "aws_nat_gateway" "nat" { + allocation_id = aws_eip.nat.id + subnet_id = aws_subnet.public.id +} + +resource "aws_route_table" "public" { + vpc_id = aws_vpc.main.id + + route { + cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.gw.id + } +} + +resource "aws_route_table" "private" { + vpc_id = aws_vpc.main.id + + route { + cidr_block = "0.0.0.0/0" + nat_gateway_id = aws_nat_gateway.nat.id + } +} + +resource "aws_route_table_association" "public" { + subnet_id = aws_subnet.public.id + route_table_id = aws_route_table.public.id +} + +resource "aws_route_table_association" "private" { + subnet_id = aws_subnet.private.id + route_table_id = aws_route_table.private.id +} + +resource "aws_security_group" "instance" { + vpc_id = aws_vpc.main.id + + // allow SSH from other machines on the subnet + ingress { + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = [ + aws_subnet.private.cidr_block, + aws_subnet.public.cidr_block + ] + } + + egress { + from_port = 0 + to_port = 65535 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_security_group" "instance_connect" { + name = "allow egress to all vpc subnets" + description = "Security group to allow SSH to vpc subnets. Created for use with EC2 Instance Connect Endpoint." + vpc_id = aws_vpc.main.id + + egress { + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = [ + aws_subnet.private.cidr_block, + aws_subnet.public.cidr_block + ] + } +} + +resource "aws_ec2_instance_connect_endpoint" "instance_connect_endpoint" { + subnet_id = aws_subnet.public.id + preserve_client_ip = false + security_group_ids = [ + aws_security_group.instance_connect.id + ] + + tags = { + Name = "firezone-gateway-instance-connect-endpoint" + } +} + +output "nat_public_ip" { + description = "The public IP of the NAT gateway" + value = aws_eip.nat.public_ip +} diff --git a/terraform/examples/google-cloud/nat-gateway/README.md b/terraform/examples/google-cloud/nat-gateway/README.md new file mode 100644 index 000000000..82f9d5d0f --- /dev/null +++ b/terraform/examples/google-cloud/nat-gateway/README.md @@ -0,0 +1,4 @@ +# Deploy Firezone on GCP with Terraform + +See [our docs for a detailed guide](/kb/automate/terraform/gcp) on deploying +Firezone on GCP with Terraform using this example. diff --git a/terraform/examples/google-cloud/nat-gateway/main.tf b/terraform/examples/google-cloud/nat-gateway/main.tf new file mode 100644 index 000000000..b26ce6232 --- /dev/null +++ b/terraform/examples/google-cloud/nat-gateway/main.tf @@ -0,0 +1,212 @@ +module "gateway_gcp_example" { + source = "github.com/firezone/firezone/terraform/modules/google-cloud/apps/gateway-region-instance-group" + # If you are changing this example along with the module, you should use the local path: + # source = "../../../modules/google-cloud/apps/gateway-region-instance-group" + + project_id = var.project_id + + compute_network = google_compute_network.firezone.id + compute_subnetwork = google_compute_subnetwork.firezone.id + + compute_instance_replicas = var.replicas + compute_instance_type = var.machine_type + compute_region = var.region + + # Since we are behind a NAT gateway, we don't need public IP addresses + # to be automatically provisioned for the instances + compute_provision_public_ipv6_address = false + compute_provision_public_ipv4_address = false + + vsn = "latest" + + observability_log_level = "info" + + token = var.token +} + +################################################################################ +## 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 "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." +} + +variable "subnet_cidr" { + type = string + description = "CIDR Range to use for subnet where Gateway(s) are deployed" +} + +provider "google" { + project = var.project_id + region = var.region +} + +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" +} + +# We create a new network and subnetwork. In real-world scenarios, +# you would likely use an existing ones where your application is deployed. +resource "google_compute_network" "firezone" { + name = "firezone-gateway" + auto_create_subnetworks = false + enable_ula_internal_ipv6 = true + depends_on = [google_project_service.compute-api] +} + +resource "google_compute_subnetwork" "firezone" { + project = var.project_id + + name = "firezone-gateways" + + stack_type = "IPV4_IPV6" + + ip_cidr_range = var.subnet_cidr + region = var.region + network = google_compute_network.firezone.id + + ipv6_access_type = "INTERNAL" + + private_ip_google_access = true +} + +# Allocate IPv4 addresses for the NAT gateway +resource "google_compute_address" "ipv4" { + project = var.project_id + name = "firezone-gateway-nat-ipv4" + ip_version = "IPV4" +} + +# Create a router and NAT to allow outbound traffic +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 = "MANUAL_ONLY" + nat_ips = [ + google_compute_address.ipv4.self_link, + ] + + source_subnetwork_ip_ranges_to_nat = "LIST_OF_SUBNETWORKS" + subnetwork { + name = google_compute_subnetwork.firezone.id + source_ip_ranges_to_nat = ["ALL_IP_RANGES"] + } +} + +# Configure Firewall to allow outbound traffic +resource "google_compute_firewall" "gateways-egress-ipv4" { + project = var.project_id + + name = "firezone-gateways-egress-ipv4" + network = google_compute_network.firezone.id + direction = "EGRESS" + + target_tags = module.gateways.target_tags + destination_ranges = ["0.0.0.0/0"] + + allow { + protocol = "all" + } +} + +resource "google_compute_firewall" "gateways-egress-ipv6" { + project = var.project_id + + name = "firezone-gateways-egress-ipv6" + network = google_compute_network.firezone.id + direction = "EGRESS" + + target_tags = module.gateways.target_tags + destination_ranges = ["::/0"] + + allow { + protocol = "all" + } +} + +# 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 instances list --project +# gcloud compute ssh --tunnel-through-iap --project gateway-XXXX +resource "google_compute_firewall" "ssh-rule" { + name = "allow-gateways-ssh" + network = google_compute_network.firezone.id + + allow { + protocol = "tcp" + ports = ["22"] + } + + target_tags = module.gateways.target_tags + source_ranges = ["35.235.240.0/20"] // IAP CIDR +} + +output "static_ip_addresses" { + value = [google_compute_address.ipv4.address] +} + +terraform { + required_providers { + google = { + source = "hashicorp/google" + version = "5.20" + } + } +} diff --git a/terraform/examples/google-cloud/nat_gateway/main.tf b/terraform/examples/google-cloud/nat_gateway/main.tf deleted file mode 100644 index 8ee406c0e..000000000 --- a/terraform/examples/google-cloud/nat_gateway/main.tf +++ /dev/null @@ -1,40 +0,0 @@ -provider "google" { - project = var.project_id - region = var.region -} - -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" -} - -module "gateways" { - source = "github.com/firezone/firezone/terraform/modules/google-cloud/apps/gateway-region-instance-group" - # If you are changing this example along with the module, you should use the local path: - # source = "../../../modules/google-cloud/apps/gateway-region-instance-group" - - project_id = var.project_id - - compute_network = google_compute_network.firezone.id - compute_subnetwork = google_compute_subnetwork.firezone.id - - compute_instance_replicas = var.replicas - compute_instance_type = var.machine_type - compute_region = var.region - - # Since we are behind a NAT gateway, we don't need public IP addresses - # to be automatically provisioned for the instances - compute_provision_public_ipv6_address = false - compute_provision_public_ipv4_address = false - - vsn = "latest" - - observability_log_level = "info" - - token = var.token -} diff --git a/terraform/examples/google-cloud/nat_gateway/network.tf b/terraform/examples/google-cloud/nat_gateway/network.tf deleted file mode 100644 index 98a1de083..000000000 --- a/terraform/examples/google-cloud/nat_gateway/network.tf +++ /dev/null @@ -1,103 +0,0 @@ -# We create a new network and subnetwork. In real-world scenarios, -# you would likely use an existing ones where your application is deployed. -resource "google_compute_network" "firezone" { - name = "firezone-gateway" - auto_create_subnetworks = false - enable_ula_internal_ipv6 = true - depends_on = [google_project_service.compute-api] -} - -resource "google_compute_subnetwork" "firezone" { - project = var.project_id - - name = "firezone-gateways" - - stack_type = "IPV4_IPV6" - - ip_cidr_range = var.subnet_cidr - region = var.region - network = google_compute_network.firezone.id - - ipv6_access_type = "INTERNAL" - - private_ip_google_access = true -} - -# Allocate IPv4 addresses for the NAT gateway -resource "google_compute_address" "ipv4" { - project = var.project_id - name = "firezone-gateway-nat-ipv4" - ip_version = "IPV4" -} - -# Create a router and NAT to allow outbound traffic -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 = "MANUAL_ONLY" - nat_ips = [ - google_compute_address.ipv4.self_link, - ] - - source_subnetwork_ip_ranges_to_nat = "LIST_OF_SUBNETWORKS" - subnetwork { - name = google_compute_subnetwork.firezone.id - source_ip_ranges_to_nat = ["ALL_IP_RANGES"] - } -} - -# Configure Firewall to allow outbound traffic -resource "google_compute_firewall" "gateways-egress-ipv4" { - project = var.project_id - - name = "firezone-gateways-egress-ipv4" - network = google_compute_network.firezone.id - direction = "EGRESS" - - target_tags = module.gateways.target_tags - destination_ranges = ["0.0.0.0/0"] - - allow { - protocol = "all" - } -} - -resource "google_compute_firewall" "gateways-egress-ipv6" { - project = var.project_id - - name = "firezone-gateways-egress-ipv6" - network = google_compute_network.firezone.id - direction = "EGRESS" - - target_tags = module.gateways.target_tags - destination_ranges = ["::/0"] - - allow { - protocol = "all" - } -} - -# 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 instances list --project -# gcloud compute ssh --tunnel-through-iap --project gateway-XXXX -resource "google_compute_firewall" "ssh-rule" { - name = "allow-gateways-ssh" - network = google_compute_network.firezone.id - - allow { - protocol = "tcp" - ports = ["22"] - } - - target_tags = module.gateways.target_tags - source_ranges = ["35.235.240.0/20"] // IAP CIDR -} diff --git a/terraform/examples/google-cloud/nat_gateway/outputs.tf b/terraform/examples/google-cloud/nat_gateway/outputs.tf deleted file mode 100644 index a57040bed..000000000 --- a/terraform/examples/google-cloud/nat_gateway/outputs.tf +++ /dev/null @@ -1,3 +0,0 @@ -output "static_ip_addresses" { - value = [google_compute_address.ipv4.address] -} diff --git a/terraform/examples/google-cloud/nat_gateway/variables.tf b/terraform/examples/google-cloud/nat_gateway/variables.tf deleted file mode 100644 index 74232a2f9..000000000 --- a/terraform/examples/google-cloud/nat_gateway/variables.tf +++ /dev/null @@ -1,55 +0,0 @@ -################################################################################ -## 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 "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." - sensitive = true -} - -variable "subnet_cidr" { - type = string - description = "CIDR Range to use for subnet where Gateway(s) are deployed" -} diff --git a/terraform/examples/google-cloud/nat_gateway/versions.tf b/terraform/examples/google-cloud/nat_gateway/versions.tf deleted file mode 100644 index 11a0305bb..000000000 --- a/terraform/examples/google-cloud/nat_gateway/versions.tf +++ /dev/null @@ -1,8 +0,0 @@ -terraform { - required_providers { - google = { - source = "hashicorp/google" - version = "5.20" - } - } -} diff --git a/terraform/modules/aws/firezone-gateway/main.tf b/terraform/modules/aws/firezone-gateway/main.tf new file mode 100644 index 000000000..837c0cea0 --- /dev/null +++ b/terraform/modules/aws/firezone-gateway/main.tf @@ -0,0 +1,54 @@ +resource "aws_launch_configuration" "lc" { + name = "firezone-gateway-lc" + image_id = var.base_ami + instance_type = var.instance_type + security_groups = var.instance_security_groups + associate_public_ip_address = false + + lifecycle { + create_before_destroy = true + } + + user_data = <<-EOF + #!/bin/bash + set -e + + sudo apt-get update + sudo apt-get install -y curl uuid-runtime + + FIREZONE_TOKEN="${var.firezone_token}" \ + FIREZONE_VERSION="${var.firezone_version}" \ + FIREZONE_NAME="${var.firezone_name}" \ + FIREZONE_ID="$(uuidgen)" \ + FIREZONE_API_URL="${var.firezone_api_url}" \ + bash <(curl -fsSL https://raw.githubusercontent.com/firezone/firezone/main/scripts/gateway-systemd-install.sh) + + EOF +} + +resource "aws_autoscaling_group" "asg" { + desired_capacity = var.desired_capacity + max_size = var.max_size + min_size = var.min_size + vpc_zone_identifier = [var.private_subnet] + launch_configuration = aws_launch_configuration.lc.id + + tag { + key = "Name" + value = "firezone-gateway-instance" + propagate_at_launch = true + } + + dynamic "tag" { + for_each = var.extra_tags + content { + key = tag.value.key + propagate_at_launch = tag.value.propagate_at_launch + value = tag.value.value + } + } + + lifecycle { + create_before_destroy = true + } +} diff --git a/terraform/modules/aws/firezone-gateway/variables.tf b/terraform/modules/aws/firezone-gateway/variables.tf new file mode 100644 index 000000000..a0c5a7eea --- /dev/null +++ b/terraform/modules/aws/firezone-gateway/variables.tf @@ -0,0 +1,85 @@ +variable "base_ami" { + description = "The base AMI for the instances" + type = string +} + +variable "instance_type" { + description = "The instance type" + type = string + default = "t3.nano" +} + +variable "desired_capacity" { + description = "The desired number of instances" + type = number + default = 3 +} + +variable "min_size" { + description = "The minimum number of instances" + type = number + default = 3 +} + +variable "max_size" { + description = "The maximum number of instances" + type = number + default = 5 +} + +variable "firezone_token" { + description = "The Firezone token" + type = string + nullable = false + sensitive = true +} + +variable "firezone_version" { + description = "The Gateway version to deploy" + type = string + default = "latest" +} + +variable "firezone_name" { + description = "Name for the Gateways used in the admin portal" + type = string + default = "$(hostname)" +} + +variable "firezone_api_url" { + description = "The Firezone API URL" + type = string + default = "wss://api.firezone.dev" +} + +variable "vpc" { + description = "The VPC id to use" + type = string +} + +variable "private_subnet" { + description = "The private subnet id" + type = string +} + +variable "public_subnet" { + description = "The public subnet id" + type = string +} + +variable "instance_security_groups" { + description = "The security group ids to attach to the instances" + type = list(string) +} + +variable "extra_tags" { + description = "Extra tags for the Auto Scaling group" + + type = map(object({ + key = string + value = string + propagate_at_launch = bool + })) + + default = {} +} diff --git a/website/public/images/kb/automate/aws-logo.svg b/website/public/images/kb/automate/aws-logo.svg new file mode 100644 index 000000000..4715937ff --- /dev/null +++ b/website/public/images/kb/automate/aws-logo.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + diff --git a/website/public/images/kb/automate/gcp-logo.svg b/website/public/images/kb/automate/gcp-logo.svg new file mode 100644 index 000000000..ae6d94748 --- /dev/null +++ b/website/public/images/kb/automate/gcp-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/website/public/images/kb/automate/terraform-logo.svg b/website/public/images/kb/automate/terraform-logo.svg new file mode 100644 index 000000000..e98f8b71f --- /dev/null +++ b/website/public/images/kb/automate/terraform-logo.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/terraform/examples/google-cloud/nat_gateway/online-gateways.png b/website/public/images/kb/automate/terraform/gcp/online-gateways.png similarity index 100% rename from terraform/examples/google-cloud/nat_gateway/online-gateways.png rename to website/public/images/kb/automate/terraform/gcp/online-gateways.png diff --git a/website/src/app/kb/automate/_page.tsx b/website/src/app/kb/automate/_page.tsx new file mode 100644 index 000000000..8f8abd30f --- /dev/null +++ b/website/src/app/kb/automate/_page.tsx @@ -0,0 +1,6 @@ +"use client"; +import Content from "./readme.mdx"; + +export default function _Page() { + return ; +} diff --git a/website/src/app/kb/automate/page.tsx b/website/src/app/kb/automate/page.tsx new file mode 100644 index 000000000..a25acda88 --- /dev/null +++ b/website/src/app/kb/automate/page.tsx @@ -0,0 +1,17 @@ +import { Metadata } from "next"; +import _Page from "./_page"; +import LastUpdated from "@/components/LastUpdated"; + +export const metadata: Metadata = { + title: "Automate • Firezone Docs", + description: "Automation recipes for deploying and managing Firezone.", +}; + +export default function Page() { + return ( + <> + <_Page /> + + + ); +} diff --git a/website/src/app/kb/automate/readme.mdx b/website/src/app/kb/automate/readme.mdx new file mode 100644 index 000000000..fc30f978f --- /dev/null +++ b/website/src/app/kb/automate/readme.mdx @@ -0,0 +1,49 @@ +import SupportOptions from "@/components/SupportOptions"; +import Alert from "@/components/DocsAlert"; +import Image from "next/image"; +import Link from "next/link"; +import NextStep from "@/components/NextStep"; +import { KbCards, KbCard } from "@/components/KbCards"; +import { FaPlus } from "react-icons/fa"; + +# Automate Firezone + +These guides contain automation recipes for deploying Firezone using various +infrastructure as code (IaC) tools. + +## Get started + +Follow one of the guides below to setup a production-ready deployment of +Firezone on your infrastructure. + + + + Terraform + + AWS + + }> + Deploy a scalable cluster of Firezone Gateways behind a NAT gateway on AWS + with a single egress IP. + + + Terraform + + GCP + + }> + Deploy a scalable cluster of Firezone Gateways behind a Cloud NAT on GCP + with a single egress IP. + + + + + diff --git a/website/src/app/kb/automate/terraform/aws/_page.tsx b/website/src/app/kb/automate/terraform/aws/_page.tsx new file mode 100644 index 000000000..8f8abd30f --- /dev/null +++ b/website/src/app/kb/automate/terraform/aws/_page.tsx @@ -0,0 +1,6 @@ +"use client"; +import Content from "./readme.mdx"; + +export default function _Page() { + return ; +} diff --git a/website/src/app/kb/automate/terraform/aws/page.tsx b/website/src/app/kb/automate/terraform/aws/page.tsx new file mode 100644 index 000000000..ef64ae004 --- /dev/null +++ b/website/src/app/kb/automate/terraform/aws/page.tsx @@ -0,0 +1,17 @@ +import { Metadata } from "next"; +import _Page from "./_page"; +import LastUpdated from "@/components/LastUpdated"; + +export const metadata: Metadata = { + title: "Deploy Firezone on AWS • Firezone Docs", + description: "Example Terraform configuration to deploy Firezone on AWS.", +}; + +export default function Page() { + return ( + <> + <_Page /> + + + ); +} diff --git a/website/src/app/kb/automate/terraform/aws/readme.mdx b/website/src/app/kb/automate/terraform/aws/readme.mdx new file mode 100644 index 000000000..044ad22ca --- /dev/null +++ b/website/src/app/kb/automate/terraform/aws/readme.mdx @@ -0,0 +1,87 @@ +import SupportOptions from "@/components/SupportOptions"; +import Alert from "@/components/DocsAlert"; + +# Deploy Firezone on AWS with Terraform + +In this guide, we'll deploy a cluster of Firezone Gateways in a private subnet +on AWS that are configured to egress traffic to the internet through an AWS +[NAT Gateway](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html). + +## 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 an IP allowlist to access a third-party or partner application such as a + client's DB or third-party API. +- Use an IP allowlist 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. + +## Prerequisites + +1. [Terraform](https://www.terraform.io/downloads.html) +1. [AWS account](https://aws.amazon.com/) with the necessary permissions to + create the resources. +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](/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 `desired_capacity` to deploy more or fewer Firezone +Gateways. There's no limit to the number of Firezone Gateways you can deploy in +a single VPC. A basic AutoScaling Group is provisioned as part of the linked +module. + +We've tested with `t3.nano` 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. [Download](https://raw.githubusercontent.com/firezone/firezone/main/terraform/examples/aws/nat-gateway/main.tf) + the `main.tf` from the example module. +1. Customize it as desired. At a minimum, you will need to set the + `firezone_token` and change `base_ami` and `region` to match your + environment. +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 AWS + project. + +You can see the IP addresses assigned to the NAT Gateway in the Terraform +output. These are the IP addresses that your Firezone Gateway(s) will share to +egress traffic. + +## 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 a few minutes of downtime as Terraform destroys the existing +Firezone Gateway(s) and deploys new ones in their place. + +## Output + +`nat_public_ip` will contain the public IP address of the NAT Gateway you can +use to whitelist your Firezone Gateway(s) in your third-party or partner +application. + +# Cleanup + +To clean up the resources created by this example, run `terraform destroy`. + + diff --git a/website/src/app/kb/automate/terraform/gcp/_page.tsx b/website/src/app/kb/automate/terraform/gcp/_page.tsx new file mode 100644 index 000000000..8f8abd30f --- /dev/null +++ b/website/src/app/kb/automate/terraform/gcp/_page.tsx @@ -0,0 +1,6 @@ +"use client"; +import Content from "./readme.mdx"; + +export default function _Page() { + return ; +} diff --git a/website/src/app/kb/automate/terraform/gcp/page.tsx b/website/src/app/kb/automate/terraform/gcp/page.tsx new file mode 100644 index 000000000..6007bd70b --- /dev/null +++ b/website/src/app/kb/automate/terraform/gcp/page.tsx @@ -0,0 +1,18 @@ +import { Metadata } from "next"; +import _Page from "./_page"; +import LastUpdated from "@/components/LastUpdated"; + +export const metadata: Metadata = { + title: "Deploy Firezone on GCP • Firezone Docs", + description: + "Example Terraform configuration to deploy Firezone on Google Cloud Platform.", +}; + +export default function Page() { + return ( + <> + <_Page /> + + + ); +} diff --git a/terraform/examples/google-cloud/nat_gateway/README.md b/website/src/app/kb/automate/terraform/gcp/readme.mdx similarity index 80% rename from terraform/examples/google-cloud/nat_gateway/README.md rename to website/src/app/kb/automate/terraform/gcp/readme.mdx index 2d4808889..2307df127 100644 --- a/terraform/examples/google-cloud/nat_gateway/README.md +++ b/website/src/app/kb/automate/terraform/gcp/readme.mdx @@ -1,4 +1,8 @@ -# GCP NAT Gateway Example +import SupportOptions from "@/components/SupportOptions"; +import Alert from "@/components/DocsAlert"; +import Image from "next/image"; + +# Deploy Firezone on GCP with Terraform 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 @@ -31,12 +35,12 @@ load balance for each other. No other configuration is necessary. 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 Site](/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 + [Multiple Gateways](/kb/deploy/gateways#deploy-multiple-gateways) for + instructions on how to obtain a Firezone Gateway token that can be used across multiple instances. ## Sizing @@ -51,6 +55,8 @@ have a high volume of traffic or lots of concurrent connections. ## Deployment +1. [Download](https://raw.githubusercontent.com/firezone/firezone/main/terraform/examples/google-cloud/nat_gateway/main.tf) + the `main.tf` from the example module. 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: @@ -78,11 +84,13 @@ 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) - -
+Online Gateways ## Upgrading diff --git a/website/src/app/kb/deploy/gateways/readme.mdx b/website/src/app/kb/deploy/gateways/readme.mdx index 5de802176..44831e124 100644 --- a/website/src/app/kb/deploy/gateways/readme.mdx +++ b/website/src/app/kb/deploy/gateways/readme.mdx @@ -125,11 +125,10 @@ Resources in a Site. This effectively shards Client connections across all Gateways in a Site, achieving higher overall throughput than otherwise possible with a single Gateway. -#### Deploy using Terraform +### Automated Gateway deployment -See our -[Terraform examples](https://github.com/firezone/firezone/tree/main/terraform/examples) -for deploying and scaling Gateways using Terraform on various cloud providers. +See [our automation recipes](/kb/automate) for deploying Gateways on various +cloud providers using Terraform. ### Keeping Gateways up to date diff --git a/website/src/app/page.tsx b/website/src/app/page.tsx index 3feaacc97..3f82bcaf5 100644 --- a/website/src/app/page.tsx +++ b/website/src/app/page.tsx @@ -329,8 +329,8 @@ export default function Page() {
-
-
+
+
@@ -374,74 +374,80 @@ export default function Page() {
-

- Clients are available for every major platform, require no - configuration, and stay connected even when switching WiFi - networks. -

-

- - Download Client apps - -

-
-
-
-
- Gateway -
-
- Gateway -
-
- Gateway -
-
- Gateway -
+
+

+ Clients are available for every major platform, require no + configuration, and stay connected even when switching WiFi + networks. +

+

+ + Download Client apps + +

+
+
+
+
+
+
+ Gateway +
+
+ Gateway +
+
+ Gateway +
+
+ Gateway +
+
+
+                
+                  FIREZONE_TOKEN=<your-token> \
./ + firezone-gateway +
+
+
+
+

+ Gateways are lightweight Linux binaries you deploy anywhere you + need access. Just configure a token with your preferred + orchestration tool and you're done. +

+

+ + Deploy your first Gateway + +

-
-              
-                FIREZONE_TOKEN=<your-token> \
./ - firezone-gateway -
-
-

- Gateways are lightweight Linux binaries you deploy anywhere you - need access. Just configure a token with your preferred - orchestration tool and you're done. -

-

- - Deploy your first Gateway - -

diff --git a/website/src/components/DocCards/index.tsx b/website/src/components/DocCards/index.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/website/src/components/KbCards/index.tsx b/website/src/components/KbCards/index.tsx new file mode 100644 index 000000000..8cb4eccdf --- /dev/null +++ b/website/src/components/KbCards/index.tsx @@ -0,0 +1,35 @@ +import { Route } from "next"; +import Link from "next/link"; + +export function KbCard({ + title, + href, + logo, + children, +}: { + title: string; + href: Route; + logo: React.ReactNode; + children: React.ReactNode; +}) { + return ( + +

+ {title} +

+ {logo} +
{children}
+ + ); +} + +export function KbCards({ children }: { children: React.ReactNode }) { + return ( +
+ {children} +
+ ); +} diff --git a/website/src/components/KbSidebar/index.tsx b/website/src/components/KbSidebar/index.tsx index f40893d85..6bbc62919 100644 --- a/website/src/components/KbSidebar/index.tsx +++ b/website/src/components/KbSidebar/index.tsx @@ -117,6 +117,19 @@ export default function KbSidebar() { +
  • + +
  • + Overview +
  • +
  • + Terraform + AWS +
  • +
  • + Terraform + GCP +
  • + +
  • Use Firezone