Skip to content

Environment Variables

Akram El Assas edited this page May 26, 2026 · 29 revisions

Table of Contents

  1. Introduction
  2. Environment Variable Expansion
  3. GUI
  4. CLI Option: --envVars
  5. CLI Example
  6. PowerShell Option: -EnvVars
  7. PowerShell Example
  8. Tips

Introduction

Servy allows you to define environment variables for the service process, enabling fine-grained control over the runtime context.

Environment variable expansion is supported in multiple areas of Servy configuration:

  • Service binary paths (--path / -Path)
  • Startup directories (--startupDir / -StartupDir)
  • Process parameters (--params / -Params)
  • Environment variables (--envVars / -EnvVars)

This makes it possible to reference existing system variables, user-defined variables, or paths dynamically in your configuration.

Environment Variable Expansion

Servy uses a sophisticated expansion engine that allows variables to reference each other. The resolution follows this specific order:

  1. System Environment: All current system and process environment variables are loaded first.
  2. Custom Overrides: Variables defined in the Environment Variables field (or --envVars) are added next. If a custom variable has the same name as a system variable, the custom value wins.
  3. Cross-Reference Expansion: Finally, all variables are scanned for %VAR% placeholders. These placeholders are resolved using the final merged set of variables.

Protected Variables

For security reasons Servy refuses to let --envVars / -EnvVars override a hard-coded list of variables that would otherwise enable privilege escalation or runtime injection (DLL/JIT profiler hijacking, debugger probes, search-path attacks, etc.). Any attempt to override one of these is silently ignored each time the service starts (during environment-variable expansion) and a warning is recorded in %ProgramData%\Servy\logs\Servy.Service.log:

Security: Blocked an attempt to override protected variable 'PATH'. Custom values for this variable are ignored to prevent privilege escalation.

The current list includes: PATH, COMSPEC, SYSTEMROOT, WINDIR, SYSTEMDRIVE, TEMP, TMP, PATHEXT, PROGRAMFILES, PROGRAMFILES(X86), PROGRAMW6432, COMMONPROGRAMFILES, COMMONPROGRAMFILES(X86), COMMONPROGRAMW6432, APPDATA, LOCALAPPDATA, PUBLIC, HOMEDRIVE, HOMEPATH, HOME, USERDOMAIN, USERDOMAIN_ROAMINGPROFILE, LOGONSERVER, USERNAME, USERPROFILE, ALLUSERSPROFILE, PROGRAMDATA, PSMODULEPATH, COR_ENABLE_PROFILING, COR_PROFILER, COR_PROFILER_PATH, DOTNET_STARTUP_HOOKS, DOTNET_ROOT, DOTNET_ROOT(x86), DOTNET_HOST_PATH, DOTNET_BUNDLE_EXTRACT_BASE_DIR, DOTNET_ADDITIONAL_DEPS, DOTNET_SHARED_STORE, JAVA_TOOL_OPTIONS, _JAVA_OPTIONS, CLASSPATH, JAVA_HOME, NODE_OPTIONS, NODE_PATH, PYTHONSTARTUP, PYTHONPATH, PYTHONHOME, LD_PRELOAD, and LD_LIBRARY_PATH.

If you need to extend PATH for the service process, modify the system PATH or use a custom variable name and reference it inside your application configuration.

Example of Expansion Logic

If your system has TEMP=C:\Windows\Temp and you define:

  • MY_ROOT=C:\ServyApp
  • MY_LOGS=%MY_ROOT%\logs
  • APP_TEMP=%TEMP%

The final environment seen by your process will be:

  • MY_ROOT: C:\ServyApp
  • MY_LOGS: C:\ServyApp\logs
  • APP_TEMP: C:\Windows\Temp

Note

Variable Ordering and Circular References: Variables are resolved using a multi-pass fixed-point algorithm, so the order in which you define them does not matterMY_LOGS=%MY_ROOT%\logs resolves correctly even if MY_ROOT is defined later in the list. The expansion engine runs up to 5 passes; chains deeper than that will leave unresolved %VAR% placeholders and Servy logs a warning ("Environment variable expansion reached maximum pass limit").

Avoid circular references: A direct two-variable cycle (A=%B%, B=%A%) is immediately caught and logged as a warning (Direct cycle detected for variable...), falling back to a safe literal placeholder state. Longer indirect cycles (A=%B%\suffix, B=%C%\suffix, C=%A%\suffix) are detected and logged as a warning once the 5-pass limit is exceeded.

GUI

The advanced tab in Servy allows setting environment variables for the service process:

servy-config-advanced-env

CLI Option: --envVars

The --envVars command-line option lets you specify environment variables for the service process.

  • Syntax: --envVars="VAR1=value1; VAR2=value2"
  • Separate multiple variables with semicolons (;) - Special characters can be escaped:
    • \= to escape =
    • \" to escape "
    • \; to escape ;
    • \\ to escape \
    • %% to escape % (collapses to a single %, matching cmd.exe behaviors) (starting from v8.5+)
  • Supports environment variable expansion. Example:
    --envVars="VAR1=%ProgramData%\MyApp; VAR2=%VAR1%\bin; CHANCE=100%%"
  • Useful for setting runtime context without changing system-wide environment variables.

CLI Example

servy-cli install `
  --name="MyNodeService" `
  --description="My NodeJS Server" `
  --path="%ProgramFiles%\nodejs\node.exe" `
  --startupDir="C:\Apps\App" `
  --params="C:\Apps\App\index.js" `
  --startupType="Automatic" `
  --envVars="NODE_ENV=production; APP_CONFIG=C:\Apps\App\config.json"

PowerShell Option: -EnvVars

The -EnvVars parameter lets you define environment variables when installing a service via PowerShell.

  • Type: string (semicolon-separated list, optional)
  • Apply the same escaping rules as the CLI.
  • Multiple variables are separated with semicolons (;)
  • Variables are applied only to the service process, not system-wide.

PowerShell Example

Import-Module "C:\Program Files\Servy\Servy.psm1" -Force

$installParams = @{
    Name         = "MyNodeService"
    Description  = "My NodeJS Server"
    Path         = "C:\Program Files\nodejs\node.exe"
    StartupDir   = "C:\Apps\App"
    Params       = "C:\Apps\App\index.js"
    StartupType  = "Automatic"

    EnvVars      = "NODE_ENV=production; APP_CONFIG=C:\Apps\App\config.json"
}

Install-ServyService @installParams

Tips

  • Case Insensitivity: Environment variable names are case-insensitive. Defining node_env will correctly override an existing NODE_ENV.
  • Expansion Order: You can reference both existing system variables (like %ProgramData%) and other custom variables defined in the same list.
  • Safe Percent Escaping: To pass a literal percent character into your environment safely and prevent it from being processed as an expansion block, use a double percent sign (%%). For example, defining ALERT_MSG=Battery at 100%% will expand correctly to Battery at 100% inside the service process.
  • Verification: To troubleshoot, if you aren't sure if your variables are applying correctly, run this to dump the environment to a file (PowerShell Admin):
servy-cli install --name="EnvTest" --path="C:\Windows\System32\cmd.exe" --params="/c set > C:\servy_env.txt && timeout /t 3600 /nobreak > nul" --envVars="MY_ROOT=C:\ServyApp; MY_LOGS=%MY_ROOT%\logs"
servy-cli restart --name="EnvTest"
Get-Content C:\servy_env.txt | Select-String "MY_LOGS"

Clone this wiki locally