# Stream through a proxy {.lead} 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](https://github.com/nominal-io/nominal-simulink/releases). Each release has an archive per platform, named `nmproxy---`: 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](https://github.com/nominal-io/nominal-simulink), 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](site:/quickstart/quickstart/api-keys-setup/) shows, unless it's there already. Then create `nmproxy.yaml`: ```yaml allowed_datasets: - "" ``` `nmproxy` reads the profile named `default`. To read another, add `profile: ""`, and when the config file is somewhere else, `profile_file: ""`. 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: ":15400"`. [nmproxy](../ref/nmproxy.md) lists every setting. ## 3. Start it ```shell ./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](campaigns.md) 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=