Skip to content

Examples & Recipes

aelassas edited this page Aug 19, 2026 · 115 revisions

This documentation shows how to run almost any application as a native Windows service using the Servy CLI. It includes practical examples across languages, runtimes, and infrastructure tools. Use the table of contents to jump directly to the runtime or setup you need.

Table of Contents

  1. Introduction
  2. Quick Start (Any App)
  3. How Servy Runs Your App
  4. Service Account & Permissions
  5. Verifying the Service
  6. Common Problems & Fixes
  7. Tips & Notes
  8. See Also
  1. Node.js / Next.js / Express
  2. Deno
  3. Bun
  1. Docker
  2. Docker Compose
  3. Nginx
  4. Redis
  5. PocketBase
  1. Ollama AI Instance
  2. Ghost CMS
  1. Go
  2. Rust
  3. C / C++
  4. Zig
  5. Pascal / Delphi
  6. Fortran
  1. .NET
  2. Java
  3. Elixir
  4. Erlang
  1. PowerShell
  2. Batch
  3. Python
  4. PHP
  5. Laravel Queue Worker
  6. Ruby
  7. VBScript
  8. AutoHotkey
  9. WSL Bash
  1. Julia
  2. R
  1. Haskell
  2. Dart
  3. Lua
  4. Perl
  5. OCaml
  6. Kopia

Introduction

Servy can run any app into a native Windows service. This page provides examples for the most popular languages and frameworks, ready to run as background services.

Services can be installed and configured through the Servy Desktop App or the PowerShell module, but this page focuses on real-world examples using the Servy CLI for automation, scripting, and CI/CD pipelines.

Once installed, the Servy directory is automatically added to the system PATH environment variable. This allows you to run servy-cli directly from any elevated Command Prompt or PowerShell session.

Quick Start (Any App)

The basic pattern for running any application as a Windows service is:

servy-cli install `
  --name="MyService" `
  --path="C:\path\to\app.exe" `
  --params="optional arguments" `
  --startupDir="C:\path\to" `
  --startupType="Automatic"

If your app runs correctly from a terminal, it will run correctly as a service using this pattern.

Example: Run a simple HTTP server

servy-cli install `
  --name="HelloServer" `
  --path="C:\Program Files\nodejs\node.exe" `
  --params="server.js" `
  --startupDir="C:\apps\hello" `
  --startupType="Automatic"

If node server.js works in your terminal, this service will work.

How Servy Runs Your App

Servy runs your application as a native Windows service by registering it with the Windows Service Control Manager (SCM).

Your application does not need to implement Windows Service APIs or be service-aware. Servy launches your executable or command when the service starts, monitors it if recovery is enabled, runs pre-launch and post-launch hooks, and stops it when the service is stopped, including pre-stop and post-stop hooks.

Key characteristics:

  • Your application runs in Session 0, like all Windows services.
  • Standard input/output is not interactive.
  • Environment variables, working directory, and arguments are explicitly defined at install time.
  • The service lifecycle (start, stop, restart) is fully managed by the SCM.

If your application cannot run unattended, requires a desktop session, or expects user interaction, it is not suitable to run as a Windows service.

Service Account & Permissions

By default, services are installed to run under the LocalSystem account.

Keep in mind:

  • Network access may differ from your user account
  • Mapped drives are not available
  • Environment variables must be system-wide

If your application needs access to network shares, databases, or restricted folders, configure a dedicated service account instead of running under the default LocalSystem account.

Use the --user and --password options when installing the service, and ensure the account has Modify permissions for:

  • %ProgramData%\Servy
  • The application's startup directory
  • Any additional files, folders, or network resources the app depends on

Example: Install using a dedicated service account

# Set the password in the current process environment first
$env:SERVY_PASSWORD = "your_secret_password"

servy-cli install `
  --name="MySecureService" `
  --path="C:\apps\secure\app.exe" `
  --startupDir="C:\apps\secure" `
  --user="DOMAIN\svc-myapp" `
  --startupType="Automatic"

# Clear sensitive variables from memory immediately after use
Remove-Item Env:SERVY_PASSWORD

Important

Security: Avoid --password on the command line - it is visible in OS process listings and shell history. See the Security page for details.

For more details about service accounts, trust boundaries, and security considerations, see the Security Model documentation.

Verifying the Service

After installation:

sc.exe query MyService
sc.exe start MyService
sc.exe stop MyService

Or using Servy CLI:

servy-cli status --name="MyService"
servy-cli start --name="MyService"
servy-cli stop --name="MyService"

Or open Servy Manager to:

  • Start / stop the service
  • View logs
  • Adjust restart and failure policies
  • View CPU / RAM live performance graphs
  • Preview service stdout/stderr
  • Preview service dependencies

JavaScript & TypeScript Runtimes

Run a Node.js / Next.js / Express App as a Service

servy-cli install `
  --name="MyNodeApp" `
  --description="Node.js Express API" `
  --path="C:\Program Files\nodejs\node.exe" `
  --params="server.js" `
  --startupDir="C:\apps\myapp" `
  --startupType="Automatic"

Run an npm script (npm start) as a Service:

servy-cli install `
  --name="MyNodeApp" `
  --description="Node.js App via npm" `
  --path="C:\Program Files\nodejs\npm.cmd" `
  --params="start" `
  --startupDir="C:\apps\myapp" `
  --startupType="Automatic"

Run a Next.js Production App as a Service:

servy-cli install `
  --name="MyNextApp" `
  --description="Next.js App" `
  --path="C:\Program Files\nodejs\npm.cmd" `
  --params="start" `
  --startupDir="C:\apps\myapp" `
  --startupType="Automatic"

This runs:

npm start -> next start

which is the correct way to run Next.js in production.

Run a Deno App as a Service

servy-cli install `
  --name="MyDenoService" `
  --description="Deno background script" `
  --path="C:\tools\deno\deno.exe" `
  --params="run --allow-net worker.ts" `
  --startupDir="C:\apps\deno" `
  --startupType="Automatic"

Notes:

  • The --allow-net flag is an example; add other permissions (--allow-read, --allow-write, etc.) as needed.
  • Works for both scripts and Deno HTTP servers.

Run a Bun App as a Service

servy-cli install `
  --name="MyBunService" `
  --description="Bun backend service" `
  --path="C:\tools\bun\bun.exe" `
  --params="C:\apps\bun\server.ts" `
  --startupDir="C:\apps\bun" `
  --startupType="Automatic"

Notes:

  • Bun automatically detects whether the file is a script or server.
  • You can pass arguments like --port 3000 in --params if needed.

Containers & Infrastructure

Run a Docker Container as a Service

servy-cli install `
  --name="MyDockerService" `
  --description="Docker container service" `
  --path="C:\Program Files\Docker\Docker\resources\bin\docker.exe" `
  --params="run --rm --name myapp -p 8080:80 myimage:latest" `
  --startupDir="C:\Program Files\Docker\Docker\resources\bin" `
  --startupType="Automatic"

Notes:

  • --rm ensures the container is cleaned up when it stops.
  • Adjust -p and myimage:latest as needed.

Run a Docker Compose Stack as a Service

This is useful when you want your entire container stack to start automatically at boot without relying on Docker Desktop auto-start behavior.

servy-cli install `
  --name="MyDockerComposeService" `
  --description="Docker Compose stack service" `
  --path="C:\Program Files\Docker\Docker\resources\bin\docker-compose.exe" `
  --params="-f C:\apps\mycompose\docker-compose.yml up" `
  --startupDir="C:\apps\mycompose" `
  --startupType="Automatic"

Notes:

  • This runs the entire docker-compose.yml stack as a background service.
  • Do not add --detach: it makes docker-compose exit immediately after starting the containers, so the service would stop right away (see Service starts then stops immediately below) and stopping the service would no longer stop the stack. In foreground mode the service status tracks the stack and a service stop shuts the containers down cleanly.

Run an Nginx Web Server as a Service

Running the Windows port of Nginx as a service ensures the web server persists across reboots.

servy-cli install `
  --name="Nginx" `
  --description="Nginx Web Server" `
  --path="C:\nginx\nginx.exe" `
  --params='-g "daemon off;"' `
  --startupDir="C:\nginx" `
  --startupType="Automatic"

To ensure consistent UTF-8 output for logs (especially when shipping logs or using non-ASCII characters), wrap Nginx with cmd.exe and force code page 65001:

servy-cli install `
  --name="Nginx" `
  --description="Nginx Web Server" `
  --path="C:\Windows\System32\cmd.exe" `
  --params='/c "C:\nginx\start-nginx.cmd"' `
  --startupDir="C:\nginx" `
  --startupType="Automatic"

Where start-nginx.cmd is as follows:

@echo off
chcp 65001 >nul
cd /d C:\nginx
nginx.exe -g "daemon off;"

Nginx logs go to: C:\nginx\logs\

Run a Redis Server as a Service

servy-cli install `
  --name="Redis" `
  --description="Redis In-Memory Data Store" `
  --path="C:\redis\redis-server.exe" `
  --params="redis.windows.conf" `
  --startupDir="C:\redis" `
  --startupType="Automatic"

Note

Redis for Windows is not officially supported by Redis Labs. For production use, consider running Redis in Docker or WSL.

Run a PocketBase Instance as a Service

PocketBase is a single-file backend that is highly effective when run as a service.

servy-cli install `
  --name="PocketBase" `
  --description="PocketBase backend" `
  --path="C:\apps\pocketbase\pocketbase.exe" `
  --params="serve --http=0.0.0.0:8090" `
  --startupDir="C:\apps\pocketbase" `
  --startupType="Automatic"

AI and Modern Tools

Run an Ollama AI Instance as a Service

Keep your local LLM API available in the background.

servy-cli install `
  --name="Ollama" `
  --description="Ollama Local AI API" `
  --path="C:\Users\Admin\AppData\Local\Programs\Ollama\ollama.exe" `
  --params="serve" `
  --startupType="Automatic"

