The SMS tab has one control — a "Forward to URL" checkbox and field, with
SAVE/RETURN buttons where RETURN discards. The instructions described a
destination dropdown that isn't there. Also flags that the generated URLs are
long (~90 chars relay, ~150+ direct) and worth re-opening the tab to confirm
they saved whole.
Adds a provider-risk section: the realistic way to lose the number is account
action or a lapsed balance rather than the company folding, so keep the
balance small, save a recent invoice offline (porting out needs a signed LOA
plus the latest bill, which you can't download once an account is closed),
and note that Anveo states it does not block port-outs.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NAddJGE1G6eGaPzmScG5Vh
New service for one narrow job — getting SMS verification codes sent to a
VoIP number onto a phone with no SIM. Deliberately not a texting app: no
outbound path (Anveo Direct has none; that needs an Anveo Retail account, and
a free texting app covers sending), and messages arrive as push notifications
rather than being routed into Asterisk as SIP MESSAGE, since a code you read
and type is better served by a notification than a softphone chat thread.
Two modes, both driven entirely from the provider's "forward SMS to URL" box:
- direct — the provider calls ntfy itself; nothing installed here. ntfy
accepts GET publishing at /{topic}/(publish|send|trigger) with message and
title as query params, and auth via ?auth= holding base64url (unpadded) of
the literal "Bearer <token>" — confirmed against ntfy's server.go and
server_auth.go rather than its docs.
- relay — a stdlib systemd service, Caddy-fronted on its own domain with no
Authelia (the provider can't log in; a random 32-char token in the path is
the secret). Buys two things direct mode can't have: an unescaped "&" in a
message body survives intact, because the relay takes everything after the
last message= verbatim instead of parse_qs — which is why the generated URL
always puts the message placeholder last — and no ntfy credentials sit in a
third party's web portal.
Verification codes are bearer credentials, so: a 24-char random topic name
(the repo's ntfy defaults to auth-default-access: read-write, making the topic
name the read credential), constant-time token compare, a 60/min rate limit,
and the relay logs sender/recipient/length but never the message body.
The Anveo guide gains a section covering the two things that actually decide
whether codes arrive: short-code support (Anveo has it, unusually — VoIP.ms
does not except for Google) and Anveo's carrier-sourced *mobile* DIDs, which
are classified as mobile in the lookups that reject VoIP numbers at signup.
Also documents MMS and group texts being out of reach, and why the native
Messages app never sees any of this.
Verified against a stub ntfy: plain OTP, encoded "&", unencoded "&", "+" as
space, wrong token (404), missing message (400) and the rate limit (57x204
then 429) all behave; both installer modes were run end to end in a sandbox
and their generated URLs, settings files and READMEs checked.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NAddJGE1G6eGaPzmScG5Vh
services/asterisk-digital-ocean.sh was a near-verbatim copy of
services/asterisk.sh — same vendor refresh, compose template, messaging
dialplan, presence alerts, UFW rules and dashboard/trunk chaining, with the
helper functions renamed _asterisk_do_*. Two copies meant every fix had to
land twice, and several never did.
There is now one `asterisk` service. It reads the DigitalOcean metadata
service and asks either way (so a droplet with metadata blocked, or another
provider's public VM, can still opt in), then gates the genuinely
droplet-specific behaviour on that one answer: swapfile for low-RAM plans,
public-FQDN-only setup with no LAN/VLAN prompts, a Caddy site block pinned
to that FQDN, the remote-Authelia option, and the doctl Cloud Firewall.
Two things that were droplet-only for no real reason now apply everywhere:
the entrypoint patch that writes security-level events to logs/full, and
the logrotate config for that file. Without them the Security Dashboard's
Security Log tab and CrowdSec's Asterisk acquisition were silently empty on
every home/LAN install; crowdsec.sh now detects either install directory.
Existing droplets are left alone: an install at ~/docker/asterisk-digital-ocean
keeps its directory and easy-asterisk-do container names, since its Caddyfile
block, UFW rules, Cloud Firewall, CrowdSec acquisition and PSTN trunk all
name those exactly. New installs use ~/docker/asterisk / easy-asterisk.
`sudo ./setup.sh asterisk-digital-ocean` still works via a new SERVICE_ALIAS
map in setup.sh, without a second menu entry.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NAddJGE1G6eGaPzmScG5Vh
The step 4 heading said "once per DID" and the intro said steps 3-7 repeat
per DID, both of which overstate the work. The body already noted the trunk
could be reused, but the heading is what gets read first - and it actively
misleads toward creating one trunk object per number.
One inbound SIP Trunk serves the whole account: the $[E164]$ placeholder is
substituted with each DID's own number at call time, and the Asterisk side
matches whatever arrives via _X. and resolves it through
pstn-personal-dids.conf. Same for the outbound Service Trunk in step 3,
which the body already flagged as skippable for DIDs 2+.
Rewrites the heading, adds an explicit up-front note on why one suffices,
and corrects the intro to name which steps actually repeat per number.
A group-owned personal DID is now working end to end against a real
inbound call: it rings every authorized group member simultaneously, first
to answer wins, and members whose own tier/allowed_numbers don't authorize
the caller are correctly skipped.
Updates the code comments that were written before that confirmation
existed (the Busy(15) block's "NOT yet confirmed live", and the group-ring
script's unverified-SHELL() note), and documents all four fixes plus the
"Commit Changes" caveat in the Anveo setup guide's bugs-fixed section so
the next person hitting one-ring-then-busy has the trail.
Also clears the guide's "Still open" section: the 2-number account cap no
longer applies, and the interactive walkthrough it described as unbuilt
was built (_pstn_anveo_walkthrough).
Documents the actual end-to-end sequence that got a real DID working
(account setup, DID ordering, both trunk objects, droplet configuration,
permission setup, testing), including the real confirmed values (the
$0.00388/min rate, the port-5060 SIP URI forwarding format, the two
separate trunk-object types) and a summary of every real bug hit and
fixed along the way. Linked from the existing planning-notes doc.