Repository navigation
Send vCons to vcon store
vcon.store is a hosted store for
vCons. This page sends the containers sipnab writes to it.
It uses sipnab --vcon-forward, the forwarder that
Deliver the spool to a store
describes.
The forwarder sends each container byte for byte: it does not change what sipnab wrote.
A capture carries personal data:
- telephone numbers,
- addresses,
- the headers your platform sets,
- with
--retain-audio, the call audio.
vcon.store is another party's system. Decide what may leave the machine first:
-
--redactreplaces identities, addresses and correlation identifiers with keyed tokens. It also withholds the audio.- It works on a capture file (
-I), not on a live capture.
- It works on a capture file (
- A redacted container carries no audio. Its
recordingDialog Object names the parties and has nobody. - A container exported without
--redactand with--retain-audiocarries the call audio and the identifiers the signaling carried, as captured. - What may you conclude lists what a container carries.
Export the calls from a capture file with their audio.
-
--retain-audiokeeps each call's audio whole, from the first frame. - It makes sipnab put the audio in its
recordingDialog Object. - The object names the parties when each audio channel came from the media
address and port that one party advertised in its own SDP.
- Otherwise the object has no
parties. That is the usual case when a media relay carries the audio.
- Otherwise the object has no
- This container is not redacted. It carries the audio and the identifiers as captured.
sipnab -N --no-cli-print -I calls.pcap --retain-audio \
--export-vcon-when "state == 'Completed'" --export-vcon-dir spoolsipnab prints one line for the directory:
Wrote 1 vCon container(s) to 'spool'.
Add --redact and remove --retain-audio. The same command then writes
redacted containers without audio.
vcon.store authenticates with a bearer token.
- Put the token alone in a file only you can read.
- The
vcon-storekind sends it asAuthorization: Bearer <token>.
# Run all of these, in order.
umask 077
printf '%s\n' "$VCON_STORE_TOKEN" > vcon-store.key$VCON_STORE_TOKEN is the token vcon.store issued you.
- The forwarder never prints it.
- The forwarder removes it from any answer it keeps.
- Instead of a file, the
SIPNAB_VCON_FORWARD_AUTHenvironment variable can hold the token.
The forwarder refuses a file that other users can read or write, and exits
2:
--vcon-forward-auth-file 'vcon-store.key' can be read or written by other users (mode 0644); chmod 600 it
Run chmod 600 vcon-store.key and start the forwarder again.
# Run all of these, in order.
STORE_URL=https://api.vcon.store
sipnab --vcon-forward spool --vcon-forward-kind vcon-store \
--vcon-forward-url "$STORE_URL" --vcon-forward-auth-file vcon-store.key \
--vcon-forward-once
echo "exit $?"--vcon-forward-kind vcon-store does two things:
- It adds
/v1/vconsto the base URL. - It forms the header from the token.
It does not change the container. The same settings can live in sipnab.toml:
[vcon_forward]
kind = "vcon-store"
url = "https://api.vcon.store"
auth_file = "/etc/sipnab/vcon-store.key"For each container the forwarder logs a delivered line with the store's
status and moves the file to spool/delivered. The log line has this form
(here from a run against a store on 127.0.0.1:18777):
INFO sipnab::app::vcon_forward: vCon forwarder watching 'spool', delivering to http://127.0.0.1:18777/v1/vcons
INFO sipnab::app::vcon_forward: delivered 1-1966_10.0.2.20-1cc03f180ff8a774.vcon.json: POST http://127.0.0.1:18777/v1/vcons answered 201; moved to 'spool/delivered'
With --vcon-forward-once, the exit status is:
-
0when the store accepted every container, or there was none; -
1when the store refused any container, or any is still waiting; -
3when the store answered401or403.
Without --vcon-forward-once, the forwarder polls the spool until you stop it.
A container the store refused is in spool/failed, with a .error.json
record beside it that holds the store's answer. To read the counts and those
answers without sending anything:
sipnab --vcon-spool-status spoolIt prints one JSON document. Trimmed:
{
…
"pending": 0,
"delivered": 1,
"failed": 1,
"failures": [
{
"file": "1-1966_10.0.2.20-1cc03f180ff8a774.vcon.json",
"record": {
"at": "2026-10-16T11:47:53Z",
"body": "{\"error\": \"vCon already exists\"}",
"body_truncated": false,
"file": "1-1966_10.0.2.20-1cc03f180ff8a774.vcon.json",
"method": "POST",
"reason": null,
"status": 409,
"url": "http://127.0.0.1:18777/v1/vcons"
}
}
],
…
}
A capture run with --mcp or --api answers the same through:
- the MCP tool
vcon_spool_status, -
GET /v1/vcon/spool.
vcon.store answers 409 to a POST of a uuid it already holds. By default
the forwarder treats that as a refusal:
- The container goes to
spool/failed. - The store's answer is in its
.error.jsonrecord. -
--vcon-forward-onceexits1.
The log line reads:
WARN sipnab::app::vcon_forward: refused 1-1966_10.0.2.20-1cc03f180ff8a774.vcon.json: POST http://127.0.0.1:18777/v1/vcons answered 409; moved to 'spool/failed' beside 1-1966_10.0.2.20-1cc03f180ff8a774.vcon.json.error.json
To replace the held copy instead, name the store's PUT endpoint with
--vcon-forward-replace-url. The forwarder then sends the container there
after the 409. {uuid} in the template becomes the container's uuid:
sipnab --vcon-forward spool --vcon-forward-kind vcon-store --vcon-forward-url https://api.vcon.store --vcon-forward-auth-file vcon-store.key --vcon-forward-replace-url 'https://api.vcon.store/v1/vcons/{uuid}'Replacing is off by default, because it overwrites what the store holds.
To send a container that is already in spool/failed again, move it back into
spool and run the forwarder with --vcon-forward-replace-url.
The forwarder retries every 5xx answer after a back-off and keeps the
container in spool meanwhile.
sipnab signs a container only when a [[vcon.rule]] asks it to:
-
sign_only = truewrites the signed form alone, a JWS with no encryption. See Sign without encrypting. -
encrypt_towrites a signed container, encrypted. See Encrypt what a rule writes.
The containers --export-vcon-dir writes, as on this page, carry no
signature. A signature that the store adds covers what the store received. It
is not sipnab's, and it does not make an observation from a tap a recording.
sipnab records no consent, and a container carries none.
sipnab --vcon-fetch reads a container back by its uuid, with the same key
file. The vcon-store kind:
- reads
/v1/vcons/{uuid}, - sends the key as
Authorization: Bearer <key>, - removes the
_metamember the store adds.
So the file holds the container alone:
sipnab --vcon-fetch 018bcfe5-6800-8a6b-a667-78f1c5213800 --vcon-fetch-kind vcon-store --vcon-fetch-url https://api.vcon.store --vcon-fetch-auth-file vcon-store.key --vcon-fetch-out fetchedThe fetcher writes fetched/<uuid>.vcon.json, mode 0600. When a file of that
name already exists, the fetcher skips that uuid and the run exits 1. Add
--vcon-fetch-overwrite to replace the file.
More: Fetch a stored vCon.
-
The forwarder exits
3and logsanswered 401.-
The token in
vcon-store.keyis wrong or expired. -
The forwarder moved no file. Every container is still in
spool. -
Fix the token and run it again. The log line reads:
ERROR sipnab::app::vcon_forward: vCon forwarder stopped: POST http://127.0.0.1:18777/v1/vcons answered 401 for 1-1966_10.0.2.20-1cc03f180ff8a774.vcon.json: "{"error":"unauthorized"}". A 401 refuses the credentials or the client for every container alike, so nothing more is sent and every container stays in the spool. Check the credential, and that nothing replaces the User-Agent: a Cloudflare front refuses some clients with a 403 whose body names error code 1010
-
-
The forwarder exits
3and logs403witherror code: 1010.- The Cloudflare front of the store refused the request's client.
- The forwarder sends
User-Agent: sipnab/<version>. Check that nothing between it and the store replaces that header. - It moved no file, so run it again once you fix that.
-
A container lands in
spool/failedwith status409andvCon already exists.- The store already holds that uuid (
--vcon-fetchreads it back). - Follow Replace a container the store already holds.
- The store already holds that uuid (
-
Every container lands in
spool/failedwith status400andextensions: Expected object, received array.- The store refuses
extensionsas the array of strings both vCon drafts define. - sipnab writes the array and the forwarder does not change it, so such a store does not accept sipnab's containers.
- The store refuses
-
A container stays in
spool, and the log saysanswered 500; will retry.- The store failed to process the request.
- The forwarder tries again after its back-off.
Website · Repository · Issues · Generated from docs/ — edit there, not here.
Getting started
- Installation
- First CLI Triage
- Glossary
- Cookbook
- Runnable Examples
- Real World Captures
- Troubleshooting
- Tuning Capture
- Encapsulations
- Rtpengine Relays
- Backers
Using the TUI
CLI & automation
- CLI Reference
- Error Messages
- Filter DSL
- Output Formats
- SIP Response Codes
- SIP Methods
- SIP Header Fields
- SIP Parameters
- SIP Lint Rules
- MOS and Codecs
Configuration
Integrations (API & MCP)
- REST API
- Prometheus Metrics
- Authentication
- MCP
- MCP Deployment
- MCP Across an Estate
- MCP Tools
- MCP Tools Core
- MCP Tools Signaling
- MCP Tools Captures
- MCP Tools Security
- MCP Tools Media
- MCP Tools Relay
- MCP Tools TFPS
- MCP Tools Server
- MCP Tools vCon
- MCP Tools TLS
- MCP Protocol
- Uprobe Walkthrough
- Capture SIP over TLS
- WASM Plugins
- vCon Export
- vCon Capture Stack
- G729 Decoding
Your SIP server
- Use OpenSIPS as the SIP Server
- Run sipnab beside OpenSIPS
- Use Kamailio as the SIP Server
- Run sipnab beside Kamailio
- Use Asterisk as the PBX
- Run sipnab beside Asterisk
- Use FreeSWITCH in the Voice Stack
- Run sipnab beside FreeSWITCH
Add to your voice stack
- Add a vCon Server
- Send vCons to a vCon Server
- Send vCons to vcon store
- Add TFPS
- Control TFPS from sipnab
- Ban SIP Scanners with fail2ban
- Feed fail2ban from sipnab
- Add rtpengine
- Name rtpengine Media with sipnab
- Add rtpproxy
- Name rtpproxy Media with sipnab
- Add Homer
- Connect sipnab to Homer
- Add Prometheus and Grafana
- Add sipnab Metrics to Prometheus
Development & internals
- Internals Index
- Internals Subsystem Guide
- Internals Invariants
- Internals Testing
- Internals Walkthroughs
- Internals Build CI Release
- Internals Profiling
- Internals Domain Primer
- Library API
- Benchmarks
- Fault Model
- Threat Model
- Assurance Case
- Architecture
- Internals Threading
- Internals TUI Testing
- Internals Zero Copy Payloads
- Internals Uprobe Capture
- Internals Rtpengine Control Plane
- Internals Relay Control Decoding
- Internals vCon Exporter
- Internals Operator Guide Notes
- Internals Postmortems
- Internals Code Map
- Internals Lint Rules
- Internals Encapsulation Decoding
- Internals MCP Design Notes
- Internals Metrics And Output Notes