Run a Ghost CMS Instance as a Service

servy-cli install `
  --name="GhostCMS" `
  --path="C:\Program Files\nodejs\node.exe" `
  --params="current\index.js" `
  --startupDir="C:\var\www\ghost" `
  --startupType="Automatic"

Compiled Languages

Run a Go App as a Service

servy-cli install `
  --name="MyGoService" `
  --description="Go background service" `
  --path="C:\apps\my-go-app\my-go-app.exe" `
  --params="--port=8080 --mode=worker" `
  --startupDir="C:\apps\my-go-app" `
  --startupType="Automatic"

Run a Rust App as a Service

servy-cli install `
  --name="MyRustService" `
  --description="Rust background service" `
  --path="C:\apps\rustsvc\rust_svc.exe" `
  --startupDir="C:\apps\rustsvc" `
  --startupType="Automatic"

Run a C / C++ Compiled App as a Service

servy-cli install `
  --name="MyCppService" `
  --description="C++ Application" `
  --path="C:\apps\cpp-service\service.exe" `
  --startupDir="C:\apps\cpp-service" `
  --startupType="Automatic"

Run a Zig App as a Service

servy-cli install `
  --name="MyZigService" `
  --description="Zig background worker" `
  --path="C:\apps\zig\myapp.exe" `
  --startupDir="C:\apps\zig" `
  --startupType="Automatic"

Run a Pascal / Delphi App as a Service

servy-cli install `
  --name="MyPascalService" `
  --description="Delphi background app" `
  --path="C:\apps\pascal\worker.exe" `
  --startupDir="C:\apps\pascal" `
  --startupType="Automatic"

Run a Fortran App as a Service

servy-cli install `
  --name="MyFortranService" `
  --description="Fortran computational service" `
  --path="C:\apps\fortran\worker.exe" `
  --startupDir="C:\apps\fortran" `
  --startupType="Automatic"

Managed Runtimes

Run a .NET App as a Service

