FusionPBX on unprivileged LXC: FreeSWITCH realtime scheduling fails to start, silently breaking switch default settings seeding (MOH and more) - FIXED

shakle

New Member
Apr 5, 2026
6
2
3
Italy
FIX ON FRESH INSTALL

Environment:
FusionPBX 5.5/5.6, Debian 13, PHP 8.2/8.4, Proxmox unprivileged LXC container


Root cause (verified in source):

On unprivileged LXC containers, FreeSWITCH's systemd unit requests CPUSchedulingPolicy/IOSchedulingClass realtime priorities that require CAP_SYS_NICE, which an unprivileged container doesn't have — so FreeSWITCH fails to start cleanly right after install.


During install, upgrade.php --defaults calls switch_settings->settings() (resources/classes/switch_settings.php), which queries FreeSWITCH live via Event Socket (api global_getvar) to populate the switch category of v_default_settings (base, conf, db, grammar, log, mod, recordings, scripts, storage, sounds, etc.). If FreeSWITCH isn't up yet, every one of these ends up written to the DB with an empty value.


Design flaw compounding this: the insert logic only adds a row if the subcategory is entirely missing from the table — it never re-checks/repairs a row that already exists with an empty value. So simply starting FreeSWITCH later and re-running --defaults does nothing; the empty rows persist forever.


This single root cause explains both: (1) the empty default MOH category on fresh installs, and (2) the long-standing community-reported "MOH upload doesn't work" bug — both depend on the same switch settings being populated.


Verified fix:

# 1. Allow FreeSWITCH to start on unprivileged LXC
mkdir -p /etc/systemd/system/freeswitch.service.d
cat > /etc/systemd/system/freeswitch.service.d/lxc.conf <<'EOF'
[Service]
CPUSchedulingPolicy=
CPUSchedulingPriority=
IOSchedulingClass=
IOSchedulingPriority=
EOF
systemctl daemon-reload
systemctl restart freeswitch

# 2. Remove the empty rows so the seeding logic treats them as missing
su - postgres -c "psql fusionpbx -c \"DELETE FROM v_default_settings WHERE default_setting_category='switch' AND (default_setting_value IS NULL OR default_setting_value='');\""

# 3. Install zip (IT'S ESSENTIAL!! without this, `upgrade.php --defaults` does not complete successfully. Fusionpbx install.sh doesn't install it. It's non included in debian 12 and debian 13)
apt install -y zip

# 4. Re-run defaults now that FreeSWITCH is reachable
php /var/www/fusionpbx/core/upgrade/upgrade.php --defaults




Confirmed this correctly repopulates all switch settings with live values from FreeSWITCH (verified identical to a known-good production install), fixing both the MOH seeding and upload path issues.


Suggested fix for the project: (a) ship the LXC scheduling override as part of fusionpbx-install.sh when an LXC/container environment is detected, and/or (b) make upgrade.php --defaults wait for FreeSWITCH to be reachable via Event Socket before running switch_settings-&gt;settings(), and (c) have the seeding logic repair rows with empty values, not just insert missing ones.
 
Last edited: