ifcurl/forgejo/server-config/ifcurl-preview.service
Bruno Postle fef6c16946 ifcurl-preview.service: correct misleading execve comment
execve is actually permitted — it arrives via @default which is included in
@system-service.  The main service needs it for GitPython's git CLI calls.
Blocking execve only in render subprocesses would require per-process seccomp,
which is not worth the complexity for this threat model.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 08:30:41 +01:00

70 lines
2.5 KiB
Desktop File

[Unit]
Description=ifcurl preview service
Documentation=https://github.com/brunopostle/ifcurl
After=network.target
[Service]
Type=simple
User=ifcurl
Group=ifcurl
EnvironmentFile=-/etc/ifcurl/env
ExecStart=/usr/local/bin/ifcurl serve \
--host 127.0.0.1 \
--port 8000 \
--allowed-hosts git.example.com
Restart=on-failure
RestartSec=5
# Cache configuration — override in /etc/ifcurl/env:
# IFCURL_CACHE_MAX_GB=10 max bare-repo disk cache
# IFCURL_T2_MAX=8 max IFC blobs in memory
# IFCURL_T3_MAX=64 max selector results in memory
# IFCURL_SANDBOX_TIMEOUT=120 max seconds per render subprocess
# IFCURL_SANDBOX_MEMORY_MB=0 address-space cap per subprocess (0=unlimited)
# ---------------------------------------------------------------------------
# Sandbox hardening
#
# These directives apply to the service process and all child processes
# (including the render subprocesses spawned by sandbox.py). Together they
# limit the blast radius if a crafted IFC file achieves code execution inside
# a render subprocess.
#
# ProtectSystem=strict + ReadWritePaths: the service can only write to its own
# cache directory; the Forgejo data tree (/var/lib/forgejo, /etc/forgejo) is
# read-only from this unit's perspective.
#
# NoNewPrivileges + RestrictSUIDSGID: prevent privilege escalation via
# setuid binaries or capabilities.
#
# SystemCallFilter: allow the syscalls a Python/C-extension process needs
# (@system-service covers the common POSIX set including execve via @default;
# @process adds fork/clone for ifcopenshell's geometry iterator). execve is
# permitted because the main process needs it for git CLI calls (GitPython).
# The filter applies to child processes too (inherited across fork).
#
# RestrictAddressFamilies: the service only needs TCP/UDP to reach git hosts.
# AF_UNIX is excluded so a compromised subprocess cannot connect to the
# Forgejo Unix socket if one is present.
# ---------------------------------------------------------------------------
Environment=XDG_CACHE_HOME=/var/cache
CacheDirectory=ifcurl
NoNewPrivileges=yes
RestrictSUIDSGID=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/cache/ifcurl
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictNamespaces=yes
LockPersonality=yes
RestrictRealtime=yes
RestrictAddressFamilies=AF_INET AF_INET6
SystemCallArchitectures=native
SystemCallFilter=@system-service @process @files @io-event @network-io
SystemCallErrorNumber=EPERM
[Install]
WantedBy=multi-user.target