Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows #2

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ cover*.out
cmd/agent/agent
cmd/agentctl/agentctl
dist/

**/.DS_Store
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Expand Down
Binary file added docs/assets/exporter.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/remote_options.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions docs/windows.md
Original file line number Diff line number Diff line change
@@ -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"
```

<br>

![](./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.
15 changes: 15 additions & 0 deletions packaging/windows/Dockerfile
Original file line number Diff line number Diff line change
@@ -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"]
274 changes: 274 additions & 0 deletions packaging/windows/install_script.nsis
Original file line number Diff line number Diff line change
@@ -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
Binary file added packaging/windows/logo.ico
Binary file not shown.