Files
LLeMbas/deploy/lembas.service
T
Jaroslav Beneš 0a4531f02d Agents run over SSH only; put the hardening back
The local sandbox is dropped before it was built. Every hard problem in it
came from running on the machine that holds the database and the encryption
key: the service user cannot traverse /home, granting it needs ACLs,
RLIMIT_NPROC is counted per uid so a fork bomb starves the server too,
--size only applies to tmpfs so there is no disk quota, and the bind list
is a standing invitation to widen until the sandbox is decoration.

Over SSH, isolation is somebody's considered choice of host -- a throwaway
container with one project mounted into it -- using tools far better at it
than anything that could be built here. It is also the only version that is
honestly multi-user: each person brings their own credentials and their own
machine, and picks a project directory on it.

So ProtectKernelTunables goes back. It was removed for exactly one reason,
that bubblewrap cannot mount /proc without it, and that reason is gone. The
agents settings group loses everything bwrap-shaped with it.

What this costs, and the admin copy has to say so: there was a network:False
switch that made exfiltration from a compromised reply impossible, and over
SSH there is no equivalent, because the network belongs to the far side.
The security of an agent chat is now the security of the host behind its
profile, and LLeMbas cannot tell a scratch container from a live server.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 22:12:48 +02:00

55 lines
1.8 KiB
Desktop File

# LLeMbas system service template.
#
# install.sh substitutes __PREFIX__ and __SERVICE_USER__ and writes the result
# to /etc/systemd/system/lembas.service. Edit this file, not the installed copy.
#
# A system unit, not a user unit, so it survives logout and comes up at boot
# without anyone signing in.
[Unit]
Description=LLeMbas - web UI for language models
After=network-online.target
Wants=network-online.target
# The prefix is usually a bind mount; the venv and database live there, so
# starting before it is mounted would create an empty database in its place.
RequiresMountsFor=__PREFIX__
[Service]
Type=simple
User=__SERVICE_USER__
Group=__SERVICE_USER__
WorkingDirectory=__PREFIX__/app
EnvironmentFile=__PREFIX__/lembas.env
ExecStart=__PREFIX__/venv/bin/lembas serve
Restart=on-failure
RestartSec=5
# The bind address comes from LEMBAS_HOST in the environment file, which the
# installer sets to 127.0.0.1: reachable through nginx, never directly.
# --- Hardening -------------------------------------------------------------
# Agent chats run their commands over SSH, on a machine somebody chose and
# prepared -- a container, a VM, another host. Nothing an agent does executes
# here, which is what lets this stay locked down rather than being opened up to
# make room for a sandbox.
#
# ProtectSystem stays `full` rather than `strict` only because the data
# directory has to be writable and `strict` would need every path spelled out.
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=full
ProtectKernelTunables=yes
ProtectControlGroups=yes
RestrictSUIDSGID=yes
ReadWritePaths=__PREFIX__
LimitNOFILE=65535
# Bounds on the service as a whole. Not aimed at anything in particular; a web
# application that has grown a habit of holding network connections open is
# worth a ceiling.
TasksMax=2048
MemoryMax=8G
[Install]
WantedBy=multi-user.target