DOCUMENTATION
Provisioning
FreePBX UK ◈ Provisioning
FreePBX UK Documentation • Last Updated 6th October 2026

Every FreePBX UK instance starts from a maintained hardened snapshot. Nano² and the 7-day Free Trial share the Nano² snapshot; Micro⁴, Macro⁸, and Mega¹⁶ each have their own.

The most recent tested snapshot for each plan is used as the basis for the next. A fresh temporary droplet is created from it, brought fully up to date, checked, prepared, sanitised, and shut down cleanly before the replacement snapshot is captured. New snapshots are created at least monthly, and sooner when a defect is identified or developments in Debian, FreePBX, DigitalOcean, or the surrounding platform require it.

A customer order then triggers a separate automated provisioning template that personalises, hardens, validates, and cleans the new instance before customer access is released. The post-order provisioning process takes around seven minutes and requires no manual intervention.

Snapshot Image Preparation
✓
Snapshot LineageEach refresh starts from the most recent tested hardened snapshot for that plan, not from a new FreePBX installation.
A fresh temporary DigitalOcean droplet is created from the current snapshot and used to prepare its replacement. The existing snapshot remains the known-good baseline until the replacement has been completed.
✓
Plan SnapshotsMicro⁴, Macro⁸, and Mega¹⁶ each have their own hardened snapshot. Nano² and the 7-day Free Trial share the Nano² snapshot.
Plan-specific preparation, including swap sizing, is maintained in the appropriate image.
✓
Refresh CycleA replacement snapshot is created at least monthly, and sooner when a defect is identified or the platform needs to evolve with Debian, FreePBX, DigitalOcean, or related dependencies.
The current hardened snapshot is treated as the finished production standard. Changes are made in response to defects or external platform development, not as an unfinished hardening roadmap.
✓
Original FoundationThe snapshot lineage was originally built from a fresh Debian 12 droplet with FreePBX 17 and Asterisk 22 installed using IN1CLICK 1.3.3 by 20tele.com.
IN1CLICK performed its operating-system, architecture, resource, hostname, APT, network, mirror, installation, GUI, Apache, and self-cleanup checks before that original foundation image entered the hardened snapshot cycle.
✓
Pre-Snapshot UpdatesDebian packages and installed FreePBX modules are brought fully up to date before the replacement snapshot is prepared.
FreePBX ownership and configuration are normalised and the platform is restarted before the health checks are performed.
✓
Reboot CheckThe server is checked to see whether the completed system update requires a reboot.
If a reboot is required, it is performed at this point and the health checks are repeated before snapshot preparation continues. If no reboot is required, the process continues without one.
✓
Health CheckAsterisk, the FreePBX module state, and the PM2-managed FreePBX services are checked before the snapshot is accepted.
The replacement image is prepared only from a system whose FreePBX service stack is in the expected state.
✓
Locale and Timezoneen_GB.UTF-8 is generated and selected, and the operating-system timezone is set to Europe/London.
This establishes the UK locale and timezone in the base image before customer-specific provisioning runs.
✓
Cloud-Init UserThe snapshot explicitly sets cloud-init's default user to root.
This prevents DigitalOcean-created instances from depending on a nonexistent debian account during first-boot processing.
✓
SwapThe snapshot swap file is rebuilt to match the target plan and enabled permanently.
The size is selected for the plan being prepared: 1GB for Nano², 2GB for Micro⁴, 4GB for Macro⁸, or 8GB for Mega¹⁶.
✓
FirewallThe FreePBX firewall is prepared to allow the FreePBX UK console service.
This allows the portal console to reach the PBX without a manual firewall change after deployment.
✓
DatabaseOld FreePBX notification records are removed before the image is sealed.
Notifications older than the current date are deleted so cloned systems do not inherit stale dashboard notices.
✓
Snapshot CleanupMail, cloud-init instance data, system logs, Asterisk logs, temporary files, journal history, and root Bash history are purged before shutdown.
The temporary maintenance system is sanitised so customer instances do not inherit its working history or transient data.
✓
ShutdownThe filesystem is synced and the prepared server is shut down cleanly before the reusable snapshot is captured.
The finished snapshot is stored fully prepared and ready for customer provisioning.

