Deploy FreePBX with Terraform, Cloudformation or Ansible

Deploy FreePBX on AWS Using Infrastructure as Code: Complete Guide with Terraform, CloudFormation and Ansible

Are you still manually deploying FreePBX instances through the AWS console? In 2025, Infrastructure as Code (IaC) has become the standard for deploying and managing cloud resources. This comprehensive guide will show you how to deploy the our Custom FreePBX 17 image on AWS using three popular IaC tools: Terraform, CloudFormation and Ansible.

FreePBX is an open-source, web-based graphical user interface (GUI) that simplifies the management of Asterisk, the world’s most popular open-source communications engine. Designed to make voice-over-IP (VoIP) phone systems accessible and manageable for businesses of all sizes, FreePBX provides a user-friendly interface for configuring and maintaining PBX features like call routing, voicemail, IVRs, conferencing, and call recording. It supports both traditional phone lines and modern SIP-based communication, offering flexibility and scalability. Backed by a large community and supported commercially by Sangoma, FreePBX is widely adopted for building robust, customizable telephony solutions without the need for deep telecom expertise.

Why Infrastructure as Code for FreePBX?

Traditional manual deployment of FreePBX has several limitations:

  • No repeatability: Each deployment requires clicking through the same GUI steps
  • Prone to human error: Missing a security group rule or forgetting to assign an Elastic IP
  • No version control: Can’t track changes or roll back configurations
  • Difficult to scale: Deploying multiple instances becomes tedious
  • No disaster recovery plan: Recreating infrastructure manually is time-consuming

Infrastructure as Code solves all these problems while adding benefits like:

  • Automated deployments in minutes
  • Version-controlled infrastructure
  • Consistent environments across development, staging, and production
  • Easy multi-region deployments
  • Built-in documentation through code

Prerequisites

Before we begin, ensure you have:

  • An AWS account with appropriate permissions
  • Basic knowledge of AWS services (EC2, VPC, Security Groups)
  • One of the following tools installed:
    • Terraform (v1.5+)
    • AWS CLI (for CloudFormation)
    • Ansible (v2.9+)

Part 1: Deploying FreePBX with Terraform

Terraform is HashiCorp’s open-source IaC tool that uses a declarative language to define infrastructure.

Complete Terraform Configuration

Create a file named freepbx.tf:

# Provider configuration
provider "aws" {
  region = var.aws_region
}

# Data source for latest FreePBX AMI
data "aws_ami" "freepbx" {
  most_recent = true
  owners      = ["679593333241"] # AWS MarketPlace ID

  filter {
    name   = "name"
    values = ["SolveDevOps-FreePBX-17-*"]
  }

  filter {
    name   = "architecture"
    values = ["x86_64"]
  }
}

# Elastic IP
resource "aws_eip" "freepbx" {
  domain = "vpc"
  
  tags = {
    Name = "FreePBX-EIP"
  }
}

# EC2 Instance
resource "aws_instance" "freepbx" {
  ami           = data.aws_ami.freepbx.id
  instance_type = var.instance_type
  key_name      = var.key_name
  
  #subnet_id                   = aws_subnet.freepbx_public.id
  vpc_security_group_ids      = var.security_groups_ids
  #associate_public_ip_address = true

  root_block_device {
    volume_type = "gp3"
    volume_size = 60
    encrypted   = true
  }

  tags = {
    Name = "FreePBX-Server"
  }
}

# EIP Association
resource "aws_eip_association" "freepbx" {
  instance_id   = aws_instance.freepbx.id
  allocation_id = aws_eip.freepbx.id
}

# Data source for availability zones
##data "aws_availability_zones" "available" {
#  state = "available"
#}

# Outputs
output "freepbx_public_ip" {
  value = aws_eip.freepbx.public_ip
}

output "freepbx_admin_url" {
  value = "http://${aws_eip.freepbx.public_ip}/admin"
}

output "ssh_connection_string" {
  value = "ssh -i ${var.key_name}.pem admin@${aws_eip.freepbx.public_ip}"
}

Terraform Variables File

Create a terraform.tfvars file:

aws_region = "us-east-1"
instance_type = "t3.large"
key_name = "your-key-pair-name"
allowed_ips = ["YOUR_IP/32"]

Terraform Variables File

Create a vars.tf file:

# Variables
variable "aws_region" {
  description = "AWS region for FreePBX deployment"
  default     = "us-east-1"
}

variable "instance_type" {
  description = "EC2 instance type for FreePBX"
  default     = "t3.medium"
}

variable "key_name" {
  description = "AWS key pair name for SSH access"
  type        = string
}

variable "security_groups_ids" {
  description = "List of Subnet Group Ids"
  type        = list(string)
  default     = []
}

Deploying with Terraform

# Initialize Terraform
terraform init
# Review the execution plan
terraform plan
# Deploy FreePBX
terraform apply

At the end of your apply, your will end up with output like below

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

Outputs:

freepbx_admin_url = "http://1.2.3.4/admin"
freepbx_public_ip = "1.2.3.4"
ssh_connection_string = "ssh -i key.pem admin@1.2.3.4"

Part 2: Deploying FreePBX with CloudFormation

CloudFormation is AWS’s native IaC service that uses JSON or YAML templates.

Complete CloudFormation Template

Create a file named freepbx-stack.yaml:

AWSTemplateFormatVersion: '2010-09-09'
Description: 'FreePBX 17 deployment using AWS MarketPlace Image'

Parameters:
  KeyName:
    Description: Name of an existing EC2 KeyPair to enable SSH access
    Type: AWS::EC2::KeyPair::KeyName
    ConstraintDescription: Must be the name of an existing EC2 KeyPair
  
  InstanceType:
    Description: EC2 instance type for FreePBX
    Type: String
    Default: t3.large
    AllowedValues:
      - t3.large
      - t3.xlarge
    ConstraintDescription: Must be a valid EC2 instance type

Mappings:
  RegionMap:
    ap-south-1:
      AMI: ami-03e979d5acfc44589
    eu-north-1:
      AMI: ami-0c5089f6bb0d107d3
    eu-west-3:
      AMI: ami-0e8e360c164d9185c
    eu-west-2:
      AMI: ami-0777b154b363e0475
    eu-west-1:
      AMI: ami-08e969b26353741b4
    ap-northeast-3:
      AMI: ami-06c5350dff9c782a4
    ap-northeast-2:
      AMI: ami-00b1e77cd16d3a563
    ap-northeast-1:
      AMI: ami-01aaf195d29079f0b
    ca-central-1:
      AMI: ami-03a902cbcb219a98f
    sa-east-1:
      AMI: ami-04618d8dc8eb711a5
    ap-southeast-1:
      AMI: ami-0190701d77134dfc6
    ap-southeast-2:
      AMI: ami-0dc40428cb05523a3
    eu-central-1:
      MI: ami-083e759382c1b4751
    us-east-1:
      AMI: ami-055f22fdd66a5d37b
    us-east-2:
      AMI: ami-0f99bdd88c2ef5629
    us-west-1:
      AMI: ami-06404e2d1c3fdbfab
    us-west-2:
      AMI: ami-03739ba43e9d8abe9


Resources:
  # Elastic IP
  FreePBXEIP:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
      Tags:
        - Key: Name
          Value: FreePBX-EIP

  # EC2 Instance
  FreePBXInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !FindInMap [RegionMap, !Ref 'AWS::Region', AMI]
      InstanceType: !Ref InstanceType
      KeyName: !Ref KeyName
      SecurityGroupIds:
        - sg-01234567890987654
      BlockDeviceMappings:
        - DeviceName: /dev/xvda
          Ebs:
            VolumeType: gp3
            VolumeSize: 60
            Encrypted: true
      Tags:
        - Key: Name
          Value: FreePBX-Server

  # EIP Association
  EIPAssociation:
    Type: AWS::EC2::EIPAssociation
    Properties:
      InstanceId: !Ref FreePBXInstance
      EIP: !Ref FreePBXEIP

Outputs:
  PublicIP:
    Description: Public IP address of FreePBX instance
    Value: !Ref FreePBXEIP
  
  AdminURL:
    Description: FreePBX Admin URL
    Value: !Sub 'http://${FreePBXEIP}/admin'
  
  SSHConnection:
    Description: SSH connection string
    Value: !Sub 'ssh -i ${KeyName}.pem admin@${FreePBXEIP}'

Deploying with CloudFormation

aws cloudformation create-stack \
  --stack-name freepbx-stack \
  --template-body file://freepbx-stack.yaml \
  --parameters \
    ParameterKey=KeyName,ParameterValue=my_key \
    ParameterKey=InstanceType,ParameterValue=t3.large

Check stack system

# Check stack status
aws cloudformation describe-stacks --stack-name freepbx-stack

Check stack on AWS Cloudformation stack status

Part 3: Deploying FreePBX with Ansible

Ansible uses playbooks to define automation tasks. This approach combines infrastructure provisioning with configuration management.

Project Structure

freepbx-ansible/
├── playbook.yml
├── inventory.ini
├── group_vars/
│   └── all.yml
└── roles/
    └── freepbx/
        ├── tasks/
        │   └── main.yml
        ├── templates/
        │   └── sip_settings.j2
        └── vars/
            └── main.yml

