Initial commit

This commit is contained in:
Janis_Hahn 2025-12-22 14:54:16 +01:00
commit d0327a2263
10 changed files with 842 additions and 0 deletions

42
.gitignore vendored Normal file
View file

@ -0,0 +1,42 @@
# ---> Terraform
# Local .terraform directories
**/.terraform/*
# .tfstate files
*.tfstate
*.tfstate.*
# Crash log files
crash.log
crash.*.log
# Exclude all .tfvars files, which are likely to contain sensitive data, such as
# password, private keys, and other secrets. These should not be part of version
# control as they are data points which are potentially sensitive and subject
# to change depending on the environment.
# *.tfvars
# *.tfvars.json
# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json
# Ignore transient lock info files created by terraform apply
.terraform.tfstate.lock.info
# Include override files you do wish to add to version control using negated pattern
# !example_override.tf
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*
# Ignore CLI configuration files
.terraformrc
terraform.rc
# Ignore Images
PRIMARY-DISK.qcow2
AUXILIARY-DISK.qcow2

25
.terraform.lock.hcl Normal file
View file

@ -0,0 +1,25 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/stackitcloud/stackit" {
version = "0.69.0"
constraints = ">= 0.50.0"
hashes = [
"h1:ZJT3yMWfm4f2+L8XOJlp4x9dAej6TOz0POQi6yvRimc=",
"zh:0062c29953695943f44561264542c65050c35b45fc5fd279d07db40a856c7e33",
"zh:01f74068286ebbb9e7a280e893b6a941214444986ec0aad156b0a349ab3efbab",
"zh:0dde99e7b343fa01f8eefc378171fb8621bedb20f59157d6cc8e3d46c738105f",
"zh:23f695fc9299cbdff0cef3e99eccdfd6dbc85266d71f9e7eb917066821f97b2d",
"zh:2cb58760e26de6afc93b26452e1987eca0713ecca5a252e3baf4b6a9adce5ab0",
"zh:33b72f438dccbbba5015bd3e265db83fa69f693f5e93cfaf1735bcfd92f2198b",
"zh:4d22147d5881b6ea824ca11d8676dd3c24b378a87e72d849485d87c412d57c0d",
"zh:7373e3036eee52c5d915992bcd42df3227603714e9b814d1f8513e0891b87a54",
"zh:7ea4ad058e2767d7461c4b0cc02adf8591f0c3541274481611ca7c8bc4396f9d",
"zh:82e2568b28874ded800a592b84e6cd570a2f3488214422041a41918076a2db49",
"zh:ae2d827c2328c225d279e37f6e1de2605b670b2f1bddf5d43e7c932ef4ff52a3",
"zh:b206487c97f87f0cde19ef0ab1cfdeafa60ad9fbabdf0d771d96bb56d6d2e94f",
"zh:bdbbe0ba3b3b80b0f2bc09b59ea72f9564f9b93d80949f69f6469b0ab8d6b91c",
"zh:c955889cbb87227031233b2226ebe591e4a30699e3f0fc9f32b61ff2c3836dd7",
"zh:cf51867c75f3c0b58a2e8a2404d4468d0520588aa892c3b30e5beb8a8d20ce79",
]
}

42
00-variables.auto.tfvars Normal file
View file

@ -0,0 +1,42 @@
# -----------------------------------------------------------------------------
# STACKIT Cloud: Core Configuration
# -----------------------------------------------------------------------------
project_id = "6f9528aa-27c8-4e97-a0f7-51bbf3be417c"
service_account_key_path = "/Users/hahnjan/.stackit/sa-key_JSP.json"
default_region = "eu01"
default_az = "eu01-3"
# -----------------------------------------------------------------------------
# Network Settings
# -----------------------------------------------------------------------------
sophos_nets_routed = true
sophos_wan_nameservers = ["1.1.1.1", "8.8.8.8"]
sophos_default_nameservers = ["8.8.8.8", "9.9.9.9"]
# --- Network Ranges ---
sophos_wan_net_range = "10.220.1.0/24"
sophos_lan_net_range = "10.220.0.0/24"
sophos_mgmt_net_range = "10.220.2.0/24"
sophos_sync_net_range = "10.220.3.0/24"
# --- HA VIP ---
sophos_wan_vip = "10.220.1.60"
# -----------------------------------------------------------------------------
# VM Configuration
# -----------------------------------------------------------------------------
# --- IPs: Sophos 1 ---
sophos1_mgmt_ip = "10.220.2.10"
sophos1_wan_ip = "10.220.1.11"
sophos1_lan_ip = "10.220.0.12"
# --- IPs: Sophos 2 ---
sophos2_mgmt_ip = "10.220.2.20"
sophos2_wan_ip = "10.220.1.21"
sophos2_lan_ip = "10.220.0.22"
# --- Core VM Config ---
sophos_primary_image_path = "./PRIMARY-DISK.qcow2"
sophos_secondary_image_path = "./AUXILIARY-DISK.qcow2"
flavor = "m2i.2"

15
01-provider.tf Normal file
View file

@ -0,0 +1,15 @@
terraform {
required_providers {
stackit = {
source = "stackitcloud/stackit"
version = ">=0.50.0"
}
}
}
provider "stackit" {
default_region = var.default_region
service_account_key_path = var.service_account_key_path
}

147
02-config.tf Normal file
View file

@ -0,0 +1,147 @@
# -----------------------------------------------------------------------------
# STACKIT Cloud: Core Configuration Variables
# -----------------------------------------------------------------------------
variable "project_id" {
type = string
}
variable "service_account_key_path" {
type = string
}
variable "default_region" {
type = string
default ="eu01"
}
variable "default_az" {
type = string
}
# -----------------------------------------------------------------------------
# Network Variables
# -----------------------------------------------------------------------------
# --- Global Settings ---
variable "sophos_nets_routed" {
description = "Defines if the networks should be routed (true/false)"
type = bool
default = true
}
# --- Nameservers ---
variable "sophos_wan_nameservers" {
description = "List of Nameservers for the WAN interface"
type = list(string)
default = ["1.1.1.1", "8.8.8.8"]
}
variable "sophos_default_nameservers" {
description = "List of Nameservers for internal networks (LAN, MGMT, SYNC)"
type = list(string)
default = ["8.8.8.8", "9.9.9.9"]
}
# --- Network Ranges (Prefixes) ---
variable "sophos_wan_net_range" {
description = "CIDR block for the WAN network"
type = string
default = "10.220.1.0/24"
}
variable "sophos_lan_net_range" {
description = "CIDR block for the LAN network"
type = string
default = "10.220.0.0/24"
}
variable "sophos_mgmt_net_range" {
description = "CIDR block for the MGMT network"
type = string
default = "10.220.2.0/24"
}
variable "sophos_sync_net_range" {
description = "CIDR block for the SYNC network"
type = string
default = "10.220.3.0/24"
}
# --- Specific Wan HA VIP ---
variable "sophos_wan_vip" {
description = "The specific IPv4 address for the High Availability VIP interface"
type = string
default = "10.220.1.60"
}
# -----------------------------------------------------------------------------
# VM Variables
# -----------------------------------------------------------------------------
# --- Image File Paths ---
variable "sophos_primary_image_path" {
description = "Local path to the primary Sophos QCOW2 image file"
type = string
default = "./PRIMARY-DISK.qcow2"
}
variable "sophos_secondary_image_path" {
description = "Local path to the secondary (auxiliary) Sophos QCOW2 image file"
type = string
default = "./AUXILIARY-DISK.qcow2"
}
# --- VM Flavor ---
variable "flavor" {
type = string
description = "Flavor of the Sophos Appliances"
default = "m2i.2"
}
# --- IPs Sophos 1 ---
variable "sophos1_mgmt_ip" {
description = "Management IP Sophos 1"
type = string
default = "10.220.2.10"
}
variable "sophos1_wan_ip" {
description = "WAN IP Sophos 1"
type = string
default = "10.220.1.11"
}
variable "sophos1_lan_ip" {
description = "LAN IP Sophos 1"
type = string
default = "10.220.0.12"
}
# --- IPs Sophos 2 ---
variable "sophos2_mgmt_ip" {
description = "Management IP Sophos 2"
type = string
default = "10.220.2.20"
}
variable "sophos2_wan_ip" {
description = "WAN IP Sophos 2"
type = string
default = "10.220.1.22"
}
variable "sophos2_lan_ip" {
description = "LAN IP Sophos 2"
type = string
default = "10.220.0.22"
}

24
03-sophos-image.tf Normal file
View file

@ -0,0 +1,24 @@
# -----------------------------------------------------------------------------
# Images
# -----------------------------------------------------------------------------
resource "stackit_image" "sophos_primary_image" {
project_id = var.project_id
name = "sophos-primary-disk-image"
local_file_path = "./PRIMARY-DISK.qcow2"
disk_format = "qcow2"
min_disk_size = 100
config = {
uefi = false
}
}
resource "stackit_image" "sophos_secondary_image" {
project_id = var.project_id
name = "sophos-secondary-disk-image"
local_file_path = "./AUXILIARY-DISK.qcow2"
disk_format = "qcow2"
min_disk_size = 100
config = {
uefi = false
}
}

112
04-sophos-network.tf Normal file
View file

@ -0,0 +1,112 @@
# -----------------------------------------------------------------------------
# Network
# -----------------------------------------------------------------------------
resource "stackit_network" "sophos_lan_net" {
project_id = var.project_id
name = "sophos_lan_net"
ipv4_nameservers = var.sophos_default_nameservers
ipv4_prefix = var.sophos_lan_net_range
routed = var.sophos_nets_routed
}
resource "stackit_network" "sophos_wan_net" {
project_id = var.project_id
name = "sophos_wan_net"
ipv4_prefix = var.sophos_wan_net_range
ipv4_nameservers = var.sophos_wan_nameservers
routed = var.sophos_nets_routed
}
resource "stackit_network" "sophos_mgmt_net" {
project_id = var.project_id
name = "sophos_mgmt_net"
ipv4_prefix = var.sophos_mgmt_net_range
ipv4_nameservers = var.sophos_default_nameservers
routed = var.sophos_nets_routed
}
resource "stackit_network" "sophos_sync_net" {
project_id = var.project_id
name = "sophos_sync_net"
ipv4_prefix = var.sophos_sync_net_range
ipv4_nameservers = var.sophos_default_nameservers
routed = var.sophos_nets_routed
}
# -----------------------------------------------------------------------------
# VIP Interface - others are located directly at the appliances
# -----------------------------------------------------------------------------
resource "stackit_network_interface" "vip" {
project_id = var.project_id
network_id = stackit_network.sophos_wan_net.network_id
security = true
name = "VIP"
ipv4 = var.sophos_wan_vip
security_group_ids = [ stackit_security_group.sophos.security_group_id ]
}
resource "stackit_public_ip" "public-vip" {
project_id = var.project_id
network_interface_id = stackit_network_interface.vip.network_interface_id
}
output "public-vip" {
value = {
"public_ip_sophos" = stackit_public_ip.public-vip.ip
}
}
# -----------------------------------------------------------------------------
# Security Groups / Rules
# -----------------------------------------------------------------------------
resource "stackit_security_group" "sophos" {
project_id = var.project_id
name = "Sophos"
}
resource "stackit_security_group_rule" "tcp-ingress" {
project_id = var.project_id
security_group_id = stackit_security_group.sophos.security_group_id
direction = "ingress"
protocol = {
name = "tcp"
}
}
resource "stackit_security_group_rule" "icmp-ingress" {
project_id = var.project_id
security_group_id = stackit_security_group.sophos.security_group_id
direction = "ingress"
protocol = {
name = "icmp"
}
icmp_parameters = {
code = 0
type = 8
}
}
resource "stackit_security_group_rule" "tcp-egress" {
project_id = var.project_id
security_group_id = stackit_security_group.sophos.security_group_id
direction = "egress"
protocol = {
name = "tcp"
}
}
resource "stackit_security_group_rule" "icmp-egress" {
project_id = var.project_id
security_group_id = stackit_security_group.sophos.security_group_id
direction = "egress"
protocol = {
name = "icmp"
}
icmp_parameters = {
code = 0
type = 8
}
}

118
05-sophos-appliance1.tf Normal file
View file

@ -0,0 +1,118 @@
# -----------------------------------------------------------------------------
# Volumes Sophos 1
# -----------------------------------------------------------------------------
resource "stackit_volume" "sophos_primary_vol1" {
project_id = var.project_id
name = "sophos-primary-disk1"
availability_zone = var.default_az
size = 150
performance_class = "storage_premium_perf4"
source = {
id = stackit_image.sophos_primary_image.image_id
type = "image"
}
}
resource "stackit_volume" "sophos_data_vol1" {
project_id = var.project_id
name = "sophos-data-disk1"
availability_zone = var.default_az
size = 100
performance_class = "storage_premium_perf4"
source = {
id = stackit_image.sophos_secondary_image.image_id
type = "image"
}
}
# -----------------------------------------------------------------------------
# Sophos VM 1
# -----------------------------------------------------------------------------
resource "stackit_server" "sophos_appliance1" {
project_id = var.project_id
name = "Sophos-Appliance1"
boot_volume = {
source_type = "volume"
source_id = stackit_volume.sophos_primary_vol1.volume_id
}
availability_zone = var.default_az
machine_type = var.flavor
}
resource "stackit_server_volume_attach" "sophos_data_attachment1" {
project_id = var.project_id
server_id = stackit_server.sophos_appliance1.server_id
volume_id = stackit_volume.sophos_data_vol1.volume_id
depends_on = [ stackit_server.sophos_appliance1 ]
}
# -----------------------------------------------------------------------------
# Interfaces Sophos 1
# -----------------------------------------------------------------------------
resource "stackit_network_interface" "nic_mgmt_sophos1" {
project_id = var.project_id
network_id = stackit_network.sophos_mgmt_net.network_id
name = "nic_mgmt_sophos1"
security = false
ipv4 = var.sophos1_mgmt_ip
}
resource "stackit_network_interface" "nic_wan_sophos1" {
project_id = var.project_id
network_id = stackit_network.sophos_wan_net.network_id
security = true
name = "nic_wan_sophos1"
allowed_addresses = ["${stackit_network_interface.vip.ipv4}/32", "0.0.0.0/0"]
security_group_ids = [stackit_security_group.sophos.security_group_id]
ipv4 = var.sophos1_wan_ip
}
resource "stackit_network_interface" "nic_lan_sophos1" {
project_id = var.project_id
network_id = stackit_network.sophos_lan_net.network_id
security = false
name = "nic_lan_sophos1"
ipv4 = var.sophos1_lan_ip
}
resource "stackit_network_interface" "nic_sync_sophos1" {
project_id = var.project_id
network_id = stackit_network.sophos_sync_net.network_id
security = false
#security_group_ids = [ stackit_security_group.sophos.security_group_id ]
name = "nic_sync_sophos1"
}
# -----------------------------------------------------------------------------
# Interface Attachements 1
# -----------------------------------------------------------------------------
resource "stackit_server_network_interface_attach" "nic-attachment-mgmt1" {
project_id = var.project_id
server_id = stackit_server.sophos_appliance1.server_id
network_interface_id = stackit_network_interface.nic_mgmt_sophos1.network_interface_id
}
resource "stackit_server_network_interface_attach" "nic-attachment-wan1" {
project_id = var.project_id
server_id = stackit_server.sophos_appliance1.server_id
network_interface_id = stackit_network_interface.nic_wan_sophos1.network_interface_id
depends_on = [stackit_server_network_interface_attach.nic-attachment-mgmt1]
}
resource "stackit_server_network_interface_attach" "nic-attachment-lan1" {
project_id = var.project_id
server_id = stackit_server.sophos_appliance1.server_id
network_interface_id = stackit_network_interface.nic_lan_sophos1.network_interface_id
depends_on = [stackit_server_network_interface_attach.nic-attachment-wan1]
}
resource "stackit_server_network_interface_attach" "nic-attachment-sync1" {
project_id = var.project_id
server_id = stackit_server.sophos_appliance1.server_id
network_interface_id = stackit_network_interface.nic_sync_sophos1.network_interface_id
depends_on = [stackit_server_network_interface_attach.nic-attachment-lan1]
}

118
06-sophos-appliance2.tf Normal file
View file

@ -0,0 +1,118 @@
# -----------------------------------------------------------------------------
# Volumes Sophos 2
# -----------------------------------------------------------------------------
resource "stackit_volume" "sophos_primary_vol2" {
project_id = var.project_id
name = "sophos-primary-disk2"
availability_zone = var.default_az
size = 150
performance_class = "storage_premium_perf4"
source = {
id = stackit_image.sophos_primary_image.image_id
type = "image"
}
}
resource "stackit_volume" "sophos_data_vol2" {
project_id = var.project_id
name = "sophos-data-disk2"
availability_zone = var.default_az
size = 100
performance_class = "storage_premium_perf4"
source = {
id = stackit_image.sophos_secondary_image.image_id
type = "image"
}
}
# -----------------------------------------------------------------------------
# Sophos VM 2
# -----------------------------------------------------------------------------
resource "stackit_server" "sophos_appliance2" {
project_id = var.project_id
name = "Sophos-Appliance2"
boot_volume = {
source_type = "volume"
source_id = stackit_volume.sophos_primary_vol2.volume_id
}
availability_zone = var.default_az
machine_type = var.flavor
}
resource "stackit_server_volume_attach" "sophos_data_attachment2" {
project_id = var.project_id
server_id = stackit_server.sophos_appliance2.server_id
volume_id = stackit_volume.sophos_data_vol2.volume_id
depends_on = [ stackit_server.sophos_appliance2 ]
}
# -----------------------------------------------------------------------------
# Interfaces Sophos 2
# -----------------------------------------------------------------------------
resource "stackit_network_interface" "nic_mgmt_sophos2" {
project_id = var.project_id
network_id = stackit_network.sophos_mgmt_net.network_id
name = "nic_mgmt_sophos2"
security = false
ipv4 = var.sophos2_mgmt_ip
}
resource "stackit_network_interface" "nic_wan_sophos2" {
project_id = var.project_id
network_id = stackit_network.sophos_wan_net.network_id
security = true
name = "nic_wan_sophos2"
allowed_addresses = ["${stackit_network_interface.vip.ipv4}/32", "0.0.0.0/0"]
security_group_ids = [stackit_security_group.sophos.security_group_id]
ipv4 = var.sophos2_wan_ip
}
resource "stackit_network_interface" "nic_lan_sophos2" {
project_id = var.project_id
network_id = stackit_network.sophos_lan_net.network_id
security = false
name = "nic_lan_sophos2"
ipv4 = var.sophos2_lan_ip
}
resource "stackit_network_interface" "nic_sync_sophos2" {
project_id = var.project_id
network_id = stackit_network.sophos_sync_net.network_id
security = false
#security_group_ids = [ stackit_security_group.sophos.security_group_id ]
name = "nic_sync_sophos2"
}
# -----------------------------------------------------------------------------
# Interface Attachements 2
# -----------------------------------------------------------------------------
resource "stackit_server_network_interface_attach" "nic-attachment-mgmt2" {
project_id = var.project_id
server_id = stackit_server.sophos_appliance2.server_id
network_interface_id = stackit_network_interface.nic_mgmt_sophos2.network_interface_id
}
resource "stackit_server_network_interface_attach" "nic-attachment-wan2" {
project_id = var.project_id
server_id = stackit_server.sophos_appliance2.server_id
network_interface_id = stackit_network_interface.nic_wan_sophos2.network_interface_id
depends_on = [stackit_server_network_interface_attach.nic-attachment-mgmt2]
}
resource "stackit_server_network_interface_attach" "nic-attachment-lan2" {
project_id = var.project_id
server_id = stackit_server.sophos_appliance2.server_id
network_interface_id = stackit_network_interface.nic_lan_sophos2.network_interface_id
depends_on = [stackit_server_network_interface_attach.nic-attachment-wan2]
}
resource "stackit_server_network_interface_attach" "nic-attachment-sync2" {
project_id = var.project_id
server_id = stackit_server.sophos_appliance2.server_id
network_interface_id = stackit_network_interface.nic_sync_sophos2.network_interface_id
depends_on = [stackit_server_network_interface_attach.nic-attachment-lan2]
}

199
README.md Normal file
View file

@ -0,0 +1,199 @@
# Sophos HA on STACKIT
This directory contains the **Terraform configuration** for deploying a **High Availability (HA) cluster** of two **Sophos Firewalls** on the **STACKIT** cloud platform. The configuration includes all necessary resources such as networks, virtual machines (appliances), volumes, interfaces, and security groups.
## Content Readme
* [Directory Structure](#directory-structure)
* [Prerequisites](#prerequisites)
* [Infrastructure Guide](#infrastructure-guide)
* [Application Guide](#application-guide)
---
## Directory Structure
#### [`01-provider.tf`](./01-provider.tf)
This file initializes the **STACKIT Terraform Provider**. It defines which cloud platform is being managed and specifies the version to be used. The **latest version** is always selected; in the specific deployment, **Version 0.69.0** was used.
#### [`02-config.tf`](./02-config.tf)
This is where the most important **configuration variables** are defined, determining the target project and hardware specifications. Parameters include `project_id`, the path to the `service_account_key_path`, and default settings for `default_region`, `default_az`, and the VM `flavor` (e.g., `m2i.2`).
#### [`03-sophos-image.tf`](./03-sophos-image.tf)
This file configures the creation of the necessary STACKIT images. The local **QCOW2 files** (`PRIMARY-DISK.qcow2` and `AUXILIARY-DISK.qcow2`), which contain the Sophos installation, are converted into usable cloud images.
#### [`04-sophos-network.tf`](./04-sophos-network.tf)
Here, the four **Sophos-specific networks** (Management, LAN, Synchronization, WAN) and the associated components are configured:
* `sophos_mgmt_net`
* `sophos_lan_net`
* `sophos_sync_net`
* `sophos_wan_net`
* A **VIP (Virtual IP) Interface** for HA operation. The VIP should not be attached to any VM.
* A **Public IP address** for external access (e.g., WAN).
* The necessary **Security Groups and Rules** to control traffic.
#### [`05-sophos-appliance1.tf`](./05-sophos-appliance1.tf) and [`06-sophos-appliance2.tf`](./06-sophos-appliance2.tf)
These files each define one of the two Sophos VMs that form the HA cluster. The configuration includes:
* Creation of the two **Volumes** (boot and auxiliary disk) for the VM.
* Creation of the **VM** itself.
* Creation and correct sequential attachment of the **four network interfaces**:
1. Management (`mgmt`)
2. LAN (`lan`)
3. Synchronization (`sync`)
4. WAN (`wan`)
---
## Prerequisites
Before deploying the Sophos HA construct, ensure the following tools and assets are available:
### 1. Software Tools
* **Terraform CLI:** You need the **Terraform Command Line Interface** installed and configured to execute the Infrastructure-as-Code files (`*.tf`).
* **STACKIT CLI (Optional):** The **STACKIT Command Line Interface** is not strictly required for the Terraform deployment itself but can be useful for managing your STACKIT Project and is *recommended* for mapping the MAC addresses.
### 2. Sophos Assets
* **Sophos Images (QCOW2 Format):** The Sophos appliance images must be available as **two QCOW2 files**.
* Place these files directly in the root directory and ensure they are named exactly:
* `PRIMARY-DISK.qcow2`
* `AUXILIARY-DISK.qcow2`
* **Sophos Serial Number/License:** A valid **Sophos Serial Number** or **License** is required to activate the appliances and enable HA functionality after they have been successfully deployed.
---
## Infrastructure Guide
### Step 1: Prepare the Environment
1. **Clone the Repository:**
```bash
git clone <repository-url>
cd Sophos-HA
```
2. **Provide Sophos Images:**
* Place the two Sophos QCOW2 image files directly into the root directory of the cloned repository.
* Ensure they are named correctly or adjust the path as a variable: `PRIMARY-DISK.qcow2` and `AUXILIARY-DISK.qcow2`.
### Step 2: Configure Terraform Variables
1. **Create Variables File:**
* The required variables are defined in `02-config.tf`. To provide the values, create a new file named **`00-variables.auto.tfvars`** in the root directory.
* Fill in the values based on your project and environment:
2. **Configure STACKIT Service Account:**
* **Generate** a STACKIT Service Account Key (JSON format) and place the path to this key in the `service_account_key_path` variable.
3. **Configure Terraform Backend:**
* **Recommendation:** For production environments, it is highly recommended to configure a remote backend (e.g., a **STACKIT Object Storage Bucket**) in `01-provider.tf` to store the `tfstate` securely. Alternatively, you can use the default local backend configuration for testing purposes.
### Step 3: Execute Terraform
1. **Initialize Terraform:**
* Ensure that you are in the project folder (`cd Sophos-HA`).
* Initialize the working directory and download the necessary providers (including the STACKIT provider).
```bash
terraform init
```
2. **Review the Plan:**
* Check the infrastructure changes Terraform intends to make.
```bash
terraform plan
```
3. **Apply the Configuration:**
* Execute the plan to deploy all resources (Networks, Images, Volumes, VMs/Appliances).
```bash
terraform apply
```
* Wait until the process is complete and the VMs are fully provisioned and booted.
### Step 4: Initial Sophos Appliance Configuration
After successful deployment, the two Sophos Appliances need an initial configuration via the console to enable management access.
1. **Access the Console:**
* In the STACKIT Portal, access the **Console** of **Appliance 1** (`sophos-appliance1`).
2. **Initial Login:**
* The Sophos appliance should boot into the main menu.
* The standard password for Sophos appliances is **`admin`** (case sensitive).
3. **Configure Management Interface:**
* From the main menu, select **`1. Network Configuration`**.
* Select **`1. Interface Configuration`**.
* Identify the interface corresponding to the **Management Network** (e.g., Port 1) and configure it with the pre-defined ipv4 IP and CIDR block from the Terraform configuration (specifically the **`sophos_mgmt_net`** ).
4. **Repeat for Appliance 2:**
* Perform the same initial console configuration for **Appliance 2** (`sophos-appliance2`), assigning it the pre-defined IP and CIDR within the same `sophos_mgmt_net` subnet.
5. **Access Web Interface:**
* Use a jump host VM within the same subnet `sophos_mgmt_net` or your local device with appropriate routing to access the Sophos WebAdmin console. (`https://<mgmt-ip>:4444`)
## Application Guide
This section outlines the configuration steps required within the Sophos WebAdmin interface to establish the High Availability (HA) cluster and configure public connectivity.
### Step 1: Initial Wizard and Registration
1. **Run the Setup Wizard:**
* Log in to the WebAdmin of both appliances (`https://<mgmt-ip>:4444`).
* Complete the basic setup wizard on **both** appliances.
* **Firmware Check:** Ensure both appliances are running the **exact same firmware version**.
* *Tip:* If firmware versions match immediately, you can configure the second appliance as an "HA Spare" directly during the first wizard step. Otherwise, configure both as standalone first and update firmware.
2. **Registration:**
* After the reboot, log in with the admin credentials.
* Register both firewalls. A valid license (minimum **Home License**) is required to enable HA functionality.
### Step 2: Configure Sync Interface
Perform these steps on **both** appliances:
1. **Network Configuration:**
* Navigate to **Network > Interfaces**.
* Edit the Port identified as the **Sync Interface**.
* Set the **Network Zone** to **DMZ**.
* Assign the IP address allocated by Terraform for the Sync network.
2. **Device Access:**
* Navigate to **Administration > Device Access**.
* Enable **SSH** on the **DMZ** zone (required for HA communication).
### Step 3: Configure High Availability (HA)
Configure the **Auxiliary (Sophos 2)** appliance first, then the **Primary (Sophos 1)**.
#### 1. Configure Sophos 2 (Auxiliary)
* Navigate to **System Services > High Availability**.
* **Initial Device Role:** Select **Auxiliary (Interactive Mode)**.
* **Node Name:** Assign a name (e.g., `Sophos-Node2`).
* **Passphrase:** Set a secure passphrase (note this down, it must match on the Primary).
* **Dedicated HA Link:** Select the **DMZ Port** configured in Step 3.
* Click **Save** or **Enable HA**.
#### 2. Configure Sophos 1 (Primary)
* Navigate to **System Services > High Availability**.
* **Initial Device Role:** Select **Primary (Interactive Mode)**.
* **Cluster ID:** Select an ID (0-63).
* **Node Name:** Assign a name (e.g., `Sophos-Node1`).
* **Passphrase:** Enter the same passphrase used on the Auxiliary.
* **Dedicated HA Link:** Select the **DMZ Port**.
* **Peer HA Link IPv4:** Enter the IP address of the **Sophos 2 Sync Interface**.
* **Monitored Ports:** Select the interfaces to monitor (usually LAN and WAN).
* **Peer Administration Settings:** Enter the **Management IP** of Sophos 2.
* **Hypervisor MAC:** Set **Use host or hypervisor-assigned MAC address** to **True**.
* *Important:* This setting is critical for STACKIT/OpenStack environments to ensure traffic routing works correctly during failover.
* Click **Enable HA**.
### Step 4: Post-HA Network Configuration (VIP)
Once the HA cluster is built, the primary appliance handles traffic. You must now configure the public-facing interface to use the Virtual IP (VIP).
1. **Assign VIP Address:**
* On the active (Primary) appliance, navigate to **Network > Interfaces**.
* Edit the **WAN Port**.
* Manually change the IP address to the **local VIP Address**.
2. **Enable WAN Services:**
* Navigate to **Administration > Device Access**.
* Enable necessary services on the **WAN** zone (e.g., User Portal, VPN).
* **Testing:** Temporarily enable **Ping** on WAN to verify connectivity.
### Step 5: Verification and Failover Test
1. **Ping Test:**
* Ping the **Public IP** output by the Terraform script. It should be reachable.
2. **Failover Test:**
* Shut down the **Primary VM** via the STACKIT Portal or Sophos WebUI.
* The **Auxiliary VM** should take over the role of Primary after a short interruption.
* Verify that the Public IP remains pingable.