Follow the packet. The installer ends by checking whether the gateway it just started is reachable. The browser, when you point it at the gateway, makes its own HTTP request to the same listener. When the wrapper log shows Jetty bound to 0.0.0.0:8088 but the installer reports Gateway Startup Issue – Unable to start the gateway, the gateway is up. The failure is in the check. This reference covers Ignition 8.0.16 on macOS Catalina 10.15.6, installed to /usr/local/ignition on a company-managed MacBook Pro. In that case, entering localhost:8088 directly in the browser reached the gateway and cleared the problem.
What request does the installer make, and where does it stop?
When installation finishes, the Java Service Wrapper starts the gateway as a daemon. The log confirms this with --> Wrapper Started as Daemon. The installer's last page then decides pass or fail based on whether it can see the gateway running. On failure it shows the Gateway Startup Issue page with an Open Logs button that opens the wrapper log.
The data path has three hops, all on the same machine:
| Hop | Component | Evidence it worked |
|---|---|---|
| 1. Service start | Java Service Wrapper Standard Edition 64-bit 3.5.42, running as a daemon |
Wrapper Started as Daemon, then Launching a JVM
|
| 2. Application start | Gateway JVM (11.0.7+10-LTS) with embedded Jetty 9.4.24.v20191120 | Started o.e.j.w.WebAppContext@...{Commissioning,/,...,AVAILABLE} |
| 3. Network listener | Jetty ServerConnector, HTTP/1.1 |
Started ServerConnector@...{HTTP/1.1,[http/1.1]}{0.0.0.0:8088} |
All three hops completed. The log has no stack trace, no jvm 2 restart, and no bind error. Whatever the installer tested stopped somewhere between the installer process and the TCP listener, not inside the gateway. When the browser request to localhost:8088 succeeds, the listener is confirmed reachable over loopback and the installer verdict is a false negative.
What does the wrapper log prove, line by line?
Read the log as a startup timeline. The left timestamp column comes from the wrapper (local time). The bracketed timestamps inside gateway log lines come from the gateway's own logging pattern.
| Wrapper time | Event | Meaning |
|---|---|---|
| 14:44:00 | Wrapper started as daemon, version 3.5.42 | Service launched by the OS |
| 14:44:02 |
Launching a JVM, WrapperManager: Initializing
|
First JVM instance (jvm 1) created |
| 14:44:04 |
logback.xml found at /usr/local/ignition/data/logback.xml
|
Install directory and data folder are readable |
| 14:44:09–14:44:12 | Appenders built: SysoutAppender, SQLiteAppender named DB, async wrappers SysoutAsync and DBAsync; SQLite JDBC 3.23.1 |
Log database created and writable |
| 14:44:12 |
W [WebResourceManagerImpl] metro keystore alias fallback to metro-key
|
Warning only; default applied |
| 14:44:13 |
WebServerManager setup, property defaults, Setup complete
|
Web server configuration resolved |
| 14:44:13 | Commissioning State updated from commissioning to needs_commissioning |
Fresh install waiting for first-run setup |
| 14:44:14 | Commissioning web app AVAILABLE at /
|
Setup wizard is being served |
| 14:44:14 | Connector on 0.0.0.0:8088, Started @11704ms
|
Listening on all IPv4 interfaces, port 8088 |
The@11704msfigure is JVM uptime when Jetty finished starting. Most of that time went to building the SQLite appender, from about 14:44:09.598 to 14:44:12.036. A first boot on a laptop that scans newly written files is slower than later boots.
The bracketed gateway time ([18:44:12]14:44:12). That offset is a timezone difference between the two logging paths. It is not a clock fault and not related to the startup verdict. Correlate by offset, not by assuming the two columns match.
The jvm 1 column matters. It counts JVM instances. If the wrapper had detected a crash or a hung JVM, the next lines would show jvm 2. A single jvm 1 run ending on a started connector means one clean start.
Is the gateway.metroKeystoreAlias warning the fault?
No. The full line is:
W [WebResourceManagerImpl] Unable to read "gateway.metroKeystoreAlias" gateway.xml property. Assuming metro keystore alias is: metro-key
It is the only W (warning) line in the log, so it gets blamed. Read it literally: the property is missing from gateway.xml, and the gateway substitutes the default alias metro-key. A fresh install has no custom keystore configuration, so the property is expected to be missing and the fallback is the designed behavior. The next line starts Jetty logging, and the web server completes setup within a second. A fatal keystore problem would stop the sequence with an exception. It would not be followed by a clean Setup complete and a started connector.
The WebServerManager lines have the same pattern: each property is "not set" and falls back to a default.
| Property | Logged default | Effect on a fresh install |
|---|---|---|
gateway.forceSecureRedirect |
false |
HTTP requests are not forced to HTTPS, so plain http://localhost:8088 is served |
gateway.includedCipherSuites |
[] |
No cipher allow-list override |
gateway.excludedCipherSuites |
[] |
No cipher deny-list override |
gateway.publicAddress.autoDetect |
true |
Gateway detects its own address for client launch URLs |
gateway.publicAddress.address, .httpPort, .httpsPort
|
blank | No fixed public address; relevant only behind NAT or a reverse proxy |
None of these affect whether the loopback listener accepts connections. Leave gateway.xml alone.
Why would a managed Mac report failure for a running gateway?
Layer one first, even on a single host. Here layer one is the loopback interface and the listening socket. The log shows the socket open, so move up the stack to whatever sits between the installer or browser and that socket. On a company-managed laptop there are several such layers. The measurement for each is in the next sections.
-
System or PAC proxy. Corporate Macs often have a system proxy or auto-config script. If
localhostor127.0.0.1is missing from the bypass list, local HTTP requests go to the proxy, which cannot reach your loopback address. Diagnostic:curl --noproxyworks while a proxy-aware client fails. -
Endpoint security and application firewalls. Security agents can delay or block a freshly installed Java binary from opening sockets or accepting connections. Diagnostic:
lsofshows no listener even though the log says the connector started, or connections time out rather than being refused. -
Name resolution.
localhostcan resolve to IPv6::1before IPv4127.0.0.1. The connector reports0.0.0.0:8088, an IPv4 wildcard. Diagnostic: test both127.0.0.1andlocalhostexplicitly.
Only the first two are consistent with a browser succeeding right after the installer failed. The Terminal checks below tell you which one applies before you change anything.
What if your wrapper.log does not end at the 8088 connector?
A log from another machine tells you nothing about yours. Before comparing symptoms, open your own wrapper.log from the logs folder under the install directory (/usr/local/ignition in this case). Confirm it is the whole file and not a truncated view from the installer page. Then match the last meaningful line to a failure class:
| Where the log ends | Failing hop | Next action |
|---|---|---|
At or before Launching a JVM
|
Wrapper cannot start Java | Read the wrapper ERROR/FATAL lines; check install directory permissions |
jvm 2, jvm 3 lines appear |
JVM crashing or hanging; wrapper restarting it | Find the last exception before each restart |
| Exception during logback or SQLite appender setup | Data folder not writable | Check ownership of /usr/local/ignition/data
|
| Bind or "address already in use" error at connector start | Port 8088 owned by another process | Identify the owner with lsof; free the port or change the gateway port |
Started ServerConnector ... {0.0.0.0:8088} |
None; gateway is up | Browse to http://localhost:8088 and commission |
Only the last row applies to the case documented here. If your log ends in one of the other rows, the installer page is reporting a real failure and the rest of this procedure does not apply until that hop is fixed.
Which fix path should you take?
Four responses are common. Compare them on whether they address the hop that actually failed.
| Approach | Targets the failed hop? | Cost | Risk | Outcome in this case |
|---|---|---|---|---|
Add gateway.metroKeystoreAlias to gateway.xml
|
No; the warning is a handled fallback | Low | Hand-editing config on a fresh install can create a real parse failure | No effect on the installer check |
| Uninstall and reinstall | No; repeats the same start sequence and check | Medium | Low, but first-boot timing repeats and so does the verdict | Likely the same screen |
Browse directly to http://localhost:8088 and commission |
Yes; tests the loopback HTTP path directly | Minimal | None | Worked |
| Change host networking (proxy bypass, security exception) | Only if the browser request also fails | Needs IT involvement on managed hardware | Policy changes on a company machine | Not needed once the browser connected |
Recommendation: dismiss the installer page, confirm the listener from Terminal, and commission through the browser. Escalate to host networking changes only if Terminal shows a listener but no local client can get an HTTP response.
How do you confirm the listener and the loopback path from Terminal?
Work from the socket outward so each step tests one more hop.
- Confirm the socket is open and owned by the gateway JVM:
Expect alsof -nP -iTCP:8088 -sTCP:LISTENjavaprocess inLISTENstate on port 8088. No output means nothing is listening. Go back to the log table above. The listener may take a moment on first boot, so re-run it before concluding. - Request the page over IPv4 loopback, bypassing any proxy:
Any HTTP status line (2xx or 3xx) proves Jetty answered, and a redirect toward the commissioning page is normal.
Connection refusedmeans no listener. A hang or timeout points to a local firewall or security agent. - Repeat by name to test resolution:
If
127.0.0.1answers andlocalhostdoes not, the name is resolving to an address the IPv4 wildcard connector does not serve. Use in the browser. - Check the system proxy configuration:
If an HTTP proxy or auto-config URL is active, confirm the exceptions list includesscutil --proxylocalhostand127.0.0.1. Ifcurl --noproxyworks but the browser does not, the proxy is intercepting loopback traffic. Ask IT to add the bypass rather than disabling the proxy yourself. - Watch the log live while you make the request:
New lines as you browse confirm the request reaches the gateway. No new lines while the browser shows an error means the request stopped before the listener.tail -f /usr/local/ignition/logs/wrapper.log
How do you commission the gateway from the browser?
The log line Commissioning State updated from commissioning to needs_commissioning means the gateway is serving only the first-run wizard at /. Until you complete it, the full gateway does not start.
- Close the installer's Gateway Startup Issue page. The gateway runs as a daemon under the wrapper and keeps running when the installer closes.
- Open
http://localhost:8088, or if the name test failed. Use plain HTTP. Withgateway.forceSecureRedirectdefaulting tofalse, there is no forced HTTPS redirect at this stage. - Step through the commissioning wizard: accept the license, create the initial administrator account, and confirm the HTTP and HTTPS ports. Keep HTTP on 8088 unless something else on the machine needs that port.
- Start the gateway from the wizard's final step and keep the page open while it moves from commissioning to normal startup.
- Keep
tail -fonwrapper.logrunning during this step. The commissioning state line updates again and module startup messages follow. Warnings about unset optional properties at this stage are the same kind of defaults described above.
If the wizard page loads but submitting it fails, inspect the wrapper.log lines written at the moment of submission. A failure there is a gateway-side error with its own exception, not a network-path issue.
How do you verify the gateway after commissioning?
A single successful page load proves the path once. Verification proves it survives a restart, because the daemon has to come up again without the installer.
- Refresh
http://localhost:8088. The gateway web interface home page should load instead of the commissioning wizard. Log in with the administrator account created during commissioning. - Re-run
lsof -nP -iTCP:8088 -sTCP:LISTENand confirm thejavalistener is still present. If you configured an HTTPS port during commissioning, run the same command against that port. - Scan
wrapper.logsince commissioning for anyjvm 2lines. Their absence means the JVM did not crash during the transition out of commissioning. - Confirm the wrapper is registered with launchd so it starts on boot:
A matching entry means the daemon is loaded.sudo launchctl list | grep -i ignition - Reboot the Mac. Wait for the log to show a new
Started ServerConnector ... {0.0.0.0:8088}line, then run and loadhttp://localhost:8088in the browser. An HTTP status line from curl and the gateway home page (not the commissioning wizard) in the browser confirm the gateway starts on its own and is reachable over loopback after a cold boot.
FAQ
What happens if I ignore the gateway.metroKeystoreAlias warning in the Ignition wrapper log?
Nothing breaks. The gateway uses the default alias metro-key and continues. In the documented log, Jetty completed setup and opened 0.0.0.0:8088 about two seconds after that warning.
What happens if I close the installer on the Gateway Startup Issue screen?
The gateway keeps running, because the Java Service Wrapper started it as a daemon independent of the installer. Browse to http://localhost:8088 to reach the commissioning wizard.
What happens if localhost:8088 refuses the connection after install?
Run lsof -nP -iTCP:8088 -sTCP:LISTEN. If no java listener appears, open wrapper.log and look for jvm 2 restarts, a port bind error, or an exception before the ServerConnector line. If a listener exists, test with curl --noproxy '*' to rule out name resolution and proxy interception.
The wrapper column prints local time, and the bracketed gateway timestamps use a different timezone. In the documented log, 14:44:12 wrapper time matches [18:44:12] gateway time. Correlate events by that fixed offset; it does not indicate a fault.