refactor(infra): Install gateways without using Docker (#4839)

This commit is contained in:
Andrew Dryga
2024-05-01 10:31:18 -06:00
committed by GitHub
parent 438469f3ac
commit 09f25d6e0c
17 changed files with 699 additions and 514 deletions

View File

@@ -238,11 +238,11 @@ jobs:
run: |
gcloud storage cp \
${BINARY_DEST_PATH} \
gs://firezone-binaries/${{ matrix.name.artifact }}/${{ env.VERSION }}-${{ inputs.sha }}/${{ matrix.arch.shortname }}
gs://firezone-staging-artifacts/${{ matrix.name.artifact }}/${{ env.VERSION }}-${{ inputs.sha }}/${{ matrix.arch.shortname }}
gcloud storage cp \
${BINARY_DEST_PATH}.sha256sum.txt \
gs://firezone-binaries/${{ matrix.name.artifact }}/${{ env.VERSION }}-${{ inputs.sha }}/${{ matrix.arch.shortname }}.sha256sum.txt
gs://firezone-staging-artifacts/${{ matrix.name.artifact }}/${{ env.VERSION }}-${{ inputs.sha }}/${{ matrix.arch.shortname }}.sha256sum.txt
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx

View File

@@ -59,3 +59,41 @@ jobs:
-t ghcr.io/firezone/${image}:${MAJOR_MINOR_VERSION} \
$SOURCE_TAG
done
- name: Authenticate to Google Cloud
id: auth
uses: google-github-actions/auth@v2
with:
workload_identity_provider: "projects/397012414171/locations/global/workloadIdentityPools/github-actions-pool/providers/github-actions"
service_account: "github-actions@github-iam-387915.iam.gserviceaccount.com"
export_environment_variables: true
create_credentials_file: true
- name: Copy Google Cloud Storage binaries to "latest" version
run: |
set -xe
IMAGES=(firezone-gateway)
ARCHITECTURES=(x86_64 aarch64 armv7)
MAJOR_VERSION="${VERSION%%.*}"
MAJOR_MINOR_VERSION="${VERSION%.*}"
for image in "${IMAGES[@]}"; do
for arch in "${ARCHITECTURES[@]}"; do
# Copy sha256sum.txt
gcloud storage cp \
gs://firezone-staging-artifacts/${{ matrix.name.artifact }}/${{ env.VERSION }}-${{ inputs.sha }}/${{ matrix.arch.shortname }}.sha256sum.txt \
gs://firezone-prod-artifacts/${image}/latest/${arch}.sha256sum.txt
gcloud storage cp \
gs://firezone-staging-artifacts/${{ matrix.name.artifact }}/${{ env.VERSION }}-${{ inputs.sha }}/${{ matrix.arch.shortname }}.sha256sum.txt \
gs://firezone-prod-artifacts/${image}/${{ env.VERSION }}/${arch}.sha256sum.txt
# Copy binaries
gcloud storage cp \
gs://firezone-staging-artifacts/${{ matrix.name.artifact }}/${{ env.VERSION }}-${{ inputs.sha }}/${{ matrix.arch.shortname }} \
gs://firezone-prod-artifacts/${image}/latest/${arch}
gcloud storage cp \
gs://firezone-staging-artifacts/${{ matrix.name.artifact }}/${{ env.VERSION }}-${{ inputs.sha }}/${{ matrix.arch.shortname }} \
gs://firezone-prod-artifacts/${image}/${{ env.VERSION }}/${arch}
done
done

View File

@@ -9,6 +9,15 @@ FIREZONE_TOKEN=${FIREZONE_TOKEN:-}
FIREZONE_API_URL=${FIREZONE_API_URL:-wss://api.firezone.dev}
RUST_LOG=${RUST_LOG:-str0m=warn,info}
# Can be used to download a specific version of the gateway from a custom URL
FIREZONE_VERSION=${FIREZONE_VERSION:-latest}
FIREZONE_ARTIFACT_URL=${FIREZONE_ARTIFACT_URL:-https://www.firezone.dev/dl/firezone-gateway}
# Optional environment variables to configure logging and tracing
FIREZONE_OTLP_GRPC_ENDPOINT=${OTLP_GRPC_ENDPOINT:-}
FIREZONE_GOOGLE_CLOUD_PROJECT_ID=${GOOGLE_CLOUD_PROJECT_ID:-}
FIREZONE_LOG_FORMAT=${FIREZONE_LOG_FORMAT:-}
if [ -z "$FIREZONE_TOKEN" ]; then
echo "FIREZONE_TOKEN is required"
exit 1
@@ -32,9 +41,12 @@ Environment="FIREZONE_ID=$FIREZONE_ID"
Environment="FIREZONE_TOKEN=$FIREZONE_TOKEN"
Environment="FIREZONE_API_URL=$FIREZONE_API_URL"
Environment="RUST_LOG=$RUST_LOG"
Environment="LOG_FORMAT=$FIREZONE_LOG_FORMAT"
Environment="GOOGLE_CLOUD_PROJECT_ID=$FIREZONE_GOOGLE_CLOUD_PROJECT_ID"
Environment="OTLP_GRPC_ENDPOINT=$FIREZONE_OTLP_GRPC_ENDPOINT"
ExecStartPre=/usr/local/bin/firezone-gateway-init
ExecStart=/usr/bin/sudo \
--preserve-env=FIREZONE_NAME,FIREZONE_ID,FIREZONE_TOKEN,FIREZONE_API_URL,RUST_LOG \
--preserve-env=FIREZONE_NAME,FIREZONE_ID,FIREZONE_TOKEN,FIREZONE_API_URL,RUST_LOG,LOG_FORMAT,GOOGLE_CLOUD_PROJECT_ID,OTLP_GRPC_ENDPOINT \
-u firezone \
-g firezone \
/usr/local/bin/firezone-gateway
@@ -53,19 +65,20 @@ cat <<EOF | sudo tee /usr/local/bin/firezone-gateway-init
set -ue
# Download latest version of the gateway if it doesn't already exist
# Download ${FIREZONE_VERSION} version of the gateway if it doesn't already exist
if [ ! -e /usr/local/bin/firezone-gateway ]; then
echo "/usr/local/bin/firezone-gateway not found. Downloading latest version..."
echo "/usr/local/bin/firezone-gateway not found."
echo "Downloading ${FIREZONE_VERSION} version from ${FIREZONE_ARTIFACT_URL}..."
arch=\$(uname -m)
# See https://www.github.com/firezone/firezone/releases for available binaries
curl -fsSL https://www.firezone.dev/dl/firezone-gateway/latest/\$arch -o /tmp/firezone-gateway
curl -fsSL ${FIREZONE_ARTIFACT_URL}/${FIREZONE_VERSION}/\$arch -o /tmp/firezone-gateway
if file /tmp/firezone-gateway | grep -q "executable"; then
mv /tmp/firezone-gateway /usr/local/bin/firezone-gateway
else
echo "/tmp/firezone-gateway is not an executable!"
echo "Ensure 'https://www.firezone.dev/dl/firezone-gateway/latest/\$arch' is accessible from this machine,"
echo "Ensure '${FIREZONE_ARTIFACT_URL}/${FIREZONE_VERSION}/\$arch' is accessible from this machine,"
echo "or download binary manually and install to /usr/local/bin/firezone-gateway."
exit 1
fi
@@ -110,3 +123,6 @@ sudo systemctl enable firezone-gateway
# Start the service
sudo systemctl start firezone-gateway
echo "Firezone Gateway installed successfully!"
echo "Run 'sudo systemctl status firezone-gateway' to check the status."

View File

@@ -24,42 +24,42 @@ provider "registry.terraform.io/cyrilgdn/postgresql" {
}
provider "registry.terraform.io/hashicorp/google" {
version = "5.20.0"
version = "5.27.0"
constraints = "~> 5.20"
hashes = [
"h1:zVFayCyqprY+NCbUCWe9RgpH3BGuAtOyLzqhA8f3VE8=",
"zh:10197fce4ddf2be32717fb3a5992b45ee1a134f8c66207ba7a2d89339bcad17e",
"zh:428c22bc9ae637adaa3c99e7ec2f5df3828c1625cebfc0ef680e520abdaff820",
"zh:4474139669a13997abd3d8282dc00905a08c695895b1b3d09e5a87753be54a24",
"zh:4bcd7a09577303d71146899f70413a7376531c940015eb6bfa047df55778d2ef",
"zh:5c5083c8deae3093a63d9a7ff18844985e35f2108fca49a812be85f3ec8e7409",
"zh:72ab7bf2a7a1ae98bf1ed790cc3babcd6399db58aa2c9bcef005f9b709b8ad98",
"zh:95cf50e8aa4fe5495b983aca1478cd7909fafc92c0e1942b764343076f367e3f",
"zh:9efd8613897beee98c11befc1f8ebfea14b5a0e88b0fdd2f737a1a2acd5e2a2f",
"zh:b91ddced2f7916338e1f7d0fa003a15bb5700d8d4f389d906f2944334d67bbc2",
"zh:db0270eb90eda9ce98668afc517365d5876c81bb12f0375d6837d204231f6df5",
"h1:WCDkdISBBLVlW4PyIkNn0hr4XMSL3ZZNKBsZ/MKFqRc=",
"zh:08301af898c1a78e78ad547482d50c95a43ef65d09fd5058800cf32cd9c8cd53",
"zh:1a4f9e5134e990132978e78ea15431d32e06bf8024fd6733a98faa811ae03efb",
"zh:383e66659d69dc4b4a1ad5d7cbc6aa4ce75015f380cfb5f47beaeb506c9e2e1c",
"zh:3aa4aff7dd9240fb387271dc791e084d010044dc58336a7a690b0f1a8890ab68",
"zh:4084b9a61e662bdd79d1304432dffc6cd3cf00021b937b01001ae9fee5727b12",
"zh:448f5d281cab53caacb8759fcd3309c7aa1ba5a210d1866b28e8bd77fd4634ab",
"zh:75457a1f0b77bc7477efe58e7b223649340147fd735ed8b8fe57a06ec8459c95",
"zh:7648c6ea04d5b1d1413cce880ed77bd7373aef1a58cd5a26394edf64dc6cac11",
"zh:b43630367e29a4c185d3eab8b3f84f818e8a91f16007f0e81d876ab96af4ee43",
"zh:b478e7d36c5e99f0c026cb05c06047ce1f24fc07284692a10e74214a853e7139",
"zh:e6f349125299401049f64e608b3d73236b139e960816fffdd208d1ba405e1804",
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
"zh:f58e490c192698ff8655081d467e57ee13558aa47f950f1d249318bf5cc93e5e",
]
}
provider "registry.terraform.io/hashicorp/google-beta" {
version = "5.20.0"
version = "5.27.0"
constraints = "~> 5.20"
hashes = [
"h1:NV6nLDJYo9Y0d06ggDM05WJapYg0rFF52RmjxGkD+88=",
"zh:2792639ca660f373ce0c0d152f28d1d2e59b590c19d960eddea3c7b70be2e811",
"zh:5a29c775934d5fdf3960687222b0c1505741104ade9a94e42a11d6bef73c1656",
"zh:71fcdf323e7e5bf91d12450ad7f948eef3df935e1875764d5f3c6316b57faa1b",
"zh:89ca5d8cb4d17d7855b7ee7c347a3bb57d5c935c4cc6d18ac78098c9c1c6008a",
"zh:c2a1e2d093ade9a5a4d5170fa4d439c2542f7d01a114af2a5a92b071268d193e",
"zh:c4999b0bb00ce68bea7b203fdd6685c8133f7593d8ce7a9214cedac4844c22b0",
"zh:c912e8f6baa182780678b1caf44863e7d829942c0e9f4a3f04bd623e1bf5f430",
"zh:d553df714bc0d94b3bcdba37a3fca2eb099d7e494502a64a20b3d0f5213b979b",
"zh:d92266f87f3679b179a238b2a3df5309da6b9d86bdcb9311cce5f4b9537938fb",
"zh:e0daa80c3691c6b977c64d22a0c4f6e180d5d3dc888306f7057adb179baab761",
"h1:Q1TtRjUkcIULvyinqWEVRl+r8VaS5Bqa/EXsWNe7CfE=",
"zh:074d29ba9a70de197f14bbed7cb418209764a491e2dcba52aebb7299e8dc7c12",
"zh:68638b88b9059fcb7931f2b7e3e136a3cfd3d974d0d424c5435aafaf6ea188b5",
"zh:9a1770398dddfdced4d42c9e2d6551dbc38937f733e00cbc0faba2944dd14443",
"zh:9cc072528ed4a3163025135f3d2026a6f2f8e8472e3188822fe1e0721f9e5359",
"zh:a441ce8a1fe57cb538d8b4301f7d9045bec0e7d796b962d2c97fd47bf9daf4f0",
"zh:a704bf6682d0db7c5578d39880f9081da6b81d458547f97f15c59ee94f5638a3",
"zh:ab548b6bc8508eeebf6da8cf577758ff5b078d0b655b1a76940b9cc7f107d3b1",
"zh:b15c056b140a8ea330efd277253d02930eec350b06831c526cd5a78cf25cd39e",
"zh:df79906421ab1d6ff733d9c167875afaafbda3d0e9f58fe581c0c9010523bbce",
"zh:ea75a33508d17132152ae3543f981359b215a586ae864546e7b45976de374e1b",
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
"zh:fee824aeb0f16837d3aaeadbabdf9e40d162344415acba8c521e43cf76d0efa8",
"zh:f734a884346550d5ce0e4563294572ae7546773ced9c1314ed21901f24b9041e",
]
}
@@ -84,22 +84,22 @@ provider "registry.terraform.io/hashicorp/null" {
}
provider "registry.terraform.io/hashicorp/random" {
version = "3.6.0"
constraints = "~> 3.5"
version = "3.6.1"
constraints = "~> 3.6"
hashes = [
"h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=",
"zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d",
"zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211",
"zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829",
"zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d",
"zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055",
"h1:a+Goawwh6Qtg4/bRWzfDtIdrEFfPlnVy0y4LdUQY3nI=",
"zh:2a0ec154e39911f19c8214acd6241e469157489fc56b6c739f45fbed5896a176",
"zh:57f4e553224a5e849c99131f5e5294be3a7adcabe2d867d8a4fef8d0976e0e52",
"zh:58f09948c608e601bd9d0a9e47dcb78e2b2c13b4bda4d8f097d09152ea9e91c5",
"zh:5c2a297146ed6fb3fe934c800e78380f700f49ff24dbb5fb5463134948e3a65f",
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
"zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17",
"zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21",
"zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839",
"zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0",
"zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c",
"zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e",
"zh:7ce41e26f0603e31cdac849085fc99e5cd5b3b73414c6c6d955c0ceb249b593f",
"zh:8c9e8d30c4ef08ee8bcc4294dbf3c2115cd7d9049c6ba21422bd3471d92faf8a",
"zh:93e91be717a7ffbd6410120eb925ebb8658cc8f563de35a8b53804d33c51c8b0",
"zh:982542e921970d727ce10ed64795bf36c4dec77a5db0741d4665230d12250a0d",
"zh:b9d1873f14d6033e216510ef541c891f44d249464f13cc07d3f782d09c7d18de",
"zh:cfe27faa0bc9556391c8803ade135a5856c34a3fe85b9ae3bdd515013c0c87c1",
"zh:e4aabf3184bbb556b89e4b195eab1514c86a2914dd01c23ad9813ec17e863a8a",
]
}

View File

@@ -19,18 +19,13 @@ module "gateways" {
compute_instance_replicas = 2
container_registry = module.google-artifact-registry.url
image_repo = module.google-artifact-registry.repo
image = "gateway"
image_tag = local.gateway_image_tag
observability_log_level = "debug"
application_name = "gateway"
observability_log_level = "info"
name = "gateway"
api_url = "wss://api.${local.tld}"
token = var.gateway_token
vsn = local.gateway_image_tag
}
# Allow gateways to access the Metabase

View File

@@ -109,6 +109,43 @@ module "google-artifact-registry" {
]
}
# Bucket where CI stores binary artifacts (eg. gateway or client)
resource "google_storage_bucket" "firezone-binary-artifacts" {
project = module.google-cloud-project.project.project_id
name = "${module.google-cloud-project.project.project_id}-artifacts"
location = "US"
lifecycle_rule {
condition {
age = 365
}
action {
type = "Delete"
}
}
lifecycle_rule {
condition {
age = 1
}
action {
type = "AbortIncompleteMultipartUpload"
}
}
public_access_prevention = "inherited"
uniform_bucket_level_access = true
}
resource "google_storage_bucket_iam_member" "public-firezone-binary-artifacts" {
bucket = google_storage_bucket.firezone-binary-artifacts.name
role = "roles/storage.objectViewer"
member = "allUsers"
}
# Create a VPC
module "google-cloud-vpc" {
source = "../../modules/google-cloud/vpc"

View File

@@ -24,65 +24,65 @@ provider "registry.terraform.io/cyrilgdn/postgresql" {
}
provider "registry.terraform.io/hashicorp/aws" {
version = "5.41.0"
version = "5.47.0"
constraints = ">= 3.29.0, >= 5.30.0"
hashes = [
"h1:DiX7N35G2NUQRyRGy90+gyePnhP4w77f8LrJUronotE=",
"zh:0553331a6287c146353b6daf6f71987d8c000f407b5e29d6e004ea88faec2e67",
"zh:1a11118984bb2950e8ee7ef17b0f91fc9eb4a42c8e7a9cafd7eb4aca771d06e4",
"zh:236fedd266d152a8233a7fe27ffdd99ca27d9e66a9618a988a4c3da1ac24a33f",
"zh:34bc482ea04cf30d4d216afa55eecf66854e1acf93892cb28a6b5af91d43c9b7",
"zh:39d7eb15832fe339bf46e3bab9852280762a1817bf1afc459eecd430e20e3ad5",
"zh:39fb07429c51556b05170ec2b6bd55e2487adfe1606761eaf1f2a43c4bb20e47",
"zh:71d7cd3013e2f3fa0f65194af29ee6f5fa905e0df2b72b723761dc953f4512ea",
"h1:T0tupfn2Ubj18Y7xmO0pFMvti1Qns2K6EGXenR6Hg30=",
"zh:06037a14e47e8f82d0b3b326cd188566272b808b7970a9249a11db26d475b83d",
"zh:116b7dd58ca964a1056249d2b6550f399b0a6bc9a7920b7ee134242114432c9f",
"zh:1aa089c81459071c1d65ba7454f1122159e1fa1b5384e6e9ef85c8264f8a9ecb",
"zh:2c1471acba40c4944aa88dda761093c0c969db6408bdc1a4fb62417788cd6bb6",
"zh:3b950bea06ea4bf1ec359a97a4f1745b7efca7fc2da368843666020dd0ebc5d4",
"zh:7191c5c2fce834d584153dcd5269ed3042437f224d341ad85df06b2247bd09b2",
"zh:76d841b3f247f9bb3899dec3b4d871613a4ae8a83a581a827655d34b1bbee0ee",
"zh:7c656ce252fafc2c915dad43a0a7da17dba975207d75841a02f3f2b92d51ec25",
"zh:8ec97118cbdef64139c52b719e4e22443e67a1f37ea1597cd45b2e9b97332a35",
"zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
"zh:9b271ae12394e7e2ce6da568b42226a146e90fd705e02a670fcb93618c4aa19f",
"zh:a884dd978859d001709681f9513ba0fbb0753d1d459a7f3434ecc5f1b8699c49",
"zh:b8c3c7dc10ae4f6143168042dcf8dee63527b103cc37abc238ea06150af38b6e",
"zh:ba94ffe0893ad60c0b70c402e163b4df2cf417e93474a9cc1a37535bba18f22d",
"zh:d5ba851d971ff8d796afd9a100acf55eaac0c197c6ab779787797ce66f419f0e",
"zh:e8c090d0c4f730c4a610dc4f0c22b177a0376d6f78679fc3f1d557b469e656f4",
"zh:ed7623acde26834672969dcb5befdb62900d9f216d32e7478a095d2b040a0ea7",
"zh:a369deca7938236a7da59f7ad1fe18137f736764c9015ed10e88edb6e8505980",
"zh:a743882fb099401eae0c86d9388a6faadbbc27b2ac9477aeef643e5de4eec3f9",
"zh:d5f960f58aff06fc58e244fea6e665800384cacb8cd64a556f8e145b98650372",
"zh:e31ffcfd560132ffbff2f574928ba392e663202a750750ed39a8950031b75623",
"zh:ebd9061b92a772144564f35a63d5a08cb45e14a9d39294fda185f2e0de9c8e28",
]
}
provider "registry.terraform.io/hashicorp/google" {
version = "5.20.0"
constraints = "~> 5.2"
version = "5.27.0"
constraints = "~> 5.20"
hashes = [
"h1:zVFayCyqprY+NCbUCWe9RgpH3BGuAtOyLzqhA8f3VE8=",
"zh:10197fce4ddf2be32717fb3a5992b45ee1a134f8c66207ba7a2d89339bcad17e",
"zh:428c22bc9ae637adaa3c99e7ec2f5df3828c1625cebfc0ef680e520abdaff820",
"zh:4474139669a13997abd3d8282dc00905a08c695895b1b3d09e5a87753be54a24",
"zh:4bcd7a09577303d71146899f70413a7376531c940015eb6bfa047df55778d2ef",
"zh:5c5083c8deae3093a63d9a7ff18844985e35f2108fca49a812be85f3ec8e7409",
"zh:72ab7bf2a7a1ae98bf1ed790cc3babcd6399db58aa2c9bcef005f9b709b8ad98",
"zh:95cf50e8aa4fe5495b983aca1478cd7909fafc92c0e1942b764343076f367e3f",
"zh:9efd8613897beee98c11befc1f8ebfea14b5a0e88b0fdd2f737a1a2acd5e2a2f",
"zh:b91ddced2f7916338e1f7d0fa003a15bb5700d8d4f389d906f2944334d67bbc2",
"zh:db0270eb90eda9ce98668afc517365d5876c81bb12f0375d6837d204231f6df5",
"h1:WCDkdISBBLVlW4PyIkNn0hr4XMSL3ZZNKBsZ/MKFqRc=",
"zh:08301af898c1a78e78ad547482d50c95a43ef65d09fd5058800cf32cd9c8cd53",
"zh:1a4f9e5134e990132978e78ea15431d32e06bf8024fd6733a98faa811ae03efb",
"zh:383e66659d69dc4b4a1ad5d7cbc6aa4ce75015f380cfb5f47beaeb506c9e2e1c",
"zh:3aa4aff7dd9240fb387271dc791e084d010044dc58336a7a690b0f1a8890ab68",
"zh:4084b9a61e662bdd79d1304432dffc6cd3cf00021b937b01001ae9fee5727b12",
"zh:448f5d281cab53caacb8759fcd3309c7aa1ba5a210d1866b28e8bd77fd4634ab",
"zh:75457a1f0b77bc7477efe58e7b223649340147fd735ed8b8fe57a06ec8459c95",
"zh:7648c6ea04d5b1d1413cce880ed77bd7373aef1a58cd5a26394edf64dc6cac11",
"zh:b43630367e29a4c185d3eab8b3f84f818e8a91f16007f0e81d876ab96af4ee43",
"zh:b478e7d36c5e99f0c026cb05c06047ce1f24fc07284692a10e74214a853e7139",
"zh:e6f349125299401049f64e608b3d73236b139e960816fffdd208d1ba405e1804",
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
"zh:f58e490c192698ff8655081d467e57ee13558aa47f950f1d249318bf5cc93e5e",
]
}
provider "registry.terraform.io/hashicorp/google-beta" {
version = "5.20.0"
constraints = "~> 5.2"
version = "5.27.0"
constraints = "~> 5.20"
hashes = [
"h1:NV6nLDJYo9Y0d06ggDM05WJapYg0rFF52RmjxGkD+88=",
"zh:2792639ca660f373ce0c0d152f28d1d2e59b590c19d960eddea3c7b70be2e811",
"zh:5a29c775934d5fdf3960687222b0c1505741104ade9a94e42a11d6bef73c1656",
"zh:71fcdf323e7e5bf91d12450ad7f948eef3df935e1875764d5f3c6316b57faa1b",
"zh:89ca5d8cb4d17d7855b7ee7c347a3bb57d5c935c4cc6d18ac78098c9c1c6008a",
"zh:c2a1e2d093ade9a5a4d5170fa4d439c2542f7d01a114af2a5a92b071268d193e",
"zh:c4999b0bb00ce68bea7b203fdd6685c8133f7593d8ce7a9214cedac4844c22b0",
"zh:c912e8f6baa182780678b1caf44863e7d829942c0e9f4a3f04bd623e1bf5f430",
"zh:d553df714bc0d94b3bcdba37a3fca2eb099d7e494502a64a20b3d0f5213b979b",
"zh:d92266f87f3679b179a238b2a3df5309da6b9d86bdcb9311cce5f4b9537938fb",
"zh:e0daa80c3691c6b977c64d22a0c4f6e180d5d3dc888306f7057adb179baab761",
"h1:Q1TtRjUkcIULvyinqWEVRl+r8VaS5Bqa/EXsWNe7CfE=",
"zh:074d29ba9a70de197f14bbed7cb418209764a491e2dcba52aebb7299e8dc7c12",
"zh:68638b88b9059fcb7931f2b7e3e136a3cfd3d974d0d424c5435aafaf6ea188b5",
"zh:9a1770398dddfdced4d42c9e2d6551dbc38937f733e00cbc0faba2944dd14443",
"zh:9cc072528ed4a3163025135f3d2026a6f2f8e8472e3188822fe1e0721f9e5359",
"zh:a441ce8a1fe57cb538d8b4301f7d9045bec0e7d796b962d2c97fd47bf9daf4f0",
"zh:a704bf6682d0db7c5578d39880f9081da6b81d458547f97f15c59ee94f5638a3",
"zh:ab548b6bc8508eeebf6da8cf577758ff5b078d0b655b1a76940b9cc7f107d3b1",
"zh:b15c056b140a8ea330efd277253d02930eec350b06831c526cd5a78cf25cd39e",
"zh:df79906421ab1d6ff733d9c167875afaafbda3d0e9f58fe581c0c9010523bbce",
"zh:ea75a33508d17132152ae3543f981359b215a586ae864546e7b45976de374e1b",
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
"zh:fee824aeb0f16837d3aaeadbabdf9e40d162344415acba8c521e43cf76d0efa8",
"zh:f734a884346550d5ce0e4563294572ae7546773ced9c1314ed21901f24b9041e",
]
}
@@ -107,22 +107,22 @@ provider "registry.terraform.io/hashicorp/null" {
}
provider "registry.terraform.io/hashicorp/random" {
version = "3.6.0"
constraints = "~> 3.5"
version = "3.6.1"
constraints = "~> 3.6"
hashes = [
"h1:I8MBeauYA8J8yheLJ8oSMWqB0kovn16dF/wKZ1QTdkk=",
"zh:03360ed3ecd31e8c5dac9c95fe0858be50f3e9a0d0c654b5e504109c2159287d",
"zh:1c67ac51254ba2a2bb53a25e8ae7e4d076103483f55f39b426ec55e47d1fe211",
"zh:24a17bba7f6d679538ff51b3a2f378cedadede97af8a1db7dad4fd8d6d50f829",
"zh:30ffb297ffd1633175d6545d37c2217e2cef9545a6e03946e514c59c0859b77d",
"zh:454ce4b3dbc73e6775f2f6605d45cee6e16c3872a2e66a2c97993d6e5cbd7055",
"h1:a+Goawwh6Qtg4/bRWzfDtIdrEFfPlnVy0y4LdUQY3nI=",
"zh:2a0ec154e39911f19c8214acd6241e469157489fc56b6c739f45fbed5896a176",
"zh:57f4e553224a5e849c99131f5e5294be3a7adcabe2d867d8a4fef8d0976e0e52",
"zh:58f09948c608e601bd9d0a9e47dcb78e2b2c13b4bda4d8f097d09152ea9e91c5",
"zh:5c2a297146ed6fb3fe934c800e78380f700f49ff24dbb5fb5463134948e3a65f",
"zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
"zh:91df0a9fab329aff2ff4cf26797592eb7a3a90b4a0c04d64ce186654e0cc6e17",
"zh:aa57384b85622a9f7bfb5d4512ca88e61f22a9cea9f30febaa4c98c68ff0dc21",
"zh:c4a3e329ba786ffb6f2b694e1fd41d413a7010f3a53c20b432325a94fa71e839",
"zh:e2699bc9116447f96c53d55f2a00570f982e6f9935038c3810603572693712d0",
"zh:e747c0fd5d7684e5bfad8aa0ca441903f15ae7a98a737ff6aca24ba223207e2c",
"zh:f1ca75f417ce490368f047b63ec09fd003711ae48487fba90b4aba2ccf71920e",
"zh:7ce41e26f0603e31cdac849085fc99e5cd5b3b73414c6c6d955c0ceb249b593f",
"zh:8c9e8d30c4ef08ee8bcc4294dbf3c2115cd7d9049c6ba21422bd3471d92faf8a",
"zh:93e91be717a7ffbd6410120eb925ebb8658cc8f563de35a8b53804d33c51c8b0",
"zh:982542e921970d727ce10ed64795bf36c4dec77a5db0741d4665230d12250a0d",
"zh:b9d1873f14d6033e216510ef541c891f44d249464f13cc07d3f782d09c7d18de",
"zh:cfe27faa0bc9556391c8803ade135a5856c34a3fe85b9ae3bdd515013c0c87c1",
"zh:e4aabf3184bbb556b89e4b195eab1514c86a2914dd01c23ad9813ec17e863a8a",
]
}

View File

@@ -1,7 +1,7 @@
# Bucket where CI stores binary artifacts (eg. gateway or client)
resource "google_storage_bucket" "firezone-binaries" {
resource "google_storage_bucket" "firezone-binary-artifacts" {
project = module.google-cloud-project.project.project_id
name = "firezone-binaries"
name = "${module.google-cloud-project.project.project_id}-artifacts"
location = "US"
@@ -29,8 +29,8 @@ resource "google_storage_bucket" "firezone-binaries" {
uniform_bucket_level_access = true
}
resource "google_storage_bucket_iam_member" "public-firezone-binaries" {
bucket = google_storage_bucket.firezone-binaries.name
resource "google_storage_bucket_iam_member" "public-firezone-binary-artifacts" {
bucket = google_storage_bucket.firezone-binary-artifacts.name
role = "roles/storage.objectViewer"
member = "allUsers"
}
@@ -155,10 +155,10 @@ resource "google_storage_bucket_iam_member" "github-actions-sccache-access" {
member = each.key
}
resource "google_storage_bucket_iam_member" "github-actions-firezone-binaries-access" {
resource "google_storage_bucket_iam_member" "github-actions-firezone-binary-artifacts-access" {
for_each = toset(local.ci_iam_members)
bucket = google_storage_bucket.firezone-binaries.name
bucket = google_storage_bucket.firezone-binary-artifacts.name
role = "roles/storage.objectAdmin"
member = each.key
}

View File

@@ -1,113 +1,39 @@
# This module deploys an empty VM ready to run Docker commands to deploy our Relay or Gateway,
# it's used weekly for internal demos and testing, and reset after each use by rebooting the VM.
data "google_compute_image" "demo" {
family = "ubuntu-2204-lts"
project = "ubuntu-os-cloud"
}
module "demo" {
source = "../../modules/google-cloud/apps/vm"
resource "google_service_account" "demo" {
project = module.google-cloud-project.project.project_id
project_id = module.google-cloud-project.project.project_id
account_id = "demo-instance"
display_name = "Custom Service Account for a Demo VM Instance"
}
compute_network = module.google-cloud-vpc.id
compute_subnetwork = google_compute_subnetwork.apps.self_link
resource "google_compute_instance" "demo" {
project = module.google-cloud-project.project.project_id
compute_region = local.region
compute_instance_availability_zone = "${local.region}-d"
name = "demo"
machine_type = "n1-standard-1"
zone = "${local.region}-d"
compute_instance_type = "f1-micro"
tags = ["demo"]
boot_disk {
auto_delete = true
initialize_params {
image = data.google_compute_image.demo.self_link
labels = {
managed_by = "terraform"
}
}
}
network_interface {
subnetwork = google_compute_subnetwork.apps.self_link
access_config {
// Ephemeral public IP
}
}
metadata = {
google-logging-enabled = "true"
google-logging-use-fluentbit = "true"
# Report health-related metrics to Cloud Monitoring
google-monitoring-enabled = "true"
}
# We can install any tools we need for the demo in the startup script
metadata_startup_script = <<EOT
set -xe \
&& sudo apt update -y \
&& sudo apt install postgresql-client jq iperf3 -y \
&& sudo apt install apt-transport-https ca-certificates curl software-properties-common -y \
&& curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
| sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \
&& echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null \
&& sudo apt update -y \
&& sudo apt install docker-ce docker-ce-cli containerd.io -y \
&& sudo usermod -aG docker $(whoami) \
&& sudo systemctl enable docker \
&& sudo systemctl start docker \
&& sudo docker run -d --restart always --name=httpbin -p 80:80 kennethreitz/httpbin \
&& echo ${module.metabase.internal_ip} metabase.fz >> /etc/hosts \
&& echo 127.0.0.1 host.firezone.local >> /etc/hosts \
&& curl -sSO https://dl.google.com/cloudagents/add-google-cloud-ops-agent-repo.sh \
&& sudo bash add-google-cloud-ops-agent-repo.sh \
&& sudo apt-get update \
&& sudo apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" install google-cloud-ops-agent
vm_name = "demo"
vm_network_tag = "app-demo"
cloud_init = <<EOT
#cloud-config
runcmd:
- sudo apt install postgresql-client jq iperf3 -y
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
| sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
- echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
- sudo apt update -y
- sudo apt install docker-ce docker-ce-cli containerd.io -y
- sudo usermod -aG docker $(whoami)
- sudo systemctl enable docker
- sudo systemctl start docker
- sudo docker run -d --restart always --name=httpbin -p 80:80 kennethreitz/httpbin
- echo ${module.metabase.internal_ip} metabase.fz >> /etc/hosts
- echo 127.0.0.1 host.firezone.local >> /etc/hosts
EOT
allow_stopping_for_update = true
service_account {
# Google recommends custom service accounts that have cloud-platform scope and permissions granted via IAM Roles.
email = google_service_account.demo.email
scopes = ["cloud-platform"]
}
}
# Grant demo users access to demo instance
resource "google_compute_instance_iam_binding" "demo-os-login" {
project = module.google-cloud-project.project.project_id
zone = google_compute_instance.demo.zone
instance_name = google_compute_instance.demo.name
role = "roles/compute.osAdminLogin"
members = formatlist("user:%s", local.demo_access)
}
resource "google_compute_instance_iam_binding" "demo-instance-admin" {
project = module.google-cloud-project.project.project_id
zone = google_compute_instance.demo.zone
instance_name = google_compute_instance.demo.name
role = "roles/compute.instanceAdmin.v1"
members = formatlist("user:%s", local.demo_access)
}
resource "google_project_iam_binding" "demo-proejct-sa" {
project = module.google-cloud-project.project.project_id
role = "roles/iam.serviceAccountUser"
members = formatlist("user:%s", local.demo_access)
}
# Create a demo DB and PostgreSQL user so that we can demo accessing the database
@@ -181,5 +107,5 @@ resource "google_compute_firewall" "demo-ssh-ipv4" {
}
source_ranges = ["0.0.0.0/0"]
target_tags = google_compute_instance.demo.tags
target_tags = module.demo.target_tags
}

View File

@@ -4,60 +4,18 @@ data "google_compute_zones" "in_region" {
}
locals {
application_name = var.application_name != null ? var.application_name : var.image
application_version = var.application_version != null ? var.application_version : replace(var.image_tag, ".", "-")
application_labels = merge({
labels = merge({
managed_by = "terraform"
application = local.application_name
}, var.application_labels)
application = "firezone-gateway"
}, var.labels)
application_tags = ["app-${local.application_name}"]
network_tags = ["firezone-gateways-${var.name}"]
google_health_check_ip_ranges = [
"130.211.0.0/22",
"35.191.0.0/16",
]
environment_variables = concat([
{
name = "LISTEN_ADDRESS_DISCOVERY_METHOD"
value = "gce_metadata"
},
{
name = "RUST_LOG"
value = var.observability_log_level
},
{
name = "RUST_BACKTRACE"
value = "full"
},
{
name = "LOG_FORMAT"
value = "google-cloud"
},
{
name = "GOOGLE_CLOUD_PROJECT_ID"
value = var.project_id
},
{
name = "OTLP_GRPC_ENDPOINT"
value = "127.0.0.1:4317"
},
{
name = "FIREZONE_TOKEN"
value = var.token
},
{
name = "FIREZONE_API_URL"
value = var.api_url
},
{
name = "FIREZONE_ENABLE_MASQUERADE"
value = "1"
}
], var.application_environment_variables)
compute_region_zones = length(var.compute_instance_availability_zones) == 0 ? data.google_compute_zones.in_region.names : var.compute_instance_availability_zones
}
@@ -71,20 +29,20 @@ data "google_compute_image" "ubuntu" {
resource "google_compute_instance_template" "application" {
project = var.project_id
name_prefix = "${local.application_name}-"
name_prefix = "${var.name}-"
description = "This template is used to create ${local.application_name} instances."
description = "This template is used to create ${var.name} Firezone Gateway instances."
machine_type = var.compute_instance_type
can_ip_forward = true
tags = local.application_tags
tags = local.network_tags
labels = merge({
container-vm = data.google_compute_image.ubuntu.name
version = local.application_version
}, local.application_labels)
version = var.vsn
}, local.labels)
scheduling {
automatic_restart = true
@@ -144,9 +102,13 @@ resource "google_compute_instance_template" "application" {
metadata = {
user-data = templatefile("${path.module}/templates/cloud-init.yaml", {
container_name = local.application_name != null ? local.application_name : var.image
container_image = "${var.container_registry}/${var.image_repo}/${var.image}:${var.image_tag}"
container_environment = local.environment_variables
project_id = var.project_id
otlp_grpc_endpoint = "127.0.0.1:4317"
firezone_token = var.token
firezone_api_url = var.api_url
firezone_version = var.vsn
firezone_artifact_url = "https://storage.googleapis.com/firezone-prod-artifacts/firezone-gateway"
})
google-logging-enabled = "true"
@@ -184,7 +146,7 @@ resource "google_compute_instance_template" "application" {
resource "google_compute_health_check" "port" {
project = var.project_id
name = "${local.application_name}-${var.health_check.name}"
name = "${var.name}-${var.health_check.name}"
check_interval_sec = var.health_check.check_interval_sec != null ? var.health_check.check_interval_sec : 5
timeout_sec = var.health_check.timeout_sec != null ? var.health_check.timeout_sec : 5
@@ -212,9 +174,9 @@ resource "google_compute_health_check" "port" {
resource "google_compute_region_instance_group_manager" "application" {
project = var.project_id
name = "${local.application_name}-${var.compute_region}"
name = "${var.name}-${var.compute_region}"
base_instance_name = local.application_name
base_instance_name = var.name
region = var.compute_region
distribution_policy_zones = local.compute_region_zones
@@ -225,7 +187,7 @@ resource "google_compute_region_instance_group_manager" "application" {
wait_for_instances_status = "STABLE"
version {
name = local.application_version
name = var.vsn
instance_template = google_compute_instance_template.application.self_link
}
@@ -258,11 +220,11 @@ resource "google_compute_region_instance_group_manager" "application" {
resource "google_compute_firewall" "http-health-checks" {
project = var.project_id
name = "${local.application_name}-healthcheck"
name = "${var.name}-healthcheck"
network = var.compute_network
source_ranges = local.google_health_check_ip_ranges
target_tags = local.application_tags
target_tags = local.network_tags
allow {
protocol = var.health_check.protocol

View File

@@ -1,165 +1,50 @@
#cloud-config
users:
- name: cloudservice
uid: 2000
package_update: true
package_upgrade: true
package_reboot_if_required: true
packages:
- apt-transport-https
- ca-certificates
- software-properties-common
write_files:
- path: /etc/otelcol-contrib/config.yaml
- path: /etc/apt/keyrings
permissions: "0755"
owner: root:root
content: ""
- path: /etc/google-cloud-ops-agent/config.yaml
permissions: "0644"
owner: root
content: |
receivers:
otlp:
protocols:
grpc:
endpoint: localhost:4317
exporters:
googlecloud:
log:
default_log_name: opentelemetry.io/collector-exported-log
processors:
memory_limiter:
check_interval: 1s
limit_percentage: 65
spike_limit_percentage: 20
batch:
resourcedetection:
detectors: [gcp]
timeout: 10s
transform:
# Several metrics labels are reserved on Google Cloud. We need to prefix them with `exported_` to prevent the exporter from failing.
# See https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/exporter/googlecloudexporter/README.md#preventing-metric-label-collisions for example.
metric_statements:
- context: datapoint
statements:
- set(attributes["exported_location"], attributes["location"])
- delete_key(attributes, "location")
- set(attributes["exported_cluster"], attributes["cluster"])
- delete_key(attributes, "cluster")
- set(attributes["exported_namespace"], attributes["namespace"])
- delete_key(attributes, "namespace")
- set(attributes["exported_job"], attributes["job"])
- delete_key(attributes, "job")
- set(attributes["exported_instance"], attributes["instance"])
- delete_key(attributes, "instance")
- set(attributes["exported_project_id"], attributes["project_id"])
- delete_key(attributes, "project_id")
- set(attributes["exported_service_name"], attributes["service_name"])
- delete_key(attributes, "service_name")
- set(attributes["exported_service_namespace"], attributes["service_namespace"])
- delete_key(attributes, "service_namespace")
- set(attributes["exported_service_instance_id"], attributes["service_instance_id"])
- delete_key(attributes, "service_instance_id")
- set(attributes["exported_instrumentation_source"], attributes["instrumentation_source"])
- delete_key(attributes, "instrumentation_source")
- set(attributes["exported_instrumentation_version"], attributes["instrumentation_version"])
- delete_key(attributes, "instrumentation_version")
service:
telemetry:
logs:
level: "debug"
pipelines:
traces:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [googlecloud]
metrics:
receivers: [otlp]
processors: [memory_limiter, batch, transform]
exporters: [googlecloud]
logs:
receivers: [otlp]
processors: [memory_limiter, batch]
exporters: [googlecloud]
- path: /etc/systemd/system/otel-collector.service
permissions: "0644"
owner: root
content: |
[Unit]
Description=Start an OpenTelemetry collector docker container
[Service]
TimeoutStartSec=0
Restart=always
ExecStartPre=/usr/bin/docker pull otel/opentelemetry-collector-contrib:0.97.0
ExecStart=/usr/bin/docker run --rm -u 2000 --name=otel-collector --network host --volume /etc/otelcol-contrib/:/etc/otelcol-contrib/ otel/opentelemetry-collector-contrib:0.97.0
ExecStop=/usr/bin/docker stop otel-collector
ExecStopPost=/usr/bin/docker rm otel-collector
- path: /etc/firezone-gateway/.env
permissions: "0644"
owner: root
content: |
%{ for env in container_environment ~}
${env.name}=${env.value}
%{ endfor ~}
- path: /etc/systemd/system/gateway.service
permissions: "0644"
owner: root
content: |
[Unit]
Description=Start an Firezone Gateway container
[Service]
TimeoutStartSec=0
Restart=always
ExecStartPre=/usr/bin/docker pull ${container_image}
ExecStart=/bin/sh -c 'docker run --rm --name=${container_name} --cap-add=NET_ADMIN --publish=8080:8080 --volume /etc/firezone --device="/dev/net/tun:/dev/net/tun" --env FIREZONE_NAME=$(hostname) --env FIREZONE_ID=$(echo $RANDOM$(hostname) | md5sum | head -c 20; echo;) --env-file="/etc/firezone-gateway/.env" ${container_image}'
ExecStop=/usr/bin/docker stop gateway
ExecStopPost=/usr/bin/docker rm gateway
- path: /etc/iptables/rules.v6
permissions: "0644"
owner: root
content: |
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p ipv6-icmp -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -j ACCEPT
-A INPUT -p udp -j ACCEPT
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A FORWARD -p tcp -j ACCEPT
-A FORWARD -p udp -j ACCEPT
-A FORWARD -p ipv6-icmp -j ACCEPT
-A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
COMMIT
combined:
receivers:
otlp:
type: otlp
metrics_mode: googlecloudmonitoring
metrics:
service:
pipelines:
otlp:
receivers: [otlp]
traces:
service:
pipelines:
otlp:
receivers: [otlp]
runcmd:
- sudo apt update -y
- sudo apt install postgresql-client jq iperf3 -y
- sudo apt install apt-transport-https ca-certificates curl software-properties-common -y
- curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
- echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
- sudo apt update -y
- sudo apt install docker-ce docker-ce-cli containerd.io -y
- sudo usermod -aG docker $(whoami)
- sudo systemctl enable docker
- sudo echo '{"ipv6":true,"fixed-cidr-v6":"fd00::/80"}' > /etc/docker/daemon.json
- sudo systemctl start docker
- sudo ip6tables-restore < /etc/iptables/rules.v6
- sudo systemctl daemon-reload
- sudo systemctl start otel-collector.service
- sudo systemctl start gateway.service
# Install Ops Agent
- curl -sSO https://dl.google.com/cloudagents/add-google-cloud-ops-agent-repo.sh
- sudo bash add-google-cloud-ops-agent-repo.sh --also-install
# Install Firezone Gateway
- FIREZONE_TOKEN="${firezone_token}" \
FIREZONE_API_URL="${firezone_api_url}" \
FIREZONE_VERSION="${firezone_version}" \
FIREZONE_ARTIFACT_URL="${firezone_artifact_url}" \
FIREZONE_LOG_FORMAT="google-cloud" \
FIREZONE_GOOGLE_CLOUD_PROJECT_ID=$(project_id) \
FIREZONE_OTLP_GRPC_ENDPOINT=$(otlp_grpc_endpoint) \
bash <(curl -fsSL https://raw.githubusercontent.com/firezone/firezone/main/scripts/gateway-systemd-install.sh)

View File

@@ -45,44 +45,6 @@ variable "compute_provision_public_ipv6_address" {
description = "Whether to provision public IPv4 address for the instances."
}
################################################################################
## Container Registry
################################################################################
variable "container_registry" {
type = string
nullable = false
default = "ghcr.io"
description = "Container registry URL to pull the image from."
}
################################################################################
## Container Image
################################################################################
variable "image_repo" {
type = string
nullable = false
default = "firezone"
description = "Repo of a container image used to deploy the application."
}
variable "image" {
type = string
nullable = false
default = "gateway"
description = "Container image used to deploy the application."
}
variable "image_tag" {
type = string
nullable = false
description = "Container image used to deploy the application."
}
################################################################################
## Observability
################################################################################
@@ -96,26 +58,18 @@ variable "observability_log_level" {
}
################################################################################
## Application
## Regional Instance Group
################################################################################
variable "application_name" {
variable "name" {
type = string
nullable = true
default = "gateway"
description = "Name of the application. Defaults to value of `var.image_name` with `_` replaced to `-`."
description = "Name of the application."
}
variable "application_version" {
type = string
nullable = true
default = null
description = "Version of the application. Defaults to value of `var.image_tag`."
}
variable "application_labels" {
variable "labels" {
type = map(string)
nullable = false
default = {}
@@ -123,6 +77,33 @@ variable "application_labels" {
description = "Labels to add to all created by this module resources."
}
################################################################################
## Firezone Gateway
################################################################################
variable "token" {
type = string
description = "Portal token to use for authentication."
}
variable "api_url" {
type = string
default = "wss://api.firezone.dev"
description = "URL of the control plane endpoint."
}
variable "artifact_url" {
type = string
default = "https://storage.googleapis.com/firezone-prod-artifacts/firezone-gateway"
description = "URL from which Firezone install script will download the gateway binary"
}
variable "vsn" {
type = string
default = "latest"
description = "Version of the Firezone gateway that is downloaded from `artifact_url`."
}
variable "health_check" {
type = object({
name = string
@@ -164,30 +145,3 @@ variable "health_check" {
description = "Health check which will be used for auto healing policy."
}
variable "application_environment_variables" {
type = list(object({
name = string
value = string
}))
nullable = false
default = []
description = "List of environment variables to set for all application containers."
}
################################################################################
## Firezone
################################################################################
variable "token" {
type = string
description = "Portal token to use for authentication."
}
variable "api_url" {
type = string
default = "wss://api.firezone.dev"
description = "URL of the control plane endpoint."
}

View File

@@ -0,0 +1,54 @@
# Create IAM role for the application instances
resource "google_service_account" "application" {
project = var.project_id
account_id = "vm-${local.vm_name}"
display_name = "${local.vm_name} app"
description = "Service account for ${local.vm_name} VM."
}
## Allow fluentbit/OPS Agent to injest logs
resource "google_project_iam_member" "logs" {
project = var.project_id
role = "roles/logging.logWriter"
member = "serviceAccount:${google_service_account.application.email}"
}
## Allow reporting application errors
resource "google_project_iam_member" "errors" {
project = var.project_id
role = "roles/errorreporting.writer"
member = "serviceAccount:${google_service_account.application.email}"
}
## Allow reporting metrics
resource "google_project_iam_member" "metrics" {
project = var.project_id
role = "roles/monitoring.metricWriter"
member = "serviceAccount:${google_service_account.application.email}"
}
## Allow reporting metrics
resource "google_project_iam_member" "service_management" {
project = var.project_id
role = "roles/servicemanagement.reporter"
member = "serviceAccount:${google_service_account.application.email}"
}
## Allow appending traces
resource "google_project_iam_member" "cloudtrace" {
project = var.project_id
role = "roles/cloudtrace.agent"
member = "serviceAccount:${google_service_account.application.email}"
}

View File

@@ -0,0 +1,138 @@
locals {
vm_name = var.vm_name
vm_labels = merge({
managed_by = "terraform"
}, var.vm_labels)
vm_network_tags = [var.vm_network_tag]
google_health_check_ip_ranges = [
"130.211.0.0/22",
"35.191.0.0/16"
]
}
# Find the latest boot image
data "google_compute_image" "boot" {
family = var.boot_image_family
project = var.boot_image_project
}
# Provision an internal IPv4 address for the VM
resource "google_compute_address" "ipv4" {
project = var.project_id
region = var.compute_region
name = local.vm_name
subnetwork = var.compute_subnetwork
address_type = "INTERNAL"
}
resource "google_compute_instance" "vm" {
project = var.project_id
name = local.vm_name
description = "This template is used to create ${local.vm_name} instances."
zone = var.compute_instance_availability_zone
machine_type = var.compute_instance_type
can_ip_forward = true
tags = local.vm_network_tags
labels = merge({
boot_image_family = var.boot_image_family
boot_image_project = var.boot_image_project
}, local.vm_labels)
boot_disk {
auto_delete = true
initialize_params {
image = data.google_compute_image.boot.self_link
labels = {
managed_by = "terraform"
boot_image_family = var.boot_image_family
boot_image_project = var.boot_image_project
}
}
}
network_interface {
subnetwork = var.compute_subnetwork
stack_type = "IPV4_ONLY"
network_ip = google_compute_address.ipv4.address
access_config {
network_tier = "PREMIUM"
# Ephemeral IP address
}
}
service_account {
email = google_service_account.application.email
scopes = [
# Those are default scopes
"https://www.googleapis.com/auth/devstorage.read_only",
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring.write",
"https://www.googleapis.com/auth/service.management.readonly",
"https://www.googleapis.com/auth/servicecontrol",
"https://www.googleapis.com/auth/trace.append",
]
}
shielded_instance_config {
enable_integrity_monitoring = true
enable_secure_boot = false
enable_vtpm = true
}
metadata = {
user-data = var.cloud_init
# Report logs to Cloud Logging and errors to Cloud Error Reporting
google-logging-enabled = "true"
google-logging-use-fluentbit = "true"
# Report VM metrics to Cloud Monitoring
google-monitoring-enabled = "true"
}
# Install the Ops Agent and some other tools that are helpful for debugging (curl, jq, etc.)
metadata_startup_script = <<EOT
set -xe \
&& sudo apt update -y \
&& sudo apt install -y apt-transport-https ca-certificates curl jq software-properties-common \
&& sudo install -m 0755 -d /etc/apt/keyrings \
&& sudo apt-get update \
&& curl -sSO https://dl.google.com/cloudagents/add-google-cloud-ops-agent-repo.sh \
&& sudo bash add-google-cloud-ops-agent-repo.sh --also-install
EOT
depends_on = [
google_project_service.compute,
google_project_service.pubsub,
google_project_service.bigquery,
google_project_service.container,
google_project_service.stackdriver,
google_project_service.logging,
google_project_service.monitoring,
google_project_service.cloudprofiler,
google_project_service.cloudtrace,
google_project_service.servicenetworking,
google_project_iam_member.logs,
google_project_iam_member.errors,
google_project_iam_member.metrics,
google_project_iam_member.service_management,
google_project_iam_member.cloudtrace,
]
allow_stopping_for_update = true
}

View File

@@ -0,0 +1,15 @@
output "service_account" {
value = google_service_account.application
}
output "target_tags" {
value = local.vm_network_tags
}
output "instance" {
value = google_compute_instance.vm
}
output "internal_ipv4_address" {
value = google_compute_address.ipv4.address
}

View File

@@ -0,0 +1,83 @@
resource "google_project_service" "compute" {
project = var.project_id
service = "compute.googleapis.com"
disable_on_destroy = false
}
resource "google_project_service" "pubsub" {
project = var.project_id
service = "pubsub.googleapis.com"
disable_on_destroy = false
}
resource "google_project_service" "bigquery" {
project = var.project_id
service = "bigquery.googleapis.com"
disable_on_destroy = false
}
resource "google_project_service" "container" {
project = var.project_id
service = "container.googleapis.com"
depends_on = [
google_project_service.compute,
google_project_service.pubsub,
google_project_service.bigquery,
]
disable_on_destroy = false
}
resource "google_project_service" "stackdriver" {
project = var.project_id
service = "stackdriver.googleapis.com"
disable_on_destroy = false
}
resource "google_project_service" "logging" {
project = var.project_id
service = "logging.googleapis.com"
disable_on_destroy = false
depends_on = [google_project_service.stackdriver]
}
resource "google_project_service" "monitoring" {
project = var.project_id
service = "monitoring.googleapis.com"
disable_on_destroy = false
depends_on = [google_project_service.stackdriver]
}
resource "google_project_service" "cloudprofiler" {
project = var.project_id
service = "cloudprofiler.googleapis.com"
disable_on_destroy = false
depends_on = [google_project_service.stackdriver]
}
resource "google_project_service" "cloudtrace" {
project = var.project_id
service = "cloudtrace.googleapis.com"
disable_on_destroy = false
depends_on = [google_project_service.stackdriver]
}
resource "google_project_service" "servicenetworking" {
project = var.project_id
service = "servicenetworking.googleapis.com"
disable_on_destroy = false
}

View File

@@ -0,0 +1,82 @@
variable "project_id" {
type = string
description = "ID of a Google Cloud Project"
}
################################################################################
## Compute
################################################################################
variable "compute_network" {
type = string
}
variable "compute_subnetwork" {
type = string
}
variable "compute_region" {
type = string
}
variable "compute_instance_availability_zone" {
type = string
description = "List of zones in the region defined in `compute_region` where replicas should be deployed."
}
variable "compute_instance_type" {
type = string
description = "Machine type to use for the instances."
}
################################################################################
## Boot Image
################################################################################
variable "boot_image_family" {
type = string
description = "Family of the boot image to use for the instances."
default = "ubuntu-2204-lts"
}
variable "boot_image_project" {
type = string
description = "Project of the boot image to use for the instances."
default = "ubuntu-os-cloud"
}
################################################################################
## Virtual Machine
################################################################################
variable "vm_name" {
type = string
nullable = true
default = null
description = "Name of the VM to create."
}
variable "vm_labels" {
type = map(string)
nullable = false
default = {}
description = "Labels to add to all created by this module resources."
}
variable "vm_network_tag" {
type = string
nullable = false
description = "Network tags to add to VM created by this module."
}
################################################################################
## Cloud-init Configuration
################################################################################
variable "cloud_init" {
type = string
description = "Cloud-init configuration to use for the VM."
}