README.md |
Linux Fax Stack Setup (HylaFax & SIP)
Linux Fax Stack using Hylafax and t38modem.
THIS GUIDE IS WIP
This guide was created using information from the opalvoid wiki (http://wiki.opalvoip.org/index.php?n=Main.HomePage)
Softwarestack
ptlib
(legacy) library for doing a little bit of everything.
Opal
Voice codec used by e.g. mumble.
t38modem
Emulates a serial modem from SIP connetion
Hylafax
Enterprise grade software, managing physical and emulated modems.
Has some problems: https://github.com/lexbailey/compilerfax/blob/main/hylafax_is_broken
Operating Systems
Unfortunately this software stack uses a lot of legacy software. Because of this, this guide was only tested on specific software versions
Debian 12 Bookworm
For Debian 12, we´ll only install dependencies which are hard requirements. For this guide we'll use ptlib 2.18.6 and opal 3.18.6.
Installing Requirements
First we'll need some packages
apt-get install build-essential git wget pkg-config libssl-dev libsrtp2-dev libspandsp-dev -y
Download sourcecode
Versions:
- libpt (2.18.6) https://sourceforge.net/projects/opalvoip/files/v3.18 Cygni/Stable 6/
- opal (3.18.6) https://sourceforge.net/projects/opalvoip/files/v3.18 Cygni/Stable 6/
- t38mdem (4.6.2) https://github.com/hehol/t38modem/releases/tag/4.6.2
ptlib
./configure
make
make install
opal
./configure
make -j5
make runtest
make install
t38modem
If you are getting error about -1
not being able to be casted to a long unsigned int
due to -Wnarrowing
inside dle.cxx
, you can add -Wno-narrowing
after the CPPFLAGS
in the Makefile to disable this error
git clone https://github.com/hehol/t38modem
cd t38modem
make
If running the t38modem executable, you should run these commands
cp /usr/local/lib/libpt.so.2.18.6 /lib
cp /usr/local/lib/libopal.so.3.18.6 /lib
To install t38modem run
cp ./t38modem /usr/local/bin
Ubuntu 20.04 LTS
Was tested on Ubuntu 20.04 LTS VM (VirtualBox, LXC?)
You can relies heavily on http://wiki.opalvoip.org/index.php?n=Main.HomePage
Versions:
- libpt (2.18.6) https://sourceforge.net/projects/opalvoip/files/v3.18 Cygni/Stable 6/
- opal (3.18.6) https://sourceforge.net/projects/opalvoip/files/v3.18 Cygni/Stable 6/
- t38mdem (4.6.2) https://github.com/hehol/t38modem/releases/tag/4.6.2
Follow http://wiki.opalvoip.org/index.php?n=Main.BuildingPTLibUnix and http://wiki.opalvoip.org/index.php?n=Main.HomePage but
- Don't use
libavformat-dev
-> Compile error in Opal - Configure script needs
pkg-config
to be installed to find ptlib install - On SourceForge downloads
.tar.bz2
files for *nix
Build PTLib
- Version 2.18.6
- Dependency of Opal, bundled with Opal source code (SourceForge)
- http://wiki.opalvoip.org/index.php?n=Main.BuildingPTLibUnix
- TODO: Remove dependencies, most of them are optional
sudo apt install \
g++ git make autoconf libpcap-dev libexpat1-dev libssl-dev libsasl2-dev libldap2-dev \
unixodbc-dev liblua5.3-dev libv8-dev libncurses-dev libsdl2-dev \
libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev pkg-config
- PTLib will be installed in the
/usr/local
tree -> setPKG_CONFIG_PATH
to be findable (compile time) - Set
LD_LIBRARY_PATH
to find PTLib at compile and run time - Set
PTLIBPLUGINDIR
(compile and run time) - (To compile as static library:
./configure --disable-shared
)
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig # compile time
export LD_LIBRARY_PATH=/usr/local/lib # compile and run time
export PTLIBPLUGINDIR=/usr/local/lib/ptlib-x.y.z # compile and run time
cd ptlib-x.y.z/
./configure
make
sudo make install
Build Opal
- Version 3.18.6
- http://wiki.opalvoip.org/index.php?n=Main.BuildingOpalUnix
- Dont use
libavcodec-dev
-> Compile error - TODO: Remove dependencies, most of them are optional
sudo apt install \
libsrtp2-dev libgsm1-dev libspeex-dev libopus-dev libx264-dev \
libvpx-dev libtheora-dev libspandsp-dev dahdi
- (To compile as static library:
./configure --disable-shared
)
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig # compile time
export LD_LIBRARY_PATH=/usr/local/lib # compile and run time
export PTLIBPLUGINDIR=/usr/local/lib/ptlib-x.y.z:/usr/local/lib/opal-a.b.c # compile and run time
cd opal-a.b.c/
./configure
make
sudo make install
t38modem
- https://github.com/hehol/t38modem, Version 4.6.2
- https://github.com/T38Modem/t38modem could also be used, but seems to be not as maintained
- If you are getting error about
-1
not being able to be casted to along unsigned int
due to-Wnarrowing
insidedle.cxx
, you can add-Wno-narrowing
after theCPPFLAGS
in the Makefile to disable this error
cd t38modem-x.y.z/
make
sudo cp ./t38modem /usr/local/bin
- t38modem can only find Opal if
LD_LIBRARY_PATH
andPTLIBPLUGINDIR
are environment variables to the program
Configuring t38modem
Init script
- To automatically start t38modem, you need to create Systemd services, as well as start and stop scripts
- script is adapted from https://web.archive.org/web/20111231021042/https://www.foriamroot.org/hylafax-6-0-debian-or-ubuntu-t38modem-1-0-asterisk-1-6/
First we'll create the configuration directory under /etc
using sudo mkdir -p /etc/t38modem/bin/
.
Then create a file named /etc/t38modem/bin/run
using the following content.
It will be the script to manage the current status of t38modem.
#!/bin/bash
# /etc/t38modem/bin/run
export LD_LIBRARY_PATH=/usr/local/lib
export PTLIBPLUGINDIR=/usr/local/lib/ptlib-x.y.z:/usr/local/lib/opal-a.b.c # Adjust lib versions!
case "$1" in
start)
. /etc/t38modem/config
# defines
# - T38MODEM_SIP_USERNAME
# - T38MODEM_SIP_PASSWORD
# - T38MODEM_SIP_SERVER
COMMAND="t38modem -u T38modem --ptty +/dev/ttyT38-1 --sip-proxy ${T38MODEM_SIP_USERNAME}:${T38MODEM_SIP_PASSWORD}@${T38MODEM_SIP_SERVER} --sip-register ${T38MODEM_SIP_USERNAME}@${T38MODEM_SIP_SERVER},${T38MODEM_SIP_PASSWORD} --sip-listen udp\$:5060 --route t38:.*=sip:<dn>@${T38MODEM_SIP_SERVER} --route sip:.*=t38:<dn>"
echo "${COMMAND}"
exec $COMMAND > /dev/null 2>&1 &
PID=$!
echo "Starting t38modem with pid $PID (pidfile /run/t38modem.pid)"
echo $PID > /run/t38modem.pid
;;
stop)
if [ ! -f "/run/t38modem.pid" ]; then
echo "t38modem is not running! (/run/t38modem.pid does not exist)"
exit 1
fi
echo -n "Stopping t38modem pid: "
PID=`cat /run/t38modem.pid`
kill -9 $PID
rm /run/t38modem.pid
echo "${PID} Done"
;;
*)
echo "Usage: $0 {start|stop}"
exit 1
;;
esac
exit 0
And then we'll have to make it executable like this.
sudo chmod +x /etc/t38modem/bin/run
Quick script overview
- Using that script, it is possible to
start
orstop
the emulated modem. -t
enables debugging- More
t
's is deeper debugging (e.g.-tttt
)
- More
- You can of course run the t38modem command without this init script
- If t38modem says it was able to create the virtual modem but
/dev/ttyT38-1
is not available, you do not have sufficient permissions - Configuration is specified in
/etc/t38modem/config
Create the configuration file
Create a file using the following contents at /etc/t38modem/config
.
# /etc/t38modem/config
T38MODEM_SIP_USERNAME="USERNAME"
T38MODEM_SIP_PASSWORD="PASSWORD"
T38MODEM_SIP_SERVER="voip.example.com"
You should give only root access to the config.
sudo chown root:root /etc/t38modem/config
sudo chmod 700 /etc/t38modem/config
Testing your setup
- You can now communicate with your modem
/dev/ttyT38-1
, just as if it was a real Hayes compatible modem (https://www.computerhope.com/atcom.htm) - Test using minicom, configure it to point to our modem. Each command is initiated by a Return
- Dial a number:
- Get the attention of the modem:
at
->OK
- Dial:
atd[NUMBER]
, replace '[NUMBER]' using the number, you want to call - If all works correctly you should be able to answer the phone and hear a single beep
- Get the attention of the modem:
- Answer a call:
- Get the attention of the modem:
at
->OK
- Call the number of your modem
- ->
RING
- Answer the call:
ata
->CONNECT
- You should now hear your modem "talking" to you
- Get the attention of the modem:
- Dial a number:
- Pitfalls:
- If you are already connected to your SIP server it may not give proper response codes. My provider returns
500 Internal Server Error
- Test the command before running the init script!
- Do not try to used
ATO
to switch to a data connection, t38modem will returnERROR
. Thats hardcoded inpmodeme.cxx
invoid ModemEngineBody::HandleCmdRest(PString &resp)
. Dont let that hodld you back.
- If you are already connected to your SIP server it may not give proper response codes. My provider returns
systemd service
If you want to run a fax server, you can create a systemd service to let your emulated fax modem start automatically on system boot.
To do this you have to copy paste the following into /etc/systemd/system/t38modem.service
.
# /etc/systemd/system/t38modem.service
[Unit]
Description=t38modem
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/etc/t38modem/bin/run start
ExecStop=/etc/t38modem/bin/run stop
PIDFile=/run/t38modem.pid
KillMode=none
Restart=always
[Install]
WantedBy=multi-user.target
Enable and start the service using the following commands:
sudo systemctl daemon-reload
sudo systemctl enable t38modem.service
sudo systemctl start t38modem.service
Install HylaFax
-
Version 6
-
sudo apt install hylafax-server
- Set Postfix Configuration to Local only in dpkg-reconfigure menu
-
Run
sudo faxsetup
- Add new modem
- Enter correct modem port (
ttyT38-1
) - Enter dialing configuration
- Accept default configuration for everything else
- It should automatically detect it to be a
T38FAX
modem
-
Look at
man sendfax
to send faxes -
fgetty
(the service to receive faxes) should be enabled automatically -
Bugs:
- If you get some protocol errors, just let HylaFax do its thing. Fax over SIP is not stable at all in my experience
Cron
- Alias your fax admin account as
FaxMaster
(/etc/aliases
)
# /etc/aliases
# [...]
# HylaFax
FaxMaster: $USER # replace with fax admin account
- Add standard tasks to crontab file:
crontab -e
0 * * * * /usr/sbin/faxqclean
25 23 * * * sh /usr/sbin/faxcron | mail FaxMaster
FaxDispatch
TODO
- TODO: Test on Debian / RockPi / RaspberryPi
- TODO: Test on Eventphone Infra
- TODO: Package t38modem with service files and config