<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kamran Biglari</title>
    <description>The latest articles on DEV Community by Kamran Biglari (@kamran_biglari_756d509684).</description>
    <link>https://dev.to/kamran_biglari_756d509684</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1963328%2F98da8cb7-3f57-4e8b-9ad3-5bc5cf7ed736.jpg</url>
      <title>DEV Community: Kamran Biglari</title>
      <link>https://dev.to/kamran_biglari_756d509684</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kamran_biglari_756d509684"/>
    <language>en</language>
    <item>
      <title>Monitoring Hetzner Cloud resources with AWS CloudWatch using Terraform</title>
      <dc:creator>Kamran Biglari</dc:creator>
      <pubDate>Mon, 10 Nov 2025 10:11:37 +0000</pubDate>
      <link>https://dev.to/kamran_biglari_756d509684/monitoring-hetzner-cloud-resources-with-aws-cloudwatch-using-terraform-2m1n</link>
      <guid>https://dev.to/kamran_biglari_756d509684/monitoring-hetzner-cloud-resources-with-aws-cloudwatch-using-terraform-2m1n</guid>
      <description>&lt;p&gt;In this tutorial, you will learn how to monitor your Hetzner Cloud infrastructure using AWS CloudWatch. This integration allows you to centralize your monitoring across both Hetzner and AWS resources in one unified dashboard.&lt;/p&gt;

&lt;p&gt;By the end of this tutorial, you will have set up automated metric collection from your Hetzner Cloud Load Balancers and Servers, with all metrics automatically pushed to AWS CloudWatch at regular intervals. This is particularly useful if your organization already uses AWS CloudWatch for monitoring and wants to include Hetzner Cloud resources in the same observability platform.&lt;/p&gt;

