Create an Amazon Machine Image (AMI) from a FreePBX Virtual Machine (VM)
Tags: aws, freepbx, devops, vmware
Published: 2022-06-14 09:14:37

Creating an Amazon Machine Image (AMI) from a FreePBX Virtual Machine (VM) is a quick and easy way to create a ready-to-use virtual machine that, once configured, can be used to run your own PBX. This guide will show you how to create an AMI from a VM running the FreePBX open source software.

## Prerequisites

- Make sure to install and configure **AWS Command Line Interface** in your host computer. You can find the instructions [here](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html).
- Please use an **IAM user with administrator privileges**.
- This has been tested on **VMware Workstation 15 Professional** edition.

## Instructions

1\. Download the latest FreePBX Distro from [here](https://www.freepbx.org/downloads/) and install it on VMware Workstation.

2\. SSH into the instance and install the following packages.

```bash
yum install -y cloud-init cloud-utils-growpart
```

3\. Modify the `/etc/cloud/cloud.cfg` file as follows.

```yaml
system_info:
  default_user:
    name: asterisk
    lock_passwd: true
    gecos: Asterisk User
    groups: [wheel, adm, systemd-journal]
    sudo: ["ALL=(ALL) NOPASSWD:ALL"]
    shell: /bin/bash
  distro: rhel
  paths:
    cloud_dir: /var/lib/cloud
    templates_dir: /etc/cloud/templates
  ssh_svcname: sshd
```

4\. Change the _/etc/ssh/sshd\_config_ file as follows.

```bash
PasswordAuthentication no
PermitRootLogin no
UseDNS no
```

5\. Shutdown the VM and export it as an **OVA** file.

<img width="100%" style="width:100%" src="https://res.cloudinary.com/yasithab/image/upload/v1655203091/blog/freepbx_vba2ai.gif">

6\. Create an S3 bucket and upload the exported OVA file either using AWS CLI or an S3 Client. I used **Cyberduck S3 Client** and it is freely available [here (https://cyberduck.io/download/).

7\. You'll need to create the following policy documents. Make sure to change **S3 bucket** and **OVA file** name based on your configurations. In this example, S3 Bucket name and OVA file name will be **ami-storage** and **FreePBX.ova**, respectively.

&ensp;&ensp;7.A. Create **trust-policy.json**. This will be used to create the **vmimport** IAM role.

```yaml
{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": { "Service": "vmie.amazonaws.com" },
         "Action": "sts:AssumeRole",
         "Condition": {
            "StringEquals":{
               "sts:Externalid": "vmimport"
            }
         }
      }
   ]
}
```

```bash
# Create vmimport IAM role
aws iam create-role --role-name vmimport --assume-role-policy-document file://trust-policy.json
```

&ensp;&ensp;7.B. Create **role-policy.json**. This will be used to assign necessary IAM policies to the vmimport role.

```yaml
{ 
   "Version": "2012-10-17", 
   "Statement": [ 
      { 
         "Effect": "Allow", 
         "Action": [ 
            "s3:ListBucket", 
            "s3:GetBucketLocation" 
         ], 
         "Resource": [ 
            "arn:aws:s3:::ami-storage" 
         ] 
      }, 
      { 
         "Effect": "Allow", 
         "Action": [ 
            "s3:GetObject" 
         ], 
         "Resource": [ 
            "arn:aws:s3:::ami-storage/*" 
         ] 
      }, 
      { 
         "Effect": "Allow", 
         "Action":[ 
            "ec2:ModifySnapshotAttribute", 
            "ec2:CopySnapshot", 
            "ec2:RegisterImage", 
            "ec2:Describe*" 
         ], 
         "Resource": "*" 
      } 
   ] 
}
```

```bash
# Create and assign necessary IAM policies to the vmimport role
aws iam put-role-policy --role-name vmimport --policy-name vmimport --policy-document file://role-policy.json
```

&ensp;&ensp;7.C. Create **containers.json**. This will be used to generate an AMI from the uploaded OVA.

```yaml
[ 
  { 
    "Description": "FreePBX", 
    "Format": "ova", 
    "UserBucket": { 
        "S3Bucket": "ami-storage", 
        "S3Key": "FreePBX.ova" 
    } 
  }
]
```

```bash
# Generate an AMI from the uploaded OVA
aws ec2 import-image --description "FreePBX" --license-type BYOL --disk-containers file://containers.json
```

&ensp;&ensp;7.D. The previous task can range in estimated completion from 15 to 60 minutes. You can check its progress with the following command by replacing the **ImportTaskId** shown in the above command.

```bash
aws ec2 describe-import-image-tasks --import-task-ids import-ami-0b900a870c359a58f
```

&ensp;&ensp;7.E. The task will remain active with `"StatusMessage": "pending"` until it reaches completion. The `"Progress"` attribute will indicate the percentage of work made up to that point. Once the state switches to `"completed"` and the previous command gives additional information about the conversion of the image to AMI format, you will be provided with a new AMI available in the same region where you creted the S3 bucket. It can be used to provision a FreePBX EC2 instance.

**If you liked the post, then you may purchase my first cup of coffee ever, thanks in advance :)**

<a href="https://www.buymeacoffee.com/yasithab" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" alt="Buy Me A Coffee" height="41" width="174"></a>

## References

1\. [Importing a VM as an Image Using VM Import/Export](https://docs.aws.amazon.com/vm-import/latest/userguide/vmimport-image-import.html)
2\. [How to create a Sentilo AWS EC2 instance from an OVA file](http://www.daniloaz.com/en/how-to-create-a-sentilo-aws-ec2-instance-from-an-ova-file/)
3\. [FreePBX Tango Scenes by Crisy Meschieri] (https://dribbble.com/shots/11875910-FreePBX-Tango-Scenes-Titanic/attachments/3501168?mode=media)