{"id":16161938,"url":"https://github.com/rajannpatel/ubuntupbx","last_synced_at":"2025-10-19T01:56:54.123Z","repository":{"id":65078475,"uuid":"579107234","full_name":"rajannpatel/ubuntupbx","owner":"rajannpatel","description":"Install FreePBX 17 with every dependency including Asterisk 20.6 as a deb package, on Ubuntu 24.04 LTS","archived":false,"fork":false,"pushed_at":"2025-03-07T06:50:24.000Z","size":3575,"stargazers_count":14,"open_issues_count":0,"forks_count":3,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-17T00:03:51.559Z","etag":null,"topics":["asterisk","freepbx","ubuntu-pro","ubuntu-server","ubuntu2404"],"latest_commit_sha":null,"homepage":"https://ubuntu.com/blog/install-freepbx-and-asterisk-on-ubuntu-24-04-lts-for-security-patches-until-2036","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rajannpatel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-12-16T17:17:48.000Z","updated_at":"2025-03-15T19:35:43.000Z","dependencies_parsed_at":"2024-10-27T19:16:33.915Z","dependency_job_id":"8162458c-67c2-4af8-8641-0826d8f9264d","html_url":"https://github.com/rajannpatel/ubuntupbx","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rajannpatel%2Fubuntupbx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rajannpatel%2Fubuntupbx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rajannpatel%2Fubuntupbx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rajannpatel%2Fubuntupbx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rajannpatel","download_url":"https://codeload.github.com/rajannpatel/ubuntupbx/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244318393,"owners_count":20433893,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asterisk","freepbx","ubuntu-pro","ubuntu-server","ubuntu2404"],"created_at":"2024-10-10T02:28:23.534Z","updated_at":"2025-10-19T01:56:49.048Z","avatar_url":"https://github.com/rajannpatel.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Install FreePBX 17 on Ubuntu 24.04 LTS\n\n- with open-source dependencies (including Asterisk) installed from Ubuntu's official repositories\n- using this [cloud-init.yaml](./cloud-init.yaml) installation template\n- on machines where Ubuntu is already installed, or on public cloud virtual machines\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u0026ensp;TABLE OF CONTENTS\u003cbr\u003e\u003csup\u003e\u0026emsp;\u0026ensp;\u0026thinsp;\u0026thinsp;CLICK TO EXPAND\u003c/sup\u003e\u003cbr\u003e\u003c/summary\u003e\n\n\u003ca name=\"server-1-icon\"\u003e\u003cimg align=\"right\" alt=\"machine\" width=\"50\" src=\"./images/icons8-server-100.png\" /\u003e\u003c/a\u003e\n\n- **[OPTION 1](#install-freepbx-and-asterisk-on-an-existing-ubuntu-machine-icon)**\u003cbr\u003e\u003csub\u003eINSTALL FREEPBX AND ASTERISK ON AN UBUNTU MACHINE\u003c/sub\u003e\u003cbr\u003e\n\n  \u003e \u003csub\u003e[STEP 1](#step-1-icon)\u003cbr\u003eDOWNLOAD AND EDIT JINJA VARIABLES IN THE CLOUD-INIT FILE FROM THIS REPOSITORY\u003c/sub\u003e\u003cbr\u003e\n\n  \u003e \u003csub\u003e[STEP 2](#step-2-icon)\u003cbr\u003eUSE J2CLI TO INTERPRET JINJA VARIABLES AND RENDER YAML OUTPUT\u003c/sub\u003e\u003cbr\u003e\n\n  \u003e \u003csub\u003e[STEP 3](#step-3-icon)\u003cbr\u003eINSTALL FREEPBX USING THE CLOUD-INIT.YAML FILE\u003c/sub\u003e\u003cbr\u003e\n\n\u003ca name=\"cloud-1-icon\"\u003e\u003cimg align=\"right\" alt=\"cloud\" width=\"50\" src=\"./images/icons8-cloud-100.png\" /\u003e\u003c/a\u003e\n\n- **[OPTION 2](#install-freepbx-and-asterisk-on-ubuntu-in-google-cloud-icon)**\u003cbr\u003e\u003csub\u003eINSTALL FREEPBX AND ASTERISK ON UBUNTU IN GOOGLE CLOUD\u003c/sub\u003e\u003cbr\u003e\n\n  \u003e \u003csub\u003e[STEP 1](#step-1-1-icon)\u003cbr\u003eMAKE A CLOUD-DEPLOYMENT WORKSPACE FOR GOOGLE CLOUD COMMAND LINE INTERFACE (GCLOUD CLI)\u003c/sub\u003e\u003cbr\u003e\n\n  \u003e \u003csub\u003e[STEP 2](#step-2-1-icon)\u003cbr\u003eINSTALL AND CONFIGURE GCLOUD CLI IN THE CLOUD-DEPLOYMENT WORKSPACE\u003c/sub\u003e\u003cbr\u003e\n\n  \u003e \u003csub\u003e[STEP 3](#step-3-1-icon)\u003cbr\u003eUSE GCLOUD CLI TO PROVISION A FREE UBUNTU VM WITH CLOUD-INIT, AND CONFIGURE THE FIREWALL\u003c/sub\u003e\u003cbr\u003e\n\n  \u003e \u003csub\u003e[HOW DO I UNDO?](#how-do-i-undo-icon)\u003cbr\u003eHOW TO DELETE THINGS IN GOOGLE CLOUD\u003c/sub\u003e\u003cbr\u003e\n\n\u003c/details\u003e\n\n---\n\n\u003ca name=\"install-freepbx-and-asterisk-on-an-existing-ubuntu-machine-icon\"\u003e\u003c/a\u003e\n\n\u003ca name=\"install-freepbx-and-asterisk-on-an-existing-ubuntu-machine-icon-png\"\u003e\u003cimg alt=\"VoIP\" width=\"50\" src=\"./images/icons8-office-phone-100.png\" /\u003e\u003cimg alt=\"FoIP\" width=\"50\" src=\"./images/icons8-fax-100.png\" /\u003e\u003cimg alt=\"on\" width=\"50\" src=\"./images/icons8-right-50.png\" /\u003e\u003cimg alt=\"Ubuntu Server\" width=\"50\" src=\"./images/icons8-server-100.png\" /\u003e\u003c/a\u003e\n\n## Install FreePBX and Asterisk on an existing Ubuntu machine\n\n\u003e [!IMPORTANT]\n\u003e \u003ca name=\"info-bubble-1\"\u003e\u003cimg align=\"right\" alt=\"Info Bubble\" width=\"50\" src=\"./images/icons8-info-100.png\" /\u003e\u003c/a\u003e\n\u003e #### Securely run FreePBX on Ubuntu 24.04 LTS until 2036\n\u003e Asterisk, NodeJS, and other FreePBX dependencies are security maintained by Canonical on Ubuntu.\n\u003e - Ubuntu Pro includes security patching for all open source software on Ubuntu for 10 years, until 2034\n\u003e - Ubuntu Pro Legacy adds 2 more years of security coverage until 2036\n\u003e - Ubuntu Pro is FREE for personal use or commercial evaluation on 5 machines\n\u003e \n\u003e \u003csub\u003eNEXT\u003c/sub\u003e\u003cp\u003eGet your free or paid [Ubuntu Pro token](https://ubuntu.com/pro/dashboard)\u003c/p\u003e\n\n| \u003ca name=\"steps-1\"\u003e\u003cimg alt=\"Steps\" width=\"50\" src=\"./images/icons8-steps-100.png\" /\u003e\u003c/a\u003e | 3\u0026nbsp;Steps |\n|:---|:---|\n| **[STEP\u0026nbsp;1](#step-1-icon)** | Download and edit Jinja variables in the cloud-init file from this repository |\n| **[STEP\u0026nbsp;2](#step-2-icon)** | Use **j2cli** to interpret Jinja variables and render YAML output |\n| **[STEP\u0026nbsp;3](#step-3-icon)** | Install FreePBX using the cloud-init.yaml file |\n\n\u003cbr\u003e\u003csub\u003ePROGRESS \u0026emsp;\u0026emsp; :heavy_plus_sign: \u0026emsp; \u003ca href=\"#step-1-icon\"\u003eSTEP 1\u003c/a\u003e\u0026emsp;\u0026emsp; :heavy_multiplication_x: \u0026emsp; STEP 2\u0026emsp;\u0026emsp; :heavy_multiplication_x: \u0026emsp;STEP 3\u003c/sub\u003e\u003cbr\u003e\u003cbr\u003e\n\n---\n\n\u003ca name=\"step-1-icon\"\u003e\u003c/a\u003e\n\n\u003ca name=\"step-1-icon-png\"\u003e\u003cimg alt=\"Download and Edit\" width=\"50\" src=\"./images/icons8-edit-file-100.png\" /\u003e\u003c/a\u003e\n\n### STEP 1\nDownload the cloud-init file from this repository\n\n```bash\ncurl -L -o cloud-init-jinja.yaml https://raw.githubusercontent.com/rajannpatel/ubuntupbx/refs/heads/main/cloud-init.yaml\nnano cloud-init-jinja.yaml\n```\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u0026ensp;Edit cloud-init-jinja.yaml and configure Jinja variables between lines 4 and 74.\u003cbr\u003e\u003csup\u003e\u0026emsp;\u0026ensp;\u0026thinsp;\u0026thinsp;CLICK TO EXPAND\u003c/sup\u003e\u003cbr\u003e\u003c/summary\u003e\n\n```markdown\n# SET OUR VARIABLES\n# =================\n\n# Ubuntu Pro token from: https://ubuntu.com/pro/dashboard (not needed for Ubuntu Pro instances on Azure, AWS, or Google Cloud)\n{% set TOKEN = '' %}\n\n# SMTP credentials (sendgrid and gmail example configurations)\n# sendgrid: https://console.cloud.google.com/marketplace/product/sendgrid-app/sendgrid-email\n# {% set SMTP_HOST = 'smtp.sendgrid.net' %}\n# {% set SMTP_PORT = '587' %}\n# {% set SMTP_USERNAME = 'apikey' %}\n# substitute `YOUR-API-KEY-HERE` below, with your API KEY, https://app.sendgrid.com/settings/api_keys\n# {% set SMTP_PASSWORD = 'YOUR-API-KEY-HERE' %}\n\n# gmail:\n# {% set SMTP_HOST = 'smtp.gmail.com' %}\n# {% set SMTP_PORT = '587' %}\n# replace `YOUREMAIL@GMAIL.COM` with your email, get `YOUR-APP-PASSWORD` from: https://myaccount.google.com/apppasswords\n# {% set SMTP_USERNAME = 'YOUREMAIL@GMAIL.COM' %}\n# {% set SMTP_PASSWORD = 'YOUR-APP-PASSWORD' %}\n\n{% set SMTP_HOST = '' %}\n{% set SMTP_PORT = '' %}\n{% set SMTP_USERNAME = '' %}\n{% set SMTP_PASSWORD = '' %}\n\n# NOTIFICATION_EMAIL address for daily crontab notifications\n{% set NOTIFICATION_EMAIL = 'youremail@example.com' %}\n\n# HOSTNAME and FQDN are used by Postfix, and necessary for Sendgrid\n# HOSTNAME: subdomain of FQDN (e.g. `server` for `server.example.com`)\n# FQDN (e.g. `example.com` or `server.example.com`)\n{% set HOSTNAME = 'voip' %}\n{% set FQDN = 'voip.example.com' %}\n\n# OPTIONAL: PRECONFIGURE FREEPBX CORE MODULE (OUTBOUND ROUTES AND TRUNKS)\n# ubuntupbx.core.backup.tar.gz was generated with the Backup \u0026 Restore FreePBX Module\n# this can be replaced with the https:// or gs:// address of your backup file, if you're copying configurations from another FreePBX installation\n{% set RESTORE_BACKUP = 'https://github.com/rajannpatel/ubuntupbx/raw/refs/heads/main/ubuntupbx.core.backup.tar.gz' %}\n# ubuntupbx.core.backup.tar.gz Outbound Routes include: N11, North America FoIP, North America VoIP, International VoIP\n# ubuntupbx.core.backup.tar.gz SIP Trunks include:\n{% set enable_T38Fax = true %}      # https://t38fax.com\n{% set enable_Flowroute = false %}  # https://flowroute.com\n{% set enable_Telnyx = false %}     # https://telnyx.com\n{% set enable_BulkVS = true %}      # https://bulkvs.com\n\n# List of public IPv4 addresses that should never be blocked by fail2ban\n# - Use standard dotted decimal notation for each IP address or CIDR (slash) notation IP ranges\n# - Separate multiple entries with a space, and do not use commas:\n# {% set USER_IPS = '192.178.0.0/15 142.251.47.238' %}\n{% set USER_IPS = '' %}\n\n# TIMEZONE: default value is fine\n# As represented in /usr/share/zoneinfo. An empty string ('') will result in UTC time being used.\n{% set TIMEZONE = 'America/New_York' %}\n\n# TIME TO INSTALL AND REBOOT UBUNTU FOR SECURITY PATCHES FROM CANONICAL IN XX:XX FORMAT\n{% set SECURITY_INSTALL_TIME = \"04:10\" %}\n{% set SECURITY_REBOOT_TIME = \"04:30\" %}\n\n# NUMBER OF DAYS TO RETAIN CDR AND CEL RECORDS IN FREEPBX\n{% set CDR_RETENTION_DAYS = \"60\" %}\n{% set CEL_RETENTION_DAYS = \"60\" %}\n\n# PHP 8.2 IS OFFICIALLY TESTED WITH FREEPBX BY SANGOMA, PHP 8.2 IS SECURITY MAINTAINED UNTIL 31 Dec 2026 FROM THE PHP GROUP (UPSTREAM)\n# PHP 8.3 IS COMPATIBLE WITH FREEPBX AND ALL AVAILABLE MODULES, PHP 8.3 GETS SECURITY PATCHING UNTIL 2036 THROUGH CANONICAL, THE PUBLISHERS OF UBUNTU\n# PHP_VERSION = 8.2|8.3\n{% set PHP_VERSION = \"8.2\" %}\n\n# =========================\n# END OF SETTING VARIABLES\n```\n\n\u003c/details\u003e\n\n\u003csub\u003ePROGRESS \u0026emsp;\u0026emsp; :heavy_check_mark: \u0026emsp;STEP 1\u0026emsp;\u0026emsp; :heavy_plus_sign: \u0026emsp; \u003ca href=\"#step-2-icon\"\u003eSTEP 2\u003c/a\u003e\u0026emsp;\u0026emsp; :heavy_multiplication_x: \u0026emsp;STEP 3\u003c/sub\u003e\u003cbr\u003e\u003cbr\u003e\n\n---\n\n\u003ca name=\"step-2-icon\"\u003e\u003c/a\u003e\n\n\u003ca name=\"step-2-icon-png\"\u003e\u003cimg alt=\"Export to YAML\" width=\"50\" src=\"./images/icons8-export-100.png\" /\u003e\u003c/a\u003e\n\n### STEP 2\nUse **j2cli** to interpret Jinja variables and render YAML output\n\n```bash\nsudo apt update\nsudo apt install j2cli\nj2 cloud-init-jinja.yaml \u003e cloud-init.yaml\n```\n\n\u003csub\u003ePROGRESS \u0026emsp;\u0026emsp; :heavy_check_mark: \u0026emsp;STEP 1\u0026emsp;\u0026emsp; :heavy_check_mark: \u0026emsp; STEP 2\u0026emsp;\u0026emsp; :heavy_plus_sign: \u0026emsp; \u003ca href=\"#step-3-icon\"\u003eSTEP 3\u003c/a\u003e\u003c/sub\u003e\u003cbr\u003e\u003cbr\u003e\n\n---\n\n\u003ca name=\"step-3-icon\"\u003e\u003c/a\u003e\n\n\u003ca name=\"step-3-icon-png\"\u003e\u003cimg alt=\"Apply cloud-init\" width=\"50\" src=\"./images/icons8-cloud-file-100.png\" /\u003e\u003c/a\u003e\n\n### STEP 3\nInstall FreePBX using the cloud-init.yaml file, and configure firewall automations\n\n1. Install FreePBX\n\n    ```bash\n    # comment shows estimated time to completion, for each command\n    sudo cloud-init single --frequency always --name ubuntu_pro --file cloud-init.yaml # 7m32s \n    sudo cloud-init single --frequency always --name timezone --file cloud-init.yaml # 1s \n    sudo cloud-init single --frequency always --name set_hostname --file cloud-init.yaml # 1s\n    sudo cloud-init single --frequency always --name update_hostname --file cloud-init.yaml # 1s\n    sudo cloud-init single --frequency always --name users_groups --file cloud-init.yaml # 1s\n    sudo cloud-init single --frequency always --name write_files --file cloud-init.yaml # 1s\n    sudo cloud-init single --frequency always --name apt_configure --file cloud-init.yaml # 14s\n    sudo cloud-init single --frequency always --name package-update-upgrade-install --file cloud-init.yaml # 17m\n    sudo cloud-init single --frequency always --name runcmd --file cloud-init.yaml # 1s\n    sudo cloud-init single --frequency always --name scripts_user # 20m15s\n    ```\n\n2. Print the FreePBX web portal address and configure Asterisk via a web browser:\n\n    ```bash\n    echo \"http://$(ip route get 1 | awk '{print $7; exit}')\"\n    ```\n\n    Connect to the Asterisk CLI, and observe output as you configure and use FreePBX:\n\n    ```bash\n    sudo su -s /bin/bash asterisk -c 'cd ~/ \u0026\u0026 asterisk -rvvvvv'\n    ```\n\n    -  The `exit` command will safely exit the Asterisk CLI.\n\n3. fail2ban blocks IPs after 3 invalid authentication attempts on SSH, Asterisk, and FreePBX. fail2ban also emails alerts when the dynamic firewall turns on, turns off, and when an IP is banned due to invalid authentication attempts on Asterisk and FreePBX.\n\n    \u003cdetails\u003e\n\n    \u003csummary\u003e\u0026ensp;Manage the fail2ban dynamic firewall\u003cbr\u003e\u003csup\u003e\u0026emsp;\u0026ensp;\u0026thinsp;\u0026thinsp;CLICK TO EXPAND\u003c/sup\u003e\u003cbr\u003e\u003c/summary\u003e\n\n    ##### Append more user and provider IPs to `ignoreip =` in jail.local\n    \n    - any additional public IPv4 addresses which should never be banned are listed in the `IP` variable\n    - Use standard dotted decimal notation for each IP address or CIDR (slash) notation IP ranges\n    - Separate multiple entries with a space, and do not use commas.\u003cbr\u003e\u003csub\u003e\u0026ensp;EXAMPLE\u003cbr\u003e\u0026ensp;`IP='192.178.0.0/15 142.251.47.238'`\u003c/sub\u003e\u003cbr\u003e\u003cbr\u003e\n\n    ```bash\n    IP=''\n    sudo sed -i \"s/ignoreip = \\(.*\\)/ignoreip = \\1 $IP/\" /etc/fail2ban/jail.local\n    sudo fail2ban-client reload\n    ```\n\n    ##### Confirm the ignoreip list is accurate\n\n    Invalid IPs in the ignoreip setting in /etc/fail2ban/jail.local will result in 0.0.0.0 (whole world) being ignored.\n\n    ```bash\n    sudo fail2ban-client get asterisk ignoreip\n    ```\n\n    ##### List all banned IPs in fail2ban jails\n\n    ```bash\n    sudo sh -c \"fail2ban-client status | sed -n 's/,//g;s/.*Jail list://p' | xargs -n1 fail2ban-client status\"\n    ```\n\n    ##### Monitor IPs fail2ban is evaluating, in realtime\n\n    ```bash\n    tail -f /var/log/fail2ban.log\n    ```\n\n    ##### Unban IP from fail2ban jails\n\n    - Replace `127.0.0.1` with the IP address that needs to be unbanned\n    - The 3 jails are named **sshd**, **asterisk**, and **freepbx**\n    - A `1` output indicates successful removal, a `0` output indicates the IP was not banned\u003cbr\u003e\u003cbr\u003e\n\n    ```bash\n    $IP='127.0.0.1'\n    sudo fail2ban-client unban sshd $IP\n    sudo fail2ban-client unban asterisk $IP\n    sudo fail2ban-client unban freepbx $IP\n    ```\n\n    \u003c/details\u003e\n\n\n\u003csub\u003ePROGRESS \u0026emsp;\u0026emsp; :heavy_check_mark: \u0026emsp;STEP 1\u0026emsp;\u0026emsp; :heavy_check_mark: \u0026emsp; STEP 2\u0026emsp;\u0026emsp; :heavy_check_mark: \u0026emsp;STEP 3\u0026emsp;\u0026emsp; :tada: \u0026emsp;COMPLETED\u003c/sub\u003e\u003cbr\u003e\u003cbr\u003e\n\n---\n\n\u003ca name=\"install-freepbx-and-asterisk-on-ubuntu-in-google-cloud-icon\"\u003e\u003c/a\u003e\n\n\u003ca name=\"install-freepbx-and-asterisk-on-ubuntu-in-google-cloud-icon-png\"\u003e\u003cimg alt=\"VoIP\" width=\"50\" src=\"./images/icons8-office-phone-100.png\" /\u003e\u003cimg alt=\"FoIP\" width=\"50\" src=\"./images/icons8-fax-100.png\" /\u003e\u003cimg alt=\"via\" width=\"50\" src=\"./images/icons8-right-50.png\" /\u003e\u003cimg alt=\"Cloud\" width=\"50\" src=\"./images/icons8-cloud-100.png\" /\u003e\n\n## Install FreePBX and Asterisk on Ubuntu in Google Cloud\n\n\u003e [!TIP]\n\u003e \u003ca name=\"info-lightbulb-icon-1\"\u003e\u003cimg align=\"right\" alt=\"Info Lightbulb\" width=\"50\" src=\"./images/icons8-tip-100.png\" /\u003e\u003c/a\u003e\n\u003e #### Run FreePBX on a FREE Ubuntu virtual machine on Google Cloud\n\u003e - $0 cost to launch\n\u003e - $0 recurring expense to run\n\u003e \n\u003e \u003csub\u003eNEXT\u003c/sub\u003e\u003cp\u003eInstall FreePBX and Asterisk on Ubuntu in Google Cloud within the [always free](https://cloud.google.com/free/docs/free-cloud-features#compute) limits\u003c/p\u003e\n\n| \u003ca name=\"steps-icon-2\"\u003e\u003cimg alt=\"Steps\" width=\"50\" src=\"./images/icons8-steps-100.png\" /\u003e\u003c/a\u003e | 3\u0026nbsp;Steps |\n|:---|:---|\n| **[STEP\u0026nbsp;1](#step-1-1-icon)** | Make a cloud-deployment workspace for Google Cloud Command Line Interface (gcloud CLI) |\n| **[STEP\u0026nbsp;2](#step-2-1-icon)** | Install and configure gcloud CLI in the cloud-deployment workspace |\n| **[STEP\u0026nbsp;3](#step-3-1-icon)** | Use gcloud CLI to provision a free Ubuntu VM with cloud-init, and configure the firewall |\n\n\u003cbr\u003e\u003csub\u003ePROGRESS \u0026emsp;\u0026emsp; :heavy_plus_sign: \u0026emsp; \u003ca href=\"#step-1-1-icon\"\u003eSTEP 1\u003c/a\u003e\u0026emsp;\u0026emsp; :heavy_multiplication_x: \u0026emsp; STEP 2\u0026emsp;\u0026emsp; :heavy_multiplication_x: \u0026emsp;STEP 3\u003c/sub\u003e\u003cbr\u003e\u003cbr\u003e\n\n---\n\n\u003ca name=\"step-1-1-icon\"\u003e\u003c/a\u003e\n\n\u003ca name=\"step-1-1-icon-png\"\u003e\u003cimg alt=\"Container or VM\" width=\"50\" src=\"./images/icons8-thin-client-100.png\" /\u003e\u003c/a\u003e\n\n### STEP 1\n#### Make a cloud-deployment workspace for gcloud CLI\n\n-  [Multipass](https://multipass.run/) creates Ubuntu VMs on Windows and macOS\n-  [LXD](https://canonical.com/lxd/) creates Ubuntu containers on Linux\n-  Both Multipass and LXD provide access to an Ubuntu terminal, which is required for Step 2\n\n\u003ca name=\"pc-icons-1\"\u003e\u003cimg alt=\"Windows\" width=\"50\" src=\"./images/icons8-windows-client-100.png\" /\u003e\u003cimg alt=\"macOS\" width=\"50\" src=\"./images/icons8-mac-client-100.png\" /\u003e\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u0026ensp;Set up a cloud-deployment workspace on Windows and macOS\u003cbr\u003e\u003csup\u003e\u0026emsp;\u0026ensp;\u0026thinsp;\u0026thinsp;CLICK TO EXPAND\u003c/sup\u003e\u003cbr\u003e\u003c/summary\u003e\n\n\u003cbr\u003eOn Windows and macOS, Multipass provides Linux VMs on demand.\n\n1. [Install Multipass](https://multipass.run/install)\n\n2. Launch a VM named \"cloud-deployment-workspace\":\n\n    ```bash\n    multipass launch --name cloud-deployment-workspace\n    ```\n\n3. Enter the Multipass VM as the \"ubuntu\" user:\n\n    ```bash\n    multipass shell cloud-deployment-workspace\n    ```\n\n\u003c/details\u003e\n\n\u003cbr\u003e\u003ca name=\"pc-icon-2\"\u003e\u003cimg alt=\"Linux\" width=\"50\" src=\"./images/icons8-linux-server-100.png\" /\u003e\u003c/a\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e\u0026ensp;Set up a cloud-deployment workspace on Linux\u003cbr\u003e\u003csup\u003e\u0026emsp;\u0026ensp;\u0026thinsp;\u0026thinsp;CLICK TO EXPAND\u003c/sup\u003e\u003cbr\u003e\u003c/summary\u003e\n\n\u003cbr\u003eOn Linux, LXD is a system container and VM manager. LXD is built on top of LXC (Linux Containers) but provides a more user-friendly and feature-rich experience. Think of LXD as the tool you use to manage LXC containers, making it easier to create, configure, and run them.\n\n1.  [Install snapd](https://snapcraft.io/docs/installing-snapd) if your Linux doesn't already have it.\n\n\n2.  [Install LXD](https://canonical.com/lxd/install)\n\n    ```bash\n    snap list lxd \u0026\u003e /dev/null \u0026\u0026 sudo snap refresh lxd --channel latest/stable || sudo snap install lxd --channel latest/stable\n    ```\n\n3.  Initialize LXD with default configurations\n\n    ```bash\n    lxd init --auto\n    ```\n\n4.  Launch a LXD container named \"cloud-deployment-workspace\" and map your user account on the host machine to the default \"ubuntu\" user account in the container:\n\n    ```bash\n    lxc launch ubuntu:noble cloud-deployment-workspace -c raw.idmap=\"both 1000 1000\"\n    ```\n\n5.  Mount your home directory into the container as a disk named \"host-home\", to conveniently access your files from within the container:\n\n    ```bash\n    lxc config device add cloud-deployment-workspace host-home disk source=~/ path=/home/ubuntu\n    ```\n\n6.  Enter the LXD container as the \"ubuntu\" user:\n\n    ```bash\n    lxc exec cloud-deployment-workspace -- su -l ubuntu\n    ```\n\n\u003c/details\u003e\n\n\u003cbr\u003e\u003csub\u003ePROGRESS \u0026emsp;\u0026emsp; :heavy_check_mark: \u0026emsp;STEP 1\u0026emsp;\u0026emsp; :heavy_plus_sign: \u0026emsp; \u003ca href=\"#step-2-1-icon\"\u003eSTEP 2\u003c/a\u003e\u0026emsp;\u0026emsp; :heavy_multiplication_x: \u0026emsp;STEP 3\u003c/sub\u003e\u003cbr\u003e\u003cbr\u003e\n\n---\n\n\u003ca name=\"step-2-1-icon\"\u003e\u003c/a\u003e\n\n\u003ca name=\"step-2-1-icon-png\"\u003e\u003cimg alt=\"Terminal\" width=\"50\" src=\"./images/icons8-terminal-100.png\" /\u003e\u003c/a\u003e\n\n### STEP 2\n#### Install and configure gcloud CLI in the cloud-deployment workspace\n\nThese steps are performed in your cloud-deployment workspace.\n\n1.  Install gcloud CLI\n\n    ```bash\n    sudo snap install google-cloud-cli --classic\n    ```\n\n2.  Authenticate with the gcloud CLI\n\n    ```bash\n    gcloud init\n    ```\n\n    1. Enter **Y** when prompted with *Would you like to log in (Y/n)?*\n    2. Visit the authentication link which starts with `https://accounts.google.com/`\n    3. Sign in with a Google account\n    4. Click **Allow** to grant access to the Google Cloud SDK\n    5. Click **Copy** to copy the verification code\n    6. Paste the verification code into the terminal window where the `gcloud init` process is running\n\n    Successful authentication within `gcloud init` produces the following output:\n\n    \u003e ```text\n    \u003e You are now logged in as [your@email.com].\n    \u003e Your current project is [None].  You can change this setting by running:\n    \u003e $ gcloud config set project PROJECT_ID\n    \u003e ```\n\n\u003cbr\u003e\u003csub\u003ePROGRESS \u0026emsp;\u0026emsp; :heavy_check_mark: \u0026emsp;STEP 1\u0026emsp;\u0026emsp; :heavy_check_mark: \u0026emsp; STEP 2\u0026emsp;\u0026emsp; :heavy_plus_sign: \u0026emsp; \u003ca href=\"#step-3-1-icon\"\u003eSTEP 3\u003c/a\u003e\u003c/sub\u003e\u003cbr\u003e\u003cbr\u003e\n\n---\n\n\u003ca name=\"step-3-1-icon\"\u003e\u003c/a\u003e\n\n\u003ca name=\"step-3-1-icon-png\"\u003e\u003cimg alt=\"Cloud\" width=\"50\" src=\"./images/icons8-upload-to-cloud-100.png\" /\u003e\u003c/a\u003e\n\n### STEP 3\n#### Use gcloud CLI to provision a free Ubuntu VM with cloud-init, and configure the firewall\n\nThese steps are performed in your cloud-deployment workspace.\n\n1. List the projects in the Google Cloud account:\n    \n    ```bash\n    gcloud projects list\n    ```\n    \n    Output will appear in this format:\n    \n    \u003e ```text\n    \u003e PROJECT_ID        NAME              PROJECT_NUMBER\n    \u003e project-id        project-name      12345678910\n    \u003e ```\n    \n2. Assign the `PROJECT_ID` environment variable with the Project ID from the `gcloud projects list` output:\n    \n    ```bash\n    PROJECT_ID=project-id\n    ```\n    \n3. Associate gcloud CLI to this `PROJECT_ID`:\n    \n    ```bash\n    gcloud config set project $PROJECT_ID\n    ```\n    \n    This Project ID will contain the \"ubuntupbx\" VM.\n    \n4.  Enable the Google Cloud Compute Engine service\n\n    ```bash\n    gcloud services enable compute.googleapis.com\n    ```\n\n5. List the available cloud zones and cloud regions where VMs can be deployed:\n\n    ```bash\n    gcloud compute zones list\n    ```\n\n    Output will appear in this format:\n\n    \u003e ```text\n    \u003e NAME                       REGION                   STATUS  NEXT_MAINTENANCE  TURNDOWN_DATE\n    \u003e us-east1-b                 us-east1                 UP\n    \u003e ```\n\n\u003ca name=\"step-3-6\"\u003e\u003c/a\u003e\n\n6. Google Cloud's free tier is only in the `us-west1`, `us-central1`, and `us-east1` regions\n\n    - Set the `REGION` environment variable with one of the 3 free tier regions\n    - Set any `ZONE` in that region from the `gcloud compute zones list` output\n\n    The following zone and region can be used:\n\n    ```bash\n    REGION=us-east1\n    ZONE=us-east1-b\n    ```\n\n7. Reserve a static IP address and label it \"pbx-external-ip\":\n    \n    ```bash\n    gcloud compute addresses create pbx-external-ip --region=$REGION\n    ```\n    \n8. Download the cloud-init YAML.\n\n    ```bash\n    curl -L -O https://raw.githubusercontent.com/rajannpatel/ubuntupbx/refs/heads/main/cloud-init.yaml\n    nano cloud-init.yaml\n    ```\n\n    \u003cdetails\u003e\n\n    \u003csummary\u003e\u0026ensp;Edit cloud-init.yaml and configure Jinja variables between lines 4 and 74.\u003cbr\u003e\u003csup\u003e\u0026emsp;\u0026ensp;\u0026thinsp;\u0026thinsp;CLICK TO EXPAND\u003c/sup\u003e\u003cbr\u003e\u003c/summary\u003e\n\n    \u003cbr\u003eSet `TOKEN` with a free or paid [Ubuntu Pro token](https://ubuntu.com/pro/dashboard) to enable all security patches, including the [Livepatch](https://ubuntu.com/security/livepatch) security patching automation tool to protect the Linux kernel.\n\n    ```markdown\n    # SET OUR VARIABLES\n    # =================\n\n    # Ubuntu Pro token from: https://ubuntu.com/pro/dashboard (not needed for Ubuntu Pro instances on Azure, AWS, or Google Cloud)\n    {% set TOKEN = '' %}\n\n    # SMTP credentials (sendgrid and gmail example configurations)\n    # sendgrid: https://console.cloud.google.com/marketplace/product/sendgrid-app/sendgrid-email\n    # {% set SMTP_HOST = 'smtp.sendgrid.net' %}\n    # {% set SMTP_PORT = '587' %}\n    # {% set SMTP_USERNAME = 'apikey' %}\n    # substitute `YOUR-API-KEY-HERE` below, with your API KEY, https://app.sendgrid.com/settings/api_keys\n    # {% set SMTP_PASSWORD = 'YOUR-API-KEY-HERE' %}\n\n    # gmail:\n    # {% set SMTP_HOST = 'smtp.gmail.com' %}\n    # {% set SMTP_PORT = '587' %}\n    # replace `YOUREMAIL@GMAIL.COM` with your email, get `YOUR-APP-PASSWORD` from: https://myaccount.google.com/apppasswords\n    # {% set SMTP_USERNAME = 'YOUREMAIL@GMAIL.COM' %}\n    # {% set SMTP_PASSWORD = 'YOUR-APP-PASSWORD' %}\n\n    {% set SMTP_HOST = '' %}\n    {% set SMTP_PORT = '' %}\n    {% set SMTP_USERNAME = '' %}\n    {% set SMTP_PASSWORD = '' %}\n\n    # NOTIFICATION_EMAIL address for daily crontab notifications\n    {% set NOTIFICATION_EMAIL = 'youremail@example.com' %}\n\n    # HOSTNAME and FQDN are used by Postfix, and necessary for Sendgrid\n    # HOSTNAME: subdomain of FQDN (e.g. `server` for `server.example.com`)\n    # FQDN (e.g. `example.com` or `server.example.com`)\n    {% set HOSTNAME = 'voip' %}\n    {% set FQDN = 'voip.example.com' %}\n\n    # OPTIONAL: PRECONFIGURE FREEPBX CORE MODULE (OUTBOUND ROUTES AND TRUNKS)\n    # ubuntupbx.core.backup.tar.gz was generated with the Backup \u0026 Restore FreePBX Module\n    # this can be replaced with the https:// or gs:// address of your backup file, if you're copying configurations from another FreePBX installation\n    {% set RESTORE_BACKUP = 'https://github.com/rajannpatel/ubuntupbx/raw/refs/heads/main/ubuntupbx.core.backup.tar.gz' %}\n    # ubuntupbx.core.backup.tar.gz Outbound Routes include: N11, North America FoIP, North America VoIP, International VoIP\n    # ubuntupbx.core.backup.tar.gz SIP Trunks include:\n    {% set enable_T38Fax = true %}      # https://t38fax.com\n    {% set enable_Flowroute = false %}  # https://flowroute.com\n    {% set enable_Telnyx = false %}     # https://telnyx.com\n    {% set enable_BulkVS = true %}      # https://bulkvs.com\n\n    # List of public IPv4 addresses that should never be blocked by fail2ban\n    # - Use standard dotted decimal notation for each IP address or CIDR (slash) notation IP ranges\n    # - Separate multiple entries with a space, and do not use commas:\n    # {% set USER_IPS = '192.178.0.0/15 142.251.47.238' %}\n    {% set USER_IPS = '' %}\n\n    # TIMEZONE: default value is fine\n    # As represented in /usr/share/zoneinfo. An empty string ('') will result in UTC time being used.\n    {% set TIMEZONE = 'America/New_York' %}\n\n    # TIME TO INSTALL AND REBOOT UBUNTU FOR SECURITY PATCHES FROM CANONICAL IN XX:XX FORMAT\n    {% set SECURITY_INSTALL_TIME = \"04:10\" %}\n    {% set SECURITY_REBOOT_TIME = \"04:30\" %}\n\n    # NUMBER OF DAYS TO RETAIN CDR AND CEL RECORDS IN FREEPBX\n    {% set CDR_RETENTION_DAYS = \"60\" %}\n    {% set CEL_RETENTION_DAYS = \"60\" %}\n\n    # PHP 8.2 IS OFFICIALLY TESTED WITH FREEPBX BY SANGOMA, PHP 8.2 IS SECURITY MAINTAINED UNTIL 31 Dec 2026 FROM THE PHP GROUP (UPSTREAM)\n    # PHP 8.3 IS COMPATIBLE WITH FREEPBX AND ALL AVAILABLE MODULES, PHP 8.3 GETS SECURITY PATCHING UNTIL 2036 THROUGH CANONICAL, THE PUBLISHERS OF UBUNTU\n    # PHP_VERSION = 8.2|8.3\n    {% set PHP_VERSION = \"8.2\" %}\n\n    # =========================\n    # END OF SETTING VARIABLES\n    ```\n    \n    \u003c/details\u003e\n\n9. Create a free-tier e2-micro VM named \"ubuntupbx\", [other VM types](https://cloud.google.com/compute/docs/machine-resource) cost money.\n    \n    ```bash\n    gcloud compute instances create ubuntupbx \\\n        --zone=$ZONE \\\n        --machine-type=e2-micro \\\n        --address=pbx-external-ip \\\n        --tags=pbx \\\n        --service-account=$(gcloud compute project-info describe --format=\"value(defaultServiceAccount)\") \\\n        --scopes=https://www.googleapis.com/auth/cloud-platform \\\n        --boot-disk-size=30 \\\n        --image-family=ubuntu-2404-lts-amd64 \\\n        --image-project=ubuntu-os-cloud \\\n        --metadata-from-file=user-data=cloud-init.yaml\n    ```\n\n\u003e [!NOTE]\n\u003e \u003ca name=\"info-bubble-2\"\u003e\u003cimg align=\"right\" alt=\"Info Bubble\" width=\"50\" src=\"./images/icons8-information-100.png\" /\u003e\u003c/a\u003e\n\u003e In the steps below, `--source-ranges` can be any number of globally routable IPv4 addresses written as individual IPs, or groups of IPs in slash notation, separated by commas (but no spaces).\u003cbr\u003e\u003csub\u003e\u0026ensp;EXAMPLE\u003cbr\u003e\u0026ensp;`192.178.0.0/15,142.251.47.238`\u003c/sub\u003e\n\u003e\n\u003e `$(curl -s http://checkip.amazonaws.com)` retrieves the globally routable IPv4 address of the machine where the command is run, using an Amazon AWS service. It appears in some commands below, as a convenience, but can be replaced with manually specified IPs.\n\n\u003e [!TIP]\n\u003e \u003ca name=\"info-lightbulb-2\"\u003e\u003cimg align=\"right\" alt=\"Info Lightbulb\" width=\"50\" src=\"./images/icons8-tip-100.png\" /\u003e\u003c/a\u003e\n\u003e Looking up an individual IP from an ISP at [arin.net](https://arin.net) can reveal the entire CIDR block of possible IPs from that ISP, if wide ranges need to be permitted in the firewall. For example, looking up a Charter Spectrum IP [174.108.85.8](https://search.arin.net/rdap/?query=174.108.85.8) reveals a CIDR of `174.96.0.0/12`. CIDR blocks for popular ISPs serving dynamic IPs to customers in North America appear in the following table:\n\u003e | ISP  | CIDR |\n\u003e | ------------- | ------------- |\n\u003e | [Charter Spectrum Charlotte](https://search.arin.net/rdap/?query=174.96.0.0)  | `174.96.0.0/12`  |\n\u003e | [Charter Spectrum Orlando (Road Runner)](https://search.arin.net/rdap/?query=67.8.0.0) | `67.8.0.0/14` |\n\u003e | [Optimum Online's Altice Fiber](https://search.arin.net/rdap/?query=174.96.0.0)  | `24.184.0.0/14`  |\n\u003e | [Verizon Wireless 5G Home Internet](https://search.arin.net/rdap/?query=75.192.0.0)  | `75.192.0.0/10`  |\n\u003e | [Google Fiber](https://search.arin.net/rdap/?query=136.32.0.0)  | `136.32.0.0/11`  |\n\n10. Permit ingress HTTP for management and optionally ICMP for ping replies\n\n    ```bash\n    gcloud compute firewall-rules create allow-management-http-icmp \\\n        --direction=INGRESS \\\n        --action=ALLOW \\\n        --target-tags=pbx \\\n        --source-ranges=\"$(curl -s http://checkip.amazonaws.com)\" \\\n        --rules=\"tcp:80,icmp\" \\\n        --description=\"Access FreePBX via web and ping\"\n    ```\n\n\u003ca name=\"step-3-11\"\u003e\u003c/a\u003e\n\n11. Permit ingress UDP traffic for analog telephone adapters (ATAs) and softphones\n\n    ##### This firewall rule allows ingress SIP traffic from your IP\n\n    ```bash\n    gcloud compute firewall-rules create allow-devices-sip-rtp-udptl \\\n        --direction=INGRESS \\\n        --action=ALLOW \\\n        --target-tags=pbx \\\n        --source-ranges=\"$(curl -s http://checkip.amazonaws.com)\" \\\n        --rules=\"udp:5060,udp:4000-4999,udp:10000-20000\" \\\n        --description=\"SIP signaling and RTP \u0026 UDPTL media for ATAs and Softphones\"\n    ```\n\n    ##### This firewall rule allows ingress SIP traffic from the Google Fiber ISP\n\n    - Change the `isp-googlefiber` firewall rule name and `--source-ranges=\"136.32.0.0/11\"` as needed.\n    - These allow ingress rules should reflect the ISP and IPv4 ranges of FoIP and VoIP SIP endpoints connecting to \"ubuntupbx\".\n    - Repeat this step for every ISP where SIP endpoints exist.\u003cbr\u003e\u003cbr\u003e\n\n    ```bash\n    gcloud compute firewall-rules create isp-googlefiber \\\n        --direction=INGRESS \\\n        --action=ALLOW \\\n        --target-tags=pbx \\\n        --source-ranges=\"136.32.0.0/11\" \\\n        --rules=\"udp:5060,udp:4000-4999,udp:10000-20000\" \\\n        --description=\"SIP signaling and RTP \u0026 UDPTL media for ATAs and Softphones\"\n    ```\n\n12. Permit ingress traffic from VoIP and/or FoIP SIP Trunk provider(s)\n\n    - allow RTP and UDPTL media streams over Asterisk's configured UDP port ranges\n    - allow SIP signaling for inbound calls when using IP authentication\u003cbr\u003e\u003cbr\u003e\n\n    \u003cdetails\u003e\n\n    \u003csummary\u003e\u0026ensp;T38Fax\u0026ensp;\u003cb\u003ePower-T.38 SIP Trunk for FoIP\u003c/b\u003e\u003cbr\u003e\u003csup\u003e\u0026emsp;\u0026ensp;\u0026thinsp;\u0026thinsp;CLICK TO EXPAND\u003c/sup\u003e\u003cbr\u003e\u003c/summary\u003e\n\n    \u003cbr\u003e[T38Fax](https://t38fax.com) proxies all the RTP and UDPTL packets through their network for observability into the quality of the RTP streams.\n    \n    ##### RTP and UDPTL ingress rule\n\n    ```bash\n    gcloud compute firewall-rules create foip-t38fax-rtp-udptl \\\n        --direction=INGRESS \\\n        --action=ALLOW \\\n        --target-tags=pbx \\\n        --source-ranges=\"8.20.91.0/24,130.51.64.0/22,8.34.182.0/24\" \\\n        --rules=\"udp:4000-4999,udp:10000-20000\" \\\n        --description=\"T38Fax incoming RTP and UDPTL media streams\"\n    ```\n\n    ##### SIP signaling ingress rule\n\n    ```bash\n    gcloud compute firewall-rules create foip-t38fax-sip \\\n        --direction=INGRESS \\\n        --action=ALLOW \\\n        --target-tags=pbx \\\n        --source-ranges=\"8.20.91.0/24,130.51.64.0/22,8.34.182.0/24\" \\\n        --rules=\"udp:5060\" \\\n        --description=\"T38Fax SIP Signaling\"\n    ```\n\n    \u003c/details\u003e\n\n    \u003cdetails\u003e\n\n    \u003csummary\u003e\u0026ensp;Flowroute\u003cbr\u003e\u003csup\u003e\u0026emsp;\u0026ensp;\u0026thinsp;\u0026thinsp;CLICK TO EXPAND\u003c/sup\u003e\u003cbr\u003e\u003c/summary\u003e\n\n    \u003cbr\u003e[Flowroute](https://flowroute.com) uses direct media delivery to ensure voice data streams traverse the shortest path between the caller and callee, therefore `--source-ranges=\"0.0.0.0/0\"` allows inbound RTP and UDPTL traffic from anywhere in the world.\n\n    ##### RTP and UDPTL ingress rule\n\n    ```bash\n    gcloud compute firewall-rules create voip-flowroute-rtp-udptl \\\n        --direction=INGRESS \\\n        --action=ALLOW \\\n        --target-tags=pbx \\\n        --source-ranges=\"0.0.0.0/0\" \\\n        --rules=\"udp:4000-4999,udp:10000-20000\" \\\n        --description=\"Flowroute incoming RTP and UDPTL media streams\"\n    ```\n\n    ##### SIP signaling ingress rule\n\n    ```bash\n    gcloud compute firewall-rules create voip-flowroute-sip \\\n        --direction=INGRESS \\\n        --action=ALLOW \\\n        --target-tags=pbx \\\n        --source-ranges=\"34.210.91.112/28,34.226.36.32/28,16.163.86.112/30,3.0.5.12/30,3.8.37.20/30,3.71.103.56/30,18.228.70.48/30\" \\\n        --rules=\"udp:5060\" \\\n        --description=\"Flowroute SIP Signaling\"\n    ```\n\n    \u003c/details\u003e\n\n    \u003cdetails\u003e\n\n    \u003csummary\u003e\u0026ensp;Telnyx\u003cbr\u003e\u003csup\u003e\u0026emsp;\u0026ensp;\u0026thinsp;\u0026thinsp;CLICK TO EXPAND\u003c/sup\u003e\u003cbr\u003e\u003c/summary\u003e\n\n    \u003cbr\u003e[Telnyx](https://telnyx.com) proxies all the RTP and UDPTL media streams through their network for observability into the quality of the RTP streams.\n\n    ##### RTP and UDPTL ingress rule\n\n    ```bash\n    gcloud compute firewall-rules create voip-telnyx-rtp-udptl \\\n        --direction=INGRESS \\\n        --action=ALLOW \\\n        --target-tags=pbx \\\n        --source-ranges=\"36.255.198.128/25,50.114.136.128/25,50.114.144.0/21,64.16.226.0/24,64.16.227.0/24,64.16.228.0/24,64.16.229.0/24,64.16.230.0/24,64.16.248.0/24,64.16.249.0/24,103.115.244.128/25,185.246.41.128/25\" \\\n        --rules=\"udp:4000-4999,udp:10000-20000\" \\\n        --description=\"Telnyx incoming RTP and UDPTL media streams\"\n    ```\n\n    ##### SIP signaling ingress rule\n\n    ```bash\n    gcloud compute firewall-rules create voip-telnyx-sip \\\n        --direction=INGRESS \\\n        --action=ALLOW \\\n        --target-tags=pbx \\\n        --source-ranges=\"192.76.120.10,64.16.250.10,185.246.41.140,185.246.41.141,103.115.244.145,103.115.244.146,192.76.120.31,64.16.250.13\" \\\n        --rules=\"udp:5060\" \\\n        --description=\"Telnyx SIP Signaling\"\n    ```\n\n    \u003c/details\u003e\n\n    \u003cdetails\u003e\n\n    \u003csummary\u003e\u0026ensp;BulkVS\u003cbr\u003e\u003csup\u003e\u0026emsp;\u0026ensp;\u0026thinsp;\u0026thinsp;CLICK TO EXPAND\u003c/sup\u003e\u003cbr\u003e\u003c/summary\u003e\n\n    \u003cbr\u003e[BulkVS](https://bulkvs.com) proxies all the RTP and UDPTL packets through their network for observability into the quality of the RTP streams.\n\n    ##### RTP and UDPTL ingress rule\n\n    ```bash\n    gcloud compute firewall-rules create voip-bulkvs-rtp-udptl \\\n        --direction=INGRESS \\\n        --action=ALLOW \\\n        --target-tags=pbx \\\n        --source-ranges=\"162.249.171.198,23.190.16.198,76.8.29.198\" \\\n        --rules=\"udp:4000-4999,udp:10000-20000\" \\\n        --description=\"BulkVS incoming RTP and UDPTL media streams\"\n    ```\n\n    ##### SIP signaling ingress rule\n\n    ```bash\n    gcloud compute firewall-rules create voip-bulkvs-sip \\\n        --direction=INGRESS \\\n        --action=ALLOW \\\n        --target-tags=pbx \\\n        --source-ranges=\"162.249.171.198,23.190.16.198,76.8.29.198\" \\\n        --rules=\"udp:5060\" \\\n        --description=\"BulkVS SIP Signaling\"\n    ```\n\n    \u003c/details\u003e\n\n13. Observe the installation progress by tailing `/var/log/cloud-init-output.log`\n    \n    ```bash\n    gcloud compute ssh ubuntupbx --zone $ZONE --command \"tail -f /var/log/cloud-init-output.log\"\n    ```\n    \n14. Authorize gcloud CLI to have SSH access to your Ubuntu virtual machine\n\n    -  First time gcloud CLI users will be prompted for a passphrase twice\n    -  This password can be left blank, press \u003ckbd\u003eEnter\u003c/kbd\u003e twice to proceed:\u003cbr\u003e\u003cbr\u003e\n    \n    \u003e ```text\n    \u003e WARNING: The private SSH key file for gcloud does not exist.\n    \u003e WARNING: The public SSH key file for gcloud does not exist.\n    \u003e WARNING: You do not have an SSH key for gcloud.\n    \u003e WARNING: SSH keygen will be executed to generate a key.\n    \u003e Generating public/private rsa key pair.\n    \u003e Enter passphrase (empty for no passphrase):\n    \u003e Enter same passphrase again:\n    \u003e ```\n    \n15. This line indicates security patches were applied, and a reboot is required\n    \n    \u003e ```text\n    \u003e 2023-08-20 17:30:04,721 - cc_package_update_upgrade_install.py[WARNING]: Rebooting after upgrade or install per /var/run/reboot-required\n    \u003e ```\n  \n    In the event of a reboot, re-run the tail command to continue observing the progress of the installation; otherwise skip this step:\n    \n    ```bash\n    gcloud compute ssh ubuntupbx --zone $ZONE --command \"tail -f /var/log/cloud-init-output.log\"\n    ```\n    \n16. When cloud-init prints this `finished at` line, press \u003ckbd\u003eCTRL\u003c/kbd\u003e + \u003ckbd\u003eC\u003c/kbd\u003e to terminate the tail process.\n    \n    \u003e ```text\n    \u003e Cloud-init v. 24.1.3-0ubuntu3.3 finished at Thu, 20 Jun 2024 03:53:16 +0000. Datasource DataSourceGCELocal.  Up 666.00 seconds\n    \u003e ```\n\n17. Access the web portal to set up Trunks and Extensions\n\n    -  These commands will print the web portal links in the terminal\n    -  \u003ckbd\u003eCTRL\u003c/kbd\u003e click the link to open\u003cbr\u003e\u003cbr\u003e\n\n    ```bash\n    dig +short -x $(gcloud compute addresses describe pbx-external-ip --region=$REGION --format='get(address)') | sed 's/\\.$//; s/^/http:\\/\\//'\n    ```\n\n    ```bash\n    echo \"http://$(gcloud compute addresses describe pbx-external-ip --region=$REGION --format='get(address)')\"\n    ```    \n\n18. Connect to the \"ubuntupbx\" VM via SSH to configure external backup schedules, and connect to the Asterisk CLI.\n\n    ```bash\n    gcloud compute ssh ubuntupbx --zone $ZONE\n    ```\n\n    Upon logging in via SSH, edit the \"root\" user's crontab.\n\n    ```bash\n    sudo crontab -e\n    ```\n\n    **nano** (option 1) will be the most intuitive option for most users.\n\n    \u003e ```text\n    \u003e Select an editor.  To change later, run 'select-editor'.\n    \u003e 1. /bin/nano        \u003c---- easiest\n    \u003e 2. /usr/bin/vim.basic\n    \u003e 3. /usr/bin/vim.tiny\n    \u003e 4. /bin/ed\n    \u003e ```\n\n    Add the following lines at the bottom of the crontab file. Replace `example-bucket-name` with the name of a Google Cloud Storage bucket in the same project as the virtual machine.\n\n    ```bash\n    @daily gcloud storage rsync /var/spool/asterisk/backup gs://example-bucket-name/backup --recursive\n    @daily gcloud storage rsync /var/spool/asterisk/monitor gs://example-bucket-name/monitor --recursive\n    ```\n\n    -  FreePBX artifacts such as backups and call recordings (if enabled) will be pruned on a schedule through crontab entries for the \"root\" user.\n    -  A Google Cloud Storage S3 Bucket is a suitable location for long term external storage of this data.\n    -  Delete stale backups and recordings from the S3 bucket on a schedule with \"maximum age\" object lifecycle policies.\n\n    Connect to the Asterisk CLI, and observe output as you configure and use FreePBX:\n\n    ```bash\n    sudo su -s /bin/bash asterisk -c 'cd ~/ \u0026\u0026 asterisk -rvvvvv'\n    ```\n\n    -  The `exit` command will safely exit the Asterisk CLI.\n    -  Running the `exit` command again will quit the SSH session.\n\n19. fail2ban blocks IPs after 3 invalid authentication attempts on SSH, Asterisk, and FreePBX. fail2ban also emails alerts when the dynamic firewall turns on, turns off, and when an IP is banned due to invalid authentication attempts on Asterisk and FreePBX.\n\n    \u003cdetails\u003e\n\n    \u003csummary\u003e\u0026ensp;Manage the fail2ban dynamic firewall\u003cbr\u003e\u003csup\u003e\u0026emsp;\u0026ensp;\u0026thinsp;\u0026thinsp;CLICK TO EXPAND\u003c/sup\u003e\u003cbr\u003e\u003c/summary\u003e\n\n    ##### Append more user and provider IPs to `ignoreip =` in jail.local\n    \n    - any additional public IPv4 addresses which should never be banned are listed in the `IP` variable\n    - Use standard dotted decimal notation for each IP address or CIDR (slash) notation IP ranges\n    - Separate multiple entries with a space, and do not use commas.\u003cbr\u003e\u003csub\u003e\u0026ensp;EXAMPLE\u003cbr\u003e\u0026ensp;`IP='192.178.0.0/15 142.251.47.238'`\u003c/sub\u003e\u003cbr\u003e\u003cbr\u003e\n\n    ```bash\n    IP=$(curl -s http://checkip.amazonaws.com)\n    gcloud compute ssh ubuntupbx --zone $ZONE --command \"sudo sed -i 's/ignoreip = \\(.*\\)/ignoreip = \\1 '\"$IP\"'/' /etc/fail2ban/jail.local\"\n    gcloud compute ssh ubuntupbx --zone $ZONE --command \"sudo fail2ban-client reload\"\n    ```\n\n    ##### Confirm the ignoreip list is accurate\n\n    Invalid IPs in the ignoreip setting in /etc/fail2ban/jail.local will result in 0.0.0.0 (whole world) being ignored.\n\n    ```bash\n    gcloud compute ssh ubuntupbx --zone $ZONE --command \"sudo fail2ban-client get asterisk ignoreip\"\n    ```\n\n    ##### List all banned IPs in fail2ban jails\n\n    ```bash\n    gcloud compute ssh ubuntupbx --zone $ZONE --command \"sudo fail2ban-client status | sed -n 's/,//g;s/.*Jail list://p' | xargs -n1 sudo fail2ban-client status\"\n    ```\n\n    ##### Monitor IPs fail2ban is evaluating, in realtime\n\n    ```bash\n    gcloud compute ssh ubuntupbx --zone $ZONE --command \"tail -f /var/log/fail2ban.log\"\n    ```\n\n    ##### Unban IP from fail2ban jails\n\n    - Replace `127.0.0.1` with the IP address that needs to be unbanned\n    - The 3 jails are named **sshd**, **asterisk**, and **freepbx**\n    - A `1` output indicates successful removal, a `0` output indicates the IP was not banned\u003cbr\u003e\u003cbr\u003e\n\n    ```bash\n    $IP='127.0.0.1'\n    gcloud compute ssh ubuntupbx --zone $ZONE --command \"sudo fail2ban-client unban sshd $IP\"\n    gcloud compute ssh ubuntupbx --zone $ZONE --command \"sudo fail2ban-client unban asterisk $IP\"\n    gcloud compute ssh ubuntupbx --zone $ZONE --command \"sudo fail2ban-client unban freepbx $IP\"\n    ```\n\n    \u003c/details\u003e\n\n\u003csub\u003ePROGRESS \u0026emsp;\u0026emsp; :heavy_check_mark: \u0026emsp;STEP 1\u0026emsp;\u0026emsp; :heavy_check_mark: \u0026emsp; STEP 2\u0026emsp;\u0026emsp; :heavy_check_mark: \u0026emsp;STEP 3\u0026emsp;\u0026emsp; :tada: \u0026emsp;COMPLETED\u003c/sub\u003e\u003cbr\u003e\u003cbr\u003e\n\n---\n\n\u003ca name=\"how-do-i-undo-icon\"\u003e\u003c/a\u003e\n\n\u003ca name=\"how-do-i-undo-icon-png\"\u003e\u003cimg alt=\"Delete\" width=\"50\" src=\"./images/icons8-delete-100.png\" /\u003e\u003c/a\u003e\n\n### **HOW DO I UNDO?**\n#### How to delete things in Google Cloud\n\n\u003e [!WARNING]\n\u003e \u003ca name=\"warning-sign-icon\"\u003e\u003cimg align=\"right\" alt=\"Warning Sign\" width=\"50\" src=\"./images/icons8-warning-100.png\" /\u003e\u003c/a\u003e\n\u003e The following steps are destructive, and will remove everything created by following the above steps, in Google Cloud.\n\nThe following steps remove the \"ubuntupbx\" VM, its static IP address, and its firewall rules.\n\n1. List all VMs in this project:\n\n    ```bash\n    gcloud compute instances list\n    ```\n\n2. To delete the \"ubuntupbx\" VM, set `ZONE` to reflect what was specified in [Step 3.6](#step-3-6):\n\n    ```bash\n    ZONE=us-east1-b\n    gcloud compute instances delete ubuntupbx --zone $ZONE\n    ```\n\n3. List all the static addresses:\n    \n    ```bash\n    gcloud compute addresses list\n    ```\n\n4. To delete the address named \"pbx-external-ip\", set `REGION` to reflect what was specified in [Step 3.6](#step-3-6)\n\n    ```bash\n    REGION=us-east1\n    gcloud compute addresses delete pbx-external-ip --region=$REGION\n    ```\n\n5. List all firewall rules in this project:\n    \n    ```bash\n    gcloud compute firewall-rules list\n    ```\n\n6. To delete the ingress firewall rules created in [Step 3.11](#step-3-11)\n\n    ```bash\n    gcloud compute firewall-rules delete allow-management-http-icmp\n    gcloud compute firewall-rules delete allow-devices-sip-rtp-udptl\n\n    gcloud compute firewall-rules delete foip-t38fax-rtp-udptl\n    gcloud compute firewall-rules delete foip-t38fax-sip\n\n    gcloud compute firewall-rules delete voip-flowroute-rtp-udptl\n    gcloud compute firewall-rules delete voip-flowroute-sip\n\n    gcloud compute firewall-rules delete voip-telnyx-rtp-udptl\n    gcloud compute firewall-rules delete voip-telnyx-sip\n\n    gcloud compute firewall-rules delete voip-bulkvs-rtp-udptl\n    gcloud compute firewall-rules delete voip-bulkvs-sip\n    ```\n\n\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\n\u003ca href=\"https://icons8.com\"\u003e\u003cimg alt=\"icon credits\" align=\"right\" src=\"./images/icons.png\"\u003e\u003c/a\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frajannpatel%2Fubuntupbx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frajannpatel%2Fubuntupbx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frajannpatel%2Fubuntupbx/lists"}