Setting up a proxy for Jaws Deploy Stack

Jaws Deploy Stack consists of the Jaws App Server and a Jaws Hub microservice. Your agents/machines need to be able to communicate with both these services. The agent installation script includes a set of embedded data and URLs that let a fresh agent connect to Jaws App Server.

General overview

Running the Agent installation script installs a lightweight background service (Windows Service or systemd on Linux). Agent binaries are downloaded from the URL specified in the installation script, which is local to your Jaws Deploy Stack installation (i.e. the binaries are bundled with the Jaws Deploy Stack, they will never be auto-updated from the Internet, unless you replace the binaries manually in your Stack installation location).

After Agent service is installed the script waits until an organization administrator accepts the Agent handshake request in Jaws App UI (under Machines list).

Once accepted, Agent background service automatically starts up and creates a connection to the Jaws App server API. After this connection is established the server will assign one of available Jaws Hubs to this Agent and will return the hub’s URL. Agent will automatically store the Hub URL and it will establish a persistent connection with that Hub.

Agents are not assigned to a Hub permanently. If your installation includes more Hubs - then Agents will negotiate hub connection on startup. All of this is handled automatically and does not require any administrative work.

For increased security you may want to run all your agents within an intranet or even in a DMZ within it. In this case it is possible to let agents communicate with Jaws App Server and Jaws Hub via proxies. This provides better control and security. There is no need to configure outbound traffic from all agents to Jaws services - only the proxies need such access. Possible setup is illustrated below.

Installation - environment variables

When installing the Jaws Deploy Stack via Docker Compose please note the following steps and settings required in the .env file:

  • The Jaws Deploy App is typically available under port 7100 and the Hub under port 7200. This can be modified via the .env file:
    - WEB_LISTEN_PORT=7100
    - HUB_LISTEN_PORT=7200
  • Decide on the proxy URLs for App and Hub that you’d like to use within the DMZ. E.g.:
    - https://jaws-app.local
    - https://jaws-hub-001.local

  • configure your HTTP proxy (e.g. Nginx, Apache) to expose App and Hub services (default ports 7100 and 7200) under the chosen proxy URLs
    - You can quickly check if the App is running: http://jaws-app.local/api/heartbeat gives a plaintext response with version number.
    - You can quickly check if the Hub is running: http://jaws-hub-011.local gives a heartbeat response.
  • Configure the chosen proxy URL in .env file:
    - HUB_PROXY_URL=https://jaws-hub-001.local
    - This URL will be communicated to Agents when they request connection to this Hub.
  • When running the App behind a proxy, and the proxy does not run on the same host as the App - then you must configure a trusted network (CIDR) or a trusted proxy IP address. This tells the App server to accept X-Forwarded-* headers from these trusted networks/IPs.
    Forwarded headers are essential for proper OIDC  flow integration. By default the App will only accept these headers from localhost. This can be controlled with the following values in .env file:
    - FORWARDED_HEADERS_KNOWN_NETWORKS e.g. 10.1.0.0/16,192.168.1.0/24 - multiple CIDRs are supported (comma-separated).
    - FORWARDED_HEADERS_KNOWN_PROXIES e.g. 10.1.0.100,192.168.1.12 - multiple IP addresses are supported (comma-separated).

Installing Agents

Once the stack is running you will need to add some machines. Head over to Machines section, click “Add machine” and download an installation script specific to the OS of the machine where the Agent will run.

The script offers a number of customizations:

  • serverUrl: set this URL if you want the agents to communicate with the server on a custom URL (typically using a reverse proxy).
    E.g. https://jaws-app.mycompany.org (default: the URL where you accessed the App to download the installation script).
  • serviceName: custom name for the installed Windows Service or systemd service. Default: JawsDeploy Agent.
  • installDir: custom installation location.

    It is possible to override this also via environment variable JAWSDEPLOY_CUSTOM_INSTALL_DIR.

    When not provided the defaults are:
    - Windows: %ProgramFiles%\JawsDeploy\Agent
    - Linux: /opt/JawsDeploy/Agent
  • allowInvalidServerSslCertificates: boolean - set to $true if Agent will communicate with App and Hub over https using untrusted/self-signed SSL certificates. Useful for testing purposes. Default: false.
  • p: boolean - install PowerShell 7. Default: true.
  • d: boolean - install .net 8 runtime. Default: true.

Example installation command when using reverse proxy for the App:

> .\jaws_agent_install.ps1 `
     [-installDir "/opt/jawsagent"] `
     [-serviceName "My Jaws Agent"] `
     -serverUrl "https://my-jaws-proxy.mycompany.org" `
     -allowInvalidServerSslCertificates $true

Local testing

Following values in docker-compose.yml might need adjustments when testing locally when some/all services are running over plain http:

JAWSDEPLOY_Authentication__OIDC__RequireHttpsMetadata - set this to false when OIDC provider is running on http. This way the App will accept a http-based OIDC provider. For production scenarios this value should not be set to false.

Nginx reverse proxy - configuration example

It is possible to apply proxy for both App and Hub. Each of these two is configured separately. Example App configuration for Nginx:

# Web socketsmap
map $http_connection $connection_upgrade
{
  "~*Upgrade" $http_connection;
  default keep-alive;
}

server
{
  server_name jaws-app.local;
  location /
  {
    proxy_set_header Host              $host;
    proxy_set_header X-Real-IP         $remote_addr;
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header X-Forwarded-Host  $host;
    proxy_set_header X-Forwarded-Port  $server_port;
    proxy_cache off;
    
    # Configuration for WebSockets        
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_http_version 1.1;
    
    # Configuration for LongPolling or if your KeepAliveInterval is longer than 60 seconds
    proxy_read_timeout 100s;
    proxy_pass http://10.0.1.5:7100;
  }
  
  # If running the app over SSL with Certbot (Let's Encrypt)
  listen 443 ssl;    
  ssl_certificate /path/to/fullchain.pem; # Certbot    
  ssl_certificate_key /path/to/privkey.pem; # Certbot    
  include /path/to/options-ssl-nginx.conf; # Certbot    
  ssl_dhparam /path/to/ssl-dhparams.pem; # Certbot
}