Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Ansible works alongside Terraform to streamline the Cloudflare Tunnel setup proc
To complete the steps in this guide, you will need:

- [A Google Cloud Project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project) and [GCP CLI installed and authenticated](https://cloud.google.com/sdk/docs/install).
- [Basic knowledge of Terraform](/cloudflare-one/connections/connect-networks/deployment-guides/terraform/) and[Terraform installed](https://developer.hashicorp.com/terraform/tutorials/certification-associate-tutorials/install-cli).
- [Basic knowledge of Terraform](/cloudflare-one/connections/connect-networks/deployment-guides/terraform/) and [Terraform installed](https://developer.hashicorp.com/terraform/tutorials/certification-associate-tutorials/install-cli).
- [A zone on Cloudflare](/fundamentals/setup/manage-domains/add-site/).
- [A Cloudflare API token](/fundamentals/api/get-started/create-token/) with `Cloudflare Tunnel` and `DNS` permissions.

Expand Down Expand Up @@ -74,32 +74,7 @@ You will need to declare the [providers](https://registry.terraform.io/browse/pr

2. Add the following providers to `providers.tf`. The `random` provider is used to generate a tunnel secret.

```txt
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
}
google = {
source = "hashicorp/google"
}
random = {
source = "hashicorp/random"
}
}
required_version = ">= 0.13"
}

# Providers
provider "cloudflare" {
api_token = var.cloudflare_token
}
provider "google" {
project = var.gcp_project_id
}
provider "random" {
}
```
<Render file="terraform/providers-v5" />

### Configure Cloudflare resources

Expand All @@ -113,30 +88,53 @@ The following configuration will modify settings in your Cloudflare account.

2. Add the following resources to `Cloudflare-config.tf`:

```txt
# Generates a 64-character secret for the tunnel.
# Using `random_password` means the result is treated as sensitive and, thus,
# not displayed in console output. Refer to: https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password
resource "random_password" "tunnel_secret" {
length = 64
}

# Creates a new locally-managed tunnel for the GCP VM.
resource "cloudflare_tunnel" "auto_tunnel" {
account_id = var.cloudflare_account_id
name = "Ansible GCP tunnel"
secret = base64sha256(random_password.tunnel_secret.result)
}

# Creates the CNAME record that routes ssh_app.${var.cloudflare_zone} to the tunnel.
resource "cloudflare_record" "ssh_app" {
zone_id = var.cloudflare_zone_id
name = "ssh_app"
value = "${cloudflare_argo_tunnel.auto_tunnel.id}.cfargotunnel.com"
type = "CNAME"
proxied = true
}
```
```tf
# Generates a 32-byte secret for the tunnel.
resource "random_bytes" "tunnel_secret" {
byte_length = 32
}

# Creates a new remotely-managed tunnel for the GCP VM.
resource "cloudflare_zero_trust_tunnel_cloudflared" "gcp_tunnel" {
account_id = var.cloudflare_account_id
name = "Ansible GCP tunnel"
tunnel_secret = random_bytes.tunnel_secret.base64
}

# Reads the token used to run the tunnel on the server.
data "cloudflare_zero_trust_tunnel_cloudflared_token" "gcp_tunnel_token" {
account_id = var.cloudflare_account_id
tunnel_id = cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id
}

# Creates the CNAME record that routes http_app.${var.cloudflare_zone} to the tunnel.
resource "cloudflare_dns_record" "http_app" {
zone_id = var.cloudflare_zone_id
name = "http_app"
content = "${cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id}.cfargotunnel.com"
type = "CNAME"
ttl = 1
proxied = true
}

# Configures tunnel with a public hostname route for clientless access.
resource "cloudflare_zero_trust_tunnel_cloudflared_config" "gcp_tunnel_config" {
tunnel_id = cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id
account_id = var.cloudflare_account_id
config = {
ingress = [
{
hostname = "http_app.${var.cloudflare_zone}"
service = "http://localhost:80"
},
{
service = "http_status:404"
}
]
}
}
```

### Configure GCP resources

Expand All @@ -158,7 +156,7 @@ The following configuration defines the specifications for the GCP virtual machi
}

# Sets up a GCP VM instance.
resource "google_compute_instance" "origin" {
resource "google_compute_instance" "http_server" {
name = "ansible-inst"
machine_type = var.machine_type
zone = var.zone
Expand Down Expand Up @@ -209,7 +207,7 @@ The following configuration defines the specifications for the GCP virtual machi

### Export variables to Ansible

The following Terraform resource exports the tunnel ID and other variables to `tf_ansible_vars_file.yml`. Ansible will use this data to configure and run `cloudflared` on the server.
The following Terraform resource exports the [tunnel token](/cloudflare-one/connections/connect-networks/configure-tunnels/remote-tunnel-permissions/) and other variables to `tf_ansible_vars_file.yml`. Ansible will use the tunnel token to configure and run `cloudflared` on the server.

1. In your configuration directory, create a new `tf` file:

Expand All @@ -219,20 +217,18 @@ The following Terraform resource exports the tunnel ID and other variables to `t

2. Copy and paste the following content into `export.tf`:

```txt
resource "local_file" "tf_ansible_vars_file" {
content = <<-DOC
# Ansible vars_file containing variable values from Terraform.
tunnel_id: ${cloudflare_argo_tunnel.auto_tunnel.id}
account: ${var.cloudflare_account_id}
tunnel_name: ${cloudflare_argo_tunnel.auto_tunnel.name}
secret: ${random_id.tunnel_secret.b64_std}
zone: ${var.cloudflare_zone}
DOC

filename = "./tf_ansible_vars_file.yml"
}
```
```tf
resource "local_file" "tf_ansible_vars_file" {
content = <<-DOC
# Ansible vars_file containing variable values from Terraform.
tunnel_id: ${cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id}
tunnel_name: ${cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.name}
tunnel_token: ${data.cloudflare_zero_trust_tunnel_cloudflared_token.gcp_tunnel_token.token}
DOC

filename = "./tf_ansible_vars_file.yml"
}
```

## 5. Create the Ansible playbook

Expand All @@ -259,38 +255,27 @@ Ansible playbooks are YAML files that declare the configuration Ansible will dep
shell: wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
- name: Depackage cloudflared.
shell: sudo dpkg -i cloudflared-linux-amd64.deb
- name: Create a cloudflared service directory.
shell: mkdir -p /etc/cloudflared/
- name: Create the config file for cloudflared and define the ingress rules for the tunnel.
copy:
dest: "/etc/cloudflared/config.yml"
content: |
tunnel: "{{ tunnel_id }}"
credentials-file: /etc/cloudflared/cert.json
logfile: /var/log/cloudflared.log
loglevel: info
ingress:
- hostname: "ssh_app.{{ zone }}"
service: ssh://localhost:22
- service: http_status:404
- name: Create the tunnel credentials file for cloudflared.
copy:
dest: "/etc/cloudflared/cert.json"
content: |
{
"AccountTag" : "{{ account | quote }}",
"TunnelID" : "{{ tunnel_id | quote }}",
"TunnelName" : "{{ tunnel_name | quote }}",
"TunnelSecret" : "{{ secret | quote }}"
}
- name: Install the tunnel as a systemd service.
shell: cloudflared service install
shell: "cloudflared service install {{ tunnel_token }}"
- name: Start the tunnel.
systemd:
name: cloudflared
state: started
enabled: true
masked: no
- name: Deploy an example Apache web server on port 80.
shell: apt update && apt -y install apache2
- name: Edit the default Apache index file.
copy:
dest: /var/www/html/index.html
content: |
<!DOCTYPE html>
<html>
<body>
<h1>Hello Cloudflare!</h1>
<p>This page was created for a Cloudflare demo.</p>
</body>
</html>
```

[Keywords](https://docs.ansible.com/ansible/latest/reference_appendices/playbooks_keywords.html#play) define how Ansible will execute the configuration. In the example above, the `vars_files` keyword specifies where variable definitions are stored, and the `tasks` keyword specifies the actions Ansible will perform.
Expand Down Expand Up @@ -323,4 +308,4 @@ It may take several minutes for the GCP instance and tunnel to come online. You

## 7. Test the connection

You can now SSH to the GCP server through the new `ssh_app.<zone>` hostname. For instructions on how to connect, refer to our [SSH guide](/cloudflare-one/connections/connect-networks/use-cases/ssh/).
To test, open a browser and go to `http://http_app.<CLOUDFLARE_ZONE>.com` (for example, `http_app.example.com`). You should see the **Hello Cloudflare!** test page.
Original file line number Diff line number Diff line change
Expand Up @@ -81,33 +81,7 @@ You will need to declare the [providers](https://registry.terraform.io/browse/pr
<Tabs syncKey="dashPlusAPI">
<TabItem label="Terraform (v5)">

```tf
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = ">= 5.3.0"
}
google = {
source = "hashicorp/google"
}
random = {
source = "hashicorp/random"
}
}
required_version = ">= 1.2"
}

# Providers
provider "cloudflare" {
api_token = var.cloudflare_token
}
provider "google" {
project = var.gcp_project_id
}
provider "random" {
}
```
<Render file="terraform/providers-v5" />

</TabItem>
<TabItem label="Terraform (v4)">
Expand Down Expand Up @@ -245,6 +219,7 @@ The following configuration will modify settings in your Cloudflare account.
]
}
```

</TabItem>
<TabItem label="Terraform (v4)">

Expand Down
31 changes: 31 additions & 0 deletions src/content/partials/cloudflare-one/terraform/providers-v5.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
{}
---

```tf
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = ">= 5.3.0"
}
google = {
source = "hashicorp/google"
}
random = {
source = "hashicorp/random"
}
}
required_version = ">= 1.2"
}

# Providers
provider "cloudflare" {
api_token = var.cloudflare_token
}
provider "google" {
project = var.gcp_project_id
}
provider "random" {
}
```
Loading