init
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
GOOGLE_APPLICATION_CREDENTIALS="secret-path-to-your-service-account-key.json"
|
||||
TF_VAR_gcp_project="your-gcp-project"
|
||||
TF_VAR_gcp_region="us-east1"
|
||||
TF_VAR_gcp_zone="b"
|
||||
@@ -0,0 +1,41 @@
|
||||
name: 01 - Build and Push Images
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "docker/**"
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push Coturn image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./docker/coturn
|
||||
push: true
|
||||
tags: ghcr.io/${{ github.repository_owner }}/stoat-coturn:4.9.0-trixie
|
||||
|
||||
- name: Build and push Caddy WAF image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./docker/caddy
|
||||
push: true
|
||||
tags: ghcr.io/${{ github.repository_owner }}/stoat-caddy-waf:latest
|
||||
@@ -0,0 +1,129 @@
|
||||
name: 02 - Deploy Infrastructure and Stack
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: read
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true'
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
||||
TF_VAR_gcp_project: ${{ vars.GCP_PROJECT || 'stoat-burrow' }}
|
||||
TF_VAR_gcp_region: ${{ vars.GCP_REGION || 'us-west1' }}
|
||||
TF_VAR_gcp_zone: ${{ vars.GCP_ZONE || 'us-west1-b' }}
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare SSH key for provisioning
|
||||
shell: bash
|
||||
run: |
|
||||
install -m 700 -d "${HOME}/.ssh"
|
||||
printf '%s\n' "${{ secrets.SSH_PRIVATE_KEY }}" > "${HOME}/.ssh/id_ed25519"
|
||||
chmod 600 "${HOME}/.ssh/id_ed25519"
|
||||
{
|
||||
echo "TF_VAR_admin_ssh_public_key<<EOF"
|
||||
ssh-keygen -y -f "${HOME}/.ssh/id_ed25519"
|
||||
echo "EOF"
|
||||
} >> "${GITHUB_ENV}"
|
||||
|
||||
- name: Prepare Google credentials file
|
||||
shell: bash
|
||||
run: |
|
||||
credentials_file="${RUNNER_TEMP}/gcp-service-account.json"
|
||||
printf '%s' "${{ secrets.GCP_SA_KEY }}" > "${credentials_file}"
|
||||
chmod 600 "${credentials_file}"
|
||||
echo "GOOGLE_APPLICATION_CREDENTIALS=${credentials_file}" >> "${GITHUB_ENV}"
|
||||
|
||||
- name: Setup OpenTofu
|
||||
uses: opentofu/setup-opentofu@v1
|
||||
|
||||
- name: Write OpenTofu backend config
|
||||
working-directory: ./tofu
|
||||
shell: bash
|
||||
run: |
|
||||
cat > backend.hcl <<EOF
|
||||
bucket = "stoat-tofu-state"
|
||||
key = "webrtc-relay/terraform.tfstate"
|
||||
region = "us-east-2"
|
||||
endpoints = {
|
||||
s3 = "https://${{ secrets.CLOUDFLARE_ACCOUNT_ID }}.r2.cloudflarestorage.com"
|
||||
}
|
||||
skip_credentials_validation = true
|
||||
skip_region_validation = true
|
||||
skip_requesting_account_id = true
|
||||
skip_s3_checksum = true
|
||||
EOF
|
||||
|
||||
- name: Tofu init and apply
|
||||
id: tofu
|
||||
working-directory: ./tofu
|
||||
shell: bash
|
||||
run: |
|
||||
tofu init -backend-config=backend.hcl
|
||||
tofu apply -auto-approve -input=false
|
||||
echo "STATIC_IP=$(tofu output -raw relay_ip)" >> "${GITHUB_ENV}"
|
||||
|
||||
- name: Wait for SSH
|
||||
shell: bash
|
||||
run: |
|
||||
for attempt in {1..30}; do
|
||||
if nc -z -w 5 "${STATIC_IP}" 22; then
|
||||
exit 0
|
||||
fi
|
||||
sleep 10
|
||||
done
|
||||
echo "SSH did not become reachable on ${STATIC_IP}" >&2
|
||||
exit 1
|
||||
|
||||
- name: Run Ansible Playbook
|
||||
uses: dawidd6/action-ansible-playbook@v2
|
||||
with:
|
||||
playbook: setup_host.yml
|
||||
directory: ./ansible
|
||||
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
inventory: |
|
||||
[turn_nodes]
|
||||
${{ env.STATIC_IP }} ansible_user=ubuntu
|
||||
options: --ssh-common-args='-o StrictHostKeyChecking=no'
|
||||
|
||||
- name: SCP compose and config files
|
||||
uses: appleboy/scp-action@v0.1.7
|
||||
with:
|
||||
host: ${{ env.STATIC_IP }}
|
||||
username: ubuntu
|
||||
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
source: "compose/*"
|
||||
target: "/opt/stoat-turn"
|
||||
strip_components: 1
|
||||
|
||||
- name: Deploy Podman compose stack
|
||||
uses: appleboy/ssh-action@v1.0.3
|
||||
with:
|
||||
host: ${{ env.STATIC_IP }}
|
||||
username: ubuntu
|
||||
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
script: |
|
||||
set -eu
|
||||
cd /opt/stoat-turn
|
||||
cat > .env <<EOF
|
||||
STATIC_IP=${{ env.STATIC_IP }}
|
||||
GITHUB_REPOSITORY_OWNER=${{ github.repository_owner }}
|
||||
TURN_REALM=${{ vars.TURN_REALM || 'turn.example.com' }}
|
||||
TURN_SHARED_SECRET=${{ secrets.TURN_SHARED_SECRET }}
|
||||
CADDY_DOMAIN=${{ vars.CADDY_DOMAIN || 'relay.example.com' }}
|
||||
CADDY_EMAIL=${{ vars.CADDY_EMAIL || 'ops@example.com' }}
|
||||
STOAT_UPSTREAM=${{ vars.STOAT_UPSTREAM || 'http://host.containers.internal:8080' }}
|
||||
TURN_TLS_CERT_FILE=${{ vars.TURN_TLS_CERT_FILE }}
|
||||
TURN_TLS_KEY_FILE=${{ vars.TURN_TLS_KEY_FILE }}
|
||||
EOF
|
||||
|
||||
printf '%s\n' "${{ secrets.GITHUB_TOKEN }}" | podman login ghcr.io -u "${{ github.actor }}" --password-stdin
|
||||
podman compose pull
|
||||
podman compose up -d
|
||||
@@ -0,0 +1,8 @@
|
||||
.codex
|
||||
.env
|
||||
.terraform/
|
||||
.terraform.lock.hcl
|
||||
*.retry
|
||||
*.tfstate
|
||||
*.tfstate.*
|
||||
compose/.env
|
||||
@@ -0,0 +1,57 @@
|
||||
# WebRTC Outpost
|
||||
|
||||
Configuration repository for a Coturn relay that supports a Stoat deployment on GCP. The stack provisions a `relay-main` Ubuntu 24.04 instance, hardens the host with `nftables`, `fail2ban`, and `unattended-upgrades`, then deploys Coturn plus a Coraza-enabled Caddy reverse proxy with Podman Compose.
|
||||
|
||||
## Repository Layout
|
||||
|
||||
- `tofu/`: OpenTofu infrastructure for the static IP, VM, and GCP firewall rule.
|
||||
- `ansible/`: Host preparation and hardening for Ubuntu 24.04.
|
||||
- `compose/`: Runtime configuration for Coturn and Caddy.
|
||||
- `docker/`: Custom images for Coturn and Caddy.
|
||||
- `.github/workflows/`: CI workflows for building images and deploying the stack.
|
||||
|
||||
## Required GitHub Secrets
|
||||
|
||||
- `R2_ACCESS_KEY_ID`
|
||||
- `R2_SECRET_ACCESS_KEY`
|
||||
- `CLOUDFLARE_ACCOUNT_ID`
|
||||
- `GCP_SA_KEY`
|
||||
- `SSH_PRIVATE_KEY`
|
||||
- `TURN_SHARED_SECRET`
|
||||
|
||||
## Recommended GitHub Variables
|
||||
|
||||
- `GCP_PROJECT`
|
||||
- `GCP_REGION`
|
||||
- `GCP_ZONE`
|
||||
- `TURN_REALM`
|
||||
- `CADDY_DOMAIN`
|
||||
- `CADDY_EMAIL`
|
||||
- `STOAT_UPSTREAM`
|
||||
- `TURN_TLS_CERT_FILE`
|
||||
- `TURN_TLS_KEY_FILE`
|
||||
|
||||
## Notes
|
||||
|
||||
- The OpenTofu S3 backend is configured at deploy time so the Cloudflare R2 endpoint does not need to be committed to the repository.
|
||||
- The Google provider reads service account credentials from the standard `GOOGLE_APPLICATION_CREDENTIALS` shell environment variable. Set it to the JSON key file path for local `tofu` runs.
|
||||
- The custom Coturn image renders runtime settings from environment variables before starting `turnserver`.
|
||||
- `TURN_TLS_CERT_FILE` and `TURN_TLS_KEY_FILE` are optional. If they are omitted, Coturn starts on `3478` only and skips the `5349` TLS listener.
|
||||
- The Ansible playbook lowers `net.ipv4.ip_unprivileged_port_start` to `80` so a rootless Podman-managed Caddy container can bind to `80` and `443`.
|
||||
|
||||
## Local OpenTofu Usage
|
||||
|
||||
Export the Google credentials path and required OpenTofu variables before running `tofu` locally:
|
||||
|
||||
```bash
|
||||
export GOOGLE_APPLICATION_CREDENTIALS="secret-path"
|
||||
export TF_VAR_gcp_project="your-gcp-project"
|
||||
export TF_VAR_gcp_region="us-west1"
|
||||
export TF_VAR_gcp_zone="us-west1-b"
|
||||
|
||||
cd tofu
|
||||
tofu init
|
||||
tofu apply
|
||||
```
|
||||
|
||||
`network_name` defaults to `default`, `instance_name` defaults to `relay-main`, and `admin_ssh_public_key` is optional unless you want SSH access provisioned on the VM.
|
||||
@@ -0,0 +1,101 @@
|
||||
---
|
||||
- name: Configure relay-main Host
|
||||
hosts: all
|
||||
become: true
|
||||
vars:
|
||||
deploy_user: "{{ ansible_user }}"
|
||||
|
||||
handlers:
|
||||
- name: reload nftables
|
||||
ansible.builtin.systemd:
|
||||
name: nftables
|
||||
state: reloaded
|
||||
|
||||
- name: restart fail2ban
|
||||
ansible.builtin.systemd:
|
||||
name: fail2ban
|
||||
state: restarted
|
||||
|
||||
tasks:
|
||||
- name: Install system dependencies
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- podman
|
||||
- podman-docker
|
||||
- docker-compose
|
||||
- podman-compose
|
||||
- nftables
|
||||
- fail2ban
|
||||
- unattended-upgrades
|
||||
state: present
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
|
||||
- name: Enable apt timers used by unattended-upgrades
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ item }}"
|
||||
enabled: true
|
||||
state: started
|
||||
loop:
|
||||
- apt-daily.timer
|
||||
- apt-daily-upgrade.timer
|
||||
|
||||
- name: Enable automatic security updates
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/apt/apt.conf.d/20auto-upgrades
|
||||
content: |
|
||||
APT::Periodic::Update-Package-Lists "1";
|
||||
APT::Periodic::Unattended-Upgrade "1";
|
||||
APT::Periodic::AutocleanInterval "7";
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
- name: Ensure target directory exists and is owned by the deployment user
|
||||
ansible.builtin.file:
|
||||
path: /opt/stoat-turn
|
||||
state: directory
|
||||
owner: "{{ deploy_user }}"
|
||||
group: "{{ deploy_user }}"
|
||||
mode: "0755"
|
||||
|
||||
- name: Allow rootless Podman to bind ports 80 and above
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/sysctl.d/60-rootless-podman-ports.conf
|
||||
content: |
|
||||
net.ipv4.ip_unprivileged_port_start = 80
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
- name: Apply sysctl settings
|
||||
ansible.builtin.command:
|
||||
cmd: sysctl --system
|
||||
changed_when: false
|
||||
|
||||
- name: Install nftables policy
|
||||
ansible.builtin.template:
|
||||
src: templates/nftables.conf.j2
|
||||
dest: /etc/nftables.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
notify: reload nftables
|
||||
|
||||
- name: Install fail2ban jail configuration
|
||||
ansible.builtin.template:
|
||||
src: templates/jail.local.j2
|
||||
dest: /etc/fail2ban/jail.local
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
notify: restart fail2ban
|
||||
|
||||
- name: Enable nftables and fail2ban
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ item }}"
|
||||
enabled: true
|
||||
state: started
|
||||
loop:
|
||||
- nftables
|
||||
- fail2ban
|
||||
@@ -0,0 +1,11 @@
|
||||
[DEFAULT]
|
||||
banaction = nftables-multiport
|
||||
backend = systemd
|
||||
bantime = 1h
|
||||
findtime = 10m
|
||||
maxretry = 5
|
||||
|
||||
[sshd]
|
||||
enabled = true
|
||||
port = ssh
|
||||
logpath = %(sshd_log)s
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/usr/sbin/nft -f
|
||||
|
||||
flush ruleset
|
||||
|
||||
table inet filter {
|
||||
chain input {
|
||||
type filter hook input priority 0;
|
||||
policy drop;
|
||||
|
||||
iif lo accept
|
||||
ct state established,related accept
|
||||
|
||||
ip protocol icmp accept
|
||||
ip6 nexthdr ipv6-icmp accept
|
||||
|
||||
tcp dport 22 accept
|
||||
tcp dport { 80, 443, 3478, 5349 } accept
|
||||
udp dport { 3478, 5349 } accept
|
||||
udp dport 49152-65535 accept
|
||||
}
|
||||
|
||||
chain forward {
|
||||
type filter hook forward priority 0;
|
||||
policy drop;
|
||||
}
|
||||
|
||||
chain output {
|
||||
type filter hook output priority 0;
|
||||
policy accept;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
STATIC_IP=203.0.113.10
|
||||
GITHUB_REPOSITORY_OWNER=example-owner
|
||||
TURN_REALM=turn.example.com
|
||||
TURN_SHARED_SECRET=replace-me
|
||||
CADDY_DOMAIN=relay.example.com
|
||||
CADDY_EMAIL=ops@example.com
|
||||
STOAT_UPSTREAM=http://host.containers.internal:8080
|
||||
TURN_TLS_CERT_FILE=
|
||||
TURN_TLS_KEY_FILE=
|
||||
TURN_TLS_LISTENING_PORT=5349
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
email {$CADDY_EMAIL:ops@example.com}
|
||||
order coraza_waf first
|
||||
admin off
|
||||
}
|
||||
|
||||
{$CADDY_DOMAIN:localhost} {
|
||||
log {
|
||||
output stdout
|
||||
format console
|
||||
}
|
||||
|
||||
encode zstd gzip
|
||||
|
||||
header {
|
||||
X-Content-Type-Options nosniff
|
||||
X-Frame-Options DENY
|
||||
Referrer-Policy no-referrer
|
||||
}
|
||||
|
||||
@health path /healthz
|
||||
respond @health 200 "ok"
|
||||
|
||||
coraza_waf {
|
||||
load_owasp_crs
|
||||
directives `
|
||||
SecRuleEngine On
|
||||
SecRequestBodyAccess On
|
||||
SecAuditEngine RelevantOnly
|
||||
`
|
||||
}
|
||||
|
||||
reverse_proxy {$STOAT_UPSTREAM:http://host.containers.internal:8080}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
services:
|
||||
caddy:
|
||||
image: ghcr.io/${GITHUB_REPOSITORY_OWNER}/stoat-caddy-waf:latest
|
||||
container_name: caddy-waf
|
||||
restart: always
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
environment:
|
||||
CADDY_DOMAIN: ${CADDY_DOMAIN}
|
||||
CADDY_EMAIL: ${CADDY_EMAIL}
|
||||
STOAT_UPSTREAM: ${STOAT_UPSTREAM}
|
||||
volumes:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
|
||||
coturn:
|
||||
image: ghcr.io/${GITHUB_REPOSITORY_OWNER}/stoat-coturn:4.9.0-trixie
|
||||
container_name: coturn-relay
|
||||
restart: always
|
||||
network_mode: host
|
||||
environment:
|
||||
EXTERNAL_IP: ${STATIC_IP}
|
||||
TURN_REALM: ${TURN_REALM}
|
||||
TURN_SHARED_SECRET: ${TURN_SHARED_SECRET}
|
||||
TURN_TLS_CERT_FILE: ${TURN_TLS_CERT_FILE:-}
|
||||
TURN_TLS_KEY_FILE: ${TURN_TLS_KEY_FILE:-}
|
||||
TURN_TLS_LISTENING_PORT: ${TURN_TLS_LISTENING_PORT:-5349}
|
||||
volumes:
|
||||
- ./turnserver.conf:/etc/coturn/turnserver.conf:ro
|
||||
- caddy_data:/caddy-data:ro
|
||||
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
@@ -0,0 +1,12 @@
|
||||
fingerprint
|
||||
use-auth-secret
|
||||
lt-cred-mech
|
||||
|
||||
listening-port=3478
|
||||
min-port=49152
|
||||
max-port=65535
|
||||
|
||||
no-cli
|
||||
stale-nonce=600
|
||||
no-loopback-peers
|
||||
no-multicast-peers
|
||||
@@ -0,0 +1,8 @@
|
||||
FROM caddy:2-builder AS builder
|
||||
|
||||
RUN xcaddy build \
|
||||
--with github.com/corazawaf/coraza-caddy/v2
|
||||
|
||||
FROM caddy:2
|
||||
|
||||
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
|
||||
@@ -0,0 +1,11 @@
|
||||
FROM coturn:4.9.0-trixie
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
|
||||
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
|
||||
RUN chmod 0755 /usr/local/bin/entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
conf_source="/etc/coturn/turnserver.conf"
|
||||
conf_rendered="/tmp/turnserver.conf"
|
||||
|
||||
: "${TURN_REALM:?TURN_REALM is required}"
|
||||
: "${TURN_SHARED_SECRET:?TURN_SHARED_SECRET is required}"
|
||||
|
||||
cp "${conf_source}" "${conf_rendered}"
|
||||
|
||||
{
|
||||
echo
|
||||
echo "realm=${TURN_REALM}"
|
||||
echo "static-auth-secret=${TURN_SHARED_SECRET}"
|
||||
} >> "${conf_rendered}"
|
||||
|
||||
if [ -n "${TURN_TLS_CERT_FILE:-}" ] && [ -n "${TURN_TLS_KEY_FILE:-}" ]; then
|
||||
{
|
||||
echo "tls-listening-port=${TURN_TLS_LISTENING_PORT:-5349}"
|
||||
echo "cert=${TURN_TLS_CERT_FILE}"
|
||||
echo "pkey=${TURN_TLS_KEY_FILE}"
|
||||
} >> "${conf_rendered}"
|
||||
fi
|
||||
|
||||
set -- turnserver -n -c "${conf_rendered}"
|
||||
|
||||
if [ -n "${EXTERNAL_IP:-}" ]; then
|
||||
set -- "$@" --external-ip "${EXTERNAL_IP}"
|
||||
fi
|
||||
|
||||
exec "$@"
|
||||
@@ -0,0 +1,5 @@
|
||||
terraform {
|
||||
required_version = ">= 1.11.5"
|
||||
|
||||
backend "s3" {}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
provider "google" {
|
||||
project = var.gcp_project
|
||||
region = var.gcp_region
|
||||
}
|
||||
|
||||
resource "google_compute_address" "turn_static_ip" {
|
||||
name = "stoat-turn-ip"
|
||||
network_tier = "PREMIUM"
|
||||
region = var.gcp_region
|
||||
}
|
||||
|
||||
resource "google_compute_instance" "turn_outpost" {
|
||||
name = var.instance_name
|
||||
machine_type = var.machine_type
|
||||
zone = var.gcp_zone
|
||||
|
||||
tags = ["webrtc-outpost", "caddy-web"]
|
||||
|
||||
boot_disk {
|
||||
initialize_params {
|
||||
image = "projects/ubuntu-os-cloud/global/images/family/ubuntu-2404-lts-amd64"
|
||||
size = 20
|
||||
}
|
||||
}
|
||||
|
||||
metadata = var.admin_ssh_public_key == "" ? {} : {
|
||||
ssh-keys = "ubuntu:${var.admin_ssh_public_key}"
|
||||
}
|
||||
|
||||
network_interface {
|
||||
network = var.network_name
|
||||
|
||||
access_config {
|
||||
nat_ip = google_compute_address.turn_static_ip.address
|
||||
network_tier = "PREMIUM"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_compute_firewall" "webrtc_rules" {
|
||||
name = "allow-webrtc-and-web"
|
||||
network = var.network_name
|
||||
|
||||
allow {
|
||||
protocol = "tcp"
|
||||
ports = ["80", "443", "3478", "5349"]
|
||||
}
|
||||
|
||||
allow {
|
||||
protocol = "udp"
|
||||
ports = ["3478", "5349", "49152-65535"]
|
||||
}
|
||||
|
||||
target_tags = ["webrtc-outpost", "caddy-web"]
|
||||
}
|
||||
|
||||
output "relay_ip" {
|
||||
description = "Public static IP for the relay."
|
||||
value = google_compute_address.turn_static_ip.address
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
variable "gcp_project" {
|
||||
description = "GCP project ID used for provider-scoped resources."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "gcp_region" {
|
||||
description = "GCP region used for regional resources."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "gcp_zone" {
|
||||
description = "GCP zone used for the relay instance."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "network_name" {
|
||||
description = "VPC network name."
|
||||
type = string
|
||||
default = "default"
|
||||
}
|
||||
|
||||
variable "instance_name" {
|
||||
description = "Name of the relay VM."
|
||||
type = string
|
||||
default = "relay-main"
|
||||
}
|
||||
|
||||
variable "machine_type" {
|
||||
description = "GCP machine type for the relay."
|
||||
type = string
|
||||
default = "e2-micro"
|
||||
}
|
||||
|
||||
variable "admin_ssh_public_key" {
|
||||
description = "Optional SSH public key injected for the ubuntu user."
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
google = {
|
||||
source = "hashicorp/google"
|
||||
version = "~> 7.26"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user