Running a server gets
grixeld up on your machine. This page is for running it as
something your team depends on: keeping it up, securing it for access
beyond your own computer, backing it up, and keeping it healthy.
#Keep it running in the background
grixeld serve runs in the foreground and stops when you
close the terminal. For a real deployment, run it under whatever keeps
services alive on your host — systemd on Linux,
launchd on macOS, or a process manager — so it restarts on
crash and on reboot. A minimal systemd unit looks like:
[Unit]
Description=Grixel server
After=network.target
[Service]
ExecStart=/usr/local/bin/grixeld serve -data-root /srv/grixel-data -grpc-addr 0.0.0.0:8090
Restart=on-failure
User=grixel
[Install]
WantedBy=multi-user.target
Point -data-root at durable storage, and run the service
as a dedicated user that owns that folder.
#Let other machines connect
By default the server listens on localhost, reachable
only from the same machine. To let teammates connect, bind a reachable
address (-grpc-addr 0.0.0.0:8090) and make sure your
firewall allows it.
Once you're exposing the server beyond your own machine, turn on
encryption. Give grixeld a TLS certificate and key:
grixeld serve -data-root /srv/grixel-data \
-grpc-addr 0.0.0.0:8090 \
-tls-cert /etc/grixel/cert.pem -tls-key /etc/grixel/key.pem
Clients then connect with grpcs:// instead of
grpc://:
grixel login -server grpcs://your-server-host:8090 -token <token>
#Back it up
Backing up the server means backing up its data root — but use the built-in command, because it knows which parts have to be captured together.
The server keeps serving. A backup copies the bulk of your data while people are working, and pauses writes for about a millisecond to capture the small bookkeeping that has to be consistent. Nobody notices.
grixeld backup -online -data-root /srv/grixel-data -out /backups/grixel
Checkpoint 2026-09-07T02-00-01Z.tar.gz
taken : 2026-09-07T02:00:01Z, online (depot serving)
writers paused for: 1 ms
Copying the object store (live — the depot keeps serving)...
copied : 41203 objects, 88.4 GiB
already held: 0 objects (this is what makes it incremental)
-out is a directory, and you point
every run at the same one:
/backups/grixel/checkpoints/2026-09-07T02-00-01Z.tar.gz
/backups/grixel/checkpoints/2026-09-08T02-00-01Z.tar.gz
/backups/grixel/objects/
Every run after the first only copies what is new. Stored files are named after their own contents and never change, so a second backup takes a day's work and skips everything else. That means keeping ten days of restore points costs one copy plus ten days of changes — not ten copies. Put it in cron and keep real history.
Old restore points do not clean themselves up. Once a week:
# Report first — nothing is deleted without -apply.
grixeld backup -prune -out /backups/grixel -keep 7
grixeld backup -prune -out /backups/grixel -keep 7 -apply
#Doing the copy yourself
On a large server you may prefer your own tooling, and it will
probably be better at resuming, rate-limiting and writing to tape than
anything built in. The objects folder inside the data root
is only ever added to, so rsync, a filesystem snapshot or
an object-store sync all work against a running server.
Take the checkpoint first, then run your copy — in that order:
grixeld checkpoint -data-root /srv/grixel-data -out /backups/cp-$(date +%FT%H%M).tar.gz
rsync -a /srv/grixel-data/.grixel/objects/ /backups/grixel/objects/
The order matters and it is the opposite of the obvious one. A checkpoint only ever names files that already exist, so a copy made afterwards is guaranteed to contain them. The other way round, the bookkeeping can name a file your copy already went past, and you have a backup with a hole in it that you find out about during a restore.
A checkpoint on its own is small — megabytes — so you can take one often and keep it somewhere else entirely.
grixeld checkpointis a server snapshot, for backups. It is unrelated togrixel checkpoint, which is a personal save-point in your own working copy — see AI assistants and agents.
#Restore it
Restore into a fresh data root. You have to say which of the two restores this is, because a backup carries the server's identity inside it:
# The original server coming back after a failure. Everyone's existing
# working copies keep working, which is the point of having the backup.
grixeld restore -in /backups/grixel \
-data-root /srv/grixel-data-restored -identity preserve
# A SECOND server built from the same backup: a staging copy, a test box,
# a forensic look at last week. It gets a new identity, so nobody's working
# copy can accidentally submit real work into it.
grixeld restore -in /backups/grixel \
-data-root /srv/grixel-staging -identity new
There is no default, on purpose. Guessing wrong in either direction causes a bad day: a staging copy that answered to the live server's identity would happily accept work meant for production, and a genuine recovery that re-minted its identity would lock out every checkout in the building.
Add -at <checkpoint> to restore an older point
instead of the newest.
It checks itself behind the running server. Start
the restored server and it verifies in the background that every file
its history references is present, logging anything missing. In a real
outage the thing you need is the server up, not a multi-hour
check before the first person can connect. If you are doing a rehearsal,
where waiting is the point, use -verify to prove it before
the command returns.
-link makes restoring a very large
server nearly instant when the backup is on the same disk, by pointing
at the existing files instead of copying them. It cannot damage the
backup.
Keep backups off the server's own disk, and rehearse a restore occasionally — an untested backup is not a backup.
#Keep it healthy
grixeld verify checks that the server can still produce
every byte it claims to hold. Two questions, and it answers both:
is anything missing (a file some commit references that
is no longer there) and has anything rotted (a stored
file whose contents have silently changed on disk — the only check that
can catch that).
It runs while the server is running. Verification changes nothing, so it does not need the server stopped.
A full pass reads every byte, which is hours on a large server. So you give it a time budget instead, and it remembers where it got to:
# In cron, nightly. Checks what fits, picks up there tomorrow, and covers
# the whole server over several nights — for ever.
grixeld verify -data-root /srv/grixel-data -for 30m -heal /backups/grixel
grixeld verify -data-root /srv/grixel-data -status # when did this last happen, and what did it find?
grixeld verify -data-root /srv/grixel-data -cancel # stop one that is running
Starting a check prints progress and then lets go: Ctrl-C detaches, it does not cancel. The run belongs to the server, so closing a laptop does not throw away three hours of work.
It gets out of the way. The check runs at full speed while the server has room and backs off to a tenth of the time whenever people are actually queued waiting for it. Each run reports how much of the time it got, so a slow night has an explanation.
It repairs what it can. -heal names
places to fetch a good copy from — a backup directory, or another
server's data root. Because every stored file is named after its own
contents, this is exact rather than a guess: a replacement is only
accepted if it matches the same fingerprint that condemned the original,
and the original is put back untouched if it does not.
A repair is always reported loudly. The data is correct again, but a disk wrote bad bytes, and that is worth going and looking at.
#Reclaim space
Deleted branches, abandoned uploads and superseded file versions
leave data behind that nothing points at any more.
grixeld gc finds it and removes it, against a
running server:
grixeld gc -data-root /srv/grixel-data -dry-run # what it would remove, and how much space
grixeld gc -data-root /srv/grixel-data # do it
grixeld gc -data-root /srv/grixel-data -for 30m # nightly: half an hour, then stop and remember where
It works the same way the integrity check does. It pauses writers for
a few milliseconds to take a consistent picture of what is still in use,
then does the long part — walking the stored data — with everyone
working normally, backing off whenever people are queued.
-status checks on one, -cancel stops one, and
Ctrl-C detaches without cancelling.
Recently written data is never removed, whether it is referenced or not. The window is 24 hours by default against a running server and cannot be set below six, because that window is what protects an upload that has not been committed yet. The report prints the exact cutoff it used:
deleted : 118 (2.3 GiB)
kept : 4 unreachable but newer than the horizon
horizon : 2026-09-07T09:14:02Z (mark minus 24h0m0s)
Against a stopped server the window defaults to one hour, since nothing is in flight to protect.
Do not run it during a backup's file copy, and you do not have to remember not to: the two know about each other and whichever is second says so.
The remaining maintenance commands still want the server stopped:
grixeld info -data-root /srv/grixel-data # a summary of the data root's state
grixeld compact -data-root /srv/grixel-data # re-pack stored data after changing the storage setting
#Watch it
grixeld exposes metrics for monitoring at
-metrics-addr (default localhost:9090, path
/metrics) in a format standard monitoring tools scrape.
Point your monitoring at it to track health and load.
#Update the server
Updating is the same as installing — re-run
the installer to get the new grixeld, then restart the
service. Take a backup first. Clients and servers on nearby versions
work together, so you don't have to update everyone at once, and a newer
grixeld starts normally on an older data root — upgrading
is never an outage.
Some releases add a storage format the previous version cannot read. Those wait for you to say so:
grixeld migrate -dry-run -data-root /srv/grixel-data # what would change, and what it costs
grixeld migrate -data-root /srv/grixel-data
It tells you what each step turns on, and says plainly when a step is one-way. Take a backup first.
#Scaling reads later
If many people on the same network read large files from one server, you can put a read-through cache in front of it so those reads are served locally instead of all hitting the main server. That's an optional add-on for later; a single server serves a team well to begin with.