Initial commit
Test / test (push) Successful in 7m5s
Release / gates (push) Successful in 7m28s
Release / build (amd64, freebsd) (push) Successful in 2m52s
Release / build (amd64, linux) (push) Successful in 2m46s
Release / build (arm64, freebsd) (push) Successful in 2m22s
Release / build (arm64, linux) (push) Successful in 2m38s
Release / build (loong64, linux) (push) Successful in 2m7s
Release / build (riscv64, linux) (push) Successful in 2m17s
Release / release (push) Successful in 1m0s
Test / test (push) Successful in 7m5s
Release / gates (push) Successful in 7m28s
Release / build (amd64, freebsd) (push) Successful in 2m52s
Release / build (amd64, linux) (push) Successful in 2m46s
Release / build (arm64, freebsd) (push) Successful in 2m22s
Release / build (arm64, linux) (push) Successful in 2m38s
Release / build (loong64, linux) (push) Successful in 2m7s
Release / build (riscv64, linux) (push) Successful in 2m17s
Release / release (push) Successful in 1m0s
Assisted-by: GLM 5.3
This commit is contained in:
+408
@@ -0,0 +1,408 @@
|
||||
.\" Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
||||
.\" SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
|
||||
.TH VOLUMEN 1 "2026-09-27" "volumen 1.0.0" "Volumen Manual"
|
||||
.SH NAME
|
||||
volumen \- lightweight publishing platform for scientists
|
||||
.SH SYNOPSIS
|
||||
.B volumen
|
||||
.RI [ command "] [" options ]
|
||||
.SH DESCRIPTION
|
||||
Volumen is a lightweight publishing platform for scientists: a headless JSON
|
||||
API plus a server-rendered admin, over posts that are files. Every post is a
|
||||
Markdown file with a TOML frontmatter block inside a content directory. The
|
||||
engine serves that directory as a JSON API under
|
||||
.BR /api/volumen ,
|
||||
serves the admin under
|
||||
.BR /admin ,
|
||||
and stores uploaded media under
|
||||
.BR /media .
|
||||
It has no database and no runtime dependency besides the binary itself; a
|
||||
public site is a separate front end that consumes the API.
|
||||
.PP
|
||||
Run
|
||||
.B volumen
|
||||
with a command named below. Each command accepts
|
||||
.B \-h
|
||||
for its own usage. An unknown command and an unknown flag exit with status 2,
|
||||
and every command rejects a stray positional argument.
|
||||
.SH COMMANDS
|
||||
.TP
|
||||
.B serve
|
||||
Start the publishing server. With no accounts yet, the first visit to
|
||||
.B /admin
|
||||
shows the first-run wizard, which creates the administrator account.
|
||||
.TP
|
||||
.B status
|
||||
Show installation status.
|
||||
.TP
|
||||
.B doctor
|
||||
Check installation health.
|
||||
.TP
|
||||
.B check-update
|
||||
Compare with the latest Gitea release.
|
||||
.TP
|
||||
.B export
|
||||
Export posts, media, and users to a tar.gz.
|
||||
.TP
|
||||
.B import
|
||||
Import a backup archive.
|
||||
.TP
|
||||
.B publish-due
|
||||
Publish scheduled posts whose date arrived.
|
||||
.TP
|
||||
.B validate
|
||||
Validate the content directory.
|
||||
.TP
|
||||
.B version
|
||||
Show version.
|
||||
.SH OPTIONS
|
||||
.SS serve
|
||||
.TP
|
||||
.BI "\-\-config" " path"
|
||||
Path to
|
||||
.IR config.toml .
|
||||
Without the flag the server reads
|
||||
.I /etc/volumen/config.toml
|
||||
if it exists, otherwise
|
||||
.IR ~/.config/volumen/config.toml ;
|
||||
when neither exists it runs on the built-in defaults, whose state paths lie
|
||||
under
|
||||
.I ~/.local/share/volumen
|
||||
(honouring
|
||||
.IR XDG_DATA_HOME ).
|
||||
.TP
|
||||
.BI "\-\-content" " dir"
|
||||
Override
|
||||
.IR content_dir .
|
||||
.TP
|
||||
.BI "\-\-host" " addr"
|
||||
Override
|
||||
.BR [server].host ,
|
||||
an IP address such as
|
||||
.B ::
|
||||
or
|
||||
.BR ::1 .
|
||||
.TP
|
||||
.BI "\-\-port" " n"
|
||||
Override
|
||||
.BR [server].port ,
|
||||
1 to 65535. A value outside the range is rejected.
|
||||
.PP
|
||||
The server bounds every connection: a 10 second read-header timeout, a 60
|
||||
second read timeout, a 120 second write timeout and a 120 second idle
|
||||
timeout, with request lines and headers capped at 1 MiB.
|
||||
.B SIGINT
|
||||
and
|
||||
.B SIGTERM
|
||||
drain in-flight requests for up to 15 seconds and then exit 0. When
|
||||
.B [scheduler].enabled
|
||||
is set, the due posts are published at start-up and then every
|
||||
.B [scheduler].interval
|
||||
seconds. Logging goes to standard error, as text or as JSON lines when
|
||||
.B [server].log_format
|
||||
is
|
||||
.BR json .
|
||||
Every request carries a 16-character id, answered in
|
||||
.B X-Request-Id
|
||||
and attached to the request's access line.
|
||||
.PP
|
||||
A fresh installation needs no bootstrap command: start the server, open
|
||||
.BR /admin ,
|
||||
and the first-run wizard creates the administrator account, the interface
|
||||
language and the colour scheme, and signs the operator in. The wizard is
|
||||
reachable until that first account exists; on a machine reachable from the
|
||||
network, start the service and claim the installation right away.
|
||||
.SS status
|
||||
.TP
|
||||
.BI "\-\-config" " path"
|
||||
Config path to inspect (default as under
|
||||
.BR serve ).
|
||||
.TP
|
||||
.BI "\-\-data" " dir"
|
||||
Data directory to inspect.
|
||||
.TP
|
||||
.BI "\-\-users-file" " path"
|
||||
Users file to inspect.
|
||||
.TP
|
||||
.B \-\-json
|
||||
Machine-readable output:
|
||||
.BR {"ok":\ true,\ "checks":\ {\ ...} } ,
|
||||
with a
|
||||
.B config_validate
|
||||
entry naming the first invalid value, a
|
||||
.B posts_unreadable
|
||||
entry when a post file cannot be parsed, and
|
||||
.B "users:\ \(dqunreadable\(dq"
|
||||
when the accounts file cannot be read.
|
||||
.PP
|
||||
Reports whether the config exists, parses and validates, the number of posts
|
||||
with the draft count, and the number of users; with no accounts yet the user
|
||||
count names the first-run wizard as the next step. Read-only: a mistyped
|
||||
.I content_dir
|
||||
is reported, never created. Exit 1 when the config is missing, unparseable
|
||||
or invalid, when content cannot be parsed, or when the users file cannot be
|
||||
read.
|
||||
.SS doctor
|
||||
.TP
|
||||
.BI "\-\-config" " path"
|
||||
Config path to check (default as under
|
||||
.BR serve ).
|
||||
.TP
|
||||
.B \-\-json
|
||||
Machine-readable output:
|
||||
.BR {"ok":\ bool,\ "checks":\ [{name,\ status,\ detail}]} .
|
||||
.PP
|
||||
Checks that the config exists, parses and validates, that every post file
|
||||
can be parsed, that every post renders, that the users file can be read,
|
||||
that the installation has its first account, and
|
||||
that no stored scrypt parameters sit below the policy floor. A missing
|
||||
account is a warning pointing at the wizard, not a failure. Exit 1 when a
|
||||
check fails.
|
||||
.SS check-update
|
||||
.TP
|
||||
.B \-\-json
|
||||
Machine-readable output:
|
||||
.BR {"current":\ ...,\ "latest":\ ...,\ "available":\ bool} ,
|
||||
keeping the same exit-code contract.
|
||||
.PP
|
||||
Compares the running version with the latest release at
|
||||
.IR https://sourcedock.dev/petrbalvin/volumen/releases .
|
||||
Exit 0 when up to date (or the local build is newer); exit 1 when a newer
|
||||
release exists or the release check failed (offline, timeout, malformed
|
||||
response); exit 2 on a usage error.
|
||||
.SS export
|
||||
.TP
|
||||
.BI "\-\-config" " path"
|
||||
Config path (default as under
|
||||
.BR serve ).
|
||||
.TP
|
||||
.BI "\-\-out" " archive"
|
||||
Output archive path (default
|
||||
.IR volumen-backup.tar.gz ,
|
||||
written mode 0600).
|
||||
.PP
|
||||
Writes a tar.gz containing
|
||||
.B posts/
|
||||
(including
|
||||
.B .revisions/
|
||||
and
|
||||
.BR media/ ),
|
||||
.BR users.toml ,
|
||||
.BR templates.toml ,
|
||||
and
|
||||
.BR tokens.toml .
|
||||
The config file is deliberately not included: it may hold the session key
|
||||
override. A file that exists but cannot be read aborts the export rather than
|
||||
writing an archive that looks complete. Exit 1 on I/O errors.
|
||||
.SS import
|
||||
.TP
|
||||
.BI "\-\-config" " path"
|
||||
Config path (default as under
|
||||
.BR serve ).
|
||||
.PP
|
||||
Restores an archive made by
|
||||
.B volumen export
|
||||
or the admin Backup panel. The named archive is the one required positional
|
||||
argument. Entries are written to the paths the deployment configures for
|
||||
them; extraction is confined to the content directory, only post files,
|
||||
revision archives and allowed image extensions are written, and the
|
||||
decompressed total is bounded at 512 MiB. Exit 1 on a malformed archive or
|
||||
one that holds no file the layout recognises.
|
||||
.SS publish-due
|
||||
.TP
|
||||
.BI "\-\-config" " path"
|
||||
Config path (default as under
|
||||
.BR serve ).
|
||||
.TP
|
||||
.B \-\-dry-run
|
||||
List the due slugs without touching files.
|
||||
.TP
|
||||
.B \-\-json
|
||||
Machine-readable output:
|
||||
.BR {"published":\ [...],\ "failed":\ n} ,
|
||||
or
|
||||
.B {"due":\ [...],\ "dry_run":\ true}
|
||||
with
|
||||
.BR \-\-dry-run .
|
||||
.PP
|
||||
Publishes every post whose
|
||||
.B publish_at
|
||||
date is today or earlier: the key is removed and
|
||||
.B date
|
||||
defaults to it when the post has none. The configured webhooks receive
|
||||
.B post.published
|
||||
for every post this publishes. Exit 1 when a post could not be written, so a
|
||||
timer notices.
|
||||
.SS validate
|
||||
.TP
|
||||
.BI "\-\-config" " path"
|
||||
Config path (default as under
|
||||
.BR serve ).
|
||||
.TP
|
||||
.B \-\-json
|
||||
Machine-readable output:
|
||||
.BR {"problems":\ [{slug,\ path,\ error}]} .
|
||||
.PP
|
||||
Scans the content directory and reports files that cannot be parsed, posts
|
||||
that fail to render, duplicate slugs, slugs that do not match the slug
|
||||
format, missing titles, a
|
||||
.B publish_at
|
||||
that is not a date, and alias conflicts. Prints
|
||||
.B content OK
|
||||
when clean, exit 1 otherwise.
|
||||
.SS version
|
||||
Prints
|
||||
.BI "volumen " version ,
|
||||
the release the toolchain recorded in the binary's build information. A
|
||||
release binary reports its tag, a checkout reports a pseudo-version, a build
|
||||
outside version control reports
|
||||
.BR "(devel)" ,
|
||||
and a dirty tree appends
|
||||
.BR +dirty .
|
||||
.SS Global flags
|
||||
.TP
|
||||
.BR \-h , " \-\-help" ", " help
|
||||
Prints the usage block and exits 0.
|
||||
.B \-h
|
||||
on a subcommand prints that subcommand's flags; on
|
||||
.B version
|
||||
it prints the version.
|
||||
.TP
|
||||
.BR \-v , " \-\-version"
|
||||
Prints
|
||||
.BI "volumen " version
|
||||
and exits 0.
|
||||
.SH EXIT STATUS
|
||||
.TP
|
||||
.B 0
|
||||
Success.
|
||||
.TP
|
||||
.B 1
|
||||
A failure the program detected: an unreadable config, a failed write, a
|
||||
content directory with a problem, a release check that could not run.
|
||||
.B check-update
|
||||
also exits 1 when a newer release simply exists.
|
||||
.TP
|
||||
.B 2
|
||||
The arguments were wrong: an unknown command, an unknown flag, or a stray
|
||||
positional argument.
|
||||
.SH CONFIGURATION
|
||||
One TOML file, \fIconfig.toml\fP, copied from the commented
|
||||
.I config.toml.example
|
||||
shipped with the release.
|
||||
Every key, its type, its default and its validation rules are documented in
|
||||
.I docs/CONFIGURATION.md
|
||||
of the repository. Sources, strongest first: the flags of
|
||||
.BR serve ,
|
||||
then the file, then the built-in defaults. A key with the wrong type or a root key swallowed by a table
|
||||
header stops the start with a message naming the key; an unknown key is
|
||||
ignored.
|
||||
.PP
|
||||
The five state files
|
||||
.BR users.toml ,
|
||||
.BR secret.key ,
|
||||
.BR templates.toml ,
|
||||
.BR tokens.toml
|
||||
and
|
||||
.B webhooks.toml
|
||||
live beside the users file, are written atomically at mode 0600 by the
|
||||
server, and are not read from the configuration file.
|
||||
.B secret.key
|
||||
holds the session secret the server generated on first start;
|
||||
.B [admin].session_key
|
||||
overrides it.
|
||||
.SH ENVIRONMENT
|
||||
The configuration itself comes from the file and the flags of
|
||||
.B serve
|
||||
only. The XDG variables
|
||||
.I XDG_CONFIG_HOME
|
||||
and
|
||||
.I XDG_DATA_HOME
|
||||
locate the per-user config and state paths used by the defaults.
|
||||
.SH FILES
|
||||
.TP
|
||||
.I /etc/volumen/config.toml
|
||||
System configuration, tried first when
|
||||
.B \-\-config
|
||||
is absent.
|
||||
.TP
|
||||
.I ~/.config/volumen/config.toml
|
||||
Per-user configuration, tried when the system file does not exist.
|
||||
.TP
|
||||
.I /var/lib/volumen/posts
|
||||
Content directory: posts,
|
||||
.BR media/ ,
|
||||
and
|
||||
.BR .revisions/ .
|
||||
.TP
|
||||
.I /var/lib/volumen/users.toml
|
||||
Admin accounts, created by the first-run wizard or the admin Settings page.
|
||||
.TP
|
||||
.IR /var/lib/volumen/secret.key ,
|
||||
.IR /var/lib/volumen/templates.toml ,
|
||||
.IR /var/lib/volumen/tokens.toml ,
|
||||
.IR /var/lib/volumen/webhooks.toml
|
||||
Session secret generated by the server, post templates, API tokens,
|
||||
admin-managed webhooks.
|
||||
.TP
|
||||
.I ~/.local/share/volumen
|
||||
Per-user state directory: the default content and users paths when no
|
||||
configuration file exists.
|
||||
.TP
|
||||
.I /etc/systemd/system/volumen.service
|
||||
Unit written by the operator;
|
||||
.I docs/DEPLOYMENT.md
|
||||
carries the text to copy.
|
||||
.TP
|
||||
.I <content_dir>/media/<uuid>.webp, <uuid>.avif, <uuid>.svg
|
||||
Uploaded images; WebP, AVIF and SVG are the only accepted formats, and the
|
||||
name is assigned by the engine. An SVG is served sandboxed, so opened at its
|
||||
own URL it runs as no one.
|
||||
.SH EXAMPLES
|
||||
Serve a checkout against its own content:
|
||||
.PP
|
||||
.B volumen serve \-\-config ./config.toml \-\-content ./posts
|
||||
.PP
|
||||
Start a fresh per-user installation and open the wizard in the browser at
|
||||
.IR http://localhost:9091/admin/ :
|
||||
.PP
|
||||
.B volumen serve
|
||||
.PP
|
||||
Publish what a timer missed, then check the content:
|
||||
.PP
|
||||
.B volumen publish-due \-\-dry-run
|
||||
.br
|
||||
.B volumen publish-due
|
||||
.br
|
||||
.B volumen validate
|
||||
.PP
|
||||
Back up one deployment and restore it into a second:
|
||||
.PP
|
||||
.B volumen export \-\-config /etc/volumen/config.toml \-\-out /backup/volumen.tar.gz
|
||||
.br
|
||||
.B volumen import \-\-config /srv/staging/config.toml /backup/volumen.tar.gz
|
||||
.PP
|
||||
Find out why a fresh install will not start:
|
||||
.PP
|
||||
.B volumen doctor \-\-config /etc/volumen/config.toml
|
||||
.br
|
||||
.B volumen status \-\-config /etc/volumen/config.toml \-\-json
|
||||
.SH AUTHOR
|
||||
Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
||||
.SH LICENCE
|
||||
PolyForm Noncommercial 1.0.0, see
|
||||
.I LICENSE
|
||||
in the repository: every non-commercial use is permitted; a commercial use
|
||||
needs a licence from the author. The artwork in
|
||||
.I internal/web/static/
|
||||
comes from the shared icon set and stays under Creative Commons BY-NC 4.0
|
||||
alone. The licence texts of the modules the binary is compiled from are in
|
||||
.IR NOTICE.md .
|
||||
.SH "SEE ALSO"
|
||||
.I docs/CLI.md
|
||||
and
|
||||
.I docs/DEPLOYMENT.md
|
||||
in the repository;
|
||||
.IR docs/API.md
|
||||
for the JSON API;
|
||||
.IR https://sourcedock.dev/petrbalvin/volumen .
|
||||
Reference in New Issue
Block a user