libredb / libredb/libredb-studio
The boot banner always prints localhost, whatever the server bound to
- Dominant language
- TypeScript
- Stars
- 726
- Forks
- 119
- Avg merge
- 7h 47m
- Merged PRs (30d)
- 265
Description
## Description
The boot banner prints `http://localhost:` whatever the server bound to.
`src/lib/startup-banner.ts:25`
```ts
/** The port the server actually listens on; never invent a hostname. */
function resolveUrl(): string {
const port = (process.env.PORT ?? "").trim();
return `http://localhost:${port || DEFAULT_PORT}`;
}
```
The comment says never invent a hostname. The port is read from the environment, the host is hardcoded, so `localhost` is invented. Whenever the server is not on loopback the banner hands the reader an address that does not answer.
This is the display half of a pair. The listening half, where the launcher binds to the inherited `HOSTNAME` inside a container, is #813. They are separate files and separate fixes, and either one can be fixed without the other.
## Steps to Reproduce
Any run where the bind address is not loopback shows it. The shortest one:
```
git clone --depth=1 https://github.com/libredb/libredb-studio
curl -sSLO https://github.com/libredb/libredb-studio/releases/download/0.15.0/libredb-studio-standalone-0.15.0-linux-arm64.tar.gz
docker run -d --name t -e HOSTNAME=0.0.0.0 -v "$PWD:/app" -w /app node:24-alpine \
sh -c 'LIBREDB_STUDIO_SKIP_PROVENANCE=1 node libredb-studio/bin/studio.js \
--archive /app/libredb-studio-standalone-0.15.0-linux-arm64.tar.gz > /tmp/l.log 2>&1'
docker exec t sh -c 'grep -i "Starting\|->" /tmp/l.log'
```
## Expected Behavior
The banner names the address the server is serving, the way `startupUrl()` in `bin/lib/launcher-utils.mjs` already does for the launcher's own line.
## Actual Behavior
Two runs, launcher 0.16.0 from `main` (`acf50738`), payload 0.15.0.
Inherited `HOSTNAME`, so the server binds to the container id:
```
Starting LibreDB Studio 0.16.0 on http://46db4676bb04:3000
LibreDB Studio 0.15.0 -> http://localhost:3000
```
The first line is right and the second contradicts it. `curl http://localhost:3000/login` from inside that container returns `000`.
`HOSTNAME=0.0.0.0`, so the server binds everywhere:
```
Starting LibreDB Studio 0.16.0 on http://127.0.0.1:3000
LibreDB Studio 0.15.0 -> http://localhost:3000
```
Here the address happens to work, but not because the banner knew: it prints the same string either way.
## Environment
- **LibreDB Studio Version**: launcher `main` (`acf50738`, reports 0.16.0); payload 0.15.0. The quoted `startup-banner.ts` is `main`, so this is current behaviour and not an artifact of the older payload
- **Browser**: not involved, reproduced with curl
- **OS**: `node:24-alpine` container on Docker 29.2.1
- **Node.js/Bun Version**: Node.js 24
- **Database Type**: not involved
## Additional Context
Worth separating from #709, which is recent and touches the same screen. #709 fixed the launcher's own `Starting ... on` line and put the address formatting in `startupUrl()`, including the wildcard and IPv6 cases. That line is correct in the runs above. The banner is a different file and #709 did not change it.
## Possible Solution
Give the banner the address the server was given and pass it through the same helper the launcher uses, so the wildcard and IPv6 cases stay consistent between the two lines. Where no address is known, saying nothing is better than naming one that may not answer.
Contributor guide
Research direction
Start with src/lib/startup-banner.ts:25 and compare its URL handling with startupUrl() in bin/lib/launcher-utils.mjs. Reproduce the container case from the issue, then verify the banner agrees with the server address for hostname, wildcard, IPv6, and unknown-address cases without inventing localhost.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- node.js, typescript
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100