In this page, we will be installing the important steps that should be taken before using your Ubuntu Server in a production environment. This includes things like configuring security settings, creating backups, and optimizing performance. By following the guidelines outlined on this page, you can ensure that your Ubuntu Server is ready to handle the demands of a production environment and keep your data and applications secure. By the end of this page, you will have a solid understanding of what needs to be done to prepare your Ubuntu Server for production use. So, let's get started.
sudo su
cd /etc/ssh
nano sshd_config
Locate the line that reads:
#PermitRootLogin prohibit-password
and modify it to:
PermitRootLogin yes
service sshd restart
If you are lazy then use the following command:
sudo sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config && sudo service sshd restart
sudo apt update
sudo apt full-upgrade
sudo apt update
sudo apt-get upgrade -y
sudo apt-get dist-upgrade -y
sudo apt-get autoremove -y
sudo apt install update-manager-core
sudo do-release-upgrade -d
sudo apt install net-tools -y
timedatectl list-timezones
sudo timedatectl set-timezone Europe/Amsterdam
timedatectl
sudo nano /etc/systemd/timesyncd.conf
[Time]
NTP=YOUR.NTP.IP.HERE
FallbackNTP=ntp.ubuntu.com
sudo timedatectl set-ntp off
sudo timedatectl set-ntp on
systemctl status systemd-timesyncd
Enable Cloud-init if you use:
Cloud Environments: If you're using cloud infrastructure (AWS, Azure, Google Cloud, etc.), cloud-init can automate the initial configuration of instances, including setting static IPs.
Automated Configuration: It can handle more than just networking—like setting up users, SSH keys, and running initialization scripts, which can be beneficial for fully automating your server setup.
Consistency: Ensures that all instances are consistently configured according to predefined templates.
Disable Cloud-init if you use:
Bare-metal Servers: For physical servers or simple virtual machines where cloud-init features are not required, you can manually configure network settings. (set a static ip address)Minimal Configuration: If your setup is simple and doesn’t require the extensive initialization capabilities of cloud-init, you might opt to configure the static IP directly using traditional methods.
sudo mkdir -p /etc/cloud/cloud.cfg.d && echo "network: {config: disabled}" | sudo tee /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg
sudo rm -rf /etc/netplan/50-cloud-init.yaml && netplan apply
ip addr show NETWORKCARDNAME
sudo rm -rf /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg && sudo reboot
ip a
sudo nano /etc/netplan/00-installer-config.yaml
network config below is to restore the defaults (disables static ip). Replace
ens33
with your network card name
network:
version: 2
ethernets:
ens33:
dhcp4: true
dhcp6: true
Use network config below for static ip. Replace
ens33
with your network card name
network:
version: 2
renderer: networkd # The renderer to use. "networkd" for systemd-networkd, or "NetworkManager" for NetworkManager.
ethernets:
ens33:
dhcp4: no # no is to disable DHCP for IPv4.
dhcp6: no # no is to disable DHCP for IPv6.
accept-ra: no # no is to disable DHCP for IPv6.
addresses:
- "192.168.1.55/24" # Static IPv4 address with a subnet mask of 255.255.255.0.
- "2a02:f6e:c2ac:0:5a47:caff:fe76:9dd1/64" # Static IPv6 address with a /64 subnet.
nameservers:
# search: [sub.domain.tld, domain.tld] # Optional search domains for DNS resolution.
addresses: [1.1.1.1, 1.0.0.1] # DNS servers to use. Cloudflare DNS in this case.
routes:
- to: default
via: 192.168.1.2 # Default Gateway
on-link: true
wakeonlan: true
sudo chmod 600 /etc/netplan/00-installer-config.yaml
sudo netplan apply
nano /etc/dhcpcd.conf
denyinterfaces INSERTNETWORKCARDNAME
Make sure you have Wake-on-LAN (WOL) enabled in your BIOS. This is because WoL is a hardware-level feature that must be enabled in the firmware before it can be utilized by the operating system.
sudo apt install ethtool
sudo ethtool NETWORKCARDNAME
Replace NETWORKCARDNAME with the name of your network interface.
sudo ethtool -s NETWORKCARDNAME wol g
Replace NETWORKCARDNAME with the name of your network interface.
sudo nano /etc/netplan/00-installer-config.yaml
Add the following lines to the configuration file for your network interface:
wakeonlan: true
Example:
network:
version: 2
renderer: networkd # or NetworkManager
ethernets:
enp87s0:
dhcp4: false
dhcp6: false
addresses: [ "192.168.1.55/24" ]
nameservers:
# search: [sub.domain.tld, domain.tld]
addresses: [1.1.1.1, 1.0.0.1]
routes:
- to: default # or 0.0.0.0/0
via: 192.168.1.1
on-link: true
wakeonlan: true
sudo netplan apply
sudo nano /etc/systemd/system/wol.service
[Unit]
Description=Enable Wake On Lan
[Service]
Type=oneshot
ExecStart = /sbin/ethtool --change NETWORKCARDNAME wol g
[Install]
WantedBy=basic.target
Replace NETWORKCARDNAME with the name of your network interface.
sudo lvm
lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv
exit
sudo resize2fs /dev/ubuntu-vg/ubuntu-lv
sudo apt update
sudo apt install -y zsh
sudo apt install -y powerline fonts-powerline
sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
Y
But why?
Improved productivity: Oh My Zsh provides many useful commands and aliases to help you navigate and use the command line more efficiently.
Customization: Oh My Zsh allows you to customize your command line interface with various themes, plugins and settings.
Better organization: Oh My Zsh organizes your command line environment with sensible defaults and conventions, making it easier to manage your files and directories.
Improved security: Oh My Zsh includes a number of security features, such as password protection for sensitive files and directories.
Autocompletion: Oh My Zsh provides autocompletion for a wide range of tools and programming languages.
Syntax highlighting: Oh My Zsh provides syntax highlighting, making it easier to read and understand your command line input.
Improved error handling: Oh My Zsh can help you identify and correct errors more quickly and easily.
Better performance: Oh My Zsh is designed to be lightweight and fast, making it a good choice for users with limited system resources.
Community support: Oh My Zsh has a large and active community that provides support, troubleshooting and feature development.
Less chance of crash due to too little ram.
sudo fallocate -l 8G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
sudo nano /etc/fstab
/swapfile swap swap defaults 0 0
sudo fallocate -l 16G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
sudo nano /etc/fstab
/swapfile swap swap defaults 0 0
Before getting packages, run sudo apt update
sudo apt update
sudo apt full-upgrade
Networking Utilities
sudo apt install net-tools -y
active/passive address reconnaissance
sudo apt install netdiscover -y
Disk Usage - advanced
sudo apt install ncdu -y
Disk Usage - basic
sudo apt install duf -y
System Info - fastfetch
sudo add-apt-repository ppa:zhangsongcui3371/fastfetch && sudo apt update && sudo apt install fastfetch
File Manager - vifm
sudo apt install vifm -y
Please note that these steps are for Ubuntu 18.04 or later, for previous versions of Ubuntu the commands may differ.
sudo apt-add-repository ppa:ubuntu-lxc/lxd-stable
sudo apt-get update
sudo apt-get install lxd
sudo lxd init
Choose the storage pool you want to use, and configure it as necessary.
Create a new container:
sudo lxc launch ubuntu:18.04 mycontainer
sudo lxc start mycontainer
sudo lxc exec mycontainer bash
sudo lxc stop mycontainer
sudo lxc delete mycontainer
sudo lxc list
sudo lxc info
sudo image list
sudo lxc image export
Check if you can see you're GPU
lshw -c video
qemu-guest-agent is optional if you are virtualizing this machine
sudo apt install qemu-guest-agent
build-essential is required for nvidia drivers to compile
sudo apt install build-essential
sudo apt install --no-install-recommends nvidia-cuda-toolkit nvidia-headless-535 nvidia-utils-535 libnvidia-encode-535
sudo apt install nvtop
run these commands only if you run Rancher/Kubernetes
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt update && sudo apt install -y nvidia-container-toolkit
sudo apt install nvidia-container-runtime
sudo apt install -y nvidia-docker2
N
reboot
If sudo apt update does not work visit this link: https://github.com/NVIDIA/nvidia-docker/issues/1626
To see the GPU UUID run this command
nvidia-smi --query-gpu=gpu_name,gpu_bus_id,vbios_version,uuid --format=csv
The command should return a non-zero value, indicating that your system supports hardware virtualization.
egrep -c '(vmx|svm)' /proc/cpuinfo
sudo kvm-ok
sudo apt install qemu-kvm libvirt-clients libvirt-daemon-system bridge-utils
sudo adduser myusername kvm
Log out and log back in for the changes to take effect.
Verify that the installation was successful:
The command should return an empty list, indicating that no virtual machines are currently running.
virsh list --all
sudo virt-install --name=myVM --ram=1024 --vcpus=1 --disk path=/var/lib/libvirt/images/myVM.img,size=10 --cdrom /path/to/ubuntu.iso
Or you can install the GUI to create a new virtual machine
sudo apt install virt-manager
virt-manager
virsh start myVM
virsh console myVM
Install FusionPBX on Ubuntu 20.04 LTS. Higher versions are not support YET.
https://ubuntu.com/download/server#downloads
sudo su
wget -O - https://raw.githubusercontent.com/fusionpbx/fusionpbx-install.sh/master/ubuntu/pre-install.sh | sh;
cd /usr/src/fusionpbx-install.sh/ubuntu && ./install.sh
Go to: Advanced -> SIP Profiles
Open External:
rtp-ip $${local_ip_v4} (Replace this with your FusionPBX server IP)
sip-ip $${local_ip_v4} (Replace this with your FusionPBX server IP)
Open Internal:
rtp-ip $${local_ip_v4} (Replace this with your FusionPBX server IP)
sip-ip $${local_ip_v4} (Replace this with your FusionPBX server IP)
cd /usr/src/fusionpbx-install.sh/ubuntu/resources && ./letsencrypt.sh
EXAMPLE
Domain Name: fpbx.arcadeparty.lan
Email Address: [email protected]
Go to Accounts > Users
Click on ADD
EXAMPLE
Username: pbxadmin
Password: P@ssWord!123
Confirm Password: P@ssWord!123
Email: [email protected]
Language: English - United States [en-us]
Time Zone: America/New_York
First Name: John
Last Name: Smith
Organization: arcadeparty
Groups: superadmin
Go to Advanced > Domains
Click on ADD
EXAMPLE
Name: fpbx.arcadeparty.lan
Description: Main domain
Go to Advanced > Access Controls
Open providers
For Nodes:
EXAMPLE
Type: allow
CIDR: 192.168.1.0/24
Description: VoIPin
Go to Accounts > Gateways
Click on ADD
EXAMPLE
Gateway: Primary GW
Username: 5596916644
Password: P@ssWord!123
From User:
From Domain:
Proxy: 64.136.174.30
Realm: 64.136.174.30
Expire Seconds: 800
Register: False
Retry Seconds: 30
Context: public
Profile: external
Description: primary gateway
Secondary gateway is optional
EXAMPLE
Gateway: Secondary GW
Username: 5596916644
Password: P@ssWord!123
From User:
From Domain:
Proxy: 64.136.173.22
Realm: 64.136.173.22
Expire Seconds: 800
Register: False
Retry Seconds: 30
Context: public
Profile: external
Description: Secondary gateway
Go to Applications > Recordings
Click on ADD and choose your WAV audio file
Click on UPLOAD
Go to Applications > IVR Menus
Click on ADD
EXAMPLE
Name: Generic IVR
Extension: 8000
Language: en-us callie
Greet Long: your WAV audio file
Greet Short:
Options:
Timeout: 3000
Exit Action: Hangup
Direct Dial: True
Ring Back:
Caller ID Name Prefix:
Context: fpbx.arcadeparty.lan
Description: generic ivr menu
Go to Dialplan > Destinations
Click on ADD
EXAMPLE
Type: Inbound
Country Code: your country calling code
Destination: 5596916644
Caller ID Name:
Caller ID Number:
Context: Public
Conditions:
Actions: 8000 Generic IVR
User:
Group:
Caller ID Name Prefix:
Record:
Hold Music: your WAV audio file
Distinctive Ring:
Account Code:
Usage: Voice
Domain: fpbx.arcadeparty.lan
Order: 100
Description: DID01
Go to Dialplan > Outbound Routes
Click on ADD
EXAMPLE
Gateway: Primary GW
Alternate 1: Secondary GW
Alternate 2: Tertiary GW
Dialplan Expression: your country region
Prefix: your country calling code
Limit:
Account Code:
Toll allow:
PIN Numbers: False
Order: 100
Enabled: True
Description: outbound route01
Go to Accounts > Extensions
Click on IMPORT
For Data you can use the template below with your preferences
extension,password,effective_caller_id_name,effective_caller_id_number,outbound_caller_id_name,outbound_caller_id_number,hold_music,user_context,description,enabled
1000,1000,Dipper Pines,1000,arcadeparty,1234567890,default,192.168.1.126,"1000 ext",true
1001,1001,Mabel Pines,1001,arcadeparty,1234567890,default,192.168.1.126,"1001 ext",true
1002,1002,Wendy Corduroy,1002,arcadeparty,1234567890,default,192.168.1.126,"1002 ext",true
1003,1003,Stanley Pines,1003,arcadeparty,1234567890,default,192.168.1.126,"1003 ext",true
Go to Accounts > Extensions
Click on ADD
EXAMPLE
Extension: 1000
Range: 1
Voicemail Password: 1000
Account Code:
Device Provisioning:
Effective Caller ID Name: Dipper Pines
Effective Caller ID Number: 1000
Outbound Caller ID Name: arcadeparty
Outbound Caller ID Number: 1234567890
Emergency Caller ID Name:
Emergency Caller ID Number:
Directory Full Name: Dipper Pines
Directory Visible: True
Directory Extension Visible: True
Max Registrations:
Limit Max: 5
Limit Destination:
Voicemail Enabled:
Voicemail Mail To :
Transcription Enabled: False
Voicemail File: Audio File Attachment
Voicemail Keep Local: True
Missed Call:
Toll Allow:
Call Timeout: 30
Call Group:
Call Screen: False
Record: Disabled
Hold Music: Default
Type: Default
Domain:
Context:
Description: ext 4000
Go to Dialplan > Dialplan Manager
In the searchbar, Search for bind
Select bind_digit_action
Click on COPY then click CONTINUE
Open the copy of bind_digit_action
EXAMPLE
Name: custom_bind_action
Number:
Hostname:
Context: global
Continue: True
Order: 085
Destination: False
Domain: Global
Enabled: True
Description: custom bind action
local,*7,exec:execute_extension,park+7000 XML ${context},${bind_target},${bind_target}
Set Tag to Action
Set Type to bind_digit_action
Set Order to 52
Go to Dialplan > Dialplan Manager
In the searchbar, Search for park
for valet_park set it to False by clicking on True
Select valet_park_in and valet_park_out
Click on COPY then click CONTINUE
Open the copy of valet_park_in
EXAMPLE
Name: custom_park_in
Number: 7000
Hostname:
Context: global
Continue: False
Order: 470
Destination: False
Domain: Global
Enabled: True
Description: custom park in
^(park\+)?(7000)$
7000@${domain_name} auto in 7001 7099
for valet_announce_slot=disable under Enabled set it to False
Click on SAVE
Go to Dialplan > Dialplan Manager
In the searchbar, Search for park
Open the copy of valet_park_out
EXAMPLE
Name: custom_park_out
Number: 7001-7099
Hostname:
Context: global
Continue: False
Order: 475
Destination: False
Domain: Global
Enabled: True
Description: custom park out
^(?:park\+)?(70[0-9][0-9])$
7000@${domain_name} $1
Go to Dialplan > Dialplan Manager
In the searchbar, Search for page
Select page-extension
Click on COPY then click CONTINUE
Open the copy of page-extension
EXAMPLE
Name: custom-page-extension
Number: 8[ext]
Hostname:
Context:
Continue: False
Order: 250
Destination: False
Domain:
Enabled: True
Description: custom page extension
^\8(\d{2,7})$
for pin_number= under Enabled set it to False
Click on SAVE
Go to Dialplan > Dialplan Manager
In the searchbar, Search for page
For page-extension set it to False by clicking on True
cd /etc/fusionpbx
mv config.conf config1.conf
cat config1.conf | grep password
Errors like ERR_CONNECTION_REFUSED can be fixed by reverting all SSL changes to default
rm -rf /usr/local/sbin/dehydrated && rm -rf /usr/src/dehydrated && rm -rf /etc/dehydrated && rm -rf /usr/src/dns-01-manual && rm -rf /var/www/dehydrated && rm -rf /etc/nginx/sites-available/fusionpbx && touch /etc/nginx/sites-available/fusionpbx
nano /etc/nginx/sites-available/fusionpbx
Copy paste the following fusionpbx nginx config file:
server {
listen 127.0.0.1:80;
server_name 127.0.0.1;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
client_max_body_size 80M;
client_body_buffer_size 128k;
location / {
root /var/www/fusionpbx;
index index.php;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
#fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/fusionpbx$fastcgi_script_name;
}
# Allow the upgrade routines to run longer than normal
location = /core/upgrade/index.php {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
#fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/fusionpbx$fastcgi_script_name;
fastcgi_read_timeout 15m;
}
# Disable viewing .htaccess & .htpassword & .db & .git
location ~ .htaccess {
deny all;
}
location ~ .htpassword {
deny all;
}
location ~^.+.(db)$ {
deny all;
}
location ~ /.git/ {
deny all;
}
}
server {
listen 80;
server_name fusionpbx;
#redirect letsencrypt to dehydrated
location ^~ /.well-known/acme-challenge {
default_type "text/plain";
auth_basic "off";
alias /var/www/dehydrated;
}
#rewrite rule - send to https with an exception for provisioning
if ($uri !~* ^.*(provision|xml_cdr).*$) {
rewrite ^(.*) https://$host$1 permanent;
break;
}
#REST api
if ($uri ~* ^.*/api/.*$) {
rewrite ^(.*)/api/(.*)$ $1/api/index.php?rewrite_uri=$2 last;
break;
}
#algo
rewrite "^.*/provision/algom([A-Fa-f0-9]{12})\.conf" /app/provision/?mac=$1&file=algom%7b%24mac%7d.conf last;
#mitel
rewrite "^.*/provision/MN_([A-Fa-f0-9]{12})\.cfg" /app/provision/index.php?mac=$1&file=MN_%7b%24mac%7d.cfg last;
rewrite "^.*/provision/MN_Generic.cfg" /app/provision/index.php?mac=08000f000000&file=MN_Generic.cfg last;
#grandstream
rewrite "^.*/provision/cfg([A-Fa-f0-9]{12})(\.(xml|cfg))?$" /app/provision/?mac=$1;
rewrite "^.*/provision/pb/([A-Fa-f0-9]{12})/phonebook\.xml$" /app/provision/?mac=$1&file=phonebook.xml;
#grandstream-wave softphone by ext because Android doesn't pass MAC.
rewrite "^.*/provision/([0-9]{5})/cfg([A-Fa-f0-9]{12}).xml$" /app/provision/?ext=$1;
#aastra
rewrite "^.*/provision/aastra.cfg$" /app/provision/?mac=$1&file=aastra.cfg;
#rewrite "^.*/provision/([A-Fa-f0-9]{12})(\.(cfg))?$" /app/provision/?mac=$1 last;
#yealink
#rewrite "^.*/provision/(y[0-9]{12})(\.cfg|\.boot)?$" /app/provision/index.php?file=$1$2;
rewrite "^.*/provision/(y[0-9]{12})(\.cfg)?$" /app/provision/index.php?file=$1.cfg;
rewrite "^.*/provision/([A-Fa-f0-9]{12})(\.(xml|cfg))?$" /app/provision/index.php?mac=$1 last;
#polycom
rewrite "^.*/provision/000000000000.cfg$" "/app/provision/?mac=$1&file={%24mac}.cfg";
#rewrite "^.*/provision/sip_330(\.(ld))$" /includes/firmware/sip_330.$2;
rewrite "^.*/provision/features.cfg$" /app/provision/?mac=$1&file=features.cfg;
rewrite "^.*/provision/([A-Fa-f0-9]{12})-sip.cfg$" /app/provision/?mac=$1&file=sip.cfg;
rewrite "^.*/provision/([A-Fa-f0-9]{12})-phone.cfg$" /app/provision/?mac=$1;
rewrite "^.*/provision/([A-Fa-f0-9]{12})-registration.cfg$" "/app/provision/?mac=$1&file={%24mac}-registration.cfg";
rewrite "^.*/provision/([A-Fa-f0-9]{12})-directory.xml$" "/app/provision/?mac=$1&file={%24mac}-directory.xml";
#cisco
rewrite "^.*/provision/file/(.*\.(xml|cfg))" /app/provision/?file=$1 last;
#Escene
rewrite "^.*/provision/([0-9]{1,11})_Extern.xml$" "/app/provision/?ext=$1&file={%24mac}_extern.xml" last;
rewrite "^.*/provision/([0-9]{1,11})_Phonebook.xml$" "/app/provision/?ext=$1&file={%24mac}_phonebook.xml" last;
#Vtech
rewrite "^.*/provision/VCS754_([A-Fa-f0-9]{12})\.cfg$" /app/provision/?mac=$1;
rewrite "^.*/provision/pb([A-Fa-f0-9-]{12,17})/directory\.xml$" /app/provision/?mac=$1&file=directory.xml;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
client_max_body_size 80M;
client_body_buffer_size 128k;
location / {
root /var/www/fusionpbx;
index index.php;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
#fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/fusionpbx$fastcgi_script_name;
}
# Allow the upgrade routines to run longer than normal
location = /core/upgrade/index.php {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
#fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/fusionpbx$fastcgi_script_name;
fastcgi_read_timeout 15m;
}
# Disable viewing .htaccess & .htpassword & .db & .git
location ~ .htaccess {
deny all;
}
location ~ .htpassword {
deny all;
}
location ~^.+.(db)$ {
deny all;
}
location ~ /.git/ {
deny all;
}
}
server {
listen 443 ssl;
server_name fusionpbx;
ssl_certificate /etc/ssl/certs/nginx.crt;
ssl_certificate_key /etc/ssl/private/nginx.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!ADH:!MD5:!aNULL;
#ssl_dhparam
#redirect letsencrypt to dehydrated
location ^~ /.well-known/acme-challenge {
default_type "text/plain";
auth_basic "off";
alias /var/www/dehydrated;
}
#REST api
if ($uri ~* ^.*/api/.*$) {
rewrite ^(.*)/api/(.*)$ $1/api/index.php?rewrite_uri=$2 last;
break;
}
#message media
rewrite "^/app/messages/media/(.*)/(.*)" /app/messages/message_media.php?id=$1&action=download last;
#algo
rewrite "^.*/provision/algom([A-Fa-f0-9]{12})\.conf" /app/provision/?mac=$1&file=algom%7b%24mac%7d.conf last;
#mitel
rewrite "^.*/provision/MN_([A-Fa-f0-9]{12})\.cfg" /app/provision/index.php?mac=$1&file=MN_%7b%24mac%7d.cfg last;
rewrite "^.*/provision/MN_Generic.cfg" /app/provision/index.php?mac=08000f000000&file=MN_Generic.cfg last;
#grandstream
rewrite "^.*/provision/cfg([A-Fa-f0-9]{12})(\.(xml|cfg))?$" /app/provision/?mac=$1;
rewrite "^.*/provision/pb/([A-Fa-f0-9]{12})/phonebook\.xml$" /app/provision/?mac=$1&file=phonebook.xml;
#grandstream-wave softphone by ext because Android doesn't pass MAC.
rewrite "^.*/provision/([0-9]{5})/cfg([A-Fa-f0-9]{12}).xml$" /app/provision/?ext=$1;
#aastra
rewrite "^.*/provision/aastra.cfg$" /app/provision/?mac=$1&file=aastra.cfg;
#rewrite "^.*/provision/([A-Fa-f0-9]{12})(\.(cfg))?$" /app/provision/?mac=$1 last;
#yealink
#rewrite "^.*/provision/(y[0-9]{12})(\.cfg|\.boot)?$" /app/provision/index.php?file=$1$2;
rewrite "^.*/provision/(y[0-9]{12})(\.cfg)?$" /app/provision/index.php?file=$1.cfg;
rewrite "^.*/provision/([A-Fa-f0-9]{12})(\.(xml|cfg))?$" /app/provision/index.php?mac=$1 last;
#polycom
rewrite "^.*/provision/000000000000.cfg$" "/app/provision/?mac=$1&file={%24mac}.cfg";
#rewrite "^.*/provision/sip_330(\.(ld))$" /includes/firmware/sip_330.$2;
rewrite "^.*/provision/features.cfg$" /app/provision/?mac=$1&file=features.cfg;
rewrite "^.*/provision/([A-Fa-f0-9]{12})-sip.cfg$" /app/provision/?mac=$1&file=sip.cfg;
rewrite "^.*/provision/([A-Fa-f0-9]{12})-phone.cfg$" /app/provision/?mac=$1;
rewrite "^.*/provision/([A-Fa-f0-9]{12})-registration.cfg$" "/app/provision/?mac=$1&file={%24mac}-registration.cfg";
rewrite "^.*/provision/([A-Fa-f0-9]{12})-directory.xml$" "/app/provision/?mac=$1&file={%24mac}-directory.xml";
#cisco
rewrite "^.*/provision/file/(.*\.(xml|cfg))" /app/provision/?file=$1 last;
#Escene
rewrite "^.*/provision/([0-9]{1,11})_Extern.xml$" "/app/provision/?ext=$1&file={%24mac}_extern.xml" last;
rewrite "^.*/provision/([0-9]{1,11})_Phonebook.xml$" "/app/provision/?ext=$1&file={%24mac}_phonebook.xml" last;
#Vtech
rewrite "^.*/provision/VCS754_([A-Fa-f0-9]{12})\.cfg$" /app/provision/?mac=$1;
rewrite "^.*/provision/pb([A-Fa-f0-9-]{12,17})/directory\.xml$" /app/provision/?mac=$1&file=directory.xml;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
client_max_body_size 80M;
client_body_buffer_size 128k;
location / {
root /var/www/fusionpbx;
index index.php;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
#fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/fusionpbx$fastcgi_script_name;
}
# Allow the upgrade routines to run longer than normal
location = /core/upgrade/index.php {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
#fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/fusionpbx$fastcgi_script_name;
fastcgi_read_timeout 15m;
}
# Disable viewing .htaccess & .htpassword & .db & .git
location ~ .htaccess {
deny all;
}
location ~ .htpassword {
deny all;
}
location ~^.+.(db)$ {
deny all;
}
location ~ /.git/ {
deny all;
}
}
sudo systemctl restart nginx
Still not working? try install script (there should be no data loss when reinstalling)
cd /usr/src/fusionpbx-install.sh/ubuntu && ./install.sh
Open-source: FusionPBX is open-source software, which means it is free to use and can be modified to suit specific needs.
Scalable: FusionPBX can be used to build small PBX systems or large enterprise-level solutions, making it a versatile option for businesses of all sizes.
Feature-rich: FusionPBX provides a wide range of features, including call routing, voicemail, IVR, and call recording, as well as support for various telephony protocols such as SIP, IAX, and WebRTC.
Web-based interface: FusionPBX provides a web-based graphical user interface (GUI) that makes it easy to manage and configure the system, even for users with little or no technical knowledge.
Add-ons and Plugins: FusionPBX has an extensive set of add-ons and plugins which enables to add more features and capabilities to the PBX, such as call center features, faxing, conferencing, and others.
Easy to install and maintain: The installation process of FusionPBX is straightforward and well-documented, and the system is designed to be easy to maintain and update.
Cost-effective: Because FusionPBX is open-source and free to use, it can be a cost-effective option for businesses, organizations, and individuals who want to set up a feature-rich telephony system without the need for a proprietary, expensive solution.
Security: FusionPBX is built on top of FreeSWITCH and it has the same security features and practices, which is a robust and secure telephony platform.
Flexible: FusionPBX allows you to customize your system to your needs by providing a wide range of settings, options, and configurations.
Community Support: FusionPBX has a large and active community that provides support and shares knowledge, which can be a great help if you encounter any issues or have questions about the software.
sudo apt-add-repository ppa:ansible/ansible
sudo apt update && sudo apt install ansible
cd /etc/ansible/
nano ansible.cfg
[defaults]
inventory=hosts
host_key_checking=false
sudo nano /etc/ansible/hosts
[master]
192.168.x.x # or hostname
[nodes]
192.168.x.x # or hostname
[master:vars]
ansible_ssh_user=master
ansible_ssh_pass=master
[nodes:vars]
ansible_ssh_user=myusername
ansible_ssh_pass=MysuporS3cretP@ass
Test the connection
ansible all -m ping
cd /etc/ansible/
mkdir playbooks && cd "$_"
nano apt-update.yml
- name: Perform apt update
hosts: all
become: yes
tasks:
- name: Update apt cache
apt:
update_cache: yes
register: apt_update_result
- name: Display apt update result
debug:
var: apt_update_result
The following apt-update.yml is a example that will send a webhook message to discord
- name: Perform apt update
hosts: all
become: yes
tasks:
- name: Update apt cache
apt:
update_cache: yes
register: apt_update_result
- name: Display apt update result
debug:
var: apt_update_result
- name: Get current timestamp
set_fact:
timestamp: "{{ ansible_date_time.iso8601 }}"
- name: Send message to Discord channel
community.general.discord:
webhook_id: "12345678901234567890"
webhook_token: "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
username: Ansible
avatar_url: "https://i.imgflip.com/5o55va.png"
embeds:
- title: "APT Update Completed"
description: "At server: {{ inventory_hostname }}"
color: 0x0dc300
footer:
text: "Author: Ansible"
image:
url: "https://media.tenor.com/7kYaaqzfDG0AAAAd/yes-guy.gif"
timestamp: "{{ ansible_date_time.iso8601 }}"
when: apt_update_result.changed
ansible-playbook apt-update.yml
Make sure you have python3 and pip installed
sudo apt install software-properties-common
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt install python3.10
sudo apt install python3-pip
python3 -m pip install --user ansible
python3 -m pip install --upgrade --user ansible
cd /home/myusername/
mkdir ansible && cd "$_"
nano ansible.cfg
[defaults]
inventory=hosts
host_key_checking=false
nano hosts
[master]
192.168.x.x # or hostname
[nodes]
192.168.x.x # or hostname
[master:vars]
ansible_ssh_user=master
ansible_ssh_pass=master
[nodes:vars]
ansible_ssh_user=myusername
ansible_ssh_pass=MysuporS3cretP@ass
Test the connection
ansible all -m ping
sudo apt install unzip
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform
This is a example container just so you can see how powerfull and easy terraform is
cd /home/myusername/terraform
mkdir homepage && cd "$_"
nano homepage.tf
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "3.0.2"
}
}
}
provider "docker" {}
resource "docker_container" "homepage" {
image = "ghcr.io/benphelps/homepage:latest"
name = "hpage"
ports {
internal = 3000
external = 8101
}
restart = "unless-stopped"
volumes {
container_path = "/app/config"
host_path = "/home/myusername/terraform/homepage/config"
}
volumes {
container_path = "/app/public/icons"
host_path = "/home/myusername/terraform/homepage/icons"
}
volumes {
container_path = "/app/public/images"
host_path = "/home/myusername/terraform/homepage/images"
}
volumes {
container_path = "/var/run/docker.sock"
host_path = "/var/run/docker.sock"
read_only = true
}
}
terraform init
terraform apply
curl -o setup-repos.sh https://raw.githubusercontent.com/webmin/webmin/master/setup-repos.sh
sh setup-repos.sh
Replace NEW_PORT_NUMBER with any port you like
sudo sed -i 's/^port=.*/port=NEW_PORT_NUMBER/' /etc/webmin/miniserv.conf && sudo systemctl restart webmin