Method Secret sauce, not open source
✓
FreePBX itself is open source. The FreePBX UK provisioning and hardening process is not. It is part of our private hosting platform and operational know-how: our secret sauce, so to speak.
This page documents what happens, the stages an instance passes through, and the standard it must meet. We do not publish every command, test, hardening routine, validation rule, or piece of internal automation used to achieve that result.
✓
We consider the current hardening process complete.
It is maintained rather than developed as an unfinished feature. Changes are made when a defect is identified or when developments in Debian, FreePBX, DigitalOcean, or the wider platform require them.

Live Progress Follow your order or rebuild
✓
Progress TerminalNew orders and server rebuilds include a live progress terminal that follows your PBX through provisioning.
Timestamped updates explain the stage being completed, from server discovery and access hardening to fresh credentials, restarts, validation, and handover.
✓
Confirmed MilestonesProgress follows provisioning milestones reported by the PBX itself.
Completed stages are shown when their reports arrive. During a wait, the terminal explains what it is watching for and flags delays while keeping the last confirmed stage visible.
✓
Patient DiscoveryThe monitor allows three discovery windows of five minutes each for the first provisioning report to arrive.
This gives a slower cloud start approximately 15 minutes to become visible. If discovery remains unsuccessful, the terminal reports that it cannot confirm progress. The PBX continues its own provisioning independently.
✓
Catch-UpWhen a delayed PBX becomes visible, the terminal catches up with the milestone history it reports.
Provisioning may already be well underway or complete. The monitor uses the reported state to show where the PBX has reached.
✓
Live TimingThe 7-minute target is timed from the provisioning start reported by the PBX.
Timing becomes available once the first report is received and reflects the reported start, including work already completed before discovery.
✓
Restart WatchThe terminal follows both planned restarts and the final service checks through to the ready confirmation.
Temporary loss of contact during a restart is expected. The monitor watches for the next milestone and follows reporting and cleanup before displaying the completed state.

Boot 1 Server Creation and Hardening
✓
NetworkCloud network management is disabled and DNS resolvers are set to Cloudflare and Google (IPv4 and IPv6).
Prevents the hosting provider from overwriting your network settings on future boots. resolv.conf is rebuilt directly and cloud-init network management is locked out permanently via 99-disable-network-config.cfg.
✓
HostnameYour server is assigned a unique .freepbxhosting.uk hostname.
Used for reverse DNS, mail headers, and system identification.
✓
SSHRoot password login is disabled. Only SSH key authentication is permitted.
The root password is replaced with a 32-byte cryptographic random string that nobody knows.
✓
Mail RelayA temporary outbound mail relay is configured so the server can send its provisioning report.
Uses SMTP2GO on port 2525 with TLS encryption and SASL authentication. Removed after use.
✓
needrestartThe needrestart utility is installed so you can identify which services require a restart after future updates.
Run needrestart at any time to see if any running processes are using outdated libraries following a manual apt upgrade.
✓
Auto Security UpdatesDebian security patches will apply automatically. General Debian updates, FreePBX, and Asterisk are excluded.
Configured via /etc/apt/apt.conf.d/52unattended-upgrades-freepbxuk. Security-only origins, no automatic reboot, freepbx17 and asterisk* explicitly blacklisted. You retain full control over manual apt upgrades and FreePBX module updates.
✓
ServicesPost-boot services are registered to handle FreePBX restart, credential rotation, and reporting.
Two systemd oneshot services are enabled: freepbxUK-once and provisioning-report.
✓
RebootThe server reboots to apply all changes cleanly.
All hardening changes applied in Boot 1 take full effect from a clean start. Boot 2 begins immediately on restart.

Boot 2 FreePBX Restart, Credential Rotation, and Clone Hardening
✓
StabilisationThe server waits 120 seconds for FreePBX services to initialise after the snapshot clone boots.
The delay gives Asterisk, PM2, the database, and dependent FreePBX services time to settle before credentials are changed.
✓
FreePBX RestartFreePBX is stopped, started, and reloaded before clone-specific changes begin.
This establishes a clean generated configuration and PM2 state before credential rotation.
✓
AMI CredentialsThe primary Asterisk Manager Interface username and password are replaced with unique random values.
A 15-character alphanumeric username and 30-character alphanumeric password are applied through fwconsole settings.
✓
ARI CredentialsThe Asterisk REST Interface username and password are replaced with unique random values.
A 15-character username and 30-character password are generated independently for each cloned instance.
✓
Database CredentialsThe FreePBX database password is randomised and written back into /etc/freepbx.conf.
The new freepbxuser password is applied in MariaDB and immediately tested with a live database connection. Provisioning stops rather than continuing if that authentication test fails.
✓
Module SecretsFreePBX-managed AMI secrets are rotated while the firewall entry is preserved.
The resulting FreePBX and Asterisk configuration is rebuilt against the new instance-specific credentials rather than inherited snapshot values.
✓
API OAuthThe FreePBX API OAuth signing keypair is regenerated for the cloned PBX.
The inherited private/public keypair is removed and recreated so the new instance has its own API signing identity. Provisioning records whether regeneration completed successfully for the final acceptance gate.
✓
Local TLS IdentityThe local Certificate Manager CA and default certificate are regenerated for the new PBX hostname.
Certificate metadata and the integration files used by the web server are refreshed so the clone does not retain the snapshot server's TLS identity.
✓
TimezoneFreePBX and PHP are explicitly set to Europe/London to match the operating system.
PHPTIMEZONE and the Apache/CLI PHP date.timezone values are set, preserving correct BST/GMT handling across FreePBX, CDRs, and PHP.
✓
Network CompatibilityA minimal /etc/network/interfaces placeholder is written for FreePBX module network discovery on Debian 12.
This satisfies modules that expect the legacy file to exist without handing network management back to it.
✓
Config Rebuildfwconsole chown and fwconsole reload regenerate FreePBX and Asterisk configuration using the new credentials and identities.
Apache is restarted after the PHP timezone update and the final reporting service is enabled for the next boot.
✓
RebootThe server reboots for the final validation boot.
Boot 3 starts from the completed clone-specific configuration rather than from inherited snapshot state.

Boot 3 Verification, Reporting, and Cleanup
✓
Asterisk GateThe reporting service waits for Asterisk to answer before final validation begins.
It polls every two seconds for up to two minutes rather than assuming that a booted operating system means FreePBX is ready.
✓
Service CheckAsterisk, MariaDB, Apache, Fail2Ban, the firewall, Postfix, RestApps, and UCP are checked.
Final validation confirms that the main FreePBX service stack has returned after the clone-specific changes and reboot cycle.
✓
Clone Hardening CheckThe provisioning report records whether the regenerated API OAuth keypair and local TLS identity completed successfully.
These checks confirm that the clone has its own machine-specific identities rather than retaining those inherited from the snapshot.
✓
Provisioning ReportFreePBX UK receives a provisioning report containing service health, clone-hardening results, and the Boot 2/Boot 3 timeline.
The temporary SMTP2GO relay is used only for this report and is removed during cleanup.
✓
CleanupTemporary SMTP credentials, cloud-init instance data, provisioning scripts, systemd units, mail traces, Bash history, and provisioning log references are removed.
Temporary OAuth and TLS validation files are also removed before handoff.

