diff --git a/server/server.js b/server/server.js index 257c1647b9d..a7b0a5aabbd 100644 --- a/server/server.js +++ b/server/server.js @@ -110,6 +110,7 @@ const { shake256, SHAKE256_LENGTH, allowDevAllOrigin, + printServerUrls, } = require("./util-server"); log.debug("server", "Importing Notification"); @@ -1741,11 +1742,7 @@ let needSetup = false; await server.start(); server.httpServer.listen(port, hostname, async () => { - if (hostname) { - log.info("server", `Listening on ${hostname}:${port}`); - } else { - log.info("server", `Listening on ${port}`); - } + printServerUrls("server", port, hostname); await startMonitors(); // Put this here. Start background jobs after the db and server is ready to prevent clear up during db migration. diff --git a/server/setup-database.js b/server/setup-database.js index 4f106530745..fc7b037e50c 100644 --- a/server/setup-database.js +++ b/server/setup-database.js @@ -4,7 +4,7 @@ const expressStaticGzip = require("express-static-gzip"); const fs = require("fs"); const path = require("path"); const Database = require("./database"); -const { allowDevAllOrigin } = require("./util-server"); +const { allowDevAllOrigin, printServerUrls } = require("./util-server"); const mysql = require("mysql2/promise"); /** @@ -307,9 +307,8 @@ class SetupDatabase { }); tempServer = app.listen(port, hostname, () => { - log.info("setup-database", `Starting Setup Database on ${port}`); - let domain = hostname ? hostname : "localhost"; - log.info("setup-database", `Open http://${domain}:${port} in your browser`); + log.info("setup-database", "Starting Setup Database"); + printServerUrls("setup-database", port, hostname); log.info("setup-database", "Waiting for user action..."); }); }); diff --git a/server/util-server.js b/server/util-server.js index cd257936df7..8f2f4fc2a10 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -985,3 +985,34 @@ async function commandExists(command) { } } module.exports.commandExists = commandExists; + +/** + * Log the server's listening URLs, similar to Vite's dev server output. + * When no hostname is specified (bound to all interfaces), it prints + * localhost plus every non-internal network address. + * @param {string} tag Log tag (e.g. "server", "setup-database") + * @param {number} port Port number + * @param {string} hostname Bound hostname, if any + * @returns {void} + */ +module.exports.printServerUrls = (tag, port, hostname) => { + if (hostname) { + log.info(tag, `Listening on http://${hostname}:${port}`); + return; + } + + const { networkInterfaces } = require("os"); + const nets = networkInterfaces(); + + log.info(tag, "Listening on:"); + log.info(tag, ` Local: http://localhost:${port}`); + + for (const iface of Object.values(nets)) { + for (const addr of iface) { + if (!addr.internal) { + const host = addr.family === "IPv6" ? `[${addr.address}]` : addr.address; + log.info(tag, ` Network: http://${host}:${port}`); + } + } + } +}; diff --git a/server/utils/simple-migration-server.js b/server/utils/simple-migration-server.js index 1bc3b94755c..5245840354c 100644 --- a/server/utils/simple-migration-server.js +++ b/server/utils/simple-migration-server.js @@ -1,6 +1,6 @@ const express = require("express"); const http = require("node:http"); -const { log } = require("../../src/util"); +const { printServerUrls } = require("../util-server"); /** * SimpleMigrationServer @@ -64,11 +64,7 @@ class SimpleMigrationServer { return new Promise((resolve) => { this.server.listen(port, hostname, () => { - if (hostname) { - log.info("migration", `Migration server is running on http://${hostname}:${port}`); - } else { - log.info("migration", `Migration server is running on http://localhost:${port}`); - } + printServerUrls("migration", port, hostname); resolve(); }); });