The VisionAppster Engine consists of a bunch of software modules that are available to all apps. The va-engine service that runs on the background is actually a VisionAppster app itself. It is started through va-run as any app could. In Linux, the init system (usually systemd) runs va-run directly. In Windows, the service control manager communicates with a service wrapper, va-engine-service.exe.

The app is called init.qml and stored in the init directory under the VisionAppster installation root. There is also an alternative app called api-init.qml that is intended for running a fixed set of apps and to publish their APIs.

Since the Engine lets one to install and run new components through the HTTP interface, it is extremely important to set up access control correctly. A failure in doing so will easily lead into a remote code execution vulnerability. Therefore, prefer api_init.qml for production use as it does not expose remote management APIs.

There are two ways the va-engine service can be configured: via command-line arguments or by modifying the init.qml or api_init.qml script. In command-line arguments, the first argument is always the path to the used init script. Additional supported arguments are documented in the init script. Operating systems differ in their ways of passing service start-up parameters.


In Linux, command-line arguments are given in a systemd unit file (/etc/systemd/system/va-engine.service) using the ExecStart variable. For example, to use api_init.qml:

# Rest of configuration omitted.

ExecStart=/opt/visionappster/bin/va-run /opt/visionappster/init/api_init.qml

If you need to edit the init scripts, they are placed in:

  • Tarball installer: /va-engine/overlay/opt/visionappster/init by default

  • Raspberry Pi and Docker: /opt/visionappster/init

  • Flatpak: Typing flatpak info -l com.visionappster.Builder will give you the root of the installed Flatpak. The init files are in files/opt/visionappster/init under the Flatpak root.

Reload the new configuration and restart the service:

sudo systemctl daemon-reload
sudo systemctl restart va-engine


In Windows, the service control manager reads service configuration from the registry. The easiest way to change start-up parameters is to use the sc service management tool to set the binPath variable. For example, to use api_init.qml:

sc config "VisionAppster Engine" ^
  binPath="C:\Program Files\VisionAppster\bin\va-engine-service.exe ..\init\api_init.qml"

The init files are stored under the VisionAppster installation directory, usually C:\Program Files\VisionAppster\init. To apply the new configuration you need to restart the service:

sc stop "VisionAppster Engine"
sc start "VisionAppster Engine"

Network interface🔗

The default behavior of the init.qml app is to bind the web server to the loopback interface only. This blocks all external connection attempts. api-init.qml binds to all available interfaces by default.

The web server can be bound to a specific interface or to all available interfaces. For example:

  • - Bind to IPv4 loopback only.

  • [::1]:2015 - Bind to IPv6 loopback only.

  • - Bind to all IPv4 interfaces.

  • [::]:2015 - Bind to all IPv6 interfaces.

  • - Bind to a specific IPv4 address.

The port number (2015) could be anything else, but some client software may assume the standard port.

Note that binding the server to a non-local interface makes it possible to access it from other computers. You may want to disable remote management (use api_init.qml) and/or use IP-based access control in this case.

The web server’s network interface can be changed on the command line using the webServer variable. For example, to allow access from remote computers, bind the web server to port 2015 on all IPv4 interfaces:


ExecStart=/opt/visionappster/bin/va-run /opt/visionappster/init/init.qml webServer=


sc config "VisionAppster Engine" ^
  binPath="C:\Program Files\VisionAppster\bin\va-engine-service.exe ..\init\init.qml webServer="

IP-based access control🔗

The web server supports IP subnet based access control. If no access control rules have been specified, requests from any IP will be accepted. Once a single rule has been set up, the default behavior changes to deny requests. The access control rules work on the TCP layer, blocking the connection before HTTP has a chance to parse the request.

The access control mechanism maintains a list of rules that either allow or deny access based on the client’s IP address. The first matching rule will determine the fate of the client. The following example denies access from a certain evil IP subnet.

// Block evil IPs.
// An empty address means "everybody". Allow everybody else.

The allowFrom and denyFrom functions accept IPv4 and IPv6 addresses and subnets. Examples:

webServer.allowFrom(''); // IPv4 address/netmask
webServer.denyFrom(''); // Same in CIDR notation
webServer.allowFrom(''); // IPv4 host address
webServer.denyFrom('fe80::a65d:36ff:fec8:aced'); // IPv6 host address
webServer.allowFrom('fe80::/64'); // IPv6 subnet
webServer.denyFrom(''); // Any IP address (v4 or v6)

IP-based access control can only be enabled by editing the init script.


CORS is a technique implemented by browsers to allow web pages to make requests to servers they did not originate from. Since this is generally unsafe, the target server must be explicitly configured to accept the requests.

The Engine’s web server disallows CORS requests by default. That is, scripts loaded from a web server other than the Engine’s own will not be able to make requests to it. Note however that this only applies to browsers. A malicious Node.js script run locally can still make requests to the server. The api-init.qml app does not expose unsafe features to the web server and therefore enables CORS:

  id: webServer
  corsEnabled: true

This allows CORS requests made by any script independent of its origin. For a more fine-grained control one can specify which domains are allowed to make CORS requests:

  id: webServer
  corsEnabled: true
  corsOrigins: ['', '']

Do not enable CORS if you don’t fully understand the security consequences. If you do, consider adding IP-based access control.

CORS can only be enabled by editing the init script.


The built-in OPC UA server will not be started by default. To enable it, pass a network interface specification on the command line using the opcUaServer variable. To bind the OPC UA server to port 4015 on all IPv4 interfaces:


ExecStart=/opt/visionappster/bin/va-run /opt/visionappster/init/init.qml opcUaServer=


sc config "VisionAppster Engine" ^
  binPath="C:\Program Files\VisionAppster\bin\va-engine-service.exe ..\init\init.qml opcUaServer="