Commit Graph

26 Commits

Author SHA1 Message Date
Adrian Duke caee776c38 log: New crate for logger implementations
Move logging-related module `radicle::logging` into its own crate.

While at it, remove the "logger" feature flag from `radicle`.

Co-authored-by: Lorenz Leutgeb <lorenz.leutgeb@radicle.dev>
2026-05-11 16:44:37 +01:00
Lorenz Leutgeb 0a0e70b1d1
node/systemd: Fix reading credentials
In `cb57e6560fe7767e79b87473a11261fbb82ce84c` the loading of systemd
credentials was refactored. The idea was to only change the accepted IDs
slightly after switching from radicle.xyz to radicle.dev. Unfortunately,
this was done in a sloppy way. The two cases for passphrase and secret
actually differ in ways that was overlooked.

Rectify these mistakes and restore the old behavior:
 1. The logic to read the passphrase from the file that contains the
    credential is moved out of `load_credential` since it only applies
    to the passphrase, not the secret.
 2. The warnings printed are now generic, and will not mention the
    passphrase in case reading the path for the secret fails.
2026-05-07 22:53:57 +02:00
Daniel Norman 6b460c4429 logger: Respect config file log level
- Fixes a bug where the log level set in the config file was
  ignored: `Logger` and `StderrLogger` captured the level in a
  `self.level` field at construction time and checked it in
  `Log::enabled`. After config was loaded, the global
  `log::set_max_level` was updated but `self.level` was not,
  so verbose messages were dropped by the per-instance filter
  even when the global filter allowed them.
- Make `log::set_max_level` the single source of truth: remove
  the `level` field and have `Log::enabled` defer to
  `log::max_level()` so the two filters can no longer drift.
- Update call sites to construct loggers without a level.
- Disable the structured logger's internal filter (set to "trace") so
  that it also falls back to `log::set_max_level`.
2026-05-07 16:23:28 +01:00
Lorenz Leutgeb cb57e6560f
node: Rename systemd Credentials
Because we changed our main domain from radicle.xyz to radicle.dev, we
should also change our systemd credential identifiers.

Handling is move into a new function, which also checks the old names
for backwards compatibility.
2026-04-27 18:21:26 +02:00
Lorenz Leutgeb 80c1bba76f
radicle: Prevent `RAD_SOCKET` from polluting tests
The value of `RAD_SOCKET` influences the outcome of `cargo test`.

Users that set this environment variable to, e.g. point `rad` at
a socket at a custom location, were surprised that execution of
tests would interact with their node.

Split `Home::socket` into two functions. `Home::socket_default` is
"pure" and only dependent on the path represented by `Home`. On the
other hand, `Home::socket_from_env` interprets the environment.

Most users will want to use `Home::socket_from_env`.
2026-04-09 17:53:49 +02:00
Lorenz Leutgeb 8bac24d6ab
rust/edition/fmt: 2021 → 2024
Reformat code with `rustfmt`, now that the edition changed from
Rust 2021 to Rust 2024.
2026-03-30 16:57:51 +02:00
Lorenz Leutgeb 03bbe52417 signals: Add support for Windows 2026-02-13 15:38:02 +00:00
Fintan Halpenny b020543c4b node: downgrade `warn!` logs
Evaluate the `warn!` logging in `radicle-node`.

If the event is a result of something being suspicious in the running
of the protocol, then it remains a `warn!`.

However, if the system ends up ignoring the event and can continue
without issues, the log level is reduced to `debug!`.
2026-01-19 17:59:06 +01:00
Adrian Duke 001aba0d29 clippy: Deny and fix `fallible_impl_from`
Instead of changing `impl From<SystemTime> for LocalTime` to `TryFrom`,
the implementation was removed, as there are not many callsites, and
they are well served by `LocalTime::now`.

radicle-localtime: drop TryFrom SystemTime

radicle-node: switch SystemTime usage with LocalTime
2026-01-16 22:52:18 +01:00
Lorenz Leutgeb ac572e64e5 node: Support systemd credential for passphrase
While it is possible to pass the passphrase via the environment, e.g.
`EnvironmentFile=<path to file that contains "RAD_PASSPHRASE=…">`
this is less secure than passing it via a file, because the environment
is inherited down the process tree.

Thus, allow using a systemd credential. The ID of the credential must be

    xyz.radicle.node.passphrase

and is not user-configurable.

Passing the passphrase via file is now possible with
`LoadCredential=xyz.radicle.node.passphrase:<path to file that contains passphrase>`

This requires just a bit of plumbing in `radicle-node`.

Because this mechanism is more secure than using the environment
variable `RAD_PASSPHRASE`, it takes priority. That is, if both the
systemd credential is available, *and* the environment variable
`RAD_PASSPHRASE` is set, the former is preferred.

Heads-up:
 1. The contents of the file must be valid UTF-8 (see documentation of
    `std::fs::read_to_string`). Assuming that the passphrase is at some
    point chosen by the user and typed on a keyboard, this does not
    seem like a severe restriction.
 2. The contents of the file are not processed otherwise, i.e. line
    breaks (notably at the end of the file) are not stripped.

The related `issue/8bd040e9de05e7fc27e373ebc1649ff4ad930e7a` asked for a
very similar feature: Passing the passphrase via a file named by the
value of the of the environment variable `RAD_PASSPHRASE_FILE`.
It was also briefly discussed at
<https://radicle.zulipchat.com/#narrow/channel/369277-heartwood/topic/.60RAD_PASSPHRASE_FILE.60/with/529104447>.
2025-10-09 10:03:21 +01:00
Lorenz Leutgeb ae39f24b58 node: Support systemd credential for secret
While it is possible to use systemd credentials via

    LoadCredential=xyz.radicle.node.secret:…
    ExecStart=radicle-node … --secret "${CREDENTIALS_DIRECTORY}/xyz.radicle.node.secret"

Make usage more convenient and directly support passing the secret key
via a systemd credential. The ID of the credential must be

    xyz.radicle.node.secret

and is not user-configurable.

A systemd service unit file might contain:

    LoadCredential=xyz.radicle.node.secret:…
    ExecStart=radicle-node …

This requires just a bit of plumbing in `radicle-node`.

The preference order for the path of the secret key is:
 1. The command line argument `--secret`.
 2. The systemd credential.
 3. The configuration file.
 4. The default location to preserve backward compatibility.

The reason to prefer the systemd credential over the configuration file
is that it uses a mechanism that is influenced by the environment of the
process, which is deemed "closer at runtime" or "more dynamic" than a
configuration file. Ad-hoc overrides are still possible via the
commandline argument.
2025-10-09 10:03:21 +01:00
Lorenz Leutgeb 474b97950b
node/log: Define syslog identifier
The argument passed to `fn logger` would only be used as a fallback.
Make it required to pass an identifier, as this is a good practice.
2025-10-01 16:46:46 +02:00
Lorenz Leutgeb 22720e718b node: Make location of secret key configurable
With this change, the location of the secret SSH key can be configured
through `${RAD_HOME}/config.json` so that the node key does not have to
be placed under `${RAD_HOME}/keys` anymore.

Further, there is now an option to override `config.json` directly when
executing `radicle-node` via the command line argument
`--secret`.

The primary motivation is more flexible deployments, for example
leveraging external secret management solutions, like
<https://systemd.io/CREDENTIALS/>.

The secret key is fingerprinted by taking the fingerprint of the public
key corresponding to the secret key. This allows to detect when the
secret key changes.
2025-09-26 13:03:57 +01:00
Fintan Halpenny ed8b086045 node: Log Panics
Register a panic handler that logs a backtrace via the `backtrace`
crate, instead of setting `RUST_BACKTRACE`.

Co-authored-by: Lorenz Leutgeb <lorenz.leutgeb@radicle.xy>
2025-09-24 10:51:34 +01:00
Sebastian Martinez 5fea9ac05c node: Add `--log-logger structured` and `--log-format json`
Optionally depend on crate `structured-logger`. Allow enabling it via
`--log-logger structured`. For future compatibility, provide
`--log-format` which currently only supports JSON.