Main Playbook

Create playbook.yml:

---
- name: Deploy FreePBX on AWS
  hosts: localhost
  connection: local
  gather_facts: false
  
  vars:
    aws_region: us-east-1
    instance_type: t3.large
    key_name: "solve-useast1"
    ami_id: "ami-055f22fdd66a5d37b" # FreePBX image

  tasks:
    - name: Allocate Elastic IP
      amazon.aws.ec2_eip:
        region: "{{ aws_region }}"
        in_vpc: yes
      register: eip

    - name: Launch FreePBX Instance
      amazon.aws.ec2_instance:
        key_name: "{{ key_name }}"
        instance_type: "{{ instance_type }}"
        image_id: "{{ ami_id }}"
        wait: yes
        region: "{{ aws_region }}"
        security_group: "sg-12345678909876543"
        volumes:
          - device_name: /dev/xvda
            ebs:
              volume_type: gp3
              volume_size: 60
              encrypted: yes
        tags:
          Name: FreePBX-Server
      register: ec2

    - name: Associate Elastic IP
      amazon.aws.ec2_eip:
        device_id: "{{ ec2.instances[0].instance_id }}"
        ip: "{{ eip.public_ip }}"
        region: "{{ aws_region }}"

    - name: Add host to inventory
      add_host:
        hostname: "{{ eip.public_ip }}"
        groups: freepbx
        ansible_user: admin
        ansible_ssh_private_key_file: "{{ key_name }}.pem"

Running the Ansible Playbook

# Install required collections
ansible-galaxy collection install amazon.aws

# Run the playbook
ansible-playbook playbook.yml

Advanced Configurations

1. Multi-AZ High Availability

For production deployments, consider implementing:

  • Active-passive failover with database replication
  • Shared storage using EFS for recordings
  • Route 53 health checks for automatic failover

2. Auto-Scaling for Call Centers

Implement auto-scaling based on:

  • Concurrent call metrics from CloudWatch
  • CPU utilization thresholds
  • Custom metrics from Asterisk AMI

3. Backup Automation

Add automated backups:

  • Daily EBS snapshots
  • FreePBX configuration backups to S3
  • Call recordings archival to Glacier

4. Monitoring and Alerting

Integrate monitoring:

  • CloudWatch metrics for system health
  • SNS notifications for critical events
  • Custom dashboards for call statistics

Security Best Practices

  1. Restrict Security Groups: Never use 0.0.0.0/0 for SSH access in production
  2. Enable Fail2ban: Configure FreePBX’s built-in intrusion detection
  3. Use SSL/TLS: Enable HTTPS and secure SIP (TLS/SRTP)
  4. Regular Updates: Automate security patches with Systems Manager
  5. IAM Roles: Use instance profiles instead of access keys
  6. Encryption: Enable EBS encryption and S3 bucket encryption

Cost Optimization

  1. Right-sizing: Start with t3.large and monitor usage
  2. Reserved Instances: Save up to 72% for production workloads
  3. Spot Instances: Use for development/testing environments
  4. Storage Optimization: Use lifecycle policies for call recordings

Troubleshooting Common Issues

Issue 1: Cannot Access Web Interface

sudo systemctl status freepbx
sudo systemctl status apache2


# Check firewall rules or security group firewalls
sudo iptables -L -n

Issue 2: No Audio on Calls

See this article.

Issue 3: High CPU Usage

# Monitor Asterisk processes
htop
asterisk -rx 'core show channels'

Conclusion

Infrastructure as Code transforms FreePBX deployment from a manual, error-prone process into a repeatable, version-controlled operation. Whether you choose Terraform for its cloud-agnostic approach, CloudFormation for native AWS integration, or Ansible for its configuration management capabilities, you now have the tools to deploy FreePBX professionally.

The Solve DevOps FreePBX image combined with these IaC approaches provides:

  • 5-minute deployments instead of hours
  • Consistent environments across all stages
  • Disaster recovery capabilities
  • Cost optimization through automation
  • Security best practices built-in

Start with the tool that best fits your existing workflow and gradually expand to implement advanced features like high availability and auto-scaling.

Next Steps

  1. Choose your preferred IaC tool and deploy a test environment
  2. Customize the templates for your specific requirements
  3. Implement monitoring and backup strategies
  4. Document your deployment process
  5. Share your improvements with the community

Did You Just Read Gibberish?

Our Tech Support Staff understand gibberish and would love to work with you. Your business needs you, lets take care of the backend stuff.

Gibberish Helpline