Skip to content

Installation wslc

Stuart Meeks edited this page Jul 4, 2026 · 5 revisions

Installation — WSL Containers (wslc)

Run FICSIT Foreman on Windows 11 using WSL Containers (wslc.exe) — the Linux container runtime built into the Windows Subsystem for Linux — with no Docker Desktop.

Preview feature — but tested. wslc shipped as a public preview in WSL 2.9.3 (June 2026). It has no Docker Compose, so the stack runs as three individual containers below. The primary path here was verified end-to-end on the preview — a bridge network with container-name DNS, Windows bind mounts, and a working browser → backend → MCP tool calls → LLM round-trip. Two preview gaps worth knowing (both covered below): wslc doesn't run image HEALTHCHECKs, and there's no restart-on-boot. If you just want the smoothest path, use Installation — Docker instead.

It runs the same ghcr.io/stuartmeeks/foreman-* images and ends up at the same place: http://localhost:8725.

Shell note. The commands below use PowerShell line-continuation — a backtick (`) at the end of each line. In cmd.exe, put each command on a single line (drop the backticks); everything else is identical.


Prerequisites — install and verify wslc

Run these in PowerShell:

wsl --update                    # get a WSL version that includes wslc
wslc version                    # confirm the CLI is present
wslc run --rm hello-world       # pulls + runs a tiny image to prove it works

Then probe the capabilities this guide depends onwslc is evolving, so confirm these before you start:

wslc --help
wslc network --help             # is there a `network create`? (needed for name-based DNS)
wslc run --help                 # confirm -d  -p  -e  -v  --name  --network

If wslc network exists and wslc run accepts --network, use the primary path below. If not, jump to Fallback: no user-defined network.


Why three separate commands (not one)

The Docker path uses docker compose up -d to start everything at once. wslc has no Compose yet, so you start each service by hand. Two of them talk to each other by container name — this is baked into the images, so the --name values below are not optional:

  • ff-client's web server proxies /api/ to http://ff-server:8724
  • ff-server reaches the MCP server at http://sf-mcp:8723/mcp

So the containers must share a network on which they can resolve each other by name, and they must be named exactly sf-mcp and ff-server.


1. Create folders for persistent data

wslc's preview doesn't confirm Docker-style named volumes, but Windows bind mounts are supported — and they keep your database and saves in a folder you control (this also avoids container file-ownership quirks). Create two folders:

mkdir C:\foreman\data           # SQLite DB, auth secret, sessions, work orders
mkdir C:\foreman\saves          # uploaded playthrough .sav files (shared by two services)

Anything under C:\foreman is fine — just use the same paths consistently below.

2. Create the shared network

wslc network create foreman-net

This gives the containers automatic name-based DNS (so ff-server can find sf-mcp, and ff-client can find ff-server). wslc network list should now show it on the bridge driver:

NETWORK ID     NAME          DRIVER
609305e105ca   foreman-net   bridge

3. Start the MCP server (sf-mcp)

wslc run -d --name sf-mcp --network foreman-net `
  -p 8723:8723 `
  -v C:\foreman\saves:/data/saves `
  -e SAVE_DATA_DIR=/data/saves `
  ghcr.io/stuartmeeks/foreman-sf-mcp:latest

Publishing -p 8723:8723 is optional (handy for hitting /health from Windows); the other services reach it over foreman-net, not via the published port. Confirm it's serving:

curl http://localhost:8723/health
{"status":"ok","version":"1.2.3.1","build":495413,"saveName":"none"}

4. Start the backend (ff-server)

wslc run -d --name ff-server --network foreman-net `
  -p 8724:8724 `
  -v C:\foreman\data:/data `
  -v C:\foreman\saves:/data/saves `
  -e MCP_URL=http://sf-mcp:8723/mcp `
  -e SAVE_DATA_DIR=/data/saves `
  -e DATABASE_URL=file:/data/foreman.db `
  -e ANTHROPIC_API_KEY=sk-ant-... `
  ghcr.io/stuartmeeks/foreman-ff-server:latest
  • ANTHROPIC_API_KEY is optional — leave it out to have each browser client supply its own key. To run on an OpenAI-compatible provider instead, pass LLM_PROVIDER / LLM_API_KEY / LLM_MODEL / LLM_BASE_URL (see Configuration).
  • MCP_URL and DATABASE_URL shown here match the image defaults; they're listed so the command is self-explanatory.
  • On first start it runs its database migrations, then boots.

Check the logs — one line proves the cross-container connection worked:

wslc container logs ff-server
All migrations have been successfully applied.
[foreman-ff-server] Loaded system prompt from /app/SYSTEM_PROMPT.md
[foreman-ff-server] Connected to MCP server at http://sf-mcp:8723/mcp (game version 1.2.3.1)
[foreman-ff-server] Listening on http://0.0.0.0:8724 (health: /health)

Connected to MCP server at http://sf-mcp:8723/mcp means ff-server resolved sf-mcp by name over foreman-net — the whole reason the shared network matters. A first-boot warning that BETTER_AUTH_SECRET was auto-generated (and persisted under /data) is normal; set it explicitly only for multi-instance setups.

5. Start the web app (ff-client)

wslc run -d --name ff-client --network foreman-net `
  -p 8725:80 `
  ghcr.io/stuartmeeks/foreman-ff-client:latest

6. Open the foreman

Browse to http://localhost:8725.


Verify and manage

wslc container list                    # all three should be running
wslc container logs ff-server          # look for DB migrations + a successful MCP connect
wslc container logs sf-mcp
wslc container logs ff-client

All three should be listed as running:

CONTAINER ID   NAME        IMAGE                  STATUS                 PORTS
6b779f558e99   ff-client   ghcr.io/stuartmeeks…   running 2 minutes ago  127.0.0.1:8725->80/tcp
19392c6fa7b6   ff-server   ghcr.io/stuartmeeks…   running 4 minutes ago  127.0.0.1:8724->8724/tcp
e64a418d2e55   sf-mcp      ghcr.io/stuartmeeks…   running 8 minutes ago  127.0.0.1:8723->8723/tcp

No health column. This wslc preview doesn't run image HEALTHCHECKs, so the STATUS above only ever shows running (never (healthy)), and wslc container inspect has no Health block. Check health yourself by hitting the endpoints — curl http://localhost:8723/health and curl http://localhost:8724/health both return {"status":"ok",...} when up.

Everyday control:

wslc container stop  ff-client ff-server sf-mcp
wslc container start sf-mcp ff-server ff-client     # start mcp first
wslc container rm    ff-client ff-server sf-mcp     # remove (your C:\foreman data stays)

Auto-start on boot: Docker Compose's restart: unless-stopped has no confirmed wslc equivalent in the preview, so the containers won't come back by themselves after a reboot. Re-run the start commands (or the script below), or wire the script into Windows Task Scheduler at logon.

To update to newer images later:

wslc container stop ff-client ff-server sf-mcp
wslc container rm   ff-client ff-server sf-mcp
wslc image pull ghcr.io/stuartmeeks/foreman-sf-mcp:latest
wslc image pull ghcr.io/stuartmeeks/foreman-ff-server:latest
wslc image pull ghcr.io/stuartmeeks/foreman-ff-client:latest
# then re-run steps 3–5. Your C:\foreman data (DB + saves) is preserved.

Optional: one-shot start script

Save as start-foreman-wslc.ps1 and run it in PowerShell (e.g. ./start-foreman-wslc.ps1 -AnthropicApiKey sk-ant-...). It's just the commands above, made idempotent.

param(
  [string]$DataRoot        = "C:\foreman",
  [string]$AnthropicApiKey = "",
  [string]$Network         = "foreman-net"
)

$ErrorActionPreference = "Stop"

New-Item -ItemType Directory -Force -Path "$DataRoot\data", "$DataRoot\saves" | Out-Null

# Create the network if it doesn't already exist (ignore the error if it does).
wslc network create $Network 2>$null

# Remove any previous containers so this is re-runnable.
wslc container rm -f ff-client ff-server sf-mcp 2>$null

wslc run -d --name sf-mcp --network $Network `
  -p 8723:8723 `
  -v "$DataRoot\saves:/data/saves" `
  -e SAVE_DATA_DIR=/data/saves `
  ghcr.io/stuartmeeks/foreman-sf-mcp:latest

$serverArgs = @(
  "run","-d","--name","ff-server","--network",$Network,
  "-p","8724:8724",
  "-v","$DataRoot\data:/data",
  "-v","$DataRoot\saves:/data/saves",
  "-e","MCP_URL=http://sf-mcp:8723/mcp",
  "-e","SAVE_DATA_DIR=/data/saves",
  "-e","DATABASE_URL=file:/data/foreman.db"
)
if ($AnthropicApiKey) { $serverArgs += @("-e","ANTHROPIC_API_KEY=$AnthropicApiKey") }
$serverArgs += "ghcr.io/stuartmeeks/foreman-ff-server:latest"
wslc @serverArgs

wslc run -d --name ff-client --network $Network `
  -p 8725:80 `
  ghcr.io/stuartmeeks/foreman-ff-client:latest

Write-Host "FICSIT Foreman is starting — open http://localhost:8725"

To stop everything: wslc container stop ff-client ff-server sf-mcp.


Fallback: no user-defined network

If your wslc build has no network create / --network, the two name-based hops (ff-serversf-mcp, and ff-clientff-server) can't resolve. Route them through the Windows host instead — this only works if your wslc exposes a host-gateway address reachable from inside a container (commonly host.docker.internal; confirm with wslc run --help / the release notes).

  1. Publish both backend ports (-p 8723:8723 on sf-mcp, -p 8724:8724 on ff-server) so they're reachable on the host.

  2. Point the backend at the MCP server via the host gateway: -e MCP_URL=http://host.docker.internal:8723/mcp (drop --network foreman-net).

  3. The client's /api/ proxy target (ff-server:8724) is baked into its image, so override it with your own nginx config mounted over the default. Save this as C:\foreman\default.conf:

    server {
      listen 80;
      root /usr/share/nginx/html;
      index index.html;
      location /api/ { proxy_pass http://host.docker.internal:8724; }
      location /    { try_files $uri $uri/ /index.html; }
    }

    then run the client with it mounted:

    wslc run -d --name ff-client `
      -p 8725:80 `
      -v C:\foreman\default.conf:/etc/nginx/conf.d/default.conf:ro `
      ghcr.io/stuartmeeks/foreman-ff-client:latest

If neither a user-defined network nor a host gateway is available in your preview build, use Installation — Docker until wslc networking matures.


See also

Clone this wiki locally