servy-cli install `
  --name="MyDotNetApp" `
  --description=".NET Worker Service" `
  --path="C:\apps\dotnetapp\MyApp.exe" `
  --startupDir="C:\apps\dotnetapp" `
  --startupType="Automatic"

Or, if using dotnet runtime with a DLL:

servy-cli install `
  --name="MyDotNetApp" `
  --description=".NET Worker Service" `
  --path="C:\Program Files\dotnet\dotnet.exe" `
  --params="C:\apps\dotnetapp\app.dll" `
  --startupDir="C:\apps\dotnetapp" `
  --startupType="Automatic"

Run a Java JAR as a Service

servy-cli install `
  --name="MyJavaService" `
  --description="Java Spring Boot App" `
  --path="%JAVA_HOME%\bin\java.exe" `
  --params="-jar C:\apps\springboot\app.jar" `
  --startupDir="C:\apps\springboot" `
  --startupType="Automatic"

By using %JAVA_HOME% system environment variable, Servy resolves the correct Java installation path at runtime instead of relying on a hardcoded version. This ensures the service continues to work after Java updates and keeps the configuration portable across different environments.

Run an Elixir Script as a Service

servy-cli install `
  --name="MyElixirService" `
  --description="Elixir background worker" `
  --path="C:\Windows\System32\cmd.exe" `
  --params='/c "C:\Program Files\Elixir\bin\elixir.bat C:\apps\elixir\worker.exs"' `
  --startupDir="C:\apps\elixir" `
  --startupType="Automatic"

For Elixir, you can point --params to any .exs script or mix task.

Run an Erlang Script as a Service

servy-cli install `
  --name="MyErlangService" `
  --description="Erlang background worker" `
  --path="C:\Program Files\erl-25.3\bin\erl.exe" `
  --params="-noshell -s my_app start -s init stop" `
  --startupDir="C:\apps\erlang" `
  --startupType="Automatic"

For Erlang, the -s parameters start the desired module and function. Adjust according to your OTP app.

Scripting & Automation

Run a PowerShell script as a Service

servy-cli install `
  --name="MyPowerShellScript" `
  --description="PowerShell automation job" `
  --path="C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" `
  --params='-File "C:\scripts\script\my script.ps1"' `
  --startupDir="C:\scripts\script" `
  --startupType="Automatic"

Run a Batch File as a Service

servy-cli install `
  --name="MyBatchScript" `
  --description="Batch automation job" `
  --path="C:\Windows\System32\cmd.exe" `
  --params="/c C:\scripts\backup-job.bat" `
  --startupDir="C:\scripts" `
  --startupType="Automatic"

Run a Python Script as a Service

servy-cli install `
  --name="MyPythonJob" `
  --description="Python background job" `
  --path="C:\Python311\python.exe" `
  --params="C:\apps\scripts\job.py" `
  --startupDir="C:\apps\scripts" `
  --startupType="Automatic"

Why --enableConsoleUI Is Required for Some Python Applications

Many Python libraries and orchestration frameworks (e.g., Prefect, Rich, Colorama) attempt to initialize interactive terminal features like colors, progress bars, or advanced logging. When running as a standard Windows service in Session 0, these applications typically fail to start because they cannot find a valid terminal handle (stdin/stdout/stderr).

Setting the --enableConsoleUI option instructs Servy to:

  • Allocate a real console buffer for the wrapped process within Session 0.
  • Provide a valid terminal handle, satisfying the application's requirement for a console environment.
  • Ensure stability for scripts that would otherwise exit immediately with an Illegal operation on a terminal or No such file or directory error when trying to access the console.

Run a PHP App as a Service

servy-cli install `
  --name="MyPHPWorker" `
  --description="PHP queue worker" `
  --path="C:\php\php.exe" `
  --params="C:\apps\worker\queue-worker.php" `
  --startupDir="C:\apps\worker" `
  --startupType="Automatic"

Run a Laravel Queue Worker as a Service

Ideal for handling background jobs in PHP/Laravel applications.

servy-cli install `
  --name="LaravelWorker" `
  --description="Laravel Queue Worker" `
  --path="C:\php\php.exe" `
  --params="artisan queue:work --tries=3" `
  --startupDir="C:\inetpub\wwwroot\myapp" `
  --startupType="Automatic"

Run a Ruby App as a Service

servy-cli install `
  --name="MyRubyApp" `
  --description="Ruby background app" `
  --path="C:\Ruby32\bin\ruby.exe" `
  --params="C:\apps\rubyapp\app.rb" `
  --startupDir="C:\apps\rubyapp" `
  --startupType="Automatic"

Run a VBScript as a Service

servy-cli install `
  --name="MyVBScript" `
  --description="VBScript automation job" `
  --path="C:\Windows\System32\cscript.exe" `
  --params="C:\scripts\tasks\job.vbs" `
  --startupDir="C:\scripts\tasks" `
  --startupType="Automatic"

If you prefer wscript.exe (windowed, but still works as a service):

servy-cli install `
  --name="MyVBScript" `
  --description="VBScript automation job" `
  --path="C:\Windows\System32\wscript.exe" `
  --params="C:\scripts\tasks\job.vbs" `
  --startupDir="C:\scripts\tasks" `
  --startupType="Automatic"

Run an AutoHotkey script as a Service

Running AutoHotkey (AHK) as a service allows scripts to execute before user login.

Warning

Desktop Interaction: Windows services run in Session 0. This means scripts requiring GUI interaction, mouse movements, or keystrokes sent to active windows will not function correctly. Use service mode for background file monitoring or logic-only scripts.

servy-cli install `
  --name="MyAutoHotkeyService" `
  --description="AutoHotkey background script" `
  --path="C:\Program Files\AutoHotkey\v2\AutoHotkey.exe" `
  --params="C:\scripts\service.ahk" `
  --startupDir="C:\scripts" `
  --startupType="Automatic"

Run a WSL Bash Script as a Service

servy-cli install `
  --name="MyWSLScript" `
  --description="WSL Bash script service" `
  --path="C:\Windows\System32\wsl.exe" `
  --params="bash /home/user/scripts/run.sh" `
  --startupDir="C:\Windows\System32" `
  --startupType="Automatic"

If you need a specific distribution:

servy-cli install `
  --name="MyUbuntuWSLService" `
  --description="WSL Ubuntu service job" `
  --path="C:\Windows\System32\wsl.exe" `
  --params="-d Ubuntu bash /home/user/app/start.sh" `
  --startupDir="C:\Windows\System32" `
  --startupType="Automatic"

Warning

Per-user distributions: WSL distros are registered per user account. Under the default LocalSystem account, wsl.exe finds no distributions and the service exits immediately (WSL_E_DISTRO_NOT_FOUND). Install the service with --user set to the account that owns the distro (see Service Account & Permissions), and note that the WSL VM lifecycle then follows that user's session policies.

Data Science & Analytics

Run a Julia Script as a Service

(Used for ML jobs, analytics, long-running computation workers)

servy-cli install `
  --name="MyJuliaService" `
  --description="Julia analytics worker" `
  --path="C:\Julia-1.10\bin\julia.exe" `
  --params="C:\apps\julia\worker.jl" `
  --startupDir="C:\apps\julia" `
  --startupType="Automatic"

Run an R Script as a Service

servy-cli install `
  --name="MyRService" `
  --description="R background job" `
  --path="C:\Program Files\R\R-4.4.1\bin\Rscript.exe" `
  --params="C:\apps\r\job.R" `
  --startupDir="C:\apps\r" `
  --startupType="Automatic"

Other Languages & Tools

Run a Haskell App as a Service

servy-cli install `
  --name="MyHaskellService" `
  --description="Haskell background worker" `
  --path="C:\apps\haskell\myapp.exe" `
  --startupDir="C:\apps\haskell" `
  --startupType="Automatic"