Result What the Customer Receives
✓
A provisioned FreePBX 17 instance with Asterisk 22 on Debian 12, created from the current hardened snapshot assigned to that service.
✓
Unique AMI, ARI, database, API OAuth, and local TLS identities created for that instance.
✓
SSH hardened for key-only root access with the inherited root password replaced by a random value.
✓
The cloud-init default user explicitly set to root so DigitalOcean first-boot processing does not depend on a nonexistent debian account.
✓
The core FreePBX service stack checked after the final provisioning reboot.
✓
Timezone correctly set to Europe/London across the OS, FreePBX, and PHP.
✓
All temporary provisioning scripts, setup credentials, cloud-init instance data, and installation logs are removed.
✓
A clean system ready for the customer's FreePBX Initial Setup and ongoing self-management.

Verify Setup Cleanup
✓
We invite you to verify the cleanup yourself. Run the following as root on any fresh instance to confirm that provisioning scripts, temporary credentials, cloud-init instance data, log references, and provisioning systemd services have been removed, while the core services remain online.
bash -c 'PASS=0;FAIL=0; GREEN="\033[0;32m"; RED="\033[0;31m"; NC="\033[0m"; TAG="free""pbxUK"; DROP="my""-droplet"; PFX="provision""ing-"; AMI="${PFX}ami.sh"; REPORT="${PFX}report.sh"; CLEANUP="${PFX}cleanup.sh"; ONCE="${TAG}-once"; SCAN="/run/.prov_scan.$$"; PATFILE="/run/.prov_patterns.$$"; TAGFILE="/run/.prov_tag.$$"; umask 077; printf "%s\n" "$TAG" > "$TAGFILE"; printf "%s\n%s\n%s\n" "$TAG" "$DROP" "${PFX}(ami\.sh|report\.sh|cleanup\.sh)" > "$PATFILE"; trap '\''rm -f "$SCAN" "$PATFILE" "$TAGFILE"'\'' EXIT; p(){ echo -e "${GREEN}[OK]${NC} $1"; PASS=$((PASS+1)); }; f(){ echo -e "${RED}[ISSUE]${NC} $1"; FAIL=$((FAIL+1)); }; echo ""; echo "FreePBX Provisioning Verification"; echo "----------------------------------"; echo "This check verifies setup cleanup and core service health."; echo ""; echo "System cleanup:"; [ ! -f "/root/$AMI" ] && p "Setup scripts removed" || f "Setup script still present"; [ ! -f "/root/$REPORT" ] && p "Reporting scripts removed" || f "Reporting script still present"; [ ! -f "/root/$CLEANUP" ] && p "Cleanup process completed" || f "Cleanup script still present"; echo ""; echo "Background services:"; UNITS="$(systemctl list-unit-files 2>/dev/null)"; case "$UNITS" in *"$ONCE"*) f "Setup service still exists";; *) p "No setup services remain";; esac; case "$UNITS" in *"${PFX}report"*) f "Reporting service still exists";; *) p "No reporting services remain";; esac; echo ""; echo "Cloud provisioning data:"; [ ! -d /var/lib/cloud/instance ] && p "Instance data removed" || f "Instance data still present"; [ ! -d /var/tmp/cloud-init ] && p "Temporary cloud files removed" || f "Temporary cloud files still present"; echo ""; echo "Mail configuration:"; postconf relayhost 2>/dev/null | grep -qE "relayhost = *$" && p "Mail relay cleared" || f "Mail relay still configured"; [ ! -f /etc/postfix/sasl_passwd ] && p "No stored mail credentials remain" || f "Mail credentials file still exists"; echo ""; echo "Timezone:"; fwconsole setting PHPTIMEZONE 2>/dev/null | grep -q "Europe/London" && p "PHPTIMEZONE set to Europe/London" || f "PHPTIMEZONE not set correctly"; grep -q "date.timezone = \"Europe/London\"" /etc/php/*/apache2/php.ini 2>/dev/null && p "PHP ini timezone correct" || f "PHP ini timezone not set correctly"; timedatectl | grep -q "Europe/London" && p "OS timezone set to Europe/London" || f "OS timezone not set correctly"; echo ""; echo "Logs and traces:"; grep -qif "$TAGFILE" /var/log/cloud-init.log 2>/dev/null && f "Provisioning references found in cloud-init log" || p "No provisioning references in cloud-init log"; grep -qif "$TAGFILE" /var/log/cloud-init-output.log 2>/dev/null && f "Provisioning references found in cloud-init output log" || p "No provisioning references in cloud-init output log"; echo ""; echo "Filesystem scan (full disk):"; echo "Searching file contents for known provisioning identifiers"; SP="/-\\|"; i=0; (find / \( -path /proc -o -path /sys -o -path /dev -o -path /run -o -path /var/lib/apt/lists \) -prune -o -type f -print0 2>/dev/null | xargs -0 -r grep -IlEf "$PATFILE" 2>/dev/null > "$SCAN" & PID=$!; while kill -0 $PID 2>/dev/null; do i=$(( (i+1) %4 )); printf "\rScanning... %s" "${SP:$i:1}"; sleep 0.2; done; wait $PID); echo ""; if [ -s "$SCAN" ]; then f "Known provisioning identifiers found on disk"; head -n 10 "$SCAN"; else p "No known provisioning identifiers found on disk"; fi; echo ""; echo "Journal scan:"; journalctl 2>/dev/null | grep -qiEf "$PATFILE" && f "Provisioning references found in journal" || p "No provisioning references in journal"; echo ""; echo "Boot history:"; BOOT_COUNT=$(journalctl --list-boots 2>/dev/null | wc -l); [ "$BOOT_COUNT" -ge 2 ] && p "Multiple boot cycles detected ($BOOT_COUNT boots)" || f "Expected multiple boot cycles, found only $BOOT_COUNT"; echo ""; echo "Core services:"; asterisk -rx "core show version" >/dev/null 2>&1 && p "Asterisk running" || f "Asterisk not running"; systemctl is-active mariadb >/dev/null 2>&1 && p "MariaDB running" || f "MariaDB not running"; systemctl is-active apache2 >/dev/null 2>&1 && p "Web server running" || f "Web server not running"; systemctl is-active fail2ban >/dev/null 2>&1 && p "Fail2Ban active" || f "Fail2Ban not running"; echo ""; echo "----------------------------------"; if [ "$FAIL" -eq 0 ]; then echo -e "${GREEN}[OK] All checks passed. Setup cleanup and core services verified.${NC}"; else echo -e "${RED}[ISSUE] Some checks failed. Review the items above.${NC}"; fi; echo ""'
Sample output:
root@my-droplet:~# bash -c '...'

FreePBX Provisioning Verification
----------------------------------
This check verifies setup cleanup and core service health.

System cleanup:
[OK] Setup scripts removed
[OK] Reporting scripts removed
[OK] Cleanup process completed

Background services:
[OK] No setup services remain
[OK] No reporting services remain

Cloud provisioning data:
[OK] Instance data removed
[OK] Temporary cloud files removed

Mail configuration:
[OK] Mail relay cleared
[OK] No stored mail credentials remain

Timezone:
[OK] PHPTIMEZONE set to Europe/London
[OK] PHP ini timezone correct
[OK] OS timezone set to Europe/London

Logs and traces:
[OK] No provisioning references in cloud-init log
[OK] No provisioning references in cloud-init output log

Filesystem scan (full disk):
Searching file contents for known provisioning identifiers
[OK] No known provisioning identifiers found on disk

Journal scan:
[OK] No provisioning references in journal

Boot history:
[OK] Multiple boot cycles detected (2 boots)

Core services:
[OK] Asterisk running
[OK] MariaDB running
[OK] Web server running
[OK] Fail2Ban active

----------------------------------
[OK] All checks passed. Setup cleanup and core services verified.

root@my-droplet:~#