-
-
Notifications
You must be signed in to change notification settings - Fork 88
Examples & Recipes
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.
- Introduction
- Quick Start (Any App)
- How Servy Runs Your App
- Service Account & Permissions
- Verifying the Service
- Common Problems & Fixes
- Tips & Notes
- See Also
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.
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.
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.
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.
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
# 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_PASSWORDImportant
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.
After installation:
sc.exe query MyService
sc.exe start MyService
sc.exe stop MyServiceOr 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
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.
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-netflag is an example; add other permissions (--allow-read,--allow-write, etc.) as needed. - Works for both scripts and Deno HTTP servers.
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 3000in--paramsif needed.
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:
-
--rmensures the container is cleaned up when it stops. - Adjust
-pandmyimage:latestas needed.
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.ymlstack as a background service. - Do not add
--detach: it makesdocker-composeexit 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.
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\
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.
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"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"servy-cli install `
--name="GhostCMS" `
--path="C:\Program Files\nodejs\node.exe" `
--params="current\index.js" `
--startupDir="C:\var\www\ghost" `
--startupType="Automatic"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"servy-cli install `
--name="MyRustService" `
--description="Rust background service" `
--path="C:\apps\rustsvc\rust_svc.exe" `
--startupDir="C:\apps\rustsvc" `
--startupType="Automatic"servy-cli install `
--name="MyCppService" `
--description="C++ Application" `
--path="C:\apps\cpp-service\service.exe" `
--startupDir="C:\apps\cpp-service" `
--startupType="Automatic"servy-cli install `
--name="MyZigService" `
--description="Zig background worker" `
--path="C:\apps\zig\myapp.exe" `
--startupDir="C:\apps\zig" `
--startupType="Automatic"servy-cli install `
--name="MyPascalService" `
--description="Delphi background app" `
--path="C:\apps\pascal\worker.exe" `
--startupDir="C:\apps\pascal" `
--startupType="Automatic"servy-cli install `
--name="MyFortranService" `
--description="Fortran computational service" `
--path="C:\apps\fortran\worker.exe" `
--startupDir="C:\apps\fortran" `
--startupType="Automatic"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"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.
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.
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.
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"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"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"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 terminalorNo such file or directoryerror when trying to access the console.
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"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"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"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"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"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.
(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"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"servy-cli install `
--name="MyHaskellService" `
--description="Haskell background worker" `
--path="C:\apps\haskell\myapp.exe" `
--startupDir="C:\apps\haskell" `
--startupType="Automatic"(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"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"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"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.
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_PARAMETERSWarning
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.
- The executable exits immediately
- Missing arguments in
--params - Incorrect working directory
Fix: Run the same command manually from a terminal.
- 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.
- App logs to relative paths
- Startup directory is incorrect
Fix: Set --startupDir explicitly and verify log paths.
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/stderrfor debugging background services. -
Permissions: Ensure the service account has NTFS Modify permissions for the application's startup directory and
%ProgramData%\Servy.
Copyright © Akram El Assas. All rights reserved.
- Home
- Overview
- Installation Guide
- Advanced Configuration
- Usage
- Servy Desktop App
- Servy Manager
- Servy CLI
- PowerShell Module
- Examples & Recipes
- Logging & Log Rotation
- Health Monitoring & Recovery
- Environment Variables
- Service Dependencies
- Pre-Launch & Post-Launch Actions
- Pre-Stop & Post-Stop Actions
- Shutdown & Teardown
- Export/Import Services
- Automation & CI/CD
- Integration with Monitoring Tools
- Service Event Notifications
- Comparison with Alternatives
- Security
- Architecture
- Building from Source
- Troubleshooting
- FAQ