# nmproxy {.lead} The command line, configuration file and log output of the relay that proxy mode sends to. ## Command line ```shell nmproxy -config nmproxy -version ``` `-config` is required to run the relay. `-version` prints the relay's release and the frame protocol version it uses, such as `nmproxy 0.1.0, frame protocol version 1`, and exits. A relay built with a plain `go build` reports its release as `dev`. `nmproxy` runs until it gets Ctrl+C or `SIGTERM`. It then sends the rows it still holds to Nominal, sets the end of each run whose execution is still sending, logs a `shutting down` line with totals, and exits. ## Configuration file The file is YAML. A key the relay doesn't know stops it at startup. Each release's archive has `nmproxy.example.yaml`, which describes every key. `listen` : Default `"0.0.0.0:15400"`. The UDP address and port to receive packets on, as `host:port`. `0.0.0.0` accepts packets on every network interface, and `127.0.0.1` only from the same computer. `profile` : Default `"default"`. The profile in Nominal's config file to read the API key and the instance's REST API base URL from, as its `token` and `base_url`. Runs go in the profile's `workspace_rid`, or in the organization's default workspace when it has none. It is the same file the block reads in direct mode, and Nominal's other clients too. [API keys setup](site:/quickstart/quickstart/api-keys-setup/) shows what the file holds. `profile_file` : Default `""`, the standard location in the home folder of the account running the relay: `~/.config/nominal/config.yml`, or `%USERPROFILE%\.config\nominal\config.yml` on Windows. The path of the config file to read `profile` from, when it is somewhere else. `allowed_datasets` : Default empty. The RIDs of the datasets the relay may write to. Data for any other dataset is dropped. When the list is empty the relay writes to any dataset the API key can, and warns at startup. `idle_timeout` : Default `5m`. How long a block can go quiet, as it does once its run ends, before the relay forgets its channel list. The relay's stream to a dataset stays open while it remembers any channel list for that dataset, so executions that follow each other within this time share one connection. A Go duration such as `30s` or `10m`, greater than zero. Leave the key out to use the default. `stats_interval` : Default `30s`. How often to log a [stats line](#stats). `0` turns it off, and a negative value stops the relay at startup. `log_level` : Default `info`. One of `debug`, `info`, `warn` or `error`. In a dry run, `debug` logs every row. `dry_run` : Default `false`. When `true`, the relay decodes and logs what arrives, and the runs it would make, without writing anything to Nominal. It then reads no profile and needs no `allowed_datasets`. A complete file: ```yaml listen: "0.0.0.0:15400" profile: "default" profile_file: "" allowed_datasets: - "" idle_timeout: 5m stats_interval: 30s log_level: "info" dry_run: false ``` ## Errors that stop the relay Each error is printed as `nmproxy: `. All but the two `receive failed` errors happen at startup. | Message | Cause | |---|---| | `reading : …` | The file named by `-config` doesn't exist or can't be read. | | `parsing : …` | The file isn't valid YAML, or has a key the relay doesn't know. | | `: listen is required` | `listen` is set to an empty string. | | `: profile is empty. Name a profile in your Nominal config file, or remove the key to use the one named default` | `profile` is set to an empty string, and `dry_run` isn't `true`. | | `finding the Nominal config file: …. Set profile_file to its path` | `profile_file` is empty, and the account running the relay has no home folder. | | `reading the Nominal config file : …. Create it with a profile holding your API key and base URL, or set profile_file to where yours is` | There is no config file at ``, or it can't be opened. | | `parsing the Nominal config file : …` | The config file isn't valid YAML. | | `the Nominal config file has no profile named "". Check profile, or add the profile to the file` | The file has profiles, but not that one. Profile names are case-sensitive. | | `profile "" in has no token. Add your API key to it as token` | The profile has no `token`, or it is `null`. | | `profile "" in has no base_url. Add your instance's API URL to it as base_url` | The profile has no `base_url`. It is the **API URL** on your organization's **API keys** page. | | `: idle_timeout cannot be negative` | `idle_timeout` is below zero. | | `: idle_timeout must be greater than zero. Remove it to use the default of 5 minutes` | `idle_timeout` is zero. | | `: stats_interval cannot be negative. Set it to 0 to turn the stats line off` | `stats_interval` is below zero. | | `: log_level "" is not one of debug, info, warn, error` | `log_level` has another value. | | `resolving "": …` | `listen` isn't a valid address. | | `listening on "": …` | The address can't be used, for example because another program has the port. | | `receive failed 100 times in a row: …` | The relay's UDP socket failed every read while it ran. | | `receive failed: …` | The relay's UDP socket closed while it ran. | ## Startup warnings `allowed_datasets is empty, so any sender that can reach the listening port can write to any dataset the API key can. List your dataset RIDs under allowed_datasets.` : The message says what to do. ` holds an API key and other accounts have access to it (mode ). Run chmod 600 on it.` : About Nominal's config file. Linux and macOS only. `could not enlarge the receive buffer, so the operating system may drop bursts of frames` : Packets arriving in bursts may be lost before the relay reads them, and show up as `gaps`. ## Log The relay logs one line per event to standard error, as `key=value` pairs: ``` time=