Terraform Template
Overview
You can deploy SFTP Gateway version 3 using Terraform.
This article covers deploying a single VM instance of SFTP Gateway Professional version 3.6.0
on Azure. The Terraform template is provided as an example, so feel free to further customize it for your business case.
Note: Make sure you are subscribed to SFTP Gateway in the Azure Marketplace before deploying the Terraform template or else you will run into an error while creating the Virtual Machine.
Running the template
This article contains two files:
sftpgw-single-instance.tf
terraform.tfvars
Create these two files on your workstation, using the file contents at the bottom of this page. Make adjustments to the terraform.tfvars
file. Then, run the following commands:
terraform init
terraform plan
When you are ready to deploy the template, run:
terraform apply
How does it work
This article contains a main Terraform template named:
sftpgw-single-instance.tf
This template provisions the following resources:
Virtual Machine
: This server is based on the SFTP Gateway marketplace VMNetwork Security Group
: Allows TCP22
from anywhere, but locks down admin ports80
,443
,2222
to a single IPPublic IP
: Static IP that retains the IP after a rebootStorage Account
: This contains the Boot Diagnostics of the VM. But it can also be used later on when configuring SFTP Gateway to point to a Storage Account.
There's also another file that contains variables:
terraform.tfvars
Since this file is named terraform.tfvars
, it will be automatically used without having to run:
terraform -var-file terraform.tfvars
You can configure the following variables:
linux_username
: The Username of your Linux admin user.admin_public_key
: Set this to your SSH public key. Alternatively, you can useadmin_password
.admin_password
: Set a password for your admin user. If you do not set this, you must useadmin_public_key
.region
: Specify your current regionadmin_ip
: Get your workstation's public IP fromcheckip.dyndns.org
. Append/32
to specify a single IP rangeresource_group_name
: Specify the name of the resource group that will be created to house your resourcesvm_size
: Optional. Specify the size of your VM. Defaults toStandard_B1ms
.disk_volume_size
: Optional. Specify the size of your disk volume. Defaults to30
GB.
Terraform file contents
sftpgw-single-instance.tf
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
}
}
}
provider "azurerm" {
features {}
}
variable "linux_username" {
type = string
description = "Username of the Linux admin user"
default = "ubuntu"
}
variable "admin_password" {
type = string
description = "Password of the Linux admin user"
default = null
}
variable "admin_public_key" {
type = string
description = "Public SSH key for the Linux admin user"
default = null
}
variable "disk_volume_size" {
type = number
description = "Disk volume size in GB. Must be at least 30."
default = 30
}
variable "resource_group_name" {
type = string
description = "Name of the Resource Group"
}
variable "region" {
type = string
description = "Region in which you deploy resources"
}
variable "admin_ip" {
type = string
description = "Public IP address range for SSH and web access. Use a CIDR range to restrict access. To get your local machine's IP, see http://checkip.dyndns.org/. (Remember to append /32 for a single IP e.g. 12.34.56.78/32) For security reasons, do not use 0.0.0.0/0."
validation {
condition = can(regex("([1-9]\\d{0,2})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/([1-9]\\d{0,1})",var.admin_ip))
error_message = "Must be a valid IP CIDR range in the form of x.x.x.x/x. Do not use 0.0.0.0/0."
}
}
variable "vm_size" {
type = string
description = "VM size. Recommended: Standard_B1ms for testing, Standard_D2_v3 for production."
default = "Standard_B1ms"
}
resource "azurerm_resource_group" "sftpgw-resource-group" {
name = var.resource_group_name
location = var.region
}
resource "azurerm_virtual_network" "sftpgw-vnet" {
name = "sftpgw-vnet"
address_space = ["10.0.0.0/16"]
location = var.region
resource_group_name = azurerm_resource_group.sftpgw-resource-group.name
}
resource "azurerm_subnet" "sftpgw-subnet" {
name = "sftpgw-subnet"
resource_group_name = azurerm_resource_group.sftpgw-resource-group.name
virtual_network_name = azurerm_virtual_network.sftpgw-vnet.name
address_prefixes = ["10.0.2.0/24"]
}
resource "azurerm_public_ip" "sftpgw-ip" {
name = "sftpgw-ip"
location = var.region
resource_group_name = azurerm_resource_group.sftpgw-resource-group.name
allocation_method = "Static"
}
resource "azurerm_network_security_group" "sftpgw-nsg" {
name = "sftpgw-nsg"
location = var.region
resource_group_name = azurerm_resource_group.sftpgw-resource-group.name
}
resource "azurerm_network_security_rule" "sftpgw-ingress-rule-22" {
name = "sftpgw-ingress-rule-22"
priority = 1001
direction = "inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.sftpgw-resource-group.name
network_security_group_name = azurerm_network_security_group.sftpgw-nsg.name
}
resource "azurerm_network_security_rule" "sftpgw-ingress-rule-80" {
name = "sftpgw-ingress-rule-80"
priority = 1002
direction = "inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "80"
source_address_prefix = var.admin_ip
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.sftpgw-resource-group.name
network_security_group_name = azurerm_network_security_group.sftpgw-nsg.name
}
resource "azurerm_network_security_rule" "sftpgw-ingress-rule-443" {
name = "sftpgw-ingress-rule-443"
priority = 1003
direction = "inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "443"
source_address_prefix = var.admin_ip
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.sftpgw-resource-group.name
network_security_group_name = azurerm_network_security_group.sftpgw-nsg.name
}
resource "azurerm_network_security_rule" "sftpgw-ingress-rule-2222" {
name = "sftpgw-ingress-rule-2222"
priority = 1004
direction = "inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "2222"
source_address_prefix = var.admin_ip
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.sftpgw-resource-group.name
network_security_group_name = azurerm_network_security_group.sftpgw-nsg.name
}
resource "azurerm_network_interface" "sftpgw-nic" {
name = "sftpgw-nic"
location = var.region
resource_group_name = azurerm_resource_group.sftpgw-resource-group.name
ip_configuration {
name = "NIC-config"
subnet_id = azurerm_subnet.sftpgw-subnet.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.sftpgw-ip.id
}
}
resource "azurerm_network_interface_security_group_association" "sftpgw-nic-association" {
network_interface_id = azurerm_network_interface.sftpgw-nic.id
network_security_group_id = azurerm_network_security_group.sftpgw-nsg.id
}
resource "random_id" "random_id" {
keepers = {
resource_group = azurerm_resource_group.sftpgw-resource-group.name
}
byte_length = 6
}
resource "azurerm_storage_account" "sftpgw-storage-account" {
name = "sftpgw${random_id.random_id.hex}"
resource_group_name = azurerm_resource_group.sftpgw-resource-group.name
location = var.region
account_replication_type = "LRS"
account_tier = "Standard"
}
resource "azurerm_linux_virtual_machine" "sftpgw-vm" {
name = "sftpgw-vm"
location = var.region
resource_group_name = azurerm_resource_group.sftpgw-resource-group.name
network_interface_ids = [azurerm_network_interface.sftpgw-nic.id]
size = var.vm_size
disable_password_authentication = var.admin_password == null ? true : false
os_disk {
name = "sftpgw-osdisk"
disk_size_gb = var.disk_volume_size
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "thorntechnologiesllc"
offer = "sftpgateway-professional"
sku = "sftpgateway-professional-3-6"
version = "latest"
}
plan {
name = "sftpgateway-professional-3-6"
publisher = "thorntechnologiesllc"
product = "sftpgateway-professional"
}
computer_name = "sftpgw-vm"
admin_username = var.linux_username
admin_password = var.admin_password
admin_ssh_key {
username = var.linux_username
public_key = var.admin_public_key
}
boot_diagnostics {
storage_account_uri = azurerm_storage_account.sftpgw-storage-account.primary_blob_endpoint
}
}
output "public_ip_address" {
value = "${azurerm_public_ip.sftpgw-ip.*.ip_address}"
}
terraform.tfvars
admin_public_key = "ssh-rsa AAAAB3NzanNKEbh"
resource_group_name = "terraform-resource-group"
region = "eastus"
admin_ip = "3.222.237.17/32"