frontend link fix
This commit is contained in:
@@ -30,6 +30,8 @@ UPDATE_LOG = "/var/log/sovran-hub-update.log"
|
|||||||
UPDATE_STATUS = "/var/log/sovran-hub-update.status"
|
UPDATE_STATUS = "/var/log/sovran-hub-update.status"
|
||||||
UPDATE_UNIT = "sovran-hub-update.service"
|
UPDATE_UNIT = "sovran-hub-update.service"
|
||||||
|
|
||||||
|
INTERNAL_IP_FILE = "/var/lib/secrets/internal-ip"
|
||||||
|
|
||||||
REBOOT_COMMAND = ["reboot"]
|
REBOOT_COMMAND = ["reboot"]
|
||||||
|
|
||||||
CATEGORY_ORDER = [
|
CATEGORY_ORDER = [
|
||||||
@@ -154,6 +156,17 @@ def _get_internal_ip() -> str:
|
|||||||
return "unavailable"
|
return "unavailable"
|
||||||
|
|
||||||
|
|
||||||
|
def _save_internal_ip(ip: str):
|
||||||
|
"""Write the internal IP to a file so credentials can reference it."""
|
||||||
|
if ip and ip != "unavailable":
|
||||||
|
try:
|
||||||
|
os.makedirs(os.path.dirname(INTERNAL_IP_FILE), exist_ok=True)
|
||||||
|
with open(INTERNAL_IP_FILE, "w") as f:
|
||||||
|
f.write(ip)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def _get_external_ip() -> str:
|
def _get_external_ip() -> str:
|
||||||
MAX_IP_LENGTH = 46
|
MAX_IP_LENGTH = 46
|
||||||
for url in [
|
for url in [
|
||||||
@@ -245,7 +258,7 @@ def _resolve_credential(cred: dict) -> dict | None:
|
|||||||
return {"label": label, "value": value, "multiline": multiline}
|
return {"label": label, "value": value, "multiline": multiline}
|
||||||
|
|
||||||
|
|
||||||
# ── Routes ───────────<EFBFBD><EFBFBD>───────────────────────────────────────────
|
# ── Routes ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
@app.get("/", response_class=HTMLResponse)
|
@app.get("/", response_class=HTMLResponse)
|
||||||
async def index(request: Request):
|
async def index(request: Request):
|
||||||
@@ -392,6 +405,8 @@ async def api_network():
|
|||||||
loop.run_in_executor(None, _get_internal_ip),
|
loop.run_in_executor(None, _get_internal_ip),
|
||||||
loop.run_in_executor(None, _get_external_ip),
|
loop.run_in_executor(None, _get_external_ip),
|
||||||
)
|
)
|
||||||
|
# Keep the internal-ip file in sync for credential lookups
|
||||||
|
_save_internal_ip(internal)
|
||||||
return {"internal_ip": internal, "external_ip": external}
|
return {"internal_ip": internal, "external_ip": external}
|
||||||
|
|
||||||
|
|
||||||
@@ -461,4 +476,14 @@ async def api_updates_status(offset: int = 0):
|
|||||||
"result": result,
|
"result": result,
|
||||||
"log": new_log,
|
"log": new_log,
|
||||||
"offset": new_offset,
|
"offset": new_offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ── Startup: seed the internal IP file immediately ───────────────
|
||||||
|
|
||||||
|
@app.on_event("startup")
|
||||||
|
async def _startup_save_ip():
|
||||||
|
"""Write internal IP to file on server start so credentials work immediately."""
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
ip = await loop.run_in_executor(None, _get_internal_ip)
|
||||||
|
_save_internal_ip(ip)
|
||||||
@@ -793,13 +793,15 @@ button.btn-reboot:hover:not(:disabled) {
|
|||||||
|
|
||||||
/* ── Credential links ─────────────────────────────────────── */
|
/* ── Credential links ─────────────────────────────────────── */
|
||||||
.creds-link {
|
.creds-link {
|
||||||
color: #58a6ff;
|
color: #7ee787;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
.creds-link:hover {
|
.creds-link:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
color: #79c0ff;
|
color: #a5f0b0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -209,37 +209,6 @@ LAUNCHER
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
config = {
|
config = {
|
||||||
# ── Save internal IP for hub credentials ────────────────────
|
|
||||||
systemd.services.save-internal-ip = {
|
|
||||||
description = "Save internal IP address for hub credentials";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
after = [ "network-online.target" ];
|
|
||||||
wants = [ "network-online.target" ];
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
RemainAfterExit = true;
|
|
||||||
};
|
|
||||||
path = [ pkgs.iproute2 pkgs.coreutils pkgs.hostname ];
|
|
||||||
script = ''
|
|
||||||
mkdir -p /var/lib/secrets
|
|
||||||
IP=$(hostname -I | awk '{print $1}')
|
|
||||||
if [ -n "$IP" ]; then
|
|
||||||
echo "$IP" > /var/lib/secrets/internal-ip
|
|
||||||
chmod 644 /var/lib/secrets/internal-ip
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# ── Refresh IP periodically (in case DHCP changes it) ──────
|
|
||||||
systemd.timers.save-internal-ip = {
|
|
||||||
wantedBy = [ "timers.target" ];
|
|
||||||
timerConfig = {
|
|
||||||
OnBootSec = "30s";
|
|
||||||
OnUnitActiveSec = "15min";
|
|
||||||
Unit = "save-internal-ip.service";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# ── Web server as a systemd service ────────────────────────
|
# ── Web server as a systemd service ────────────────────────
|
||||||
systemd.services.sovran-hub-web = {
|
systemd.services.sovran-hub-web = {
|
||||||
description = "Sovran_SystemsOS Hub Web Interface";
|
description = "Sovran_SystemsOS Hub Web Interface";
|
||||||
|
|||||||
Reference in New Issue
Block a user