Skip to main content

BrightSign Proxy configuration

Some networks require devices to reach the internet through an HTTP proxy. This guide covers how to configure that proxy on a BrightSign player, which bypass entries signageOS needs, and how the behaviour differs between the two ways signageOS can run on BrightSign.

Before you start: which mode is the device running?​

The proxy is a device-level network setting — it is stored once in the player's network configuration, and every method below writes to that same place. What differs is which methods are available to you.

CoreApp / CloudControlSupervisor
What it isCoreApp runs as a BrightScript autorun plus an Applet HTML applicationCoreApp runs as a BrightSign OS extension (a Node.js process), with no BrightScript application of ours
BrightScript✅ available⛔ no autorun runs
Applet JS API✅ available⛔ applets are not supported
Custom Scripts✅ available (browser runtime)✅ available (nodejs runtime)
Always bypass the local addresses

Whichever method you use, localhost and 127.0.0.1 must not be routed through the proxy. CoreApp runs a local HTTP service on the player for file access, and sending that traffic to a proxy breaks content playback.

Required proxy bypass​

The bypass list is stored on the device alongside the proxy address, and every method below writes it.

nc.SetProxyBypass(["localhost", "127.0.0.1"])

From the management API the bypass list is the fifth argument of setManual():

await sos.management.proxy.setManual('proxy-server.domain.com', 83, '', '', ['localhost', '127.0.0.1']);

Add your own local hosts to the same list — for example an on-premise server or a local media source:

nc.SetProxyBypass(["localhost", "127.0.0.1", "media.internal.example.com"])
warning

The bypass list is written on every setManual() call, so omitting the fifth argument stores an empty one and clears whatever was on the device — including a list configured with BrightScript. Always pass the complete list you want the device to end up with. disable() clears the proxy and the bypass list together.

The Supervisor bypasses local addresses automatically

On the Supervisor, loopback (127.0.0.0/8, ::1), private ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7) and link-local addresses (169.254.0.0/16, fe80::/10) are always routed directly, whether or not they appear in the bypass list. The explicit entries above are still required for CoreApp, and are still worth setting so the configuration behaves the same in both modes.

Option 1 — BrightScript​

The traditional method, and the only one available before the device is connected to signageOS. Place this in your custom.brs hook or your own autorun:

nc = CreateObject("roNetworkConfiguration", 0)
nc.SetProxy("http://proxy-server.domain.com:83")
nc.SetProxyBypass(["localhost", "127.0.0.1"])
nc.Apply()

With a username and password:

nc = CreateObject("roNetworkConfiguration", 0)
nc.SetProxy("http://username:password@proxy-server.domain.com:83")
nc.SetProxyBypass(["localhost", "127.0.0.1"])
nc.Apply()

Apply() persists the setting, so it survives reboots and does not need to be re-applied on every start. See Integration of custom BrightScript for where to put this code.

tip

This writes the same device network configuration that the Supervisor reads, so a player provisioned with BrightScript and later switched to the Supervisor keeps its proxy.

Option 2 — Applet JS API​

From an applet you can read and change the proxy at runtime through sos.management.proxy:

// Set a proxy — note the port is a number here
await sos.management.proxy.setManual('proxy-server.domain.com', 83, '', '', ['localhost', '127.0.0.1']);

// With credentials
await sos.management.proxy.setManual('proxy-server.domain.com', 83, 'username', 'password', ['localhost', '127.0.0.1']);

// Inspect the current state
const enabled = await sos.management.proxy.isEnabled();
const connectedTo = await sos.management.proxy.getConnectedTo();
const bypassList = await sos.management.proxy.getBypassList();

// Remove the proxy and the bypass list
await sos.management.proxy.disable();

Pass the username and password exactly as they are. Characters that would need escaping in a URL are encoded when the value is stored and decoded again when the connection is opened.

The fifth argument is the bypass list, and it is written on every call — pass the complete list each time, as described in Required proxy bypass. Empty and whitespace-only entries are dropped before the list is stored.

Not available on the Supervisor

Applets do not run on the Supervisor. Use a Custom Script instead.

Option 3 — Custom Script​

Custom Scripts work in both modes, and are the supported way to configure a proxy on device remotely. The runtime depends on the mode: use nodejs for the Supervisor and browser for CoreApp / CloudControl. The script body itself is the same, because both runtimes expose sos.management.proxy.

{
"name": "brightsign-proxy",
"version": "1.0.0",
"description": "Configure the device HTTP proxy",
"dangerLevel": "high",
"platforms": {
"brightsign": {
"rootDir": "brightsign",
"mainFile": "setProxy.js",
"runtime": "nodejs"
}
},
"configDefinition": []
}
async function run() {
await sos.management.proxy.setManual('proxy-server.domain.com', 83, 'username', 'password', ['localhost', '127.0.0.1']);

// Report the result so you can see it in Box
const connectedTo = await sos.management.proxy.getConnectedTo();
const bypassList = await sos.management.proxy.getBypassList();
postResult(JSON.stringify({ connectedTo: connectedTo, bypassList: bypassList }, null, 2));
}

run();

To remove the proxy and the bypass list, call await sos.management.proxy.disable() instead.

Changing the proxy can disconnect the device

If you point a device at a proxy it cannot reach, you lose the management connection to it — and you then cannot send another script to undo it. Recovery requires DWS, the local network, or physical access.

Verify the proxy is reachable from the device's network first, and test on a single device before rolling out.

How CoreApp / CloudControl uses the proxy​

CoreApp runs as a BrightScript application together with an HTML application, and its parts reach the network in different ways:

  • The HTML application uses the player's own network stack, so it follows the device proxy and the bypass list automatically. This is exactly why localhost and 127.0.0.1 have to be bypassed — the local file service runs over HTTP on the player itself.
  • Content, firmware and application downloads, and screenshot uploads are transferred with curl using the configured proxy.

Things worth knowing:

  • The bypass list does not apply to file transfers. Downloads and uploads go through the proxy whenever one is configured, even for hosts you listed as bypassed. If you serve content from a local server, make sure the proxy can reach it.
  • BrightScript writes one network interface, the management API writes the device configuration. roNetworkConfiguration applies to the interface it was opened with, so a player that moves between Ethernet and Wi-Fi needs the proxy set for both. setManual() and disable() write the host configuration, which is not interface-specific.
  • setManual() replaces the bypass list. A call without the fifth argument stores an empty bypass list, so a device provisioned with BrightScript loses localhost and 127.0.0.1 and playback breaks. Pass the complete bypass list on every call.
  • Reboot after changing the proxy. File transfers pick up a new proxy on the next transfer, but the HTML application is given its proxy and bypass list once, when the widget is created, so the browser keeps the old settings until the device restarts.
tip

Set the proxy and the bypass list in one step — either both in BrightScript or both in a single setManual() call — and reboot afterwards. That is the most predictable way to provision a CoreApp device.

How the Supervisor uses the proxy​

The Supervisor is a Node.js process, and Node.js does not pick up the device proxy on its own. signageOS reads the device network configuration and routes its own traffic accordingly — the management connection, configuration requests, content and firmware downloads, and its own upgrades.

Things worth knowing:

  • Only HTTP proxies are supported. The proxy address must start with http://. That refers to the connection to the proxy; traffic through it stays encrypted. https:// proxy addresses are rejected.
  • Credentials are handled for you. Enter the username and password as-is, including characters such as @, : or $.
  • Only HTTPS and WSS traffic goes through the proxy. Plain http:// and ws:// targets are always connected to directly, whatever the proxy and bypass configuration say. HTTPS and WSS are tunnelled through the proxy with HTTP CONNECT.
  • Changes made through the management API apply immediately. The Supervisor re-reads the configuration as soon as setManual() or disable() succeeds. A proxy changed outside the management API — with BrightScript, or from DWS — is picked up within about a minute. Connections that are already open keep the previous route until they reconnect, so reboot the device if you need the switch to be immediate.
  • Bypass entries are honoured, including exact hostnames, domain suffixes (.internal.example.com), wildcards (*.internal.example.com), CIDR ranges (10.0.0.0/8), <local> for hostnames without a dot and * for everything — on top of the local addresses that are always direct.

Verifying the configuration​

  1. Check what the device has stored, from an applet or a Custom Script:
    await sos.management.proxy.getConnectedTo();
    await sos.management.proxy.getBypassList();
    getConnectedTo() reports the address without credentials — the username and password are removed before the value leaves the device, so http://proxy-server.domain.com:83 is the expected result even for a proxy that authenticates.
  2. Confirm the device is online in Box. When device sends telemetry you should also see connected proxy on Device Info page.
  3. If you control the proxy, its access log is the most reliable check: you should see CONNECT entries for the signageOS hosts shortly after the device boots.

Troubleshooting​

SymptomLikely cause
Device offline after setting a proxyThe proxy is unreachable from the device's network, or the credentials are wrong
Content does not play, device otherwise onlinelocalhost / 127.0.0.1 missing from the bypass list
Playback broke right after setting the proxy from the JS API or a Custom ScriptThe call omitted the bypass list, which replaced the existing one with an empty list — call setManual() again with localhost, 127.0.0.1 and your own local hosts
Bypass list is empty after setting the proxySame cause — setManual() writes the bypass list on every call, so it must always be passed in full
Downloads still fail from a local content serverOn CoreApp the bypass list does not apply to file transfers; the proxy must be able to reach that server
Proxy appears to be ignored on a Supervisor deviceThe CoreApp build predates Supervisor proxy support — update to the latest CoreApp release (check the version in DWS)
Some Supervisor traffic never reaches the proxyOnly HTTPS and WSS are proxied; plain http:// targets always connect directly
Change did not take effect immediatelyExisting connections keep the old route until they reconnect; reboot to force it

For Supervisor-specific diagnostics, see BrightSign Supervisor Troubleshooting.

Version requirements

Correct proxy configuration is enforced from CoreApp/CloudControl 2.1.0. The bypass list argument of setManual() and the getBypassList() method require CoreApp/CloudControl 2.6.0; on earlier versions the bypass list can only be set with BrightScript. For any version older than 2.1.0, please reach out to our support team for a technical guide.