Linux Fax Stack using Hylafax and t38modem
Find a file
2024-08-01 21:39:29 +02:00
README.md Update README 2024-08-01 21:39:29 +02:00

Linux Fax Stack Setup (HylaFax & SIP)

  • This guide is WIP
  • Ubuntu 20.04 LTS VM (VirtualBox, LXC?)
  • TODO: Test on Debian / RockPi / RaspberryPi
  • TODO: Test on Eventphone Infra

Setup t38modem

  • TODO: Package t38modem with service files and config

Opal

Build PTLib

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
  • PTLib will be installed in the /usr/local tree -> set PKG_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

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

cd t38modem-x.y.z/
make
sudo cp ./t38modem /usr/local/bin
  • t38modem can only find Opal if LD_LIBRARY_PATH and PTLIBPLUGINDIR are environment variables to the program

Init script

#!/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
		# - T38MODEM_STUN
		
		if [ -z ${T38MODEM_STUN+x} ]; then
			$STUN="--stun ${T38MODEM_STUN}"
		else
			$STUN=""
		fi

		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> ${STUN}"
		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
sudo chmod +x /etc/t38modem/bin/run
  • -t enables debugging
    • More t's is deeper debugging (e.g. -tttt)
  • 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
# /etc/t38modem/config
T38MODEM_SIP_USERNAME="USERNAME"
T38MODEM_SIP_PASSWORD="PASSWORD"
T38MODEM_SIP_SERVER="voip.example.com"
# T38MODEM_STUN="stun.example.com" # optional
  • Give only root access to the config
sudo chown root:root /etc/t38modem/config
sudo chmod 700 /etc/t38modem/config
  • 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: atd0123456789
      • If all works correctly you should be able to answer the phone and hear a single beep
    • 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
  • 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!

systemd 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 the service:
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 error about 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