DEV Community

Cover image for Running LM Studio Locally Doesn't Mean It Never Connects Out
k-wada
k-wada

Posted on

Running LM Studio Locally Doesn't Mean It Never Connects Out

When we say “local LLM,” it is easy to mentally translate that into:

Everything stays inside the PC.

For inference, that can be true.

But the application running the model is still an application with network-capable features.

LM Studio, for example, may need connectivity for things such as:

  • searching for models
  • downloading models
  • downloading runtimes
  • checking for application updates

It can also expose a local API server, connect to MCP servers, enable CORS, or serve the API to other devices on the LAN.

None of those features are inherently bad.

But I wanted a much narrower environment:

one approved model, local inference, and as little external connectivity as possible.

So I treated “local execution” and “network isolation” as two separate problems.

My target state

For normal use, I wanted this:

LM Studio
   |
   +---- 127.0.0.1 / localhost ---- allowed
   |
   +---- LAN ----------------------- blocked
   |
   +---- Internet ------------------ blocked
Enter fullscreen mode Exit fullscreen mode

The important part is the loopback connection.

Blocking everything blindly can also break communication that stays entirely inside the machine.

So the rule became:

deny external communication, but deliberately preserve loopback.

Configuration is not the security boundary

LM Studio already provides useful settings.

For my baseline I disable features I do not need:

  • Serve on Local Network
  • CORS
  • per-request MCP
  • MCP servers from mcp.json
  • cloud features / web search
  • automatic model switching or unexpected model loading

I also keep the API server off because I do not need it for this evaluation.

And my mcp.json is intentionally boring:

{
  "mcpServers": {}
}
Enter fullscreen mode Exit fullscreen mode

But I do not want the security of the environment to depend entirely on application settings.

Settings can be changed.

Their internal representation can also change between versions.

So I use two layers:

LM Studio settings
        +
OS network controls
Enter fullscreen mode Exit fullscreen mode

The first expresses the intended configuration.

The second enforces the boundary.

Separate setup from normal use

This was probably the most useful design decision.

LM Studio needs the network while preparing the machine.

So I split operation into two phases.

Setup phase

Network access is temporarily available for things that genuinely require it:

Install LM Studio
        ↓
Download the approved runtime
        ↓
Download the approved model
        ↓
Verify the files
Enter fullscreen mode Exit fullscreen mode

After that, normal use does not need model discovery or downloads.

Normal-use phase

The environment becomes much smaller:

Start LM Studio
        ↓
Restore the hardened configuration
        ↓
Check MCP configuration
        ↓
Check network restrictions
        ↓
Unload previously loaded models
        ↓
Load only the approved model
        ↓
Run locally
Enter fullscreen mode Exit fullscreen mode

This avoids trying to make installation and daily operation obey the same network policy.

They are different states.

Pin the model at startup

Another thing I did not want was:

“LM Studio is approved, therefore any model inside LM Studio is approved.”

Those are two different decisions.

At startup I first unload existing models:

lms unload --all
Enter fullscreen mode Exit fullscreen mode

Then I load the model selected for the evaluation:

lms load <approved-model> \
  --context-length 8192 \
  --identifier approved-model
Enter fullscreen mode Exit fullscreen mode

The actual startup wrapper also verifies that the expected model is available before continuing.

If the expected state cannot be established, startup should fail rather than quietly falling back to something else.

That is a small change, but it makes the environment much more reproducible.

If you need the API server

My current use case does not require it, so I leave it off.

But LM Studio's CLI supports explicitly binding the server to loopback:

lms server start \
  --bind 127.0.0.1 \
  --port 1234
Enter fullscreen mode Exit fullscreen mode

That is very different from:

lms server start --bind 0.0.0.0
Enter fullscreen mode Exit fullscreen mode

The first stays on localhost.

The second makes the server reachable beyond localhost and changes the security boundary significantly.

For a controlled local evaluation, I would not expose it unless there is a concrete reason to do so.

I also verify the result

A configuration file saying “disabled” is not enough.

I want to observe what actually happens.

So the evaluation includes checks such as:

  • which processes are listening on ports
  • whether unexpected external connections appear
  • whether the API server is running
  • whether MCP configuration changed
  • which model is actually loaded
  • whether unexpected GGUF files appeared
  • whether firewall rules are still present

The distinction matters:

configuration → what should happen
verification  → what actually happened
Enter fullscreen mode Exit fullscreen mode

For this kind of environment, I want both.

“Local” describes where inference happens

This experiment changed how I think about the word local.

A local LLM tells me where the model inference runs.

It does not automatically define every network behavior of the application surrounding that model.

So my final model is:

Local inference
      ≠
Network isolation
Enter fullscreen mode Exit fullscreen mode

If I care about both, I need to design for both.

LM Studio already works well offline once the required model and runtime are available.

What I added was a smaller operational boundary around it:

prepare while connected, then run with the outside closed and only the communication that must stay inside the machine deliberately preserved.

The full implementation and notes are available in the original Legacy Tools article.

Top comments (0)