Skip to content

Windows Service Deployment ​

Run your Kittox application as a Windows Service for unattended, production-ready operation. The same executable used for Desktop GUI automatically detects service mode.

When to use ​

  • Production on Windows Server
  • Unattended operation with automatic startup
  • Applications that must survive user logoff
  • Behind a reverse proxy (Apache, nginx, or IIS) for HTTPS, security, and load balancing
  • When you need to restart individual applications without restarting the web server

Advantages over native modules (ISAPI/Apache) ​

Windows Service + ProxyISAPI / Apache module
Restart individual appsYes (via Services panel or net stop/net start)No (must restart IIS/Apache)
DLL lockingNo lock — the .exe runs independentlyDLL locked by the web server process
YAML reloadRestart the service to reload metadataRestart the entire web server
DebuggingRun as Desktop GUI, attach debuggerComplex (attach to IIS/Apache worker)
Multiple instancesEach app is a separate service on its own portAll apps share the web server process
Web server dependencyAny reverse proxy (Apache, nginx, IIS, Caddy...)Tied to a specific web server

The .dpr file ​

The same .dpr used for the Desktop GUI:

pascal
program MyApp;
uses
  Kitto.Vcl.Start,
  Controllers, Rules, UseKitto;
begin
  TKStart.Start;
end.

TKStart.Start auto-detects service mode: if the process was started by the Windows Service Control Manager (SCM), it runs as a service; otherwise it starts the desktop GUI.

Service configuration (Config.yaml) ​

yaml
AppName: MyAppX
AppPath: /myappx

Server:
  Port: 8080
  BindAddress: ''
  ThreadPoolSize: 20

Service:
  # Log server events to Windows Event Viewer
  LogToEventViewer: True

Log:
  Level: detailed
  TextFile:
    FileName: %APP_PATH%.log
    IsEnabled: True

Port assignment

Each application needs its own unique port. The examples use:

  • HelloKittoX: 3621
  • TaskittoX: 3622
  • KEmployeeX: 3623

Installing the service ​

Each example application includes ready-to-use batch scripts in the Home\ directory:

InstallService.bat:

batch
@echo off
net session >nul 2>&1
if %errorlevel% neq 0 (
    echo ERROR: This script must be run as Administrator.
    echo Right-click and select "Run as administrator".
    pause
    exit /b 1
)
echo Installing MyAppX service...
"%~dp0MyApp.exe" -install
echo Starting MyAppX service...
net start MyAppX
echo.
echo Service installed and started.
pause

UninstallService.bat:

batch
@echo off
net session >nul 2>&1
if %errorlevel% neq 0 (
    echo ERROR: This script must be run as Administrator.
    echo Right-click and select "Run as administrator".
    pause
    exit /b 1
)
echo Stopping MyAppX service...
net stop MyAppX 2>nul
echo Uninstalling MyAppX service...
"%~dp0MyApp.exe" -uninstall
echo.
echo Service stopped and uninstalled.
pause

Right-click the .bat file and select Run as administrator.

Manual installation ​

Open an elevated command prompt (Run as Administrator):

batch
:: Install the service
MyApp.exe -install

:: Start the service
net start MyAppX

:: Verify it's running
sc query MyAppX

The service name is the AppName value from Config.yaml. The service is installed with Automatic startup type.

Uninstalling manually ​

batch
:: Stop the service
net stop MyAppX

:: Uninstall
MyApp.exe -uninstall

Running under a specific account ​

By default, the service runs as Local System. For database access with Windows Authentication, change the service account:

  1. Open Services (services.msc)
  2. Find your service, right-click > Properties
  3. Go to the Log On tab
  4. Select This account and enter a domain user with database access
  5. Click OK and restart the service

Reverse proxy configuration ​

In production, place the service behind a reverse proxy for HTTPS termination, security filtering, and a clean URL structure. The service runs on localhost:port and the proxy forwards external requests to it.

Install nginx and configure conf/nginx.conf:

nginx
http {
    server {
        listen 80;
        server_name  localhost;

        # --- HelloKittoX (port 3621) ---
        location /hellokittox/ {
            proxy_pass http://127.0.0.1:3621/hellokittox/;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
        location = /hellokittox {
            return 301 /hellokittox/;
        }

        # --- TaskittoX (port 3622) ---
        location /taskittox/ {
            proxy_pass http://127.0.0.1:3622/taskittox/;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
        location = /taskittox {
            return 301 /taskittox/;
        }
    }
}

Each application needs two location blocks: one for the trailing-slash redirect and one for the actual proxy.

nginx commands:

batch
:: Test configuration
nginx.exe -t

:: Start
nginx.exe

:: Reload configuration (no downtime)
nginx.exe -s reload

:: Stop
nginx.exe -s stop

HTTPS with nginx:

nginx
server {
    listen 443 ssl;
    server_name  myserver.example.com;

    ssl_certificate      conf/ssl/server.crt;
    ssl_certificate_key  conf/ssl/server.key;

    location /hellokittox/ {
        proxy_pass http://127.0.0.1:3621/hellokittox/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    location = /hellokittox {
        return 301 /hellokittox/;
    }
}

Apache ​

Enable mod_proxy and mod_proxy_http in httpd.conf:

apache
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

Then add the proxy rules:

apache
<IfModule proxy_http_module>
    # HelloKittoX (port 3621)
    ProxyPass "/hellokittox" "http://localhost:3621/hellokittox"
    ProxyPassReverse "/hellokittox" "http://localhost:3621/hellokittox"

    # TaskittoX (port 3622)
    ProxyPass "/taskittox" "http://localhost:3622/taskittox"
    ProxyPassReverse "/taskittox" "http://localhost:3622/taskittox"

    # KEmployeeX (port 3623)
    ProxyPass "/kemployeex" "http://localhost:3623/kemployeex"
    ProxyPassReverse "/kemployeex" "http://localhost:3623/kemployeex"
</IfModule>

HTTPS: add the same ProxyPass directives inside your <VirtualHost *:443> block.

Apache vs nginx

Apache requires separate modules (mod_proxy, mod_proxy_http) and more verbose configuration. nginx has reverse proxy built-in and the configuration is more compact. Both work equally well.

IIS (Application Request Routing) ​

  1. Install Application Request Routing (ARR) and URL Rewrite modules from the IIS downloads page
  2. Open IIS Manager > server node > Application Request Routing Cache > Server Proxy Settings
  3. Check Enable proxy and click Apply
  4. Create a URL Rewrite inbound rule:
    • Pattern: ^hellokittox/(.*)
    • Action type: Rewrite
    • Rewrite URL: http://localhost:3621/hellokittox/{R:1}

Repeat for each application.

Monitoring ​

  • Services panel: services.msc shows status, allows start/stop/restart
  • Event Viewer: if LogToEventViewer: True, server start/stop and errors appear in the Application log
  • Log file: %APP_PATH%.log next to the executable (if Log/TextFile/IsEnabled: True)
  • Browser: navigate to http://localhost/myappx/ (via proxy) or http://localhost:8080/myappx/ (direct)
  • Service status: sc query MyAppX

Troubleshooting ​

IssueSolution
"Run as administrator" errorThe batch scripts check for admin privileges. Right-click > Run as administrator
Service fails to startCheck the log file next to the .exe. Common cause: port already in use
502 Bad Gateway (nginx/Apache)The service is not running or listening on the wrong port. Check Server/Port in Config.yaml
404 on proxyAppPath in Config.yaml must match the proxy path exactly
Database connection failsChange the service account (Log On tab) to a user with database access
Sessions lost on restartExpected behavior — sessions are in-memory. Users will see the "Session lost" dialog and can re-login

See also ​

Released under Apache License, Version 2.0.