FOAM has support for building, uploading, and install a complete application.
Deployment builds generate a tar ball:
node foam3/tools/build.js -ckJyour_deployment_directories,../foam3/deployment/https
Once a tar ball is prepared, it can be uploaded and the application installed
./build.sh -TStandard,Java,RemoteInstall -Jyour_deployment_directories --remote-hostname:hostname
--user:name - User name to create and run application under. Defaults to foam--user-id:id - User ID to create User with. Defaults to 3626--backup:true|false - Controls backup of previous version during install. Defaults to true.
NOTE The upload and install process assume the uploader’s ssh key is installed on the remote host, and that ssh has been configured for no-password logins.
JVM Memory configuration defaults to -Xms2048m and -Xmx4096.
These properties can be overridden after first deployment by adding them to:
/opt/name/conf/shrc.custom
#!/bin/bash
` JAVA_OPTS=”${JAVA_OPTS} -Xmx8000m”`
Or per deployment with
./build.sh -EJAVA_OPTS:"-Xms4g -Xmx8g"
or
./build.sh --system-property:Xms4g,Xmx8g
Other JVM options, such as Garbage Collection, are defined in:
/opt/name/etc/shrc.local
To override add to
/opt/name/conf/shrc.local
The Health system is intended for production monitoring (and LB integration) of the status of FOAM applications.
The HealthWebAgent reports the Health Status of an instance, intended to be consumed by Load Balancers (LB) to determine when an instance is in an appropriate state to receive traffic.
The HealthWebAgent is hosted at
/service/health?format=html
Using url query parameter format=html will return just the Health Status string suitable for Load Balancer consumption.
The default FOAM supports DOWN and UP, other states are left for application implementation. An application would provide it’s own HealthWebAgent to report appropriately. For example, reporting MAINT until replay is complete. (see foam-medusa for example)
NOTE The HealthWebAgent only works with HTTPS
The application version is available through the VersionWebAgent hosted at
service/version
When deploying clusters of applications, such as Medusa, foam provides a Heartbeat system to allow individual intances to respond to changing state of other instances.
Each instance sends a UDP heartbeat via multicast broadcast, and each instance listens for heartbeats. The healthDAO displays detected instances along with status and heartbeat stats.
The heartbeat UDP packet is sent, by default, to multicast address 230.22.41.0 and port 52241. This address and port must be open on firewalls between instances which use this type of monitoring.
The heartbeat broadcast and monitoring system is disabled by default. To enable, create services.jrl entries at the application deployment level, enabling both healthSupport and healthHeartbeatService:
p({
"class": "foam.core.boot.CSpec",
"name": "healthHeartbeatService",
"enabled": true
})
p({
"class": "foam.core.boot.CSpec",
"name": "healthHeartbeatMonitor",
"enabled": true
})
See https://content-security-policy.com/
FOAM builds the Content-Security-Policy header at runtime from entries in a DAO of CSPDirective objects. This replaces the older approach of hard-coding a CSP string in CSPFilter initParameters. FOAM ships production-ready defaults; your app can append, override, disable, and domain-scope directives as needed.
Each entry is a journal put of foam.core.http.csp.CSPDirective:
p({class:"foam.core.http.csp.CSPDirective", key:"mycompany", name:"script-src", value:"'self' https://cdn.example.com"})
FOAM’s CSPFilter groups entries by directive name and concatenates values (and hashes) from all enabled entries matching the request domain:
This enables a clean pattern: keep FOAM defaults, and add your app’s entries with a different key (e.g., “mycompany”). Only override/disable when you intentionally diverge from defaults.
<meta name="csp-nonce" ...> and applies the nonce to server-emitted style/script tags.'nonce-...' tokens to the CSP so the browser accepts nonce-bearing elements.
<style> and <script> elements (style-src-elem, script-src). They do not apply to style attributes (style-src-attr). For attributes, use ‘unsafe-hashes’ with specific hashes or avoid inline styles.Example:
// services.jrl (server emits the nonce)
p({
class: "foam.core.boot.CSpec", name: "http",
service: { class: "foam.core.jetty.HttpServer",
servletMappings: [{
class: "foam.core.servlet.ServletMapping",
servletObject: {
class: "foam.core.servlet.VirtualHostRoutingServlet",
defaultHost: "localhost",
cspNonce: "123456789120000"
},
pathSpec: "/*"
}]
}
})
// journals/cspdirectives.jrl (browser accepts nonce’d elements)
p({class:"foam.core.http.csp.CSPDirective", key:"nonce", name:"script-src", value:"'nonce-123456789120000'"})
p({class:"foam.core.http.csp.CSPDirective", key:"mycompany", name:"style-src-elem", value:"'self' https://fonts.googleapis.com 'nonce-123456789120000'"})
1) Add a new allowed source (e.g., CDN for a third-party library)
// Appends to FOAM defaults for script-src
p({class:"foam.core.http.csp.CSPDirective", key:"mycompany", name:"script-src",
value:"https://cdn.jsdelivr.net https://cdnjs.cloudflare.com"})
2) Domain-scoped directive (dev-only allowances)
// Allow source maps/fetches only on localhost
p({class:"foam.core.http.csp.CSPDirective", key:"dev", domain:"localhost",
name:"connect-src", value:"https://cdn.jsdelivr.net"})
3) Disable a FOAM default directive
// Remove FOAM’s default connect-src for all domains, then define a minimal one
p({class:"foam.core.http.csp.CSPDirective", key:"foam", name:"connect-src", enabled:false})
p({class:"foam.core.http.csp.CSPDirective", key:"mycompany", name:"connect-src", value:"'self'"})
4) Inline style attributes (style-src-attr) and hashes
// Attributes cannot use nonces; allow only specific hashed content
p({class:"foam.core.http.csp.CSPDirective", key:"mycompany", name:"style-src-attr",
value:"'unsafe-hashes'", hash:"'sha256-abc123...='"})
// The browser console will print the exact hash needed when a CSP violation occurs - in some cases.
FOAM apps are typically SPAs: the initial HTML is minimal and content loads via authenticated APIs. With FOAM’s auth/session layers, using a fixed nonce per deployment can be operationally simpler while still meeting security goals. If your threat model requires per-request nonces, you can rotate cspNonce dynamically and update matching CSPDirective entries accordingly.