Co-authored-by: Lorenz Leutgeb <lorenz.leutgeb@radicle.xyz>
2025-09-23 16:33:50 +02:00
Lorenz Leutgeb e563117397 node: Refactor logging initialization
Logging initialization was infallible previously, i.e., a logger would
always have to be chosen, falling back to our own logger
implementation in case of failure with setting up journald submission.

This lead to complexity like attempting to log errors from parsing
arguments, as there is a circular dependency.

Change this to make logging initialization fallible. If it fails, exit
non-zero instead of falling back to another logger. This makes the
initialization code slightly simpler.

At the same time, make choosing the logger possible via the command
line and deprecate `--log`.

Note that we still default to journald if detected.
2025-09-23 16:33:50 +02:00
Lorenz Leutgeb 79d928551b node: Remove dependency on `anyhow`
`anyhow` is only used to capture a handful of errors. It also turns out that
usage of `lexopt` was wrong, since it features `parse_with`, which neatly
integrates with `FromStr`. The types, luckily, implement this trait already –
making for cleaner parsing.

For now, the execution errors are all "transparent", which shouldn't be
much of a regression, if at all.
2025-09-04 16:28:20 +03:00
Lorenz Leutgeb 819ae5fdf5 node/main: Refactor initialization of logging
It turns out that failing to read configuration resulted in no output,
because the logger would only be set after configuration had been read.

Fix this, by setting the logger early, with a log level that is then
corrected as soon as configuration is available.

While at it, also clean this up to allow logging errors about failure to
set up the logger.
2025-08-27 11:17:18 +02:00
Lorenz Leutgeb fd34b680b5 signals: Guard most of the crate for Unix
The signals crate does not build on non-Unix-like platforms, such as
Windows. It uses constants for signals that are not exported from
`libc` on Windows, and transitive dependencies such as `sem_safe` fail
to compile.

Resolve this, by guarding most of the crate, certainly all real
features, by `cfg(unix)`.

To require less uses of the `cfg` macro, move all affected parts into a
new module, and re-export it.

The crate now builds on Windows (although it does not do anything
interesting on that platform) and its Unix interface remains unchanged.

Changes are integrated into `radicle-node`, but only affect Windows.
2025-08-22 15:19:31 +01:00
Lorenz Leutgeb 9a7c22536b radicle/config/node: Use newtypes 2025-08-19 13:16:19 +02:00
Lorenz Leutgeb 944d394247 node: Restrict use of systemd to Linux not Unix
Building with Zigbuild for macOS caused build issues. Strengthen the
condition for using systemd from the Unix family to Linux specifically.
2025-08-12 12:13:49 +02:00
Lorenz Leutgeb d7b48b9e29 radicle: Move logging setup calls to binaries 2025-08-07 08:30:59 +01:00
Lorenz Leutgeb b2a41025ce node: Enable logging via systemd journal 2025-08-07 08:30:59 +01:00
Erik Kundt 54fd8c40a0 node: clean up logging
Do not print errors to stderr anymore if logger is not enabled
2025-07-30 13:41:17 +01:00
Fintan Halpenny 174792813a node: register backtrace
To better help debugging when things go wrong after `radicle-node` crashes,
`RUST_BACKTRACE` is registered in the `main`. According to this [StackOverflow
answer][so], this should not affect performance

[so]: https://stackoverflow.com/questions/29421727/how-much-overhead-does-rust-backtrace-1-have/45402131#45402131
2025-07-30 13:41:17 +01:00
Lorenz Leutgeb 5bc2dc677b repo: Move workspace crates into `crates` subdirectory
This keeps the top level of the repo cleaner, e.g.
<https://github.com/radicle-dev/heartwood> scrolls less and
<https://app.radicle.xyz/nodes/rosa.radicle.xyz/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5/>
might show more files at the top level.

This way we also don't have to explicitly name all crates in
`Cargo.toml`.
2025-06-09 15:09:21 +02:00
Renamed from radicle-node/src/main.rs (Browse further)