irodsfsd

module
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 11, 2026 License: BSD-3-Clause

README

irodsfsd

irodsfsd is a Linux daemon that manages multiple irodsfs FUSE mounts (and plain DAVFS/NFS mounts) through a gRPC/REST API and a small embedded web UI. Desired mounts are persisted in an embedded, encrypted database, so a daemon restart reconciles them back to the running state automatically instead of relying on an external process supervisor to know about each mount.

Status: under active development. The core daemon — persistence, startup reconciliation, retry/crash recovery, graceful shutdown, per-mount logs, metrics, and the management UI — is implemented and tested. See design.md for the full design.

Features

  • Mount/unmount over gRPC and REST, backed by the same application service and validation rules for both transports.
  • irodsfs, DAVFS, and NFS mount clients. irodsfs always runs in the foreground as a supervised child process; DAVFS/NFS use the system mount/umount helpers.
  • Crash-safe persistence: mount intent (including credentials) is encrypted at rest in an embedded BadgerDB. An explicit Unmount is the only thing that tombstones a record — a mount that's simply not running yet is reconciled and restarted automatically, at startup and periodically thereafter.
  • Retry with backoff and jitter for transient mount/unmount failures, with attempt count, next-retry time, and the last error exposed through the API.
  • Graceful shutdown that safely unmounts every managed mount in parallel, each bounded by its own timeout, before the process exits.
  • Per-mount logs (stdout/stderr, rotated, secrets redacted) queryable over REST, and Prometheus metrics for mount state, operation results/durations, child crashes, and reconciliation errors.
  • A small embedded management UI at / — mount list, state, recent logs, and mount/unmount actions — served from the same origin as the REST API.

Requirements

  • Linux with FUSE (/dev/fuse) and fusermount/fusermount3 available.
  • The irodsfs binary, plus the system mount and umount utilities for DAVFS/NFS support.
  • Go 1.25+ to build from source.

Install the latest Linux release

Install the latest release for the current Linux architecture with:

curl -fsSL https://raw.githubusercontent.com/cyverse/irodsfsd/main/install.sh | bash

The installer downloads the matching GitHub Release archive, installs the systemd service, generates recovery_encryption_key when it is empty, and enables and starts irodsfsd. It preserves an existing /etc/irodsfsd/config.yaml during reinstalls. Install irodsfs separately. If irodsfs_executable_path is left at its default (/usr/local/bin/irodsfs) and nothing exists there, irodsfsd also checks /usr/bin/irodsfs - where irodsfs's own installer places it - so installing irodsfs with its default installer just works. Set irodsfs_executable_path explicitly only if irodsfs lives somewhere else.

Building

make build          # -> bin/irodsfsd

or directly with Go:

go build -o bin/irodsfsd ./cmd

Run the test suite with go test ./.... Add -race when touching MountManager's concurrent code.

Reusable Go client code is available in client/. Runnable mount, unmount, and mount-list examples are documented in client_examples/README.md; build all three with make build-client-examples.

Configuration

irodsfsd accepts YAML or JSON (detected from content, not the file extension); unknown daemon-config fields are currently ignored for forward compatibility, while mount JSON is decoded strictly. See packaging/systemd/config.yaml for a complete annotated example, and design.md section 5 for the full field reference. The only field with no safe default is recovery_encryption_key, a base64-encoded 32-byte AES key used to encrypt the mount database:

openssl rand -base64 32

Minimal example:

service_endpoint: "tcp://0.0.0.0:13020"
management_service_port: 13021
irodsfs_executable_path: "/usr/local/bin/irodsfs"
data_root_path: "/var/lib/irodsfsd"
pid_file: "/run/irodsfsd/irodsfsd.pid"
log_root_path: "/var/log/irodsfsd"
recovery_encryption_key: "<base64 32-byte key>"
allowed_mount_root_paths:
  - "/mnt/irods"

Set allow_fuse_allow_other: true when non-root local accounts need to access an irodsfs/DAVFS mount. The daemon then forces allow_other onto every such mount automatically (it does not apply to NFS mounts). The packaged service runs as root, so it does not require user_allow_other in /etc/fuse.conf; a manually run non-root daemon does. It does not also force default_permissions: a caller such as irods-csi-driver supplies the container's own UID/GID, which has no mapping to any host account, so kernel-enforced ownership checks against it can't be trusted — a caller may still request default_permissions itself if its UID/GID is host-authoritative. See design.md section 5 for details.

iRODSFS startup exit statuses

For an iRODSFS child only, irodsfsd recognizes these documented startup exit statuses:

iRODSFS status Mount last_error.code Retry behavior
10 IRODSFS_CONFIGURATION_INVALID No retry; the mount becomes FAILED.
11 IRODSFS_AUTHENTICATION_FAILED No retry; the mount becomes FAILED.
Other non-zero status MOUNT_COMMAND_EXITED Uses the configured retry policy.

The special statuses are deliberately not interpreted for DAVFS or NFS mount helpers. Failed mount records remain available for inspection until an explicit unmount removes them.

Running

irodsfsd run     -c /etc/irodsfsd/config.yaml   # foreground, e.g. under systemd Type=simple
irodsfsd start   -c /etc/irodsfsd/config.yaml   # daemonize and detach
irodsfsd stop    -c /etc/irodsfsd/config.yaml --wait 20s
irodsfsd status  -c /etc/irodsfsd/config.yaml
irodsfsd version

For a systemd-managed install, see packaging/systemd/README.md.

Using the API

Create a mount:

curl -sX POST http://localhost:13021/api/v1/mounts \
  -H 'Content-Type: application/json' \
  -d '{
        "config": {
          "mount_path": "/mnt/irods/alice",
          "read_only": true,
          "irodsfs": {
            "account": {
              "irods_host": "data.example.org",
              "irods_zone_name": "tempZone",
              "irods_user_name": "alice",
              "irods_user_password": "secret"
            },
            "path_mappings": [
              {"irods_path": "/tempZone/home/alice", "mapping_path": "/"}
            ]
          }
        }
      }'

List mounts, fetch one, tail its logs, and unmount it:

curl http://localhost:13021/api/v1/mounts
curl http://localhost:13021/api/v1/mounts/<mount_id>
curl 'http://localhost:13021/api/v1/mounts/<mount_id>/logs?tail=100'
curl -X DELETE http://localhost:13021/api/v1/mounts/<mount_id>

Health, readiness, and metrics:

curl http://localhost:13021/healthz
curl http://localhost:13021/readyz
curl http://localhost:13021/metrics

The same operations are available over gRPC via service/api/api.proto (api.MountService), and visually through the web UI at http://localhost:13021/.

Passwords, tickets, and tokens are always redacted in API responses, the UI, logs, and events — the daemon never echoes a submitted credential back.

Project layout

cmd/                 CLI entry point and daemon lifecycle (start/run/stop/status)
cmd/commons/         shared CLI helpers (flags, PID file handling)
commons/             daemon configuration, endpoints, and shared helpers
service/             MountManager, gRPC/REST servers, retry/reconciliation, metrics
service/api/         the protobuf/gRPC contract (api.proto) and generated code
service/store/       the BadgerDB-backed mount repository
service/logstore/    per-mount log files (rotation, query, redaction)
service/web/         the embedded management UI
packaging/systemd/   systemd unit and example configuration

Documentation

  • design.md — full design: architecture, state machine, persistence, retry/recovery, API contract, security, and testing strategy.

Directories

Path Synopsis
client_examples
mount command
mount_list command
unmount command
cmd
commons
Package commons provides shared command-line process helpers.
Package commons provides shared command-line process helpers.
api
logstore
Package logstore converts a mount child's stdout/stderr into a size- and age-rotated, line-oriented log file, and lets that file be queried by tail count or time.
Package logstore converts a mount child's stdout/stderr into a size- and age-rotated, line-oriented log file, and lets that file be queried by tail count or time.
store
Package store implements MountRepository on top of an embedded BadgerDB database, encrypted at rest, so mount intent and credentials survive a daemon restart.
Package store implements MountRepository on top of an embedded BadgerDB database, encrypted at rest, so mount intent and credentials survive a daemon restart.
web
Package web holds the daemon's embedded management UI: a single self-contained HTML page (inline CSS and vanilla JavaScript, no build step, no external network requests) served at "/", sharing the REST API origin per design.md.
Package web holds the daemon's embedded management UI: a single self-contained HTML page (inline CSS and vanilla JavaScript, no build step, no external network requests) served at "/", sharing the REST API origin per design.md.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL