Files
rustingface/asset/systemd/rustingface.service
T
grenadeandClaude Opus 5 cb1ca8b6af
deploy / build (push) Waiting to run
deploy / deploy (push) Has been cancelled
feat(rustingface): implement the registry, admin CLI and deployment
Scaffolds the workspace per architecture/generic.md §1 and implements
phases 0-3 of doc/spec.md §12.

Crates:
  entities  manifest/ref/repo schemas, bucket key layout, config, the
            X-Error-Code taxonomy. No I/O.
  core      resolver, freeze pinning, single-flight, the streaming tee,
            policy, gc/verify/refresh. Defines the Store and Upstream
            ports.
  data      object_store (S3 + local) and reqwest Hub adapters.
  api       the axum surface: resolve, model/dataset info, tree, refs,
            whoami, metrics, bearer auth, range handling.
  bin       one binary: serve plus fetch/pin/refresh/list/show/rm/gc/
            verify/doctor.

Deployment targets bob.hanzalova.internal:20482 (port derived per
architecture/port-allocations.md §3), storing to the MinIO on
caveman.kosherinata.internal, fronted by hanzalova at rf.internal.
Ships the sysusers drop-in, hardened unit, firewalld service, nginx
vhost, config template, infra-setup.sh and the Gitea Actions
ci/deploy/conformance workflows.

Testing: 112 unit and integration tests, including the sovereignty
suite (cold fetch, sealed replay, single-flight, client disconnect,
range resume, freeze stability, gc-after-rm, digest mismatch), plus a
conformance suite driving a pinned huggingface_hub against a real Hub.

Deviations from the spec, all deliberate:
  - one binary with subcommands (spec §9) rather than generic.md's
    separate -api and -cli binaries; the library split is unchanged.
  - a dedicated sysusers account and hardened unit (generic.md §8)
    rather than the spec's illustrative DynamicUser unit.
  - manifests carry an optional repo_tree recorded verbatim, resolving
    spec §13's "record whole, filter on read" question for the tree
    endpoint as well as model-info.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XZG2i4AmfSqE97EJGBVb64
2026-08-31 10:46:25 +03:00

60 lines
1.9 KiB
Desktop File

[Unit]
Description=rustingface sovereign model registry
Documentation=https://git.lair.cafe/grenade/rustingface
After=network-online.target
Wants=network-online.target
[Service]
# Type=exec, not notify: the binary sends no sd_notify, and a notify unit that
# never sends READY=1 blocks `systemctl restart` until TimeoutStartSec.
Type=exec
User=rustingface
Group=rustingface
ExecStart=/usr/local/bin/rustingface serve --config /etc/rustingface/config.toml
Restart=on-failure
RestartSec=5s
# Credentials are passed by systemd rather than read from disk by the service,
# so the secret files stay root-owned and never appear in the unit's namespace
# except under $CREDENTIALS_DIRECTORY. The config names these basenames.
LoadCredential=s3-access-key:/etc/rustingface/s3-access-key
LoadCredential=s3-secret-key:/etc/rustingface/s3-secret-key
LoadCredential=hf-token:/etc/rustingface/hf-token
# Long transfers must not be killed mid-flight on stop; a detached upload that
# is cut short leaves an orphan blob, which is safe but wasteful.
TimeoutStopSec=120
# Hardening. The process holds no durable state — the bucket is the whole of it
# — so there is no StateDirectory to protect and ProtectSystem can stay strict
# with no ReadWritePaths at all.
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
ProtectClock=true
ProtectHostname=true
ProtectProc=invisible
RestrictRealtime=true
RestrictSUIDSGID=true
RestrictNamespaces=true
LockPersonality=true
MemoryDenyWriteExecute=true
SystemCallFilter=@system-service
SystemCallArchitectures=native
CapabilityBoundingSet=
AmbientCapabilities=
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
UMask=0077
# Concurrent multi-gigabyte transfers each hold a handful of sockets and part
# buffers; the default 1024 is comfortable but the headroom costs nothing.
LimitNOFILE=16384
[Install]
WantedBy=multi-user.target