&lt;p&gt;We'll use a Terraform module that leverages AWS Step Functions to periodically fetch metrics from the Hetzner Cloud API and store them in CloudWatch. This serverless approach means there are no servers to manage, and you only pay for what you use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before starting this tutorial, you should have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An active &lt;a href="https://www.hetzner.com/cloud" rel="noopener noreferrer"&gt;Hetzner Cloud&lt;/a&gt; account with at least one Load Balancer or Server running&lt;/li&gt;
&lt;li&gt;A Hetzner Cloud API token with read permissions (&lt;a href="https://docs.hetzner.com/cloud/api/getting-started/generating-api-token" rel="noopener noreferrer"&gt;How to create an API token&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;An &lt;a href="https://aws.amazon.com/" rel="noopener noreferrer"&gt;AWS account&lt;/a&gt; with appropriate permissions to create IAM roles, Step Functions, EventBridge resources, and CloudWatch metrics&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.terraform.io/downloads" rel="noopener noreferrer"&gt;Terraform&lt;/a&gt; installed (version 1.0 or higher)&lt;/li&gt;
&lt;li&gt;AWS credentials configured locally (via AWS CLI, environment variables, or AWS credentials file)&lt;/li&gt;
&lt;li&gt;Basic familiarity with Terraform and Infrastructure as Code concepts&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1 - Understanding the Architecture
&lt;/h2&gt;

&lt;p&gt;Before we begin the implementation, it's important to understand how this integration works.&lt;/p&gt;

&lt;p&gt;The solution consists of several AWS components working together:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;AWS EventBridge Connection&lt;/strong&gt;: Securely stores your Hetzner Cloud API token in AWS Secrets Manager&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Step Functions State Machine&lt;/strong&gt;: A serverless workflow that fetches metrics from the Hetzner Cloud API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS EventBridge Scheduler&lt;/strong&gt;: Triggers the Step Functions workflow at regular intervals (e.g., every 5 minutes)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS CloudWatch&lt;/strong&gt;: Stores the metrics in custom namespaces for visualization and alerting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IAM Roles and Policies&lt;/strong&gt;: Provides necessary permissions for the Step Functions workflow and scheduler&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The workflow is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The scheduler triggers the Step Functions state machine at your defined interval&lt;/li&gt;
&lt;li&gt;The state machine calls the Hetzner Cloud API using the stored credentials&lt;/li&gt;
&lt;li&gt;Metrics are retrieved and parsed&lt;/li&gt;
&lt;li&gt;Each metric is pushed to CloudWatch with appropriate dimensions (like Server ID or Load Balancer ID)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This architecture is cost-effective, with typical monthly costs of $1-2 per monitored resource when collecting metrics every 5 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 - Retrieve Your Hetzner Cloud Resource IDs
&lt;/h2&gt;

&lt;p&gt;First, you need to identify which Hetzner Cloud resources you want to monitor. You'll need either a Load Balancer ID or a Server ID.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option A: Using the Hetzner Cloud Console
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Log in to &lt;a href="https://console.hetzner.cloud/" rel="noopener noreferrer"&gt;Hetzner Cloud Console&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Select your project&lt;/li&gt;
&lt;li&gt;For Load Balancers:

&lt;ul&gt;
&lt;li&gt;Click on "Load Balancers" in the left menu&lt;/li&gt;
&lt;li&gt;Click on the Load Balancer you want to monitor&lt;/li&gt;
&lt;li&gt;The ID is shown in the URL: &lt;code&gt;https://console.hetzner.cloud/projects/YOUR_PROJECT/load-balancers/LOAD_BALANCER_ID&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;For Servers:

&lt;ul&gt;
&lt;li&gt;Click on "Servers" in the left menu&lt;/li&gt;
&lt;li&gt;Click on the Server you want to monitor&lt;/li&gt;
&lt;li&gt;The ID is shown in the URL: &lt;code&gt;https://console.hetzner.cloud/projects/YOUR_PROJECT/servers/SERVER_ID&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Option B: Using the Hetzner Cloud CLI
&lt;/h3&gt;

&lt;p&gt;If you have the &lt;a href="https://github.com/hetznercloud/cli" rel="noopener noreferrer"&gt;hcloud CLI&lt;/a&gt; installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# List all Load Balancers&lt;/span&gt;
hcloud load-balancer list

&lt;span class="c"&gt;# List all Servers&lt;/span&gt;
hcloud server list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note down the ID(s) of the resources you want to monitor. You'll need these values in the next steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 - Set Up the Terraform Configuration
&lt;/h2&gt;

&lt;p&gt;Now we'll create the Terraform configuration to deploy the monitoring infrastructure.&lt;/p&gt;

&lt;p&gt;Create a new directory for your Terraform project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;hetzner-cloudwatch-integration
&lt;span class="nb"&gt;cd &lt;/span&gt;hetzner-cloudwatch-integration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a file named &lt;code&gt;main.tf&lt;/code&gt; with the following content for monitoring a Load Balancer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;required_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 1.0"&lt;/span&gt;
  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/aws"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 5.0"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;  &lt;span class="c1"&gt;# Change to your preferred AWS region&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"loadbalancer_metrics"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"kamranbiglari/hetzner-cloudwatch-integration/aws"&lt;/span&gt;
  &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 1.0"&lt;/span&gt;
  &lt;span class="nx"&gt;hetzner_cloud_api_token&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hetzner_cloud_api_token&lt;/span&gt;
  &lt;span class="nx"&gt;metric_type&lt;/span&gt;             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"loadbalancer"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hetzner-lb-metrics"&lt;/span&gt;
  &lt;span class="c1"&gt;# Enable automatic metric collection every 5 minutes&lt;/span&gt;
  &lt;span class="nx"&gt;create_scheduler&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;schedule_expression&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rate(5 minutes)"&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;loadbalancer_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadbalancer_id&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For monitoring a Server instead, use &lt;code&gt;metric_type = "server"&lt;/code&gt; and provide &lt;code&gt;server_id&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"server_metrics"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"kamranbiglari/hetzner-cloudwatch-integration/aws"&lt;/span&gt;
  &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 1.0"&lt;/span&gt;
  &lt;span class="nx"&gt;hetzner_cloud_api_token&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hetzner_cloud_api_token&lt;/span&gt;
  &lt;span class="nx"&gt;metric_type&lt;/span&gt;             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"server"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hetzner-server-metrics"&lt;/span&gt;
  &lt;span class="nx"&gt;create_scheduler&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;schedule_expression&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rate(5 minutes)"&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;server_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;server_id&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4 - Define Variables
&lt;/h2&gt;

&lt;p&gt;Create a &lt;code&gt;variables.tf&lt;/code&gt; file to define the required variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"hetzner_cloud_api_token"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Hetzner Cloud API token with read permissions"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;sensitive&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"loadbalancer_id"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ID of the Hetzner Cloud Load Balancer to monitor"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;# Or for servers:&lt;/span&gt;
&lt;span class="c1"&gt;# variable "server_id" {&lt;/span&gt;
&lt;span class="c1"&gt;#   description = "ID of the Hetzner Cloud Server to monitor"&lt;/span&gt;
&lt;span class="c1"&gt;#   type        = string&lt;/span&gt;
&lt;span class="c1"&gt;# }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;terraform.tfvars&lt;/code&gt; file with your actual values (never commit this file to version control):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;hetzner_cloud_api_token&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"your-hetzner-api-token-here"&lt;/span&gt;
&lt;span class="nx"&gt;loadbalancer_id&lt;/span&gt;         &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"123456"&lt;/span&gt;  &lt;span class="c1"&gt;# Replace with your actual ID&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, you can set these values as environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TF_VAR_hetzner_cloud_api_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-hetzner-api-token-here"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TF_VAR_loadbalancer_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"123456"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5 - Deploy the Infrastructure
&lt;/h2&gt;

&lt;p&gt;Initialize Terraform to download the required providers and modules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see output indicating that Terraform has successfully initialized and downloaded the module.&lt;/p&gt;

&lt;p&gt;Review the planned changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform plan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Terraform will show you all the resources that will be created:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS EventBridge Connection (for storing the API token)&lt;/li&gt;
&lt;li&gt;IAM Role and Policy for Step Functions&lt;/li&gt;
&lt;li&gt;IAM Role and Policy for EventBridge Scheduler&lt;/li&gt;
&lt;li&gt;Step Functions State Machine&lt;/li&gt;
&lt;li&gt;EventBridge Scheduler&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If everything looks correct, apply the configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Type &lt;code&gt;yes&lt;/code&gt; when prompted to confirm. The deployment typically takes 30-60 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6 - Verify the Deployment
&lt;/h2&gt;

&lt;p&gt;After Terraform completes, let's verify that everything is working correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check the Step Functions State Machine
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://console.aws.amazon.com/states/" rel="noopener noreferrer"&gt;AWS Step Functions Console&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Select your AWS region (the one you specified in the &lt;code&gt;provider&lt;/code&gt; block)&lt;/li&gt;
&lt;li&gt;You should see a state machine named &lt;code&gt;hetzner-lb-metrics&lt;/code&gt; (or whatever name you specified)&lt;/li&gt;
&lt;li&gt;Wait a few minutes for the first scheduled execution to run&lt;/li&gt;
&lt;li&gt;Click on the state machine to see the execution history&lt;/li&gt;
&lt;li&gt;Click on a completed execution to see the workflow details and verify it succeeded&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Check CloudWatch Metrics
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://console.aws.amazon.com/cloudwatch/" rel="noopener noreferrer"&gt;AWS CloudWatch Console&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;In the left navigation, click on "All metrics"&lt;/li&gt;
&lt;li&gt;You should see a custom namespace named either:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;HetznerLoadBalancer&lt;/code&gt; (for Load Balancer metrics)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;HetznerServer&lt;/code&gt; (for Server metrics)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click on the namespace to explore the available metrics&lt;/li&gt;
&lt;li&gt;Select a metric to view its data&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For Load Balancers, you'll see metrics like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;open_connections&lt;/strong&gt;: Number of currently open connections&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;connections_per_second&lt;/strong&gt;: Rate of new connections&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;requests_per_second&lt;/strong&gt;: HTTP/HTTPS requests processed per second&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;bandwidth_in&lt;/strong&gt; and &lt;strong&gt;bandwidth_out&lt;/strong&gt;: Network traffic in bytes per second&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Servers, you'll see metrics like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;cpu&lt;/strong&gt;: CPU utilization percentage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;disk_iops_read&lt;/strong&gt; and &lt;strong&gt;disk_iops_write&lt;/strong&gt;: Disk operations per second&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;disk_bandwidth_read&lt;/strong&gt; and &lt;strong&gt;disk_bandwidth_write&lt;/strong&gt;: Disk throughput&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;network_bandwidth_in&lt;/strong&gt; and &lt;strong&gt;network_bandwidth_out&lt;/strong&gt;: Network traffic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;network_packets_in&lt;/strong&gt; and &lt;strong&gt;network_packets_out&lt;/strong&gt;: Packet counts&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 7 - Create CloudWatch Dashboards (Optional)
&lt;/h2&gt;

&lt;p&gt;Now that your metrics are flowing into CloudWatch, you can create custom dashboards for visualization.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the CloudWatch Console, click "Dashboards" in the left navigation&lt;/li&gt;
&lt;li&gt;Click "Create dashboard"&lt;/li&gt;
&lt;li&gt;Give it a name like "Hetzner Load Balancer Monitoring"&lt;/li&gt;
&lt;li&gt;Click "Add widget"&lt;/li&gt;
&lt;li&gt;Select "Line" or "Number" widget type&lt;/li&gt;
&lt;li&gt;Choose your metrics from the &lt;code&gt;HetznerLoadBalancer&lt;/code&gt; or &lt;code&gt;HetznerServer&lt;/code&gt; namespace&lt;/li&gt;
&lt;li&gt;Configure the graph settings and save the widget&lt;/li&gt;
&lt;li&gt;Add more widgets as needed to create a comprehensive dashboard&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can create graphs showing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU usage over time for servers&lt;/li&gt;
&lt;li&gt;Request rate trends for load balancers&lt;/li&gt;
&lt;li&gt;Network bandwidth utilization&lt;/li&gt;
&lt;li&gt;Connection counts and patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 8 - Set Up CloudWatch Alarms (Optional)
&lt;/h2&gt;

&lt;p&gt;CloudWatch alarms can notify you when metrics exceed thresholds.&lt;/p&gt;

&lt;p&gt;Here's an example of creating an alarm using Terraform. Add this to your &lt;code&gt;main.tf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_cloudwatch_metric_alarm"&lt;/span&gt; &lt;span class="s2"&gt;"high_cpu"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;alarm_name&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hetzner-server-high-cpu"&lt;/span&gt;
  &lt;span class="nx"&gt;comparison_operator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"GreaterThanThreshold"&lt;/span&gt;
  &lt;span class="nx"&gt;evaluation_periods&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="nx"&gt;metric_name&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"cpu"&lt;/span&gt;
  &lt;span class="nx"&gt;namespace&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"HetznerServer"&lt;/span&gt;
  &lt;span class="nx"&gt;period&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;
  &lt;span class="nx"&gt;statistic&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Average"&lt;/span&gt;
  &lt;span class="nx"&gt;threshold&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
  &lt;span class="nx"&gt;alarm_description&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"This metric monitors server CPU utilization"&lt;/span&gt;
  &lt;span class="nx"&gt;dimensions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;ServerId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;server_id&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;# Optional: Add SNS topic for notifications&lt;/span&gt;
  &lt;span class="c1"&gt;# alarm_actions = [aws_sns_topic.alerts.arn]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;terraform apply&lt;/code&gt; again to create the alarm.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 9 - Monitor Multiple Resources
&lt;/h2&gt;

&lt;p&gt;To monitor multiple Load Balancers or Servers, you can create multiple module instances:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# First Load Balancer&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"loadbalancer_metrics_1"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"kamranbiglari/hetzner-cloudwatch-integration/aws"&lt;/span&gt;
  &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 1.0"&lt;/span&gt;
  &lt;span class="nx"&gt;hetzner_cloud_api_token&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hetzner_cloud_api_token&lt;/span&gt;
  &lt;span class="nx"&gt;metric_type&lt;/span&gt;             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"loadbalancer"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hetzner-lb-metrics-1"&lt;/span&gt;
  &lt;span class="nx"&gt;create_scheduler&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;schedule_expression&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rate(5 minutes)"&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;loadbalancer_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"123456"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;# Second Load Balancer&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt; &lt;span class="s2"&gt;"loadbalancer_metrics_2"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"kamranbiglari/hetzner-cloudwatch-integration/aws"&lt;/span&gt;
  &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 1.0"&lt;/span&gt;
  &lt;span class="c1"&gt;# Reuse the EventBridge Connection from the first module&lt;/span&gt;
  &lt;span class="nx"&gt;create_event_connection&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="nx"&gt;event_connection_arn&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadbalancer_metrics_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;event_connection_arn&lt;/span&gt;
  &lt;span class="nx"&gt;metric_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"loadbalancer"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hetzner-lb-metrics-2"&lt;/span&gt;
  &lt;span class="nx"&gt;create_scheduler&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;schedule_expression&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rate(5 minutes)"&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;loadbalancer_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"789012"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the second module reuses the EventBridge Connection from the first module to avoid storing the API token multiple times. This is more efficient and secure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 10 - Query Metrics Using AWS CLI (Optional)
&lt;/h2&gt;

&lt;p&gt;You can also query metrics programmatically using the AWS CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Get CPU metrics for a server&lt;/span&gt;
aws cloudwatch get-metric-statistics &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--namespace&lt;/span&gt; HetznerServer &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--metric-name&lt;/span&gt; cpu &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--dimensions&lt;/span&gt; &lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ServerId,Value&lt;span class="o"&gt;=&lt;/span&gt;789012 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--start-time&lt;/span&gt; 2025-01-01T00:00:00Z &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--end-time&lt;/span&gt; 2025-01-01T01:00:00Z &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--period&lt;/span&gt; 300 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--statistics&lt;/span&gt; Average

&lt;span class="c"&gt;# Get requests per second for a load balancer&lt;/span&gt;
aws cloudwatch get-metric-statistics &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--namespace&lt;/span&gt; HetznerLoadBalancer &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--metric-name&lt;/span&gt; requests_per_second &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--dimensions&lt;/span&gt; &lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;LoadBalancerId,Value&lt;span class="o"&gt;=&lt;/span&gt;123456 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--start-time&lt;/span&gt; 2025-01-01T00:00:00Z &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--end-time&lt;/span&gt; 2025-01-01T01:00:00Z &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--period&lt;/span&gt; 300 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--statistics&lt;/span&gt; Average,Maximum
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 11 - Customize Collection Frequency
&lt;/h2&gt;

&lt;p&gt;The default collection frequency is every 5 minutes. You can adjust this by changing the &lt;code&gt;schedule_expression&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Every minute&lt;/span&gt;
&lt;span class="nx"&gt;schedule_expression&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rate(1 minute)"&lt;/span&gt;
&lt;span class="c1"&gt;# Every 10 minutes&lt;/span&gt;
&lt;span class="nx"&gt;schedule_expression&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rate(10 minutes)"&lt;/span&gt;
&lt;span class="c1"&gt;# Using cron syntax - every 5 minutes&lt;/span&gt;
&lt;span class="nx"&gt;schedule_expression&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"cron(0/5 * * * ? *)"&lt;/span&gt;
&lt;span class="c1"&gt;# Every hour at minute 0&lt;/span&gt;
&lt;span class="nx"&gt;schedule_expression&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"cron(0 * * * ? *)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep in mind that more frequent collections will increase your AWS costs slightly, but the impact is minimal (a few cents per month per resource).&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 12 - Clean Up (Optional)
&lt;/h2&gt;

&lt;p&gt;If you want to remove the monitoring infrastructure, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Type &lt;code&gt;yes&lt;/code&gt; when prompted. This will remove all created AWS resources. Note that CloudWatch metric data is retained for 15 months by default, even after you delete the infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Congratulations! You have successfully integrated your Hetzner Cloud infrastructure with AWS CloudWatch. Your metrics are now being collected automatically every 5 minutes and are available for visualization, alerting, and analysis in CloudWatch.&lt;/p&gt;

&lt;p&gt;This integration provides several benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Centralized monitoring&lt;/strong&gt;: All your infrastructure metrics in one place&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated collection&lt;/strong&gt;: No manual intervention required&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost-effective&lt;/strong&gt;: Serverless architecture means you only pay for what you use&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalable&lt;/strong&gt;: Easy to add more resources to monitor&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure&lt;/strong&gt;: API tokens are stored encrypted in AWS Secrets Manager&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next steps you might consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create comprehensive CloudWatch dashboards for your team&lt;/li&gt;
&lt;li&gt;Set up CloudWatch alarms with SNS notifications for critical metrics&lt;/li&gt;
&lt;li&gt;Integrate with AWS CloudWatch Insights for advanced querying&lt;/li&gt;
&lt;li&gt;Export metrics to other tools using CloudWatch Metric Streams&lt;/li&gt;
&lt;li&gt;Explore the &lt;a href="https://registry.terraform.io/modules/kamranbiglari/hetzner-cloudwatch-integration/aws" rel="noopener noreferrer"&gt;Terraform module documentation&lt;/a&gt; for advanced configuration options&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>hetzner</category>
      <category>terraform</category>
    </item>
  </channel>
</rss>