Run a Dart Server or Script as a Service

(Shelf web services, background workers, API servers, etc.)

servy-cli install `
  --name="MyDartService" `
  --description="Dart backend service" `
  --path="C:\tools\dart-sdk\bin\dart.exe" `
  --params="C:\apps\dart\server.dart" `
  --startupDir="C:\apps\dart" `
  --startupType="Automatic"

Run a Lua Script as a Service

servy-cli install `
  --name="MyLuaService" `
  --description="Lua automation script" `
  --path="C:\Lua\5.4\lua.exe" `
  --params="C:\apps\lua\script.lua" `
  --startupDir="C:\apps\lua" `
  --startupType="Automatic"

Run a Perl Script as a Service

servy-cli install `
  --name="MyPerlService" `
  --description="Perl Script" `
  --path="C:\Perl64\bin\perl.exe" `
  --params="C:\apps\perl-task\task.pl" `
  --startupDir="C:\apps\perl-task" `
  --startupType="Automatic"

Run an OCaml Script or App as a Service

servy-cli install `
  --name="MyOCamlService" `
  --description="OCaml background worker" `
  --path="C:\OCaml\bin\ocaml.exe" `
  --params="C:\apps\ocaml\worker.ml" `
  --startupDir="C:\apps\ocaml" `
  --startupType="Automatic"

