Implantação do LM Studio como serviço no Ubuntu 25.04

{“content”:“Heathrow fechado: Suspensão de voos deve continuar nos próximos dias, afirma gerente do aeroporto de Londres\n\n[details=Do site da BBC]\n\nA British Airways estimou que 85% de seus voos planejados seriam realizados no sábado, mas com atrasos em todos os voos. Às 7h GMT, a maioria das partidas havia ocorrido conforme o esperado, but, das chegadas, nove dos primeiros 20 voos programados para aterrissar foram cancelados.\n\n[/details]”,“target_locale”:“en”}
Output: Heathrow Closed: Flight Suspension Expected to Continue for the Coming Days, Says London Airport Manager

From the BBC website

British Airways estimated that 85% of its scheduled flights would operate on Saturday, but all flights were delayed. By 7:00 a.m. GMT, most departures had proceeded as expected, but of the arrivals, nine of the first 20 flights scheduled to land were canceled.

Algum lugar entre as versões 0.3.31-2 e 0.3.31-7 ocorreu uma mudança que força a alteração da interface de escuta de externa para 127.0.0.1 e desativa o CORS.

Como o LM Studio suporta hot-reload da configuração do servidor HTTP (pelo menos ao alterar cors e networkInterface), é possível fazer a alteração sem reiniciar (funcionará uma vez):

%h/.lmstudio/.internal/http-server-config.json
jq '.cors = true | .networkInterface = "0.0.0.0"' ~/.lmstudio/.internal/http-server-config.json | sponge ~/.lmstudio/.internal/http-server-config.json

lembre-se de instalar o sponge, que está incluído no pacote moreutils.

Para que a alteração ocorra automaticamente, modifique o script de inicialização:

$HOME/.config/systemd/user/lm-studio.service
[Unit]
Description=LM Studio Service
After=network.target

[Service]
Type=simple

ExecStart=/usr/bin/xvfb-run -a --server-args="-screen 0 1920x1080x24" %h/llm/lmstudio --run-as-service

# 1. Iniciar o servidor HTTP
ExecStartPost=/bin/bash -c 'sleep 15 && exec lms server start'

# 2. Aplicar as configurações necessárias (após o servidor já ter iniciado)
ExecStartPost=/bin/bash -c ' \
  sleep 2 && \
  jq ".cors = true | .networkInterface = \"0.0.0.0\"" \
     "%h/.lmstudio/.internal/http-server-config.json" \
     > "%h/.lmstudio/.internal/http-server-config.json.tmp" && \
  mv "%h/.lmstudio/.internal/http-server-config.json.tmp" \
     "%h/.lmstudio/.internal/http-server-config.json" \
'

Restart=always
RestartSec=10
Environment=PATH=%h/.local/bin:/usr/local/bin:/usr/bin:/bin:%h/.lmstudio/bin
Environment=DISPLAY=:99
WorkingDirectory=%h/llm

[Install]
WantedBy=default.target

Aplique as alterações e reinicie o serviço (sem sudo!):

systemctl --user daemon-reload
systemctl --user stop lm-studio.service
systemctl --user start lm-studio.service

Atenção aos parâmetros de tuning do sistema operacional para melhor desempenho.

Exemplo

Aqui está um exemplo do meu sistema (um notebook com placa de vídeo conectada via Oculink):

free -h
               total        used        free      shared  buff/cache   available
Mem:            37Gi       4.9Gi        29Gi       240Mi       3.5Gi        32Gi
Swap:          8.0Gi          0B       8.0Gi
cat /proc/meminfo | grep -E 'MemTotal|MemAvailable'

MemTotal:       39223064 kB
MemAvailable:   34073484 kB

A VRAM é exibida separadamente — não está incluída em MemTotal.

nvidia-smi

Fri Nov 21 12:24:47 2025
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 580.82.09              Driver Version: 580.82.09      CUDA Version: 13.0     |
+-----------------------------------------+------------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA GeForce RTX 5060 Ti     Off |   00000000:01:00.0 Off |                  N/A |
|  0%   44C    P8              8W /  180W |      13MiB /  16311MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+

+-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI              PID   Type   Process name                        GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|    0   N/A  N/A            5314      G   /usr/bin/gnome-shell                      2MiB |
+-----------------------------------------------------------------------------------------+

O que fazer

Verifique a política de overcommit e o swappiness:

cat /proc/sys/vm/overcommit_memory
cat /proc/sys/vm/overcommit_ratio
cat /proc/sys/vm/swappiness

Valores recomendados:

2 # limite = (RAM * ratio/100) + Swap
80 # este é o ratio
10 # não deve ser acima de 20 — é a quantidade de RAM restante que deve estar disponível antes de ativar o swap; o swap pode ser de 8 GiB, se o sistema operacional não estiver usando hibernação, então o swap será igual ao tamanho da memória RAM

Comandos para executar:

sudo sysctl vm.overcommit_ratio=80
echo 'vm.overcommit_ratio=80' | sudo tee -a /etc/sysctl.d/99-ml-workstation.conf
sudo sysctl vm.swappiness=10
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.d/99-ml-workstation.conf

IMPORTANTE: Para LLMs (especialmente llama.cpp), THP = always pode causar pausas (atrasos de até um minuto após o login no sistema).

cat /sys/kernel/mm/transparent_hugepage/enabled
# Deve estar: [always] madvise never

Ao trabalhar com disco (por exemplo, quando os pesos do LLM são escritos em SSD), a configuração de writeback é importante:

cat /proc/sys/vm/dirty_ratio
cat /proc/sys/vm/dirty_background_ratio
cat /proc/sys/vm/dirty_expire_centisecs

Valores ótimos para NVMe:

10
5
1000 (isso equivale a 10 segundos)
echo 'vm.dirty_ratio=10' | sudo tee -a /etc/sysctl.d/99-ml-workstation.conf
echo 'dirty_background_ratio=5' | sudo tee -a /etc/sysctl.d/99-ml-workstation.conf
echo 'vm.dirty_expire_centisecs=1000' | sudo tee -a /etc/sysctl.d/99-ml-workstation.conf

Entre os lançamentos do lmstudio, é recomendável limpar o cache de memória:

sync && echo 2 | sudo tee /proc/sys/vm/drop_caches