← All Articles

Deploying IMTerm on Windows

IMTerm supports two Windows deployment approaches. WSL2 is recommended for server deployments because it provides the same Linux environment as production and simplifies NFS and service management. The native Windows binary is the right choice for organizations that cannot run WSL2 or need a self-contained Windows Server deployment with no Linux subsystem.


Two Approaches

Approach When to use Notes
WSL2 Server deployments, multi-user, HA cluster Full Linux environment, same as production. NFS, systemd, and nginx all work identically.
Native Windows binary Local/demo use, environments where WSL2 is prohibited Single imterm.exe binary, no Linux required. Fewer deployment tools available.

Approach A: WSL2 (Recommended for Server)

Install WSL2

On Windows 10 (build 19041+) or Windows 11, open PowerShell as Administrator and run:

wsl --install

This one command enables WSL2, installs Ubuntu, and configures the Linux kernel. Restart when prompted. After restart, Ubuntu opens automatically for initial setup (create a Linux username and password).

To verify WSL2 is running:

wsl --list --verbose

Install IMTerm inside WSL2

Once inside the WSL2 Ubuntu shell, follow the standard Linux installation instructions. The WSL2 environment is a full Linux kernel - IMTerm runs identically to a bare-metal Linux deployment.

# Inside WSL2 Ubuntu shell
tar xzf imterm-v2.3.9-linux-amd64.tar.gz
cd imterm-v2.3.9/
sudo ./imterm-setup    # interactive enterprise setup

IMTerm binds to a port inside WSL2. To make it accessible from the Windows host and network, forward the port:

# In PowerShell on the Windows host - forward port 8080 from WSL2 to the Windows NIC
netsh interface portproxy add v4tov4 `
  listenaddress=0.0.0.0 listenport=8080 `
  connectaddress=127.0.0.1 connectport=8080

Users on the network then connect to http://windowsserver:8080. IMTerm runs in the WSL2 layer and is unaware of the port proxy.


Approach B: Native Windows Binary

The native Windows binary (imterm.exe) is a statically linked executable with no dependencies. Extract the ZIP and run:

# Local mode - opens browser automatically
.\imterm.exe --local

# Server mode - bind to all interfaces
.\imterm.exe --addr 0.0.0.0:8080 --data-dir C:\imterm\data

Forward slashes work in all Windows path settings in config.yaml (Go handles both separators). Use forward slashes to avoid YAML escaping issues:

# config.yaml on Windows
data_dir: "C:/imterm/data"    # forward slashes work fine
tls:
  cert: "C:/imterm/certs/imterm.crt"
  key: "C:/imterm/certs/imterm.key"

Firewall Rules

IMTerm listens on port 8080 (HTTP) or 443 (HTTPS if TLS is configured). Open the inbound rule in Windows Defender Firewall:

# Allow inbound TCP 8080 for IMTerm
New-NetFirewallRule `
  -DisplayName "IMTerm Server" `
  -Direction Inbound `
  -Protocol TCP `
  -LocalPort 8080 `
  -Action Allow

For HTTPS on port 443, change -LocalPort 8080 to -LocalPort 443. In a domain environment, deploy this rule via Group Policy (Computer Configuration > Windows Settings > Security Settings > Windows Defender Firewall).


Running as a Windows Service

Option 1: NSSM (recommended)

NSSM (Non-Sucking Service Manager) wraps any executable as a Windows service with full restart-on-failure and stdout/stderr logging. Download NSSM from nssm.cc.

# Install IMTerm as a service
nssm install IMTerm "C:\imterm\imterm.exe"
nssm set IMTerm AppParameters "--config C:\imterm\config.yaml"
nssm set IMTerm AppDirectory "C:\imterm"
nssm set IMTerm DisplayName "IMTerm Terminal Server"
nssm set IMTerm Description "IMTerm multi-protocol terminal emulator"
nssm set IMTerm Start SERVICE_AUTO_START

# Set environment variables (for LDAP password, OIDC secret, etc.)
nssm set IMTerm AppEnvironmentExtra OIDC_CLIENT_SECRET=your-secret-here

# Start the service
nssm start IMTerm

View logs:

nssm set IMTerm AppStdout "C:\imterm\logs\imterm.log"
nssm set IMTerm AppStderr "C:\imterm\logs\imterm-err.log"
nssm set IMTerm AppRotateFiles 1
nssm set IMTerm AppRotateBytes 10485760    # 10 MB rotation

Option 2: Task Scheduler

For environments where NSSM cannot be installed, use Task Scheduler to run IMTerm at system startup:

$action = New-ScheduledTaskAction -Execute "C:\imterm\imterm.exe" `
  -Argument "--config C:\imterm\config.yaml" `
  -WorkingDirectory "C:\imterm"
$trigger = New-ScheduledTaskTrigger -AtStartup
$settings = New-ScheduledTaskSettingsSet -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1)
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest
Register-ScheduledTask -TaskName "IMTerm" -Action $action `
  -Trigger $trigger -Settings $settings -Principal $principal

