diff --git a/.gitignore b/.gitignore index eb53399430cf..28faf32e8150 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ cover*.out cmd/agent/agent cmd/agentctl/agentctl dist/ + +**/.DS_Store \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index dfe06086939e..6bb2b38167da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ can be found at [#317](https://github.com/grafana/agent/issues/317). # Master (unreleased) +- [ENHANCEMENT] Windows NSIS (Installer) code added but not building automatically yet, along with dependencies (@mattdurham) + - [FEATURE] Added [ElasticSearch exporter](https://github.com/justwatchcom/elasticsearch_exporter) integration. (@colega) diff --git a/Makefile b/Makefile index c08d52fc1ebb..1fb87d819878 100644 --- a/Makefile +++ b/Makefile @@ -199,6 +199,7 @@ dist: dist-agent dist-agentctl dist-packages pushd dist && sha256sum * > SHA256SUMS && popd .PHONY: dist + dist-agent: dist/agent-linux-amd64 dist/agent-linux-arm64 dist/agent-linux-armv6 dist/agent-linux-armv7 dist/agent-darwin-amd64 dist/agent-windows-amd64.exe dist/agent-linux-amd64: @CGO_ENABLED=1 GOOS=linux GOARCH=amd64; $(seego) build $(CGO_FLAGS) -o $@ ./cmd/agent @@ -212,6 +213,10 @@ dist/agent-darwin-amd64: @CGO_ENABLED=1 GOOS=darwin GOARCH=amd64; $(seego) build $(CGO_FLAGS) -o $@ ./cmd/agent dist/agent-windows-amd64.exe: @CGO_ENABLED=1 GOOS=windows GOARCH=amd64; $(seego) build $(CGO_FLAGS) -o $@ ./cmd/agent +dist/agent-windows-installer.exe: dist/agent-windows-install-dockerbuild + docker run --rm -t -v $(CURDIR)/dist:/app windows_nsis +dist/agent-windows-install-dockerbuild: dist/agent-windows-amd64.exe + cp ./dist/agent-windows-amd64.exe ./packaging/windows && docker build ./packaging/windows -t windows_nsis dist-agentctl: dist/agentctl-linux-amd64 dist/agentctl-linux-arm64 dist/agentctl-linux-armv6 dist/agentctl-linux-armv7 dist/agentctl-darwin-amd64 dist/agentctl-windows-amd64.exe dist/agentctl-linux-amd64: diff --git a/docs/assets/exporter.png b/docs/assets/exporter.png new file mode 100644 index 000000000000..83712510a1d2 Binary files /dev/null and b/docs/assets/exporter.png differ diff --git a/docs/assets/remote_options.png b/docs/assets/remote_options.png new file mode 100644 index 000000000000..01e2d0d6cc0b Binary files /dev/null and b/docs/assets/remote_options.png differ diff --git a/docs/windows.md b/docs/windows.md new file mode 100644 index 000000000000..4f3bed3aba19 --- /dev/null +++ b/docs/windows.md @@ -0,0 +1,35 @@ +# Windows Installation + +## Overview + +The installer will install Grafana Agent into the default directory (C:\Program Files (x86)\Grafana Agent) and setting Agent as a service via [NSSM](https://nssm.cc/), optionally you can select to install the [Windows Exporter](https://github.com/prometheus-community/windows_exporter) with all default options. + +## Installation + +![](./assets/remote_options.png) + +**Remote Write** is used to specify any compatible Prometheus Endpoint. **User** and **Password** are used for basic auth. This will generate a configuration snippet like the below. + +``` + prometheus_remote_write: + - url: https://example.com + basic_auth: + username: "legit_username" + password: "legit_password" +``` + +
+ +![](./assets/exporter.png) + +Selecting the checkbox will install the Windows Exporter and start the Windows Exporter has a service, serving metrics from `localhost:9182/metrics`. + +After installation ensure that you can reach `http://localhost:12345/-/healthy` and `http://localhost:12345/agent/api/v1/targets`. + +## Security + +The Agent configuration is installed alongside the Agent itself, by default. Depending on your configuration, you may not want that for security reasons and may instead want to make it protected. You can do that by changing the files attributes or changing the configuration via `nssm.exe" set "Grafana Agent" AppParameters "--config.file=\"CustomDirectory\agent-config.yaml\""`, then restarting the service. + +## Uninstall + +Via Remove Programs or uninstaller.exe in the directory the Agent is installed in. This will turn off and remove the Agent and Windows Export services then delete any installed files in the default directory. diff --git a/packaging/windows/Dockerfile b/packaging/windows/Dockerfile new file mode 100644 index 000000000000..db8bb10e94d7 --- /dev/null +++ b/packaging/windows/Dockerfile @@ -0,0 +1,15 @@ +FROM debian +RUN apt-get update && \ + apt-get install -y nsis && \ + apt-get install -y wget && \ + apt-get install -y unzip +RUN mkdir app +WORKDIR /home +RUN wget https://nssm.cc/release/nssm-2.24.zip +RUN unzip nssm-2.24.zip +RUN wget --secure-protocol=auto --https-only https://github.com/prometheus-community/windows_exporter/releases/download/v0.15.0/windows_exporter-0.15.0-amd64.exe +RUN mv ./nssm-2.24/win64/nssm.exe ./nssm.exe +COPY logo.ico logo.ico +COPY install_script.nsis install_script.nsis +COPY agent-windows-amd64.exe agent-windows-amd64.exe +ENTRYPOINT ["makensis", "-V4", "/home/install_script.nsis"] \ No newline at end of file diff --git a/packaging/windows/install_script.nsis b/packaging/windows/install_script.nsis new file mode 100644 index 000000000000..ba657129a86c --- /dev/null +++ b/packaging/windows/install_script.nsis @@ -0,0 +1,274 @@ +Unicode true +# This installs two files, agent-windows-amd64.exe and logo.ico, creates a start menu shortcut, builds an uninstaller, and +# adds uninstall information to the registry for Add/Remove Programs + +!define APPNAME "Grafana Cloud Agent" +!define DESCRIPTION "The Grafana Cloud Agent collects observability data and sends it to a compatible remote write endpoint" +# These will be displayed by the "Click here for support information" link in "Add/Remove Programs" +!define HELPURL "https://github.com/grafana/agent/discussions" # "Support Information" link +!define UPDATEURL "https://github.com/grafana/agent/releases" # "Product Updates" link +!define ABOUTURL "https://github.com/grafana/agent" # "Publisher" link +!include LogicLib.nsh + +RequestExecutionLevel admin #Require admin rights on NT6+ (When UAC is turned on) + +InstallDir "$PROGRAMFILES\${APPNAME}" + +# This will be in the installer/uninstaller's title bar +Name "${APPNAME}" +Icon "logo.ico" +outFile "/app/grafana-agent-installer.exe" + +!include LogicLib.nsh +!include nsDialogs.nsh +!include FileFunc.nsh + + +# Everything must be global Vars + +# These are handles to dialogs +Var Dialog +Var RemoteWriteLabel +Var RemoteWriteText + +Var RemoteWriteUserLabel +Var RemoteWriteUserText + +Var RemoteWritePasswordLabel +Var RemoteWritePasswordText + +Var EnableExporterLabel +Var EnableExporterCheck + +# These are strings that hold the values + +Var RemoteUrl +Var RemoteUser +Var RemotePassword +Var EnableExporterValue + +# Silent install params + +Var PassedInParameters + +Page directory +Page custom remoteWriteInfo remoteWriteInfoLeave +Page custom enableWindowsExporter enableWindowsExporterLeave +Page instfiles + + + +!macro VerifyUserIsAdmin +UserInfo::GetAccountType +pop $0 +${If} $0 != "admin" #Require admin rights on NT4+ + messageBox mb_iconstop "Administrator rights required!" + setErrorLevel 740 #ERROR_ELEVATION_REQUIRED + quit +${EndIf} +!macroend + + +Section SilentInstaller + IfSilent ThisIsSilent RunInstaller + ThisIsSilent: + ${GetParameters} $PassedInParameters + ${GetOptions} $PassedInParameters "/RemoteURL" $RemoteUrl + ${GetOptions} $PassedInParameters "/RemoteUser" $RemoteUser + ${GetOptions} $PassedInParameters "/RemotePassword" $RemotePassword + ${GetOptions} $PassedInParameters "/EnableExporter" $EnableExporterValue + Call Install + # TODO add error conditions + Return + RunInstaller: + Return +SectionEnd + + +Section "install" + IfSilent ThisIsSilent RunInstaller + ThisIsSilent: + Return + RunInstaller: + Call Install +SectionEnd + +Section "uninstall" + # Remove Start Menu launcher + delete "$SMPROGRAMS\${APPNAME}\${APPNAME}.lnk" + # Try to remove the Start Menu folder - this will only happen if it is empty + rmDir "$SMPROGRAMS\${APPNAME}" + # NSSM is the best way to wrap a generic exe has a service, else the service wont respond correctly to control messages + # This is cleanup on the service and removing the exporter. + ExecWait `"$INSTDIR\nssm.exe" stop "Grafana Agent"` + ExecWait `"$INSTDIR\nssm.exe" remove "Grafana Agent" confirm` + # If these arent running we are going to ignore the errors + ExecWait `"$INSTDIR\nssm.exe" stop "Windows Exporter"` + ExecWait `"$INSTDIR\nssm.exe" remove "Windows Exporter" confirm` + + # Remove files + delete $INSTDIR\agent-windows-amd64.exe + delete $INSTDIR\logo.ico + delete $INSTDIR\agent-config.yaml + delete $INSTDIR\windows_exporter-0.15.0-amd64.exe + delete $INSTDIR\nssm.exe + + # Always delete uninstaller as the last action + delete $INSTDIR\uninstall.exe + + # Try to remove the install directory - this will only happen if it is empty + rmDir $INSTDIR + + # Remove uninstaller information from the registry + DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" +SectionEnd + +Function remoteWriteInfo + nsDialogs::Create 1018 + Pop $Dialog + + ${If} $Dialog == error + Abort + ${EndIf} + ${NSD_CreateLabel} 0 0 100% 12u "Enter URL for remote write" + Pop $RemoteWriteLabel + + ${NSD_CreateText} 0 13u 100% 12u "" + Pop $RemoteWriteText + + ${NSD_CreateLabel} 0 26u 100% 12u "Enter User for remote write" + Pop $RemoteWriteUserLabel + + ${NSD_CreateText} 0 39u 100% 12u "" + Pop $RemoteWriteUserText + + ${NSD_CreateLabel} 0 52u 100% 12u "Enter Password for remote write" + Pop $RemoteWritePasswordLabel + + ${NSD_CreateText} 0 65u 100% 12u "" + Pop $RemoteWritePasswordText + + nsDialogs::Show +FunctionEnd + + +Function remoteWriteInfoLeave + ${NSD_GetText} $RemoteWriteText $RemoteUrl + ${NSD_GetText} $RemoteWriteUserText $RemoteUser + ${NSD_GetText} $RemoteWritePasswordText $RemotePassword +FunctionEnd + +Function enableWindowsExporter + nsDialogs::Create 1018 + Pop $Dialog + + ${If} $Dialog == error + Abort + ${EndIf} + + ${NSD_CreateLabel} 0 0 100% 12u "Add and Enable Windows Exporter" + Pop $EnableExporterLabel + + ${NSD_CreateCheckBox} 0 13u 100% 12u "" + Pop $EnableExporterCheck + + nsDialogs::Show +FunctionEnd + +Function enableWindowsExporterLeave + ${NSD_GetState} $EnableExporterCheck $EnableExporterValue + ${If} $EnableExporterValue == ${BST_CHECKED} + StrCpy $EnableExporterValue "true" + ${Else} + StrCpy $EnableExporterValue "false" + ${EndIf} +FunctionEnd + + +Function .onInit + setShellVarContext all + !insertmacro VerifyUserIsAdmin +FunctionEnd + +# Uninstaller +Function un.onInit + SetShellVarContext all + + #Verify the uninstaller - last chance to back out + MessageBox MB_OKCANCEL "Permanantly remove ${APPNAME}?" IDOK next + Abort + next: + !insertmacro VerifyUserIsAdmin +FunctionEnd + +Function Install + # Files for the install directory - to build the installer, these should be in the same directory as the install script (this file) + setOutPath $INSTDIR + # Files added here should be removed by the uninstaller (see section "uninstall") + file "agent-windows-amd64.exe" + file "logo.ico" + file "nssm.exe" + file "windows_exporter-0.15.0-amd64.exe" + # Add any other files for the install directory (license files, app data, etc) here + + # Uninstaller - See function un.onInit and section "uninstall" for configuration + writeUninstaller "$INSTDIR\uninstall.exe" + + # Registry information for add/remove programs + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME} - ${DESCRIPTION}" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "InstallLocation" "$\"$INSTDIR$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayIcon" "$\"$INSTDIR\logo.ico$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "Publisher" "$\"https://github.com/grafana/agent$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "HelpLink" "$\"${HELPURL}$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "URLUpdateInfo" "$\"${UPDATEURL}$\"" + WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "URLInfoAbout" "$\"${ABOUTURL}$\"" + # There is no option for modifying or repairing the install + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "NoModify" 1 + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "NoRepair" 1 + Call WriteConfig + + # Create our batch file, since services cant run with parameters + ExecWait `"$INSTDIR\nssm.exe" install "Grafana Agent" "$INSTDIR\agent-windows-amd64.exe"` + ExecWait '"$INSTDIR\nssm.exe" set "Grafana Agent" AppParameters "--config.file=\"$INSTDIR\agent-config.yaml\""' + ExecWait `"$INSTDIR\nssm.exe" start "Grafana Agent"` + ${If} $EnableExporterValue == "true" + ExecWait `"$INSTDIR\nssm.exe" install "Windows Exporter" "$INSTDIR\windows_exporter-0.15.0-amd64.exe"` + ExecWait `"$INSTDIR\nssm.exe" start "Windows Exporter"` + ${EndIf} +FunctionEnd + +Function WriteConfig + # Write the config file, its easier to do this way than replacing an values in a templated file + FileOpen $9 "$INSTDIR\agent-config.yaml" w #Opens a Empty File and fills it + FileWrite $9 `server:$\n` + FileWrite $9 ` http_listen_port: 12345$\n` + FileWrite $9 `prometheus:$\n` + FileWrite $9 ` wal_directory: /tmp/grafana-agent-wal$\n` + FileWrite $9 ` global:$\n` + FileWrite $9 ` scrape_interval: 15s$\n` + FileWrite $9 ` configs:$\n` + FileWrite $9 ` - name: integrations$\n` + FileWrite $9 ` scrape_configs:$\n` + ${If} $EnableExporterValue == "true" + FileWrite $9 ` - job_name: integrations/windows-exporter$\n` + FileWrite $9 ` metrics_path: /metrics$\n` + FileWrite $9 ` static_configs:$\n` + FileWrite $9 ` - targets:$\n` + FileWrite $9 ` - localhost:9182$\n` + FileWrite $9 ` remote_write:$\n` + FileWrite $9 ` - url: $RemoteUrl$\n` + FileWrite $9 ` basic_auth:$\n` + FileWrite $9 ` username: "$RemoteUser"$\n` + FileWrite $9 ` password: $RemotePassword$\n` + ${EndIf} + FileWrite $9 `integrations:$\n` + FileWrite $9 ` prometheus_remote_write:$\n` + FileWrite $9 ` - url: $RemoteUrl$\n` + FileWrite $9 ` basic_auth:$\n` + FileWrite $9 ` username: "$RemoteUser"$\n` + FileWrite $9 ` password: $RemotePassword` + FileClose $9 # and close the file + Return +FunctionEnd diff --git a/packaging/windows/logo.ico b/packaging/windows/logo.ico new file mode 100644 index 000000000000..1f36fdd3311b Binary files /dev/null and b/packaging/windows/logo.ico differ