Skip to content

Add web bind address#357

Open
dpw13 wants to merge 5 commits intoopensensor:mainfrom
dpw13:feat/bind_ip
Open

Add web bind address#357
dpw13 wants to merge 5 commits intoopensensor:mainfrom
dpw13:feat/bind_ip

Conversation

@dpw13
Copy link
Copy Markdown
Contributor

@dpw13 dpw13 commented Apr 4, 2026

Useful for deployments with many network interfaces or behind a proxy, to avoid exposing the unencrypted HTTP port.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a configurable web bind address so deployments can restrict which network interface the (unencrypted) HTTP server listens on, reducing accidental exposure on multi-homed hosts or behind proxies.

Changes:

  • Introduces web_bind_ip configuration across INI/env/defaults, API, and server startup (libuv bind).
  • Exposes the setting in the web UI (settings form + i18n) and includes it in config export/backup JSON.
  • Documents bind_ip in configuration docs and wires it into the Docker entrypoint default config.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
web/public/locales/en.json Adds UI label for the new bind address setting.
web/js/utils/settings-utils.js Adds default web_bind_ip value for frontend settings model.
web/js/components/preact/SettingsView.jsx Adds bind address field to settings load/save + renders an input.
src/web/libuv_server.c Binds the listener to the configured IPv4 address and improves logging.
src/web/api_handlers_system.c Includes web_bind_ip in system backup JSON.
src/web/api_handlers_settings.c Exposes web_bind_ip in GET settings and accepts it in POST updates.
src/web/api_handlers_common_utils.c Includes web_bind_ip in generic config JSON output.
src/core/main.c Passes bind address into HTTP server config and updates log messages.
src/core/config.c Adds env mapping/default/INI/save/print/reload logging for web_bind_ip.
include/web/http_server.h Extends http_server_config_t with bind_ip.
include/core/config.h Adds web_bind_ip to the core config struct.
docs/CONFIGURATION.md Documents the new [web] bind_ip setting.
docker-entrypoint.sh Adds bind_ip to the generated default config in container entrypoint.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +753 to 755
} else if (strcmp(name, "bind_ip") == 0) {
strncpy(config->web_bind_ip, value, 31);
} else if (strcmp(name, "root") == 0) {
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strncpy(config->web_bind_ip, value, 31); does not guarantee NUL-termination when value is length >= 31. This can leave web_bind_ip unterminated and later %s logging / uv_ip4_addr reads past the buffer. Ensure the destination is always NUL-terminated (or use a bounded copy helper that always terminates).

Copilot uses AI. Check for mistakes.
Comment on lines 109 to 112
// Web server settings
{"WEB_PORT", CONFIG_TYPE_INT, CONFIG_OFFSET(web_port), 0, NULL, 8080, false},
{"WEB_BIND_IP", CONFIG_TYPE_STRING, CONFIG_OFFSET(web_bind_ip), 32, "0.0.0.0", 0, false},
{"WEB_AUTH_ENABLED", CONFIG_TYPE_BOOL, CONFIG_OFFSET(web_auth_enabled), 0, NULL, 0, true},
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Config loading already has unit tests (e.g., tests/unit/test_config.c covers web_port defaults/env overrides). This PR adds a new config field (WEB_BIND_IP, default 0.0.0.0) but no corresponding tests to prevent regressions in defaults, INI parsing, and env override behavior. Please add unit coverage for the new field similar to the existing web_port tests.

Copilot uses AI. Check for mistakes.
matteius and others added 3 commits April 7, 2026 21:32
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +486 to +507
// Web bind address
cJSON *web_bind_ip = cJSON_GetObjectItem(settings, "web_bind_ip");
if (web_bind_ip && cJSON_IsString(web_bind_ip)) {
const char *new_bind_ip = web_bind_ip->valuestring;
bool bind_ip_empty = (new_bind_ip == NULL);

if (!bind_ip_empty) {
while (isspace((unsigned char)*new_bind_ip)) {
new_bind_ip++;
}
bind_ip_empty = (*new_bind_ip == '\0');
}

if (bind_ip_empty) {
log_warn("Rejected empty web_bind_ip update");
} else if (strcmp(g_config.web_bind_ip, new_bind_ip) != 0) {
strncpy(g_config.web_bind_ip, new_bind_ip, sizeof(g_config.web_bind_ip) - 1);
g_config.web_bind_ip[sizeof(g_config.web_bind_ip) - 1] = '\0';
settings_changed = true;
restart_required = true;
log_info("Updated web_bind_ip: %s (restart required)", g_config.web_bind_ip);
}
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

web_bind_ip updates are only checked for non-empty, then persisted and logged. Since this value is later written into the INI via fprintf("bind_ip = %s\n", ...) and parsed by uv_ip4_addr, allowing whitespace/control characters or non-IPv4 strings can corrupt the saved config (newline injection) or make the web server fail to start on next restart. Consider trimming both leading/trailing whitespace and validating the value as an IPv4 address (or explicitly document/implement IPv6/hostnames) before accepting it.

Copilot uses AI. Check for mistakes.
Comment on lines 478 to +487
// Web port
cJSON *web_port = cJSON_GetObjectItem(settings, "web_port");
if (web_port && cJSON_IsNumber(web_port)) {
g_config.web_port = web_port->valueint;
settings_changed = true;
log_info("Updated web_port: %d", g_config.web_port);
}

// Web bind address
cJSON *web_bind_ip = cJSON_GetObjectItem(settings, "web_bind_ip");
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

web_port is updated and persisted, but restart_required is not set (unlike web_bind_ip and web_thread_pool_size). Since the running libuv server won’t rebind to a new port without a restart, the settings API response/UI will incorrectly imply the change is live. Set restart_required = true (and ideally return an appropriate restart_required_message) when web_port changes.

Copilot uses AI. Check for mistakes.
Comment on lines 935 to +937
// Initialize HTTP server (libuv + llhttp)
log_info("Initializing web server on port %d (daemon_mode: %s)",
config.web_port, daemon_mode ? "true" : "false");
log_info("Initializing web server on %s:%d (daemon_mode: %s)",
config.web_bind_ip, config.web_port, daemon_mode ? "true" : "false");
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Daemon-mode port verification still attempts to connect to INADDR_LOOPBACK regardless of the configured bind address. With web_bind_ip now configurable, binding to a specific non-loopback interface (e.g., 192.168.x.x) will cause this verification to fail and log misleading warnings. Update the verification logic to connect to the configured bind address (or treat 0.0.0.0 as a special case and verify via loopback).

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants