Skip to content

Standalone Deployment (Desktop GUI)

The simplest deployment mode: your Kittox application runs as a standard Windows executable with an embedded HTTP server (Indy). No external web server is required.

When to use

  • Development and debugging
  • Single-user or small team deployments
  • Quick demos and prototyping
  • Intranet applications with limited users

The .dpr file

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

TKStart.Start auto-detects whether the process is running as a desktop GUI or as a Windows Service (see Windows Service Deployment).

Desktop GUI features

TKMainForm (Kitto.Vcl.MainForm.pas) provides:

  • Start/Stop buttons to control the HTTP server
  • Log viewer with real-time server logs
  • Session monitor showing active sessions
  • Config selector to switch between multiple Config.yaml files
  • Home URL display with clickable link to open the browser

Watching sessions from your own code

The session list is exposed as a snapshot of values, not as live session objects, so a host form (or any application code) can read it without racing the worker threads that own those sessions:

pascal
var
  LInfo: TKWebSessionInfo;
begin
  for LInfo in Engine.GetSessionInfos do
    Memo.Lines.Add(Format('%s  %s  %s  %s', [LInfo.Id, LInfo.UserName,
      LInfo.ClientAddress, DateTimeToStr(LInfo.LastRequestDateTime)]));
end;

TKWebSessionInfo carries Id, DisplayName, CreationDateTime, LastRequestDateTime, UserName, ClientAddress and UserAgent. SetSessionDisplayName(ASessionId, ADisplayName) labels a session in the monitor and returns False if that session no longer exists.

OnSessionStart and OnSessionEnd deliver the session id, not the session object:

pascal
Engine.OnSessionEnd := procedure(AEngine: TKWebEngine; ASessionId: string)
  begin
    // ... the session is already gone; only the id is meaningful here
  end;

Changed in 4.0.15 — a breaking change for host code

Both events used to hand over the TKWebSession object. They are delivered asynchronously through TThread.Queue, while the session is freed one statement after the event is fired, so a handler that dereferenced the object read freed memory — access violations on the main thread of the desktop and service hosts, invisible to the request pipeline and to the log. The session monitor had the same defect, and reading it was enough to trigger one.

If your host code assigns OnSessionStart / OnSessionEnd, change the handler signature to (AEngine: TKWebEngine; ASessionId: string) — note no const, since TProc<> passes by value — and read what you need through GetSessionInfos instead of keeping the object.

Server configuration (Config.yaml)

yaml
Server:
  # TCP port to listen on (default: 8080)
  Port: 8080
  # Bind to a specific interface (default: '' = all interfaces)
  # Use '127.0.0.1' to restrict to localhost only
  BindAddress: ''
  # Number of worker threads in the Indy thread pool (default: 20)
  ThreadPoolSize: 20

Engine:
  Session:
    # Session timeout in minutes (default: 10)
    TimeOut: 30
    # Session cleanup thread interval in seconds
    CleanupInterval: 5

Deployment steps

  1. Compile your application as a .exe (Release, Win64)
  2. Copy the executable and the Home/ directory to the target machine
  3. Edit Config.yaml with the production database connection and settings
  4. Run the executable
  5. Open a browser and navigate to http://localhost:8080/myapp/ (adjust port and path as configured)

Using behind a reverse proxy

For production deployments exposed to the internet, it is recommended to run as a Windows Service behind a reverse proxy (nginx, Apache, or IIS ARR). This provides:

  • HTTPS termination
  • Multiple apps on the same port under different paths
  • Independent restarts without affecting other apps
  • Security filtering

See Proxy Configuration for nginx, Apache, and IIS setup.

See also

Released under Apache License, Version 2.0.