If you compiled your OCaml code to a native executable (e.g., worker.exe), you can skip ocaml.exe and set --path directly to the executable:

servy-cli install `
  --name="MyOCamlService" `
  --description="OCaml compiled worker" `
  --path="C:\apps\ocaml\worker.exe" `
  --startupDir="C:\apps\ocaml" `
  --startupType="Automatic"

This way, you can run either scripts or compiled OCaml apps as Windows services using Servy.

Run Kopia as a Service

Setting up Kopia as a Windows service is a smart move. It ensures your backups run in the background without needing a user to be logged in, and using Servy makes the process straightforward.

To keep your backup server credentials safe from being exposed in command-line histories, logs, or process enumeration tools, pass the startup parameters securely using the SERVY_PROCESS_PARAMETERS environment variable (starting from Servy v8.5):

# Set the sensitive arguments securely inside your current session memory
$env:SERVY_PROCESS_PARAMETERS = 'server start --insecure --address=127.0.0.1:51515 --server-username=admin --server-password=somepwd'

# Install the service without passing secrets over the command line
servy-cli install `
  --name="KopiaService" `
  --description="Kopia Service" `
  --path="C:\Program Files\KopiaUI\resources\server\kopia.exe" `
  --startupDir="C:\Program Files\KopiaUI\resources\server" `
  --startupType="Automatic" `
  --stdout="C:\Program Files\KopiaUI\resources\server\stdout.log" `
  --stderr="C:\Program Files\KopiaUI\resources\server\stderr.log" `
  --enableSizeRotation `
  --rotationSize="10"

# Clear the session variable after deployment
Remove-Item Env:SERVY_PROCESS_PARAMETERS

Warning

Production Security Warning: Passing sensitive fields directly over raw CLI arguments (--params) can expose passwords to any system monitoring tool or user with process-listing clearance. Always use the SERVY_PROCESS_PARAMETERS marshal pattern shown above when deploying real production passwords. For more details, consult the Security Guidance.

  • server start: This keeps Kopia running in the background as a local server.
  • --insecure: Since it's only listening on 127.0.0.1 (localhost), this is generally fine for a local setup, but you can configure TLS if preferred.
  • --address: Defines the port where the Kopia UI/API will live.

Adjust Kopia command args as needed. See the official docs.

Once Kopia is running as a service (server mode), use Kopia's internal Policy system via the Web UI (easiest) or via the Command Line to schedule your snapshots.

Common Problems & Fixes

Service starts then stops immediately

  • The executable exits immediately
  • Missing arguments in --params
  • Incorrect working directory

Fix: Run the same command manually from a terminal.

Works in terminal but not as a service

  • App relies on user-specific environment variables
  • Uses mapped network drives
  • Insufficient NTFS permissions

Fix: Use a dedicated service account and system-wide environment variables.

No logs are produced

  • App logs to relative paths
  • Startup directory is incorrect

Fix: Set --startupDir explicitly and verify log paths.

Tips & Notes

If your application can be started from the command line, Servy can run it as a Windows service.

If it cannot, Servy will not hide the problem. It will surface it clearly through logs and exit codes.

  • Environment Variables: If your application relies on specific environment variables (like JAVA_HOME), ensure they are set as System variables, as services run under the SYSTEM account by default.
  • Logging: Use Servy Manager to configure log rotation and capture stdout/stderr for debugging background services.
  • Permissions: Ensure the service account has NTFS Modify permissions for the application's startup directory and %ProgramData%\Servy.

See Also

Clone this wiki locally