Setup Wizard (imterm-setup.exe)

The Windows package includes imterm-setup.exe, an interactive setup wizard that guides you through the same 18-phase setup as the Linux imterm-setup TUI. Run as Administrator:

.\imterm-setup.exe

The wizard configures TLS, authentication (local, LDAP, or OIDC), AS/400 connection profiles, and optionally installs IMTerm as an NSSM service. It runs 18 verification checks at the end and produces a config.yaml ready for production use.

For automated (unattended) deployment:

.\imterm-setup.exe --profile production.yaml --yes

The --yes flag skips all confirmation prompts and accepts the defaults in the profile file.


Ansible Playbook

For automated deployment across multiple Windows servers, use the provided Ansible playbook. It installs the binary, creates the config, opens the firewall rule, and installs the NSSM service.

---
- name: Deploy IMTerm on Windows
  hosts: imterm_servers
  gather_facts: yes

  vars:
    imterm_version: "2.3.9"
    imterm_install_dir: "C:/imterm"
    imterm_data_dir: "C:/imterm/data"
    imterm_port: 8080

  tasks:
    - name: Create install directory
      win_file:
        path: "{{ imterm_install_dir }}"
        state: directory

    - name: Copy IMTerm binary
      win_copy:
        src: "imterm-v{{ imterm_version }}-windows-amd64.zip"
        dest: "{{ imterm_install_dir }}/imterm.zip"

    - name: Extract binary
      win_unzip:
        src: "{{ imterm_install_dir }}/imterm.zip"
        dest: "{{ imterm_install_dir }}"

    - name: Deploy config.yaml
      win_template:
        src: config.yaml.j2
        dest: "{{ imterm_install_dir }}/config.yaml"

    - name: Open firewall port
      win_firewall_rule:
        name: IMTerm
        localport: "{{ imterm_port }}"
        action: allow
        direction: in
        protocol: tcp
        state: present
        enabled: yes

    - name: Install as NSSM service
      win_nssm:
        name: IMTerm
        application: "{{ imterm_install_dir }}/imterm.exe"
        app_parameters_free_form: "--config {{ imterm_install_dir }}/config.yaml"
        state: started
        start_mode: auto

config.yaml Path Conventions on Windows

Go's path handling accepts forward slashes on Windows in all contexts. Use forward slashes throughout config.yaml to avoid YAML string escaping issues with backslashes:

# Good - forward slashes, no escaping needed
data_dir: "C:/imterm/data"
audit:
  log_path: "C:/imterm/logs/audit.jsonl"
tls:
  cert: "C:/imterm/certs/imterm.crt"
  key: "C:/imterm/certs/imterm.key"

# Avoid - backslashes require escaping in YAML
# data_dir: "C:\\imterm\\data"    # works but harder to read

RAM Planning on Windows

Windows Server has a higher base memory footprint than Linux. Reserve 6-8 GB for the OS and system processes before applying the IMTerm sizing formula:

safe_sessions = floor((available_ram_gb - 8) / 0.032 * 0.80)

For a 32 GB Windows Server node:

  • Available after OS reserve: 32 - 8 = 24 GB
  • Maximum sessions: 24 / 0.032 = 750
  • Safe sessions (80%): 750 x 0.80 = 600 sessions

The same 32 GB Linux node handles approximately 700 safe sessions. Windows overhead costs roughly 100 sessions per 32 GB node at this scale.

See the Capacity Planning and Sizing Guide for the full formula and a sizing table, and use the interactive calculator to compute values for your hardware.