USB Modems
Connect USB GSM modems to your server for SMS sending without an Android phone.
Overview
The Vendel modem agent is a lightweight Go binary that connects USB GSM modems to your Vendel instance. It receives message assignments in real-time via Server-Sent Events (SSE), sends SMS using AT commands, and reports delivery status back to the server.
Prerequisites
- A USB GSM modem with a SIM card inserted (any AT-compatible modem)
-
Serial port access — add your user to the
dialoutgroup:
Log out and back in for the group change to take effect.sudo usermod -aG dialout $USER - Go 1.21+ (only needed if building from source)
- An Vendel instance running and accessible from the agent host
Step 1: Create a modem device
In the Vendel dashboard, go to Devices and click Add Device. Select USB Modem as the device type, enter a name and the SIM card's phone number. Save the API key shown after creation — you'll need it to configure the agent.
Step 2: Get the agent
Option 1: Download pre-built binary
Download the latest release for your platform:
Linux x86_64
amd64 · .tar.gz
Linux ARM64
arm64 · .tar.gz
Linux ARM
armv7 · .tar.gz
macOS Intel
amd64 · .tar.gz
macOS Apple Silicon
arm64 · .tar.gz
Windows x86_64
amd64 · .zip
Windows ARM64
arm64 · .zip
Extract and install:
# Linux / macOS
tar -xzf vendel-modem-agent_*.tar.gz
sudo mv vendel-modem-agent /usr/local/bin/
# Windows — extract the .zip and add vendel-modem-agent.exe to your PATH Option 2: Build from source
Requires Go 1.21+:
git clone https://github.com/JimScope/vendel.git
cd vendel/modem-agent
go build -o vendel-modem-agent . Step 3: Configure
The agent uses two environment variables:
-
VENDEL_URL— Your Vendel server URL (default:http://localhost:8090) -
MODEMS— Comma-separated list of modem definitions in the formatapi_key:command_port[:notify_port]
The notify_port is optional and defaults to the command port
for single-port modems. Dual-port modems (like the Huawei E173) use
separate ports for commands and unsolicited notifications.
# Single modem
MODEMS=dk_abc123:/dev/ttyUSB0:/dev/ttyUSB1
# Multiple modems
MODEMS=dk_abc123:/dev/ttyUSB0:/dev/ttyUSB1,dk_xyz789:/dev/ttyUSB2:/dev/ttyUSB3 Step 4: Run
VENDEL_URL=https://app.vendel.cc MODEMS=dk_abc123:/dev/ttyUSB0:/dev/ttyUSB1 ./vendel-modem-agent Or use a .env file (copy from .env.example):
cp .env.example .env
# Edit .env with your values
./vendel-modem-agent Docker deployment
If you're already running Vendel with Docker Compose, you can run the
modem agent as an opt-in service instead of building from source. Add
these variables to your .env file:
# Modem agent (required when using --profile modem)
MODEMS=dk_abc123:/dev/ttyUSB0:/dev/ttyUSB1
# Host serial device to map into the container (default: /dev/ttyUSB0)
MODEM_DEVICE_0=/dev/ttyUSB0 Then start with the modem profile:
docker compose --profile modem up -d
The modem-agent container will wait for the Vendel app to be healthy
before starting, and connects to the backend via Docker internal DNS
(http://app:8090). The host serial device is mapped into
the container automatically.
View modem agent logs:
docker compose --profile modem logs -f modem-agent Systemd service
If you're not using Docker, you can run the agent as a systemd service for production use so it starts automatically on boot:
# /etc/systemd/system/vendel-modem-agent.service
[Unit]
Description=Vendel Modem Agent
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=vendel
Group=dialout
Environment=VENDEL_URL=https://app.vendel.cc
Environment=MODEMS=dk_abc123:/dev/ttyUSB0:/dev/ttyUSB1
ExecStart=/usr/local/bin/vendel-modem-agent
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target sudo systemctl daemon-reload
sudo systemctl enable --now vendel-modem-agent Multi-modem setup
The agent supports multiple modems simultaneously. Each modem runs
independently in its own goroutine with its own SSE connection and serial
port. List all modems in the MODEMS variable separated by
commas:
MODEMS=dk_key1:/dev/ttyUSB0:/dev/ttyUSB1,dk_key2:/dev/ttyUSB2:/dev/ttyUSB3 Each modem must have its own device registered in the dashboard with its own API key. Messages are distributed among all available devices (including Android phones) via round-robin.
Incoming SMS
The agent automatically monitors for incoming SMS on all connected
modems. Received messages are reported to Vendel and trigger your
configured webhooks with the sms_received event.
Supported modems
Any AT-compatible USB GSM modem should work. Tested models include:
- Huawei E173 / E1752 / E3531
- ZTE MF180 / MF190
- Alcatel MW40
- SIMCom SIM800 / SIM900 modules
- Quectel M95 / UC20 / EC25
If your modem is not listed but supports standard AT commands for SMS (AT+CMGS, AT+CMGR), it should work. Open an issue on GitHub if you encounter compatibility problems.