Stream through a proxy#
Send the model’s data to nmproxy, a relay that writes it to Nominal, so the computer running
the model holds no API key and does no HTTPS work.
In proxy mode the block sends its rows as UDP packets to nmproxy, which can run on another
computer or on the same one. nmproxy holds the API key and writes the rows to Nominal. The
computer running the model needs only the dataset’s RID and the relay’s address. Use proxy mode
when that computer shouldn’t hold an API key, such as a shared test bench, or when it has no
processing time to spare for sending data.
computer running the model relay Nominal
Nominal Stream Sink ── UDP ──► nmproxy ── HTTPS ──►
(no API key) (API key)
1. Get nmproxy#
Download nmproxy from the latest release on the
releases page. Each release has an
archive per platform, named nmproxy-<version>-<os>-<arch>: a .zip for Windows on x86-64,
and a .tar.gz for Linux on x86-64 or ARM64 and for macOS on Apple silicon. Each archive holds
the nmproxy program and nmproxy.example.yaml, an example configuration to start from.
SHA256SUMS, beside the archives, has their checksums.
To build it from source instead, run go build ./cmd/nmproxy from the nmproxy folder of the
nominal-simulink repository, with Go 1.25 or
later.
2. Configure it#
nmproxy reads the API key and your instance’s API URL from a profile in Nominal’s config file,
the same file the block reads in direct mode. On the relay computer, signed in as the account
that will run nmproxy, create ~/.config/nominal/config.yml
(%USERPROFILE%\.config\nominal\config.yml on Windows) as
API keys setup shows, unless it’s there already.
Then create nmproxy.yaml:
allowed_datasets:
- "<dataset RID>"
nmproxy reads the profile named default. To read another, add profile: "<profile>", and
when the config file is somewhere else, profile_file: "<path>".
List every dataset the relay should write to under allowed_datasets. nmproxy doesn’t
authenticate senders, so without the list anything that can reach its port can write to any
dataset your API key can. Data for a dataset that isn’t listed is dropped, with the warning
refusing a dataset that is not in allowed_datasets.
Nominal’s config file holds your API key in plain text, so keep it out of version control and
shared folders. On Linux and macOS, nmproxy warns at startup unless only the file’s owner has
access to it (chmod 600).
nmproxy listens on UDP port 15400 on every network interface. To accept packets on one
interface only, set listen: "<interface address>:15400". nmproxy lists
every setting.
3. Start it#
./nmproxy -config nmproxy.yaml
nmproxy logs a listening line with its address, and keeps running until you press Ctrl+C.
4. Point the block at it#
In the block’s dialog, set Mode to Via proxy. Set Proxy host to the relay computer’s
name or IP address, in single quotes ('127.0.0.1' when it runs on the same computer), and
Proxy port to the port nmproxy listens on (15400 unless you changed it). Dataset RID
and the channel names stay as they were. The block reads no profile in proxy mode, and the dialog
greys out Profile and Profile file.
Run the model. nmproxy logs configuration registered with the dataset and the number of
channels, then session started. When the model stops, it logs session ended.
Create run works in proxy mode too, as
Run a campaign of simulations describes. The relay then creates the run with its
own profile and logs run created, and sets the run’s end and logs run ended when the model
stops.
5. Read the stats line#
Every 30 seconds, nmproxy logs a summary:
time=<time> level=INFO msg=stats configs=1 sessions=1 rows=30000 gaps=0 reorders=0 unknown_config=0 bad_frames=0 wrong_version=0 write_errors=0
The counts after sessions are since the previous summary. rows above 0 means data is reaching
the relay. gaps counts packets that went missing between the model and the relay, and
write_errors counts writes to Nominal that failed. nmproxy
describes every field.
The block’s own end-of-run warning covers only rows it couldn’t hand to the network. Anything lost after that shows up only in the relay’s log.
Check the connection without an API key#
A configuration file containing only dry_run: true makes nmproxy decode and log what
arrives, without writing anything to Nominal. A dry run reads no profile, so it needs no API key,
and no allowed_datasets. When the model starts sending, the log shows
stream opened (dry run: nothing will be written) with the dataset and the number of channels,
and with Create run on, run (dry run: not created) with the run’s title. Adding
log_level: debug logs every row.
When data doesn’t reach Nominal#
When rows stays at 0, packets aren’t reaching the relay. nmproxy with listen set to
127.0.0.1 accepts packets only from its own computer, so when the model runs elsewhere, use
the relay’s network address or leave listen unset. A firewall on the relay computer also has
to allow UDP on the port.
wrong_version above 0 means the blockset and nmproxy come from different releases.
nmproxy -version prints the frame protocol version the relay uses.
unknown_config rising while nothing is written means the relay never registered the block’s
channel list. Either the dataset isn’t in allowed_datasets, and the relay logs a
refusing a dataset that is not in allowed_datasets warning that names it, or the relay
couldn’t start writing to the dataset, and it logs could not open a stream for a new configuration
with the error. A malformed RID causes the second.
When rows climbs but write_errors does too, the relay’s write failed lines give Nominal’s
reason. Check the profile’s base_url and token, and the dataset RID, against the
API keys page and the dataset.
A run the relay couldn’t create or end shows as a could not create the run or
could not set the end of the run warning, with Nominal’s reason. The rows still reach the
dataset.