Configuration

Configuration File

The service reads its settings from appsettings.json, located in the same directory as the executable. The Jenkins section contains all service-specific settings.

Settings Reference

Setting Required Default Description
JenkinsURL Yes Full Jenkins URL including port. Must include an explicit port — default ports (80/443) are rejected. Example: https://jenkins.example.com:8443
AgentName No Machine hostname The agent/node name as configured in Jenkins. Case-sensitive.
AgentSecret Yes The JNLP secret generated by Jenkins for this agent. Case-sensitive.
JavaPath No JAVA_HOME env var Full path to the JDK/OpenJDK bin folder. Example: C:\Program Files\Java\jdk-21.0.2\bin
CustomArguments No (empty) Additional arguments passed to java.exe. Space-separated, supports quoted values and escaped quotes (\"). Example: -noCertificateCheck
DebugMode No false true to enable debug-level logging, false to disable.
CompactLog No false true to write CLEF (Compact Log Event Format) JSON to agent.clef instead of human-readable agent.log.
RetainedLogs No 3 Number of rolled log files to keep. Oldest are permanently deleted (skips recycle bin).
MaxRetries No 0 Maximum auto-recovery attempts before the watchdog gives up. 0 = infinite retries (recommended).
SecretMode No Unprotected How AgentSecret is stored/resolved. See Secret Protection Modes below.

JSON Format

{
  "Jenkins": {
    "JenkinsURL": "https://jenkins.example.com:8443",
    "AgentSecret": "your-agent-secret-here",
    "SecretMode": "Unprotected",
    "AgentName": "",
    "JavaPath": "",
    "CustomArguments": "",
    "DebugMode": false,
    "CompactLog": false,
    "RetainedLogs": 3,
    "MaxRetries": 0
  },
  "Telemetry": {
    "Enabled": false,
    "OtlpEndpoint": "http://localhost:4317",
    "ServiceName": "JenkinsAsService"
  }
}
Tip

The AgentName defaults to the machine hostname if left empty. This is usually the correct value unless the Jenkins node name differs from the hostname.

Validation Flow

flowchart TD
    A["Read appsettings.json"] --> B["Bind to ServiceSettings via IOptions"]
    B --> C{JenkinsURL filled?}
    C -->|No| D[Log error & stop]
    C -->|Yes| E{AgentSecret filled?}
    E -->|No| D
    E -->|Yes| F["Parse URL via System.Uri"]
    F --> G{Explicit port?}
    G -->|No / default port| D
    G -->|Yes| H[Resolve Java path]
    H --> I["Test TCP connectivity (2s timeout)"]
    I -->|Fail| D
    I -->|Pass| J["Download agent.jar (ETag cached)"]
    J --> K[Start agent + watchdog]

Java Path Resolution

The service resolves the Java executable in this order:

  1. Use JavaPath from config if set and java.exe exists at that path
  2. Fall back to JAVA_HOME environment variable root
  3. Fall back to JAVA_HOME\bin
  4. If none work → log error and stop

URL Validation

The JenkinsURL is parsed using System.Uri:

Secret Protection Modes

SecretMode controls how the AgentSecret is stored and resolved at runtime.

Mode AgentSecret field contains How resolved
Unprotected Plaintext secret Returned as-is
Dpapi Base64-encoded DPAPI ciphertext ProtectedData.Unprotect (machine-scoped, non-portable)
EnvironmentVariable Name of a system env var (default: JENKINS_SECRET) Environment.GetEnvironmentVariable(..., Machine)
CredentialManager Windows Credential Manager target name CredentialManager.GetCredentials(targetName).Password
Warning

DPAPI mode binds the secret to the machine. Moving appsettings.json to another machine will fail decryption. Re-run update-secret after a machine migration.

CLI: update-secret

The JenkinsAsService.exe update-secret subcommand writes (or re-writes) appsettings.json with the secret processed for the chosen mode. Used by the MSI installer and manually.

JenkinsAsService.exe update-secret [options]
  --secret <value>       Plaintext secret (command-line)
  --secret-file <path>   Read from file (deleted after reading)
  --secret-env <var>     Read from named environment variable
  --url <value>          Jenkins controller URL
  --mode <value>         Dpapi | EnvironmentVariable | CredentialManager | Unprotected
  --agent-name <value>   Node name (default: hostname)
  --java-path <value>    Java bin folder (default: JAVA_HOME)
  --impersonate          Run Credential Manager write as a different user
  --username <value>     Username for impersonation (DOMAIN\user)
  --silent               Non-interactive (all values from flags)
Tip

In silent mode with --impersonate, provide the password via the JAS_IMPERSONATE_PASSWORD environment variable to avoid command-line exposure.

Telemetry (OpenTelemetry)

Disabled by default. Set Enabled: true to export metrics via OTLP.

Setting Default Description
Enabled false Enable OpenTelemetry metrics export
OtlpEndpoint http://localhost:4317 OTLP gRPC endpoint (Datadog agent, Grafana Alloy, etc.)
ServiceName JenkinsAsService service.name resource attribute

Exported metrics: