From 3234acf43523859efe249b7b624e5152c285796f Mon Sep 17 00:00:00 2001 From: max Date: Sun, 27 Sep 2026 19:13:22 +0200 Subject: [PATCH] feat(release): v0.3.4 - in-place installer upgrades, mutual exclusion guards, 2FA, and telemetry cap --- README.md | 2 +- RELEASE_NOTES.md | 17 ++++++ compilation/install_linux_client.sh | 20 +++++++ compilation/install_linux_server.sh | 24 +++++++- compilation/installer_client.iss | 92 ++++++++++++++++++++++++++--- compilation/installer_client.nsi | 53 +++++++++++++++-- compilation/installer_server.iss | 81 +++++++++++++++++++++++-- compilation/installer_server.nsi | 44 +++++++++++++- 8 files changed, 310 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index c47ec6d..bf859bc 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ # LOGAR: Fleet Log Aggregation & Centralized Provisioning System ### *Secure Log Aggregation, PKI Fleet Licensing & Centralized Delivery for Autonomous AI Analysis* -[![Version](https://img.shields.io/badge/version-0.3.3-blue.svg)](RELEASE_NOTES.md) +[![Version](https://img.shields.io/badge/version-0.3.4-blue.svg)](RELEASE_NOTES.md) [![Tests](https://img.shields.io/badge/tests-42%20passed-success.svg)](tests/) [![Security](https://img.shields.io/badge/mTLS-TLS%201.3-green.svg)](https://gitea.eibl.tech/me0nline/LOGAR/wiki/PKI-and-Licensing) [![Branding](https://img.shields.io/badge/branding-guide-cyan.svg)](https://gitea.eibl.tech/me0nline/LOGAR/wiki/Branding-Guide) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 4a53d01..e6d056f 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,22 @@ # LOGAR Release Notes +## [v0.3.4] - 2026-09-27 + +### 🔄 In-Place Installer Upgrades & Mutual Exclusion Guards +- **Seamless In-Place Upgrades**: Windows (Inno Setup & NSIS) and Linux installers now detect existing installations automatically. In upgrade mode, installers stop background services, update core binaries and runtime in-place, and restart services without overwriting configuration files (`server_config.json`, `client_config.json`), database state (`logar_state.db`), state tracking (`client_state.json`), or mTLS certificates. +- **Host Mutual Exclusion Validation**: Added pre-installation validation across all installers to prevent accidental co-installation of LOGAR Server and LOGAR Client on the same host, showing descriptive guidance to administrators. + +### 🛡️ WebUI 2FA & Telemetry Stability +- **Server Hub TOTP Two-Factor Authentication**: Implemented RFC 6238 TOTP 2FA for the LOGAR Server Hub web portal (`:8443`), featuring interactive QR code setup, secret generation, and secure session validation. +- **Telemetry Stream UI Buffer Capping**: Limited the live verified telemetry stream view to the latest 50 events in the Server Hub dashboard for enhanced browser performance and UI stability. + +### 🔑 Licensing Authority Management & Registry Tooling +- **Revocation, Reinstatement & License Deletion**: Enhanced the Master Licensing Authority (`logar.eibl.tech`) with instant license revocation, reinstatement of revoked licenses, and conditional permanent deletion of revoked records. +- **Interactive Capability Explorer**: Added interactive implementation breakdown modals across core capabilities on the public project landing page. +- **Automated Gitea Container Pruning**: Added `prune_images.py` utility to maintain clean container registries by keeping only the latest active image versions. + +--- + ## [v0.3.3] - 2026-09-27 ### 🎨 Brand Identity, Centralized Asset Library & Design System diff --git a/compilation/install_linux_client.sh b/compilation/install_linux_client.sh index 028d847..61110a5 100644 --- a/compilation/install_linux_client.sh +++ b/compilation/install_linux_client.sh @@ -7,6 +7,26 @@ ENROLL_SECRET="${2:-}" INSTALL_DIR="/opt/logar-client" CONFIG_DIR="/etc/logar" +# 1. Mutual Exclusion Check: Deny installation if LOGAR Server is present +if [ -f "/opt/logar-server/Server" ] || [ -f "/etc/systemd/system/logar-server.service" ]; then + echo "[-] Error: LOGAR Server is already installed on this machine." >&2 + echo "[-] LOGAR Client cannot be installed on a host where LOGAR Server is present (LOGAR Server includes built-in log collection)." >&2 + echo "[-] Please uninstall LOGAR Server first before installing LOGAR Client." >&2 + exit 1 +fi + +# 2. Existing LOGAR Client Detection for In-Place Update Mode +IS_UPDATE=0 +if [ -f "${INSTALL_DIR}/Linux_Client" ] || [ -f "/etc/systemd/system/logar-client.service" ]; then + IS_UPDATE=1 + echo "[*] Existing LOGAR Client installation detected. Performing in-place upgrade..." +fi + +if [ "${IS_UPDATE}" -eq 1 ] && command -v systemctl >/dev/null 2>&1; then + echo "[*] Stopping LOGAR Client service for upgrade..." + systemctl stop logar-client.service || true +fi + echo "[+] Installing LOGAR Client..." mkdir -p "${INSTALL_DIR}" "${CONFIG_DIR}/certs" chmod 700 "${CONFIG_DIR}/certs" diff --git a/compilation/install_linux_server.sh b/compilation/install_linux_server.sh index 5d96b8e..47519f6 100644 --- a/compilation/install_linux_server.sh +++ b/compilation/install_linux_server.sh @@ -21,14 +21,34 @@ echo "============================================================" echo " LOGAR Server Enterprise Linux Installer" echo "============================================================" -# Interactive configuration if running in a terminal without CLI arguments -if [ -t 0 ]; then +# 1. Mutual Exclusion Check: Deny installation if LOGAR Client is present +if [ -f "/opt/logar-client/Linux_Client" ] || [ -f "/etc/systemd/system/logar-client.service" ]; then + echo "[-] Error: LOGAR Client is already installed on this machine." >&2 + echo "[-] LOGAR Server cannot be installed on a host where LOGAR Client is present (LOGAR Server includes built-in log collection)." >&2 + echo "[-] Please uninstall LOGAR Client first before installing LOGAR Server." >&2 + exit 1 +fi + +# 2. Existing LOGAR Server Detection for In-Place Update Mode +IS_UPDATE=0 +if [ -f "${INSTALL_DIR}/Server" ] || [ -f "/etc/systemd/system/logar-server.service" ]; then + IS_UPDATE=1 + echo "[*] Existing LOGAR Server installation detected. Performing in-place upgrade..." +fi + +# Interactive configuration if running in a terminal without CLI arguments (only for fresh install) +if [ "${IS_UPDATE}" -eq 0 ] && [ -t 0 ]; then read -r -p "Enter Data and Configuration Directory [${CONFIG_DIR}]: " USER_CFG if [ -n "${USER_CFG}" ]; then CONFIG_DIR="${USER_CFG}" fi fi +if [ "${IS_UPDATE}" -eq 1 ] && command -v systemctl >/dev/null 2>&1; then + echo "[*] Stopping LOGAR Server service for upgrade..." + systemctl stop logar-server.service || true +fi + mkdir -p "${INSTALL_DIR}" "${CONFIG_DIR}" "/var/log/logar" if [ -f "dist/Server.bin" ]; then diff --git a/compilation/installer_client.iss b/compilation/installer_client.iss index f5213de..5bc2c87 100644 --- a/compilation/installer_client.iss +++ b/compilation/installer_client.iss @@ -1,11 +1,13 @@ [Setup] +AppId={{9C4A6F1D-8975-476E-8512-4217DE029A88}} AppName=LOGAR Client -AppVersion=0.3.3 +AppVersion=0.3.4 AppPublisher=LOGAR AppPublisherURL=https://logar.eibl.tech AppSupportURL=https://logar.eibl.tech AppUpdatesURL=https://logar.eibl.tech DefaultDirName={autopf}\LOGAR +UsePreviousAppDir=yes OutputDir=..\dist OutputBaseFilename=LOGAR-Client-Setup PrivilegesRequired=admin @@ -17,9 +19,9 @@ WizardImageFile=assets\wizard_sidebar.bmp WizardSmallImageFile=assets\wizard_small.bmp VersionInfoCompany=LOGAR VersionInfoDescription=LOGAR Windows Edge Log Forwarder Setup -VersionInfoVersion=0.3.3.0 +VersionInfoVersion=0.3.4.0 VersionInfoProductName=LOGAR Client -VersionInfoProductVersion=0.3.3 +VersionInfoProductVersion=0.3.4 [Files] Source: "..\dist\Win_Client.exe"; DestDir: "{app}"; Flags: ignoreversion @@ -54,6 +56,58 @@ Type: filesandordirs; Name: "{commonappdata}\LOGAR" var DataDirPage: TInputDirWizardPage; ConfigFilePage: TInputFileWizardPage; + IsUpdateMode: Boolean; + ExistingDataDir: String; + +function InitializeSetup(): Boolean; +var + ServerFound: Boolean; + Val: String; +begin + Result := True; + IsUpdateMode := False; + ExistingDataDir := ''; + ServerFound := False; + + // 1. Mutual Exclusion Check: Deny installation if LOGAR Server is already present + if RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\LOGAR\LOGAR-Server') or + RegValueExists(HKEY_LOCAL_MACHINE, 'Software\LOGAR\LOGAR-Server', 'DataDir') or + RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\{{4F3D675E-1E4E-43B6-8C84-B47DE290BE4A}}_is1') or + RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{{4F3D675E-1E4E-43B6-8C84-B47DE290BE4A}}_is1') or + RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\LOGAR Server_is1') or + RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\LOGAR Server_is1') or + FileExists(ExpandConstant('{autopf}\LOGAR-Server\Server.exe')) then + begin + ServerFound := True; + end; + + if ServerFound then + begin + MsgBox('LOGAR Server is already installed on this machine.'#13#10#13#10 + + 'LOGAR Client cannot be installed on a LOGAR Server host (LOGAR Server already provides built-in log collection).'#13#10#13#10 + + 'Please uninstall LOGAR Server first if you wish to run a standalone forwarder client.', + mbCriticalError, MB_OK); + Result := False; + Exit; + end; + + // 2. Existing LOGAR Client Detection for In-Place Update Mode + if RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\LOGAR\LOGAR-Client') or + RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\{{9C4A6F1D-8975-476E-8512-4217DE029A88}}_is1') or + RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{{9C4A6F1D-8975-476E-8512-4217DE029A88}}_is1') or + RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\LOGAR Client_is1') or + RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\LOGAR Client_is1') or + FileExists(ExpandConstant('{autopf}\LOGAR\Win_Client.exe')) then + begin + IsUpdateMode := True; + if RegQueryStringValue(HKEY_LOCAL_MACHINE, 'Software\LOGAR\LOGAR-Client', 'DataDir', Val) then + ExistingDataDir := Val; + + MsgBox('An existing installation of LOGAR Client was detected.'#13#10#13#10 + + 'Setup will perform an in-place update: core binaries will be updated, while your existing configuration (client_config.json), state tracking, and certificates will be preserved.', + mbInformation, MB_OK); + end; +end; procedure InitializeWizard; begin @@ -67,7 +121,10 @@ begin '' ); DataDirPage.Add('Data Directory:'); - DataDirPage.Values[0] := ExpandConstant('{commonappdata}\LOGAR'); + if (ExistingDataDir <> '') then + DataDirPage.Values[0] := ExistingDataDir + else + DataDirPage.Values[0] := ExpandConstant('{commonappdata}\LOGAR'); ConfigFilePage := CreateInputFilePage( DataDirPage.ID, @@ -80,8 +137,23 @@ begin ConfigFilePage.Add('Client Configuration (client_config.json):', 'JSON Files (*.json)|*.json|All Files (*.*)|*.*', '.json'); end; +function ShouldSkipPage(PageID: Integer): Boolean; +begin + Result := False; + if IsUpdateMode then + begin + if (PageID = wpSelectDir) or (PageID = DataDirPage.ID) or (PageID = ConfigFilePage.ID) then + Result := True; + end; +end; + function GetDataDir(Param: String): String; begin + if IsUpdateMode and (ExistingDataDir <> '') then + begin + Result := ExistingDataDir; + Exit; + end; Result := DataDirPage.Values[0]; if Result = '' then Result := ExpandConstant('{commonappdata}\LOGAR'); @@ -107,13 +179,17 @@ begin end else if CurStep = ssPostInstall then begin + RegWriteStringValue(HKEY_LOCAL_MACHINE, 'Software\LOGAR\LOGAR-Client', 'InstallDir', ExpandConstant('{app}')); RegWriteStringValue(HKEY_LOCAL_MACHINE, 'Software\LOGAR\LOGAR-Client', 'DataDir', GetDataDir('')); - CfgPath := GetConfigFile(''); - if (CfgPath <> '') and FileExists(CfgPath) then + if not IsUpdateMode then begin - DestCfg := GetDataDir('') + '\client_config.json'; - FileCopy(CfgPath, DestCfg, False); + CfgPath := GetConfigFile(''); + if (CfgPath <> '') and FileExists(CfgPath) then + begin + DestCfg := GetDataDir('') + '\client_config.json'; + FileCopy(CfgPath, DestCfg, False); + end; end; end; end; diff --git a/compilation/installer_client.nsi b/compilation/installer_client.nsi index 1c43ec0..6bdd39d 100644 --- a/compilation/installer_client.nsi +++ b/compilation/installer_client.nsi @@ -9,13 +9,13 @@ RequestExecutionLevel admin BrandingText "LOGAR Centralized Log Aggregator & Forwarder" -VIProductVersion "0.3.3.0" +VIProductVersion "0.3.4.0" VIAddVersionKey "ProductName" "LOGAR Client" VIAddVersionKey "CompanyName" "LOGAR" VIAddVersionKey "LegalCopyright" "© 2026 LOGAR" VIAddVersionKey "FileDescription" "LOGAR Windows Edge Log Forwarder Setup" -VIAddVersionKey "FileVersion" "0.3.3.0" -VIAddVersionKey "ProductVersion" "0.3.3.0" +VIAddVersionKey "FileVersion" "0.3.4.0" +VIAddVersionKey "ProductVersion" "0.3.4.0" # --- Visual Graphics & Branding --- !define MUI_ICON "assets/logo.ico" @@ -28,6 +28,7 @@ VIAddVersionKey "ProductVersion" "0.3.3.0" Var DATADIR Var CFGFILE +Var IS_UPDATE Var CfgDialog Var CfgFileInput Var CfgBrowseBtn @@ -43,6 +44,7 @@ Var CfgBrowseBtn # Directory Page 1: Installation Directory !define MUI_PAGE_HEADER_TEXT "Choose Installation Location" !define MUI_PAGE_HEADER_SUBTEXT "Choose the folder in which to install program binaries." +!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfUpdate !define MUI_DIRECTORYPAGE_VARIABLE $INSTDIR !insertmacro MUI_PAGE_DIRECTORY @@ -51,6 +53,7 @@ Var CfgBrowseBtn !define MUI_PAGE_HEADER_SUBTEXT "Choose where state tracking, certificates, and configuration files should be stored." !define MUI_DIRECTORYPAGE_TEXT_TOP "Choose the folder where LOGAR Client should store state tracking (client_state.json), configuration (client_config.json), and mTLS certificates.$\r$\n$\r$\nDefault is recommended for automatic background service access." !define MUI_DIRECTORYPAGE_TEXT_DESTINATION "Data & Storage Folder" +!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfUpdate !define MUI_DIRECTORYPAGE_VARIABLE $DATADIR !insertmacro MUI_PAGE_DIRECTORY @@ -71,13 +74,51 @@ Page custom ConfigPageCreate ConfigPageLeave !insertmacro MUI_LANGUAGE "English" +Function SkipIfUpdate + ${If} $IS_UPDATE == "1" + Abort + ${EndIf} +FunctionEnd + Function .onInit SetShellVarContext all StrCpy $DATADIR "$APPDATA\LOGAR" StrCpy $CFGFILE "" + StrCpy $IS_UPDATE "0" + + # 1. Mutual Exclusion Check: Deny installation if LOGAR Server is present + ReadRegStr $0 HKLM "Software\LOGAR\LOGAR-Server" "DataDir" + ReadRegStr $1 HKLM "Software\LOGAR\LOGAR-Server" "InstallDir" + ${If} $0 != "" + ${OrIf} $1 != "" + ${OrIf} ${FileExists} "$PROGRAMFILES64\LOGAR-Server\Server.exe" + ${OrIf} ${FileExists} "$PROGRAMFILES\LOGAR-Server\Server.exe" + MessageBox MB_ICONSTOP|MB_OK "LOGAR Server is already installed on this machine.$\r$\n$\r$\nLOGAR Client cannot be co-installed on a LOGAR Server host (LOGAR Server already provides built-in log collection).$\r$\n$\r$\nPlease uninstall LOGAR Server first if you wish to run a standalone forwarder client." + Abort + ${EndIf} + + # 2. Existing LOGAR Client Detection for In-Place Update Mode + ReadRegStr $0 HKLM "Software\LOGAR\LOGAR-Client" "DataDir" + ReadRegStr $1 HKLM "Software\LOGAR\LOGAR-Client" "InstallDir" + ${If} $0 != "" + ${OrIf} $1 != "" + ${OrIf} ${FileExists} "$INSTDIR\Win_Client.exe" + StrCpy $IS_UPDATE "1" + ${If} $0 != "" + StrCpy $DATADIR $0 + ${EndIf} + ${If} $1 != "" + StrCpy $INSTDIR $1 + ${EndIf} + MessageBox MB_ICONINFORMATION|MB_OK "An existing installation of LOGAR Client was detected.$\r$\n$\r$\nSetup will perform an in-place update: program files will be updated while your existing configuration (client_config.json), state tracking, and certificates are preserved." + ${EndIf} FunctionEnd Function ConfigPageCreate + ${If} $IS_UPDATE == "1" + Abort + ${EndIf} + nsDialogs::Create 1018 Pop $CfgDialog ${If} $CfgDialog == error @@ -130,8 +171,9 @@ Section "Install" CreateDirectory "$DATADIR" ExecWait 'icacls "$DATADIR" /grant "*S-1-5-32-545:(OI)(CI)M" /T /Q' - # If client config file was selected, copy to data directory - ${If} $CFGFILE != "" + # If client config file was selected and not updating existing config, copy to data directory + ${If} $IS_UPDATE != "1" + ${AndIf} $CFGFILE != "" ${AndIf} ${FileExists} "$CFGFILE" CopyFiles /SILENT "$CFGFILE" "$DATADIR\client_config.json" ${EndIf} @@ -145,6 +187,7 @@ Section "Install" ExecWait '"$INSTDIR\nssm.exe" start LOGAR_Client' WriteUninstaller "$INSTDIR\uninstall.exe" + WriteRegStr HKLM "Software\LOGAR\LOGAR-Client" "InstallDir" "$INSTDIR" WriteRegStr HKLM "Software\LOGAR\LOGAR-Client" "DataDir" "$DATADIR" SectionEnd diff --git a/compilation/installer_server.iss b/compilation/installer_server.iss index d3a5ab5..54e1948 100644 --- a/compilation/installer_server.iss +++ b/compilation/installer_server.iss @@ -1,11 +1,13 @@ [Setup] +AppId={{4F3D675E-1E4E-43B6-8C84-B47DE290BE4A}} AppName=LOGAR Server -AppVersion=0.3.3 +AppVersion=0.3.4 AppPublisher=LOGAR AppPublisherURL=https://logar.eibl.tech AppSupportURL=https://logar.eibl.tech AppUpdatesURL=https://logar.eibl.tech DefaultDirName={autopf}\LOGAR-Server +UsePreviousAppDir=yes OutputDir=..\dist OutputBaseFilename=LOGAR-Server-Setup PrivilegesRequired=admin @@ -17,9 +19,9 @@ WizardImageFile=assets\wizard_sidebar.bmp WizardSmallImageFile=assets\wizard_small.bmp VersionInfoCompany=LOGAR VersionInfoDescription=LOGAR Cloud Hub & TCP Ingestion Server Setup -VersionInfoVersion=0.3.3.0 +VersionInfoVersion=0.3.4.0 VersionInfoProductName=LOGAR Server -VersionInfoProductVersion=0.3.3 +VersionInfoProductVersion=0.3.4 [Files] Source: "..\dist\Server.exe"; DestDir: "{app}"; Flags: ignoreversion @@ -54,6 +56,58 @@ Type: filesandordirs; Name: "{commonappdata}\LOGAR-Server" [Code] var DataDirPage: TInputDirWizardPage; + IsUpdateMode: Boolean; + ExistingDataDir: String; + +function InitializeSetup(): Boolean; +var + ClientFound: Boolean; + Val: String; +begin + Result := True; + IsUpdateMode := False; + ExistingDataDir := ''; + ClientFound := False; + + // 1. Mutual Exclusion Check: Deny installation if LOGAR Client is already present + if RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\LOGAR\LOGAR-Client') or + RegValueExists(HKEY_LOCAL_MACHINE, 'Software\LOGAR\LOGAR-Client', 'DataDir') or + RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\{{9C4A6F1D-8975-476E-8512-4217DE029A88}}_is1') or + RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{{9C4A6F1D-8975-476E-8512-4217DE029A88}}_is1') or + RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\LOGAR Client_is1') or + RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\LOGAR Client_is1') or + FileExists(ExpandConstant('{autopf}\LOGAR\Win_Client.exe')) then + begin + ClientFound := True; + end; + + if ClientFound then + begin + MsgBox('LOGAR Client is already installed on this machine.'#13#10#13#10 + + 'LOGAR Server cannot be installed on a host where LOGAR Client is present (LOGAR Server already includes built-in local log collection).'#13#10#13#10 + + 'Please uninstall LOGAR Client before installing LOGAR Server.', + mbCriticalError, MB_OK); + Result := False; + Exit; + end; + + // 2. Existing LOGAR Server Detection for In-Place Update Mode + if RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\LOGAR\LOGAR-Server') or + RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\{{4F3D675E-1E4E-43B6-8C84-B47DE290BE4A}}_is1') or + RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{{4F3D675E-1E4E-43B6-8C84-B47DE290BE4A}}_is1') or + RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\LOGAR Server_is1') or + RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\LOGAR Server_is1') or + FileExists(ExpandConstant('{autopf}\LOGAR-Server\Server.exe')) then + begin + IsUpdateMode := True; + if RegQueryStringValue(HKEY_LOCAL_MACHINE, 'Software\LOGAR\LOGAR-Server', 'DataDir', Val) then + ExistingDataDir := Val; + + MsgBox('An existing installation of LOGAR Server was detected.'#13#10#13#10 + + 'Setup will perform an in-place update: core binaries will be updated, while your existing configuration (server_config.json), database (logar_state.db), and certificates will be preserved.', + mbInformation, MB_OK); + end; +end; procedure InitializeWizard; begin @@ -67,11 +121,29 @@ begin '' ); DataDirPage.Add('Data Directory:'); - DataDirPage.Values[0] := ExpandConstant('{commonappdata}\LOGAR-Server'); + if (ExistingDataDir <> '') then + DataDirPage.Values[0] := ExistingDataDir + else + DataDirPage.Values[0] := ExpandConstant('{commonappdata}\LOGAR-Server'); +end; + +function ShouldSkipPage(PageID: Integer): Boolean; +begin + Result := False; + if IsUpdateMode then + begin + if (PageID = wpSelectDir) or (PageID = DataDirPage.ID) then + Result := True; + end; end; function GetDataDir(Param: String): String; begin + if IsUpdateMode and (ExistingDataDir <> '') then + begin + Result := ExistingDataDir; + Exit; + end; Result := DataDirPage.Values[0]; if Result = '' then Result := ExpandConstant('{commonappdata}\LOGAR-Server'); @@ -91,6 +163,7 @@ begin end else if CurStep = ssPostInstall then begin + RegWriteStringValue(HKEY_LOCAL_MACHINE, 'Software\LOGAR\LOGAR-Server', 'InstallDir', ExpandConstant('{app}')); RegWriteStringValue(HKEY_LOCAL_MACHINE, 'Software\LOGAR\LOGAR-Server', 'DataDir', GetDataDir('')); end; end; diff --git a/compilation/installer_server.nsi b/compilation/installer_server.nsi index cb9cbdc..93c4a6d 100644 --- a/compilation/installer_server.nsi +++ b/compilation/installer_server.nsi @@ -8,13 +8,13 @@ RequestExecutionLevel admin BrandingText "LOGAR Centralized Log Aggregator & Ingestion Hub" -VIProductVersion "0.3.3.0" +VIProductVersion "0.3.4.0" VIAddVersionKey "ProductName" "LOGAR Server" VIAddVersionKey "CompanyName" "LOGAR" VIAddVersionKey "LegalCopyright" "© 2026 LOGAR" VIAddVersionKey "FileDescription" "LOGAR Cloud Hub & TCP Ingestion Server Setup" -VIAddVersionKey "FileVersion" "0.3.3.0" -VIAddVersionKey "ProductVersion" "0.3.3.0" +VIAddVersionKey "FileVersion" "0.3.4.0" +VIAddVersionKey "ProductVersion" "0.3.4.0" # --- Visual Graphics & Branding --- !define MUI_ICON "assets/logo.ico" @@ -26,6 +26,7 @@ VIAddVersionKey "ProductVersion" "0.3.3.0" !define MUI_UNWELCOMEFINISHPAGE_BITMAP "assets/wizard_sidebar.bmp" Var DATADIR +Var IS_UPDATE # --- UI Pages --- !define MUI_ABORTWARNING @@ -38,6 +39,7 @@ Var DATADIR # Directory Page 1: Installation Directory !define MUI_PAGE_HEADER_TEXT "Choose Installation Location" !define MUI_PAGE_HEADER_SUBTEXT "Choose the folder in which to install program binaries." +!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfUpdate !define MUI_DIRECTORYPAGE_VARIABLE $INSTDIR !insertmacro MUI_PAGE_DIRECTORY @@ -46,6 +48,7 @@ Var DATADIR !define MUI_PAGE_HEADER_SUBTEXT "Choose where database, certificates, and configuration files should be stored." !define MUI_DIRECTORYPAGE_TEXT_TOP "Choose the folder where LOGAR Server should store its database (logar_state.db), configuration (server_config.json), and mTLS certificates.$\r$\n$\r$\nDefault is recommended for automatic background service access." !define MUI_DIRECTORYPAGE_TEXT_DESTINATION "Data & Storage Folder" +!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfUpdate !define MUI_DIRECTORYPAGE_VARIABLE $DATADIR !insertmacro MUI_PAGE_DIRECTORY @@ -63,9 +66,43 @@ Var DATADIR !insertmacro MUI_LANGUAGE "English" +Function SkipIfUpdate + ${If} $IS_UPDATE == "1" + Abort + ${EndIf} +FunctionEnd + Function .onInit SetShellVarContext all StrCpy $DATADIR "$APPDATA\LOGAR-Server" + StrCpy $IS_UPDATE "0" + + # 1. Mutual Exclusion Check: Deny installation if LOGAR Client is present + ReadRegStr $0 HKLM "Software\LOGAR\LOGAR-Client" "DataDir" + ReadRegStr $1 HKLM "Software\LOGAR\LOGAR-Client" "InstallDir" + ${If} $0 != "" + ${OrIf} $1 != "" + ${OrIf} ${FileExists} "$PROGRAMFILES64\LOGAR\Win_Client.exe" + ${OrIf} ${FileExists} "$PROGRAMFILES\LOGAR\Win_Client.exe" + MessageBox MB_ICONSTOP|MB_OK "LOGAR Client is already installed on this machine.$\r$\n$\r$\nLOGAR Server cannot be installed on a host where LOGAR Client is present (LOGAR Server already includes built-in local log collection).$\r$\n$\r$\nPlease uninstall LOGAR Client before installing LOGAR Server." + Abort + ${EndIf} + + # 2. Existing LOGAR Server Detection for In-Place Update Mode + ReadRegStr $0 HKLM "Software\LOGAR\LOGAR-Server" "DataDir" + ReadRegStr $1 HKLM "Software\LOGAR\LOGAR-Server" "InstallDir" + ${If} $0 != "" + ${OrIf} $1 != "" + ${OrIf} ${FileExists} "$INSTDIR\Server.exe" + StrCpy $IS_UPDATE "1" + ${If} $0 != "" + StrCpy $DATADIR $0 + ${EndIf} + ${If} $1 != "" + StrCpy $INSTDIR $1 + ${EndIf} + MessageBox MB_ICONINFORMATION|MB_OK "An existing installation of LOGAR Server was detected.$\r$\n$\r$\nSetup will perform an in-place update: program files will be updated while your existing database, configuration (server_config.json), and certificates are preserved." + ${EndIf} FunctionEnd Section "Install" @@ -95,6 +132,7 @@ Section "Install" ExecWait '"$INSTDIR\nssm.exe" start LOGAR_Server' WriteUninstaller "$INSTDIR\uninstall.exe" + WriteRegStr HKLM "Software\LOGAR\LOGAR-Server" "InstallDir" "$INSTDIR" WriteRegStr HKLM "Software\LOGAR\LOGAR-Server" "DataDir" "$DATADIR" SectionEnd