snapraid/manual-daemon.html
Andrea Mazzoleni f4679d3f6e Auto update
2026-03-30 10:01:17 +02:00

1571 lines
60 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="A backup program for disk arrays. It stores parity information of your data and it recovers from up to six disk failures">
<meta name="keywords" content="snapraid snapshot raid backup disk array redundancy parity">
<title>SnapRAID Daemon Manual</title>
<link rel="stylesheet" href="style.css">
<link rel="apple-touch-icon" sizes="180x180" href="/beta/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/beta/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/beta/favicon-16x16.png">
<link rel="manifest" href="/beta/site.webmanifest">
<script src="script.js"></script>
<!-- Google Analytics 4 -->
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-W1Z5FKHYQ4"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-W1Z5FKHYQ4');
</script>
<!-- Google Universal Analytics -->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-21967501-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<header>
<div class="container nav-container">
<a href="index" class="logo">
<img src="android-chrome-192x192.png" width="32" height="32"/>
SnapRAID
</a>
<nav>
<input type="checkbox" id="menu-toggle">
<label for="menu-toggle" class="menu-icon"><svg viewBox="0 0 24 24" width="24" height="24" fill="currentColor"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/></svg></label>
<ul>
<li><a href="index" >Home</a></li>
<li><a href="ui" >UI & Daemon</a></li>
<li><a href="howitworks" >How it Works</a></li>
<li><a href="design" >Design</a></li>
<li><a href="compare" >Compare</a></li>
<li><a href="manual" class="active">Manual</a></li>
<li><a href="faq" >FAQ</a></li>
<li><a href="support" >Support</a></li>
<li><a href="download" class="nav-cta">Download</a></li>
<li>
<button class="theme-toggle" aria-label="Toggle theme">
<svg class="sun-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>
<svg class="moon-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>
</button>
</li>
</ul>
</nav>
</div>
</header>
<div class="container manual-layout">
<aside class="manual-sidebar">
<h4>Components</h4>
<select id="manual-selector" style="width: 100%; padding: 5px; background: var(--bg-surface); color: var(--text-primary); border: 1px solid var(--border-color); border-radius: 4px; margin-bottom: 2rem;">
<option value="manual">Command Line</option>
<option value="manual-daemon">Daemon</option>
<option value="manual-log">Log</option>
</select>
<h4>Contents</h4>
<ul id="manual-toc-list">
<!-- Populated by JavaScript -->
</ul>
</aside>
<main id="manual-container">
<div class="manual-doc">
<div class="manual-section-level-1">
<h1 id="sec1" class="manual-title-level-1">
Synopsis
</h1>
<pre>
snapraidd [-c, --conf CONFIG] [-f, --foreground] [-p, --pidfile FILE]
&nbsp;&nbsp;&nbsp;&nbsp;[-N, --no-cache] [-v, --verbose]
</pre>
<pre>
snapraidd [-V, --version] [-H, --help]
</pre>
</div>
<div class="manual-section-level-1">
<h1 id="sec2" class="manual-title-level-1">
Description
</h1>
<p>SnapRAID Daemon is a specialized companion service designed to move SnapRAID
from a manual, command-line interface (CLI) workflow to an <b>always-on</b>
background service.
</p><p>Under the hood, the daemon uses the same SnapRAID CLI binary, providing the
same level of reliability.
</p><p>The daemon automates critical maintenance tasks, including the scheduling of
sync and scrub operations. It further enhances array reliability by monitoring
SMART values and providing a robust notification engine for real-time health
updates. For energy efficiency, it manages automatic disk spindown during
periods of inactivity.
</p><p>The daemon provides a modern REST API interface along with an integrated Web UI.
This allows you to monitor array health, trigger maintenance tasks, and
configure the daemon through a user-friendly browser interface or programmatically
via the API.
</p></div>
<div class="manual-section-level-1">
<h1 id="sec3" class="manual-title-level-1">
Options
</h1>
<p>The SnapRAID Daemon provides the following options:
</p><div class="manual-option-list">
<div class="manual-option-entry">
<div class="manual-option-name">
-c, --conf CONFIG
</div><div class="manual-option-description">
Specifies the path to the configuration file. Default:
<b>$PREFIX/etc/snapraidd.conf</b> and <b>/etc/snapraidd.conf</b> if
not found. The $PREFIX variable represents the installation
path chosen at build time (typically via the <b>--prefix</b>
argument to the configure script).
</div>
</div>
</div>
<div class="manual-option-list">
<div class="manual-option-entry">
<div class="manual-option-name">
-f, --foreground
</div><div class="manual-option-description">
Runs the process in the foreground. This prevents the
daemon from detaching from the terminal (daemonizing).
</div>
</div>
</div>
<div class="manual-option-list">
<div class="manual-option-entry">
<div class="manual-option-name">
-p, --pidfile FILE
</div><div class="manual-option-description">
Overrides the default location for the PID file. Default:
<b>/run/snapraidd.pid</b>.
</div>
</div>
</div>
<div class="manual-option-list">
<div class="manual-option-entry">
<div class="manual-option-name">
-N, --no-cache
</div><div class="manual-option-description">
Forces the daemon to load web interface assets directly from the
filesystem for every request, bypassing internal memory caching.
This is intended for development environments to allow real-time
testing of UI changes.
This option is only effective when <b>net_web_root</b> is configured
to point to an expanded directory on the filesystem.
It has no effect if the web assets are being served from a
compressed .zip file, as the daemon must crawl and index the
archive's contents at startup regardless of this flag.
This option is not recommended for production use due to the
increased I/O overhead and for security reasons, as it could
potentially expose the system to directory traversal
vulnerabilities if not properly isolated.
</div>
</div>
</div>
<div class="manual-option-list">
<div class="manual-option-entry">
<div class="manual-option-name">
-v, --verbose
</div><div class="manual-option-description">
Verbose logging including all HTTP requests.
</div>
</div>
</div>
<div class="manual-option-list">
<div class="manual-option-entry">
<div class="manual-option-name">
-H, --help
</div><div class="manual-option-description">
Prints a short help screen.
</div>
</div>
</div>
<div class="manual-option-list">
<div class="manual-option-entry">
<div class="manual-option-name">
-V, --version
</div><div class="manual-option-description">
Prints the program version.
</div>
</div>
</div>
</div>
<div class="manual-section-level-1">
<h1 id="sec4" class="manual-title-level-1">
Getting Started
</h1>
<p>The daemon acts as a management layer for the SnapRAID CLI. Therefore,
SnapRAID CLI must be installed and fully configured before starting the
service.
</p><p>Because the daemon performs direct hardware-level telemetry probes
(such as reading SMART attributes and managing disk power states), it
requires elevated privileges to function correctly. On Linux systems,
the daemon must be run as the root user. On Windows, it must be
executed as a service with equivalent system access rights.
</p><p>It is important to note that the daemon never directly reads the
SnapRAID CLI configuration file <b>snapraid.conf</b>. Instead, it relies
entirely on the output and logs generated by the SnapRAID binary.
</p><p>By processing these logs, the daemon identifies the <b>data</b>, <b>parity</b>,
and <b>extra</b> disks and establishes the current state of the array.
</p><p>During the installation process of the daemon, a default configuration
file is provisioned to enable the REST API and the Web UI. For users
installing via binary packages, this file is typically placed at
<b>/etc/snapraidd.conf</b>. If you are installing from source, it is
recommended to run <b>./configure --sysconfdir=/etc</b> during the build
process to ensure the configuration is placed in the standard <b>/etc</b>
directory.
</p><p>Using this default configuration file, the UI is accessible locally
via a web browser at the following address:
</p><p><a href="http://localhost:7627">http://localhost:7627</a>
<br>
</p><p>The default port, 7627, was chosen as a mnemonic, representing the
word <b>SNAP</b> as typed on a standard telephone keypad.
</p><p>At startup, the daemon parses historical logs from <b>/var/log/snapraid</b>
to reconstruct the current state of the array. These logs are
generated and saved by the daemon itself during the execution
of SnapRAID CLI commands. Consequently, on the very first run, this
directory will be empty.
</p><p>In this initial scenario, the daemon automatically triggers a SnapRAID
<b>read</b> command. This allows SnapRAID to process its internal <b>content</b>
files and provide the daemon with the necessary metadata to establish
the array's baseline state.
</p><p>Once the service is running, you should review <b>/etc/snapraidd.conf</b>
or use the <b>Settings</b> panel in the UI to tailor the behavior to your
environment.
</p><p>Typical post-installation steps include:
</p><ul>
<li>
Defining a <b>maintenance_schedule</b> for automated sync and scrub
operations.
</li>
<li>
Setting <b>spindown_idle_minutes</b> to optimize energy usage for
disks not in active use.
</li>
<li>
Configuring the <b>notify_result</b> system to receive alerts
regarding array health and task outcomes.
</li>
</ul>
<p>To make manual changes to the <b>/etc/snapraidd.conf</b> file effective,
you must either restart the daemon or send a <b>SIGHUP</b> signal to the
running process.
</p><p>Example:
</p><pre>
sudo killall -HUP snapraidd
</pre>
<p>Unlike manual file edits, changes made through the UI are applied to
the running process and saved to the configuration file pressing the
<b>Save</b> button.
</p><p>By default, the daemon binds to the loopback interface, meaning the
UI is accessible only from the local machine and not from other devices
on the network. To allow access from other devices on the network,
you must modify the <b>net_*</b> options to bind the daemon to a reachable
network interface.
</p></div>
<div class="manual-section-level-1">
<h1 id="sec5" class="manual-title-level-1">
Health
</h1>
<p>The array's aggregate health is determined by evaluating historical log
data alongside real-time hardware telemetry.
</p><p>If the array transitions into a problematic state, the daemon issues
an alert through the configured notification system. Note that the
detection of such states is not instantaneous, it occurs during the
telemetry collection cycle, the frequency of which is determined by
the <b>probe_interval_minutes</b> option.
</p><p>In the REST API, the health state is reported by the <b>health</b> field.
Whenever the health is not PASSED, a supplementary <b>health_reason</b> field
is provided to give a discursive explanation of the specific condition or
failure detected.
</p><p>The Web UI also reflects these states by displaying a prominent top
banner across all pages if the health is in a problematic state. This
ensures that critical issues are visible regardless of the specific
dashboard view being accessed.
</p><p>The possible health states are:
</p><div class="manual-tag-list">
<div class="manual-tag-entry">
<div class="manual-tag-name">
PENDING
</div><div class="manual-tag-description">
The health has not yet been assessed. The daemon requires a
successful hardware probe where all disks are spinning at
least once to read SMART attributes.
Issuing an <b>up</b> command is sufficient to satisfy this.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
PASSED
</div><div class="manual-tag-description">
The array is fully healthy. All disks report positive SMART
status and the last scrub found no data corruption.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
CORRUPT
</div><div class="manual-tag-description">
Silent errors (hash or parity mismatches) were detected, though
no physical hardware issues were identified.
In this state, scheduled maintenance remains active.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
PREFAIL
</div><div class="manual-tag-description">
The SMART telemetry reports a pre-failing condition (e.g.,
reallocated sectors), or a task encountered input/output errors
while accessing files.
File input/output errors are temporary and they are cleared
automatically after a successful sync.
Automated maintenance is suspended in this state, and manual
intervention is required.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
FAILING
</div><div class="manual-tag-description">
The SMART telemetry reports a critical failing condition, or a
disk has disappeared from the system.
Automated maintenance is suspended in this state, and immediate
manual intervention is required.
</div>
</div>
</div>
<p>Individual tasks also maintain a health state reflecting only the
problems identified during that specific operation.
For example, an array in a CORRUPT state may still produce a PASSED
result for a <b>probe</b> task if that operation encountered no specific
errors.
</p></div>
<div class="manual-section-level-1">
<h1 id="sec6" class="manual-title-level-1">
Configuration
</h1>
<p>The SnapRAID Daemon is configured via a plain-text .conf file,
defaulting to $PREFIX/etc/snapraidd.conf and if not found to
/etc/snapraidd.conf. The $PREFIX variable represents the installation
path chosen at build time (typically via the <b>--prefix</b> argument to
the configure script).
</p><p>This file governs the behavior of the automation engine, network
accessibility, safety interlocks, and hardware monitoring parameters.
</p><p>The configuration system is designed with a <b>triple-tier</b> management
philosophy to balance operational convenience with rigorous system
security:
</p><p>Tier 1 Core Network (Immutable) - This tier includes critical security
</p><p>and networking parameters, such as the master API toggle, port
bindings, and access control lists. These settings are completely
inaccessible via the REST API.
To modify them, you must perform a manual file edit followed
by a SIGHUP signal to reload the configuration into memory.
</p><p>Tier 2 Protected Operations (Secured) - These parameters involve
</p><p>security-sensitive automation, such as system user assignments,
external script paths, and logging policies. By default, these
options are read-only via the REST API. They can only be
modified via API PATCH requests if the <b>net_config_full_access</b>
flag is manually enabled in this file.
</p><p>Tier 3 Dynamic Logic (Live) - This tier consists of standard
</p><p>operational settings like maintenance schedules, scrub intensities,
and disk monitoring intervals. These parameters are fully
accessible and can be modified in real-time via the API.
Changes made through the REST interface are instantly applied
to the running process and persisted back to this file while
preserving all existing manual comments.
</p><p>To make changes to the <b>/etc/snapraidd.conf</b> file effective, you must
either restart the daemon or send a SIGHUP signal to the running process.
This is required for any manual edit to ensure the daemon's memory state
stays in sync with the file and to prevent the API from accidentally
overwriting your changes.
</p><p>Example:
</p><pre>
sudo killall -HUP snapraidd
</pre>
<p>For a comprehensive view of how these settings are applied in a
real-world environment, refer to the comments in the <b>snapraidd.conf</b>
file installed.
</p><div class="manual-section-level-2">
<h2 id="sec6-1" class="manual-title-level-2">
System
</h2>
<p>These settings control the core execution environment and the
underlying daemon.
These options are not visible or modifiable via the REST API.
They require a manual edit of the configuration file and a
configuration reload (SIGHUP) or daemon restart to apply.
</p><div class="manual-section-level-3">
<h3 id="sec6-1-1" class="manual-title-level-3">
sys_engine
</h3>
<p>Sets the absolute path to the SnapRAID executable. If omitted,
the daemon searches /usr/bin and /usr/local/bin on Linux, /usr/bin
in Wine, and the daemon's base directory on Windows.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-1-2" class="manual-title-level-3">
sys_log_directory
</h3>
<p>Defines where the output of individual SnapRAID commands is stored.
If left unset, the daemon defaults to /var/log/snapraid in Linux
and /log in the installation directory in Windows.
</p><p>Setting this option to an empty value (sys_log_directory = ) will
explicitly disable the saving of command output to persistent files.
</p><p>IMPORTANT: While it is possible to leave this empty to avoid saving files,
these logs are used by the daemon to reconstruct the past state of the
array (e.g., tracking the last successful sync or scrub). If no log
directory is provided, the daemon will lose its <b>memory</b> of previous
task results every time it is restarted.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-1-3" class="manual-title-level-3">
sys_log_retention_days
</h3>
<p>To prevent your storage from filling up, sys_log_retention_days sets the
age at which old command logs are deleted. Logs are kept indefinitely
if this is set to 0 or left unset.
</p></div>
</div>
<div class="manual-section-level-2">
<h2 id="sec6-2" class="manual-title-level-2">
Network &amp; REST API
</h2>
<p>These settings control the network interface. These options are not
visible from the REST API. They require a manual edit of the
configuration file and a configuration reload (SIGHUP) to apply.
</p><div class="manual-section-level-3">
<h3 id="sec6-2-1" class="manual-title-level-3">
net_enabled
</h3>
<p>Acts as the master toggle for the network interface. When set to 1,
the daemon enables the REST API and prepares to serve the web dashboard.
If set to 0 or left blank, the daemon operates in a secure, local-only
mode, and no network ports are opened.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-2-2" class="manual-title-level-3">
net_port
</h3>
<p>Defines the specific IP address and port(s) to which the daemon binds.
The format follows [IP_ADDRESS:]PORT[s].
</p><div class="manual-tag-list">
<div class="manual-tag-entry">
<div class="manual-tag-name">
IPv4/IPv6
</div><div class="manual-tag-description">
Bind to specific local addresses (e.g., 127.0.0.1:7627 or
[::1]:7627).
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
Port
</div><div class="manual-tag-description">
Providing only a port (e.g., 7627) binds to all available
IPv4 interfaces (0.0.0.0).
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
Multiple_Ports
</div><div class="manual-tag-description">
Multiple listeners can be configured by providing a
comma-separated list.
</div>
</div>
</div>
<p>If left unset, the daemon defaults to 127.0.0.1:7627,[::1]:7627
retrying with only 127.0.0.1:7627 if it fails.
</p><p>To export the service to a VPN like Tailscale or a local network, you
should bind to all interfaces by specifying only the port number.
</p><p>Examples:
</p><pre>
net_port=127.0.0.1:7627 - IPv4 loopback only (Recommended).
net_port=[::1]:7627 - IPv6 loopback only.
net_port=7627 - All IPv4 interfaces (Required for Tailscale/LAN).
net_port=[::]:7627 - All IPv6 interfaces.
net_port=127.0.0.1:7627,127.0.0.1:8080 - Listen on multiple ports on loopback.
</pre>
</div>
<div class="manual-section-level-3">
<h3 id="sec6-2-3" class="manual-title-level-3">
net_acl
</h3>
<p>Restricts API and dashboard access to specific client IP addresses or
subnets using a comma-separated Access Control List (ACL).
</p><p>The syntax uses + to allow and - to deny, supporting CIDR notation
(e.g., /24). The rules are processed sequentially, and the last
matching rule determines the outcome.
If unset, it defaults to accept everything. If any rules are defined,
the daemon adopts a <b>deny by default</b> stance.
</p><p>To allow access via Tailscale or similar services, ensure you add the
relevant network prefix (e.g., +100.0.0.0/8).
</p><p>Examples:
</p><pre>
net_acl=+127.0.0.1,+::1 - Allow IPv4 and IPv6 loopback.
net_acl=+100.0.0.0/8,+127.0.0.1 - Allow Tailscale and loopback.
net_acl=+192.168.1.0/24 - Allow local subnet only.
</pre>
</div>
<div class="manual-section-level-3">
<h3 id="sec6-2-4" class="manual-title-level-3">
net_security_headers
</h3>
<p>When enabled (1), the daemon injects several browser-level security
hardening headers into every HTTP response. These include
Content-Security-Policy (restricting resource loading),
X-Frame-Options (preventing clickjacking via iframes),
X-Content-Type-Options (disabling MIME-sniffing),
and Referrer-Policy.
</p><p>This should only be disabled (0) if the daemon is behind a reverse
proxy (like Nginx or Traefik) that is already configured to handle
these security headers.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-2-5" class="manual-title-level-3">
net_allowed_origin
</h3>
<p>Configures Cross-Origin Resource Sharing (CORS) to determine which web
applications can interact with the API.
</p><div class="manual-tag-list">
<div class="manual-tag-entry">
<div class="manual-tag-name">
self
</div><div class="manual-tag-description">
(Default/Recommended) Dynamically reflects the <b>Host</b> header
of the request, allowing the built-in UI to work across various hostnames or IPs.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
none
</div><div class="manual-tag-description">
Omits CORS headers entirely, blocking browser-based access from any origin.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
URL
</div><div class="manual-tag-description">
Restricts access to a specific origin (e.g., http://192.168.1.50:3000).
</div>
</div>
</div>
</div>
<div class="manual-section-level-3">
<h3 id="sec6-2-6" class="manual-title-level-3">
net_config_full_access
</h3>
<p>A security flag that determines whether sensitive configuration parameters
can be modified via the REST API.
</p><p>By default (0), security-sensitive options are strictly read-only to
prevent unauthorized system modifications or privilege escalation
through the web interface.
</p><p>When set to 1, the following configuration options become accessible
for modification via PATCH requests:
</p><div class="manual-tag-list">
<div class="manual-tag-entry">
<div class="manual-tag-name">
hook_run_as_user
</div><div class="manual-tag-description">
The account used for executing hook_script.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
hook_script
</div><div class="manual-tag-description">
The absolute path to the hook script.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
notify_run_as_user
</div><div class="manual-tag-description">
The account used for notification commands.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
notify_heartbeat
</div><div class="manual-tag-description">
The command used for health monitoring pings.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
notify_result
</div><div class="manual-tag-description">
The command used for sending task reports.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
notify_result_level
</div><div class="manual-tag-description">
The severity threshold for sending notifications.
</div>
</div>
</div>
</div>
<div class="manual-section-level-3">
<h3 id="sec6-2-7" class="manual-title-level-3">
net_web_root
</h3>
<p>Specifies the source of the web dashboard assets. The daemon supports
both a standard directory and a single compressed ZIP file for asset
delivery.
</p><p>The daemon resolves the location of the assets based on the following
rules:
</p><div class="manual-tag-list">
<div class="manual-tag-entry">
<div class="manual-tag-name">
ZIP_Filename
</div><div class="manual-tag-description">
If a simple filename is provided (e.g., commander.zip),
the daemon searches for it in $PREFIX/share/snapraidd/ or
/usr/share/snapraidd/.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
ZIP_Path
</div><div class="manual-tag-description">
If a path to a ZIP file is provided, it must be absolute
(e.g., /opt/snapraid/ui.zip). The daemon will attempt to use
this specific file exclusively and will not perform a search
in system directories.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
Directories
</div><div class="manual-tag-description">
If the target is a directory rather than a ZIP archive,
the path must be absolute (e.g., /var/www/snapraid-ui/).
</div>
</div>
</div>
<p>If the specified path or filename cannot be resolved, if a directory
path is not absolute, or if the ZIP archive is inaccessible or
malformed, the built-in HTTP server will be unable to serve the web
interface.
</p><p>The daemon recursively crawls the directory or archive at startup to
provide high-performance, compressed delivery of the UI.
</p><p>When a directory is specified, assets are cached in memory, as a result,
manual changes to asset files on the disk will not be reflected in the
UI until the daemon is restarted. This behavior can be bypassed by using
the -N, --no-cache option during daemon startup, which is recommended
for development environments only.
</p></div>
</div>
<div class="manual-section-level-2">
<h2 id="sec6-3" class="manual-title-level-2">
Automation &amp; Maintenance
</h2>
<p>These settings control the automation and maintenance tasks run by
the SnapRAID Daemon.
</p><p>For security reasons, some of them can be set via the REST API only if the
net_config_full_access option is enabled.
</p><div class="manual-section-level-3">
<h3 id="sec6-3-1" class="manual-title-level-3">
maintenance_schedule
</h3>
<p>Defines the timing for the automated maintenance sequence, which
consists of a sync, followed by a scrub, and concluding with a report.
Multiple schedules can be specified by separating them with commas.
If this option is unset, automated maintenance is disabled.
</p><p>The format must be either "HH:MM" or "Day HH:MM".
Hours are specified in a 24-hour format (00-23), and days are
represented by their short names (Mon, Tue, Wed, Thu, Fri, Sat, Sun).
</p><p>Examples:
"02:00" - Run every night at 2 AM.
"Mon 03:00, Thu 04:00" - Run every Monday at 3 AM and Thursday at 4 AM.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-3-2" class="manual-title-level-3">
sync_threshold_deletes
</h3>
<p>Sets the maximum number of deleted or missing files allowed before a
sync operation is automatically aborted. This serves as a safety
mechanism to prevent accidental parity loss due to unintended mass
deletions. This safety check is enforced during automated maintenance
schedules and tasks initiated through the Web UI.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-3-3" class="manual-title-level-3">
sync_threshold_updates
</h3>
<p>Sets the maximum number of modified or updated files allowed before a
sync operation is aborted. Similar to the delete threshold, this
prevents the parity from being overwritten if an unexpected number
of files have changed. This safety check is enforced during automated
maintenance schedules and tasks initiated through the Web UI.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-3-4" class="manual-title-level-3">
sync_prehash
</h3>
<p>If set to 1, the sync command is executed with the --prehash option.
This calculates the hash of all files before the synchronization process
begins. By hashing data before the system is subjected to the high
CPU and I/O load typical of a sync operation, it protects against
silent data corruption caused by faulty memory that may only trigger
under critical system stress.
If missing or set to 0, no pre-hashing is performed.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-3-5" class="manual-title-level-3">
sync_prevent_truncations
</h3>
<p>If set to 1, the sync is halted to prevent overwriting
parity with empty file data. This provides a safety
barrier against truncated data, which may occur during system
crashes or filesystem errors.
If this is missing or set to 0, the sync is allowed
to proceed even if files have shrunk to zero size.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-3-6" class="manual-title-level-3">
scrub_percentage
</h3>
<p>Determines the portion of the array verified after a successful sync.
You may use decimal points to specify fractions of a percent
(e.g., 0.7 to verify 0.7% of the array).
If missing or set to 0, the scrub phase is skipped entirely.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-3-7" class="manual-title-level-3">
scrub_older_than
</h3>
<p>Specifies that only blocks older than the defined number of days
should be scrubbed. This allows the daemon to focus verification on
older data while skipping recently synced blocks.
If missing or set to 0, no age-based filtering is applied.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-3-8" class="manual-title-level-3">
touch_zero_subseconds
</h3>
<p>If set to 1, a specific timestamp alignment pass is performed
immediately before the sync during the maintenance window.
If this is missing or set to 0, this pass is skipped.
</p><p>Many filesystems or file-copying utilities may leave file
timestamps with exactly zero nanoseconds. This lack of
precision can cause the synchronization engine to misidentify
moved or renamed files as entirely new content.
</p><p>Setting this to 1 triggers the touch command to update these
sub-second parts of the timestamps to a random value. This
ensures high-resolution tracking is available to correctly
identify relocated data without re-processing the underlying
file blocks.
</p></div>
</div>
<div class="manual-section-level-2">
<h2 id="sec6-4" class="manual-title-level-2">
Disk Monitoring &amp; Power
</h2>
<p>The following settings manage how the daemon interacts with physical
hardware to monitor disk health and optimize energy consumption
</p><div class="manual-section-level-3">
<h3 id="sec6-4-1" class="manual-title-level-3">
probe_interval_minutes
</h3>
<p>Controls the frequency at which the daemon checks disk SMART attributes.
To prevent unnecessary disk wear, the daemon only performs this check
if the disks are already spinning.
If set to 0 or left blank, SMART monitoring is disabled.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-4-2" class="manual-title-level-3">
spindown_idle_minutes
</h3>
<p>Manages power consumption by automatically spinning down disks after
the specified duration of inactivity.
</p><p>This timer monitors the global activity of the disks across the entire
operating system. A disk will only be spun down if it has remained
completely idle for the specified period. If any other application,
service, or system process accesses the disk, the idle timer is reset.
</p><p>If this option is unset, the daemon will not manage disk power states,
relying instead on the OS or hardware controllers.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-4-3" class="manual-title-level-3">
hook_script
</h3>
<p>Defines an absolute path to an executable script to be triggered by
daemon events.
</p><p>The script is executed with a single positional argument that
represents the lifecycle stage of the task currently being processed
by the daemon:
</p><div class="manual-tag-list">
<div class="manual-tag-entry">
<div class="manual-tag-name">
task-begin
</div><div class="manual-tag-description">
Triggered immediately before the daemon begins a
scheduled sequence of actions that access the array
(e.g., sync, scrub, or maintenance).
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
task-end
</div><div class="manual-tag-description">
Triggered after the entire sequence of actions has
concluded successfully.
</div>
</div>
</div>
<p>task-error: Triggered if the task sequence is aborted, interrupted,
</p><p>or encounters an operational failure.
</p><p>Note that 'task-end' reflects only whether the task finished its
execution cycle. It does not necessarily reflect hardware or data
integrity. For example, a sync command may return 'task-end' even if
the array is technically in a corrupt state, provided the sync process
itself finished without crashing.
</p><p>Future versions of the daemon will introduce new event types that may
not relate to array access or follow the <b>task-</b> naming convention.
It is strongly recommended to implement a default handler to ignore
unrecognized events
</p><p>SECURITY REQUIREMENTS:
* The path MUST be absolute (starting with /).
* The script file MUST NOT be world-writable (recommended: 700 or 755).
* The script owner MUST match the user running the daemon or be root.
* The script MUST contain a valid shebang (e.g., #!/bin/sh).
</p><p>This remains inactive if no path is defined.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-4-4" class="manual-title-level-3">
hook_run_as_user
</h3>
<p>Specifies the user account used to execute the hook_script.
If this is missing or blank, the script is executed with the
same privileges as the daemon process.
</p><p>On Linux, <b>nobody</b> is the standard choice for maximum isolation.
On Windows, <b>LocalService</b> is the preferred choice as it provides
minimal local access while maintaining network capabilities.
Alternatively, <b>NetworkService</b> can be used if the script specifically
requires the computer's network identity to access remote resources.
</p></div>
</div>
<div class="manual-section-level-2">
<h2 id="sec6-5" class="manual-title-level-2">
Notifications
</h2>
<p>These settings control the notification operations performed by the
daemon.
</p><div class="manual-section-level-3">
<h3 id="sec6-5-1" class="manual-title-level-3">
notify_syslog_enabled
</h3>
<p>When set to 1, daemon activity is sent to the operating system system
log (syslog/journald). While lifecycle events like starting and
stopping are always captured, task-related messages are filtered by
<b>notify_syslog_level</b>.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-5-2" class="manual-title-level-3">
notify_syslog_level
</h3>
<p>Sets the minimum severity for syslog task entries.
Possible values are <b>info</b>, <b>warning</b>, <b>error</b>, and <b>critical</b>.
The default is <b>error</b>.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-5-3" class="manual-title-level-3">
notify_heartbeat
</h3>
<p>Defines a command to run ONLY if the maintenance task was successful
(it is not triggered by other tasks, such as heal or undelete).
This is ideal for external monitoring services like <b>Dead Man's Snitch</b>
or Healthchecks.io. If this ping stops, it indicates the server is down
or the task is failing.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-5-4" class="manual-title-level-3">
notify_result
</h3>
<p>Specifies a command triggered after every report task generated by
high-level tasks or by a SMART telemetry change. The command is only
executed if the task's result matches the <b>notify_result_level</b>.
The daemon pipes a structured, plain-text task report directly into
the command's stdin.
</p><p>The daemon automatically chooses a wide (80-col) or narrow (32-col)
report based on the command and arguments used (e.g., presence of <b>mail</b>
or <b>smtps</b> strings). Users can manually override this by adding --wide or
--narrow to the command string. These tags are stripped before execution.
</p><p>Before execution, the daemon scans the command string and replaces the
following tokens with dynamic values corresponding to the current
task's state and results:
</p><div class="manual-tag-list">
<div class="manual-tag-entry">
<div class="manual-tag-name">
%s
</div><div class="manual-tag-description">
Subject string (e.g., "[ERROR] SnapRAID Maintenance").
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
%l
</div><div class="manual-tag-description">
Task level (critical, error, warning, info, debug).
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
%n
</div><div class="manual-tag-description">
ntfy priority (urgent, high, default, low, min).
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
%t
</div><div class="manual-tag-description">
ntfy tag (rotating_light, warning, default, -1, +1, heavy_check_mark).
</div>
</div>
</div>
<p>If the command contains --mail-from or --mail-rcpt, the daemon
automatically prepends standard email headers (From, To, Subject)
followed by a blank line to the report text. This ensures
compatibility with curl's SMTP engine.
</p><p>When using curl for SMTP, it is recommended to use the --netrc flag.
This allows curl to read credentials from a local file rather than
exposing passwords in the command line or process list.
</p><p>File format (~/.netrc):
</p><pre>
machine smtp.gmail.com
login your_email@gmail.com
password your-16-char-app-password
</pre>
<p>If <b>notify_run_as_user</b> is configured, ensure that user has a valid
home directory containing a .netrc file with 600 permissions for SMTP
authentication. Failure to do so may result in authentication errors
(e.g., curl error 55).
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-5-5" class="manual-title-level-3">
notify_result_level
</h3>
<p>Controls the filter for <b>notify_result</b>. The notification is sent only
if the task result is equal to or more severe than this level.
Valid values are <b>info</b> (always send), <b>warning</b>, <b>error</b>, and <b>critical</b>.
The default is <b>error</b>.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-5-6" class="manual-title-level-3">
notify_run_as_user
</h3>
<p>The user account used for notify_heartbeat, notify_result and mail
notifications. If missing or left blank, the task runs with the
daemon's current privileges.
</p><p>On Linux, <b>nobody</b> is the standard choice for maximum isolation.
On Windows, <b>LocalService</b> is the preferred choice as it provides
minimal local access while maintaining network capabilities.
Alternatively, <b>NetworkService</b> can be used if the script specifically
requires the computer's network identity to access remote resources.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec6-5-7" class="manual-title-level-3">
notify_differences
</h3>
<p>If set to 1, the daemon logs a detailed list of file changes discovered
before a sync begins. If set to 0 or missing, no difference report is
generated.
</p></div>
</div>
<div class="manual-section-level-2">
<h2 id="sec6-6" class="manual-title-level-2">
Notification Examples
</h2>
<p>The following examples demonstrate common notification and heartbeat
configurations
</p><div class="manual-section-level-3">
<h3 id="sec6-6-1" class="manual-title-level-3">
External Heartbeat Monitoring (Healthchecks.io)
</h3>
<p>To monitor that automated maintenance is running successfully, use a service
like Healthchecks.io.
</p><p>In this example, curl sends a simple GET request to a unique monitoring URL.
The flags ensure that curl fails silently on server errors (-f), does not hang
indefinitely (--max-time), and attempts to overcome transient network issues (--retry).
</p><pre>
notify_heartbeat = curl -f --max-time 30 --retry 3 <a href="https://hc-ping.com/your_private_uuid">https://hc-ping.com/your_private_uuid</a>
</pre>
</div>
<div class="manual-section-level-3">
<h3 id="sec6-6-2" class="manual-title-level-3">
Push Notifications (ntfy.sh)
</h3>
<p>This uses curl to send the report as a POST request to a push notification service.
It utilizes the --narrow flag to ensure the report is readable on mobile devices
and maps SnapRAID status to ntfy titles, priorities, and emojis via placeholders.
</p><pre>
notify_result = curl --narrow -f --max-time 30 --retry 3 -H "Title: %s" -H "Priority: %n" -H "Tag: %t" -H "Email: your_email@example.com" --data-binary @- <a href="https://ntfy.sh/your_private_topic">https://ntfy.sh/your_private_topic</a>
</pre>
</div>
<div class="manual-section-level-3">
<h3 id="sec6-6-3" class="manual-title-level-3">
Local System Mail (mail)
</h3>
<p>A traditional approach using the standard Linux mail utility. This is
ideal if you have a local Mail Transfer Agent (MTA) like Postfix or
Exim already configured on your system.
</p><pre>
notify_result = mail -s "%s" your_user@localhost
</pre>
</div>
<div class="manual-section-level-3">
<h3 id="sec6-6-4" class="manual-title-level-3">
Direct Delivery (SMTP-over-SSL)
</h3>
<p>This leverages curl's built-in SMTP engine for direct delivery to an
external provider. By using the --netrc option, login credentials
remain secured in a separate file rather than being exposed in the
process list or logs.
</p><pre>
notify_result = curl --netrc --url smtps://smtp.gmail.com:465 --ssl-reqd --mail-from your_email@gmail.com --mail-rcpt your_email@gmail.com --upload-file -
</pre>
</div>
</div>
</div>
<div class="manual-section-level-1">
<h1 id="sec7" class="manual-title-level-1">
REST API
</h1>
<p>The SnapRAID Daemon provides a comprehensive RESTful JSON interface
for monitoring and controlling the parity array.
</p><p>For complete technical documentation, including request schemas and
specific error codes, please refer to the <b>snapraidd.yaml</b> OpenAPI
specification file typically located in the documentation directory of
the installation.
</p><div class="manual-section-level-2">
<h2 id="sec7-1" class="manual-title-level-2">
Maintenance &amp; Recovery
</h2>
<p>The API prioritizes orchestrated workflows over raw command execution.
These high-level endpoints encapsulate complex SnapRAID logic into
single, automated tasks that manage the lifecycle of the array and the
recovery of data.
They typically conclude with a <b>report</b> command that generates a
notification containing the operation's results.
</p><div class="manual-section-level-3">
<h3 id="sec7-1-1" class="manual-title-level-3">
/snapraid/v1/maintenance
</h3>
<p>Triggers the complete automated maintenance sequence. It orchestrates
a parity synchronization, followed by a data integrity scrub, and
concludes by issuing a system-wide health report.
This is the primary endpoint for routine array upkeep.
This task is subject to the <b>sync_threshold_deletes</b> and
<b>sync_threshold_updates</b> safety checks defined in the configuration.
The percentage of the array checked and the age filter are determined
by the <b>scrub_percentage</b> and <b>scrub_older_than</b> settings.
</p><p>Example:
</p><pre>
curl -X POST <a href="http://localhost:7627/snapraid/v1/maintenance">http://localhost:7627/snapraid/v1/maintenance</a>
</pre>
<p>It is implemented with the sequence of commands: up, diff, sync, scrub, and
report.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec7-1-2" class="manual-title-level-3">
/snapraid/v1/heal
</h3>
<p>Executes a specialized silent error recovery workflow. The daemon
automatically runs a targeted fix operation to repair detected corruption,
immediately follows up with a verification scrub of the affected
blocks to ensure the recovery was successful, and concludes by issuing
a report of the result.
</p><p>Example:
</p><pre>
curl -X POST <a href="http://localhost:7627/snapraid/v1/heal">http://localhost:7627/snapraid/v1/heal</a>
</pre>
<p>It is implemented with the sequence of commands: up, fix -e, scrub -p bad,
and report.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec7-1-3" class="manual-title-level-3">
/snapraid/v1/undelete
</h3>
<p>Invokes the SnapRAID restoration engine to recover files that have been
deleted from data disks but still exist in the parity information.
This is used to roll back accidental deletions to the state of the
last successful synchronization.
</p><p>Example:
</p><pre>
curl -s -X POST <a href="http://localhost:7627/snapraid/v1/undelete">http://localhost:7627/snapraid/v1/undelete</a> \
&nbsp;&nbsp;&nbsp;&nbsp;-H "Content-Type: application/json" \
&nbsp;&nbsp;&nbsp;&nbsp;-d '{ "filters": [ "*.txt" ] }'
</pre>
<p>It is implemented with the sequence of commands: up, fix -m -f ...,
and report.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec7-1-4" class="manual-title-level-3">
/snapraid/v1/suspend_idle
</h3>
<p>Probes the disks to gather their latest activity state and executes a
conditional spindown operation. The daemon will only issue the
down_idle command to disks that have exceeded the
<b>spindown_idle_minutes</b> threshold. In this case, no report is
generated.
</p><p>Example:
</p><pre>
curl -X POST <a href="http://localhost:7627/snapraid/v1/suspend_idle">http://localhost:7627/snapraid/v1/suspend_idle</a>
</pre>
<p>It is implemented with the sequence of commands: probe, down_idle.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec7-1-5" class="manual-title-level-3">
/snapraid/v1/refresh
</h3>
<p>Forces the daemon to re-synchronize its internal state with the
content file. This is intended for use after manual interventions
performed outside the daemon interface (e.g., replacing
a failed disk, fixing UUID mismatches, or manually updating configuration).
</p><p>The operation executes a <b>read</b> task to load the current content file
data, followed by a <b>report</b> task to evaluate and broadcast the
resulting array health.
</p><p>This is specifically useful for clearing <b>FAILING</b> or <b>PREFAIL</b> modes
once the underlying hardware or configuration issues have been
resolved manually.
</p><p>Example:
</p><pre>
curl -X POST <a href="http://localhost:7627/snapraid/v1/refresh">http://localhost:7627/snapraid/v1/refresh</a>
</pre>
</div>
</div>
<div class="manual-section-level-2">
<h2 id="sec7-2" class="manual-title-level-2">
Monitoring &amp; Inventory
</h2>
<p>These endpoints provide high-level visibility into the global state of
the storage stack and the health of the underlying physical hardware.
</p><div class="manual-section-level-3">
<h3 id="sec7-2-1" class="manual-title-level-3">
/snapraid/v1/array
</h3>
<p>Provides a high-level telemetry summary of the entire parity array.
This includes global metadata such as total capacity across all disks,
aggregate space utilization, the current state of parity protection,
and the timestamp of the last successful maintenance.
</p><p>Example:
</p><pre>
curl -s <a href="http://localhost:7627/snapraid/v1/array">http://localhost:7627/snapraid/v1/array</a> | jq
</pre>
</div>
<div class="manual-section-level-3">
<h3 id="sec7-2-2" class="manual-title-level-3">
/snapraid/v1/disks
</h3>
<p>Returns a comprehensive inventory of every physical disk associated
with the SnapRAID configuration. It reports real-time hardware
metrics including SMART health status, temperature, and the current
power state (Active/Spin-up vs. Standby/Spin-down).
</p><p>Example:
</p><pre>
curl -s <a href="http://localhost:7627/snapraid/v1/disks">http://localhost:7627/snapraid/v1/disks</a> | jq
</pre>
</div>
</div>
<div class="manual-section-level-2">
<h2 id="sec7-3" class="manual-title-level-2">
Runtime Configuration
</h2>
<p>Provides a programmatic interface to retrieve and modify the
operational parameters of the daemon in real-time.
</p><div class="manual-section-level-3">
<h3 id="sec7-3-1" class="manual-title-level-3">
/snapraid/v1/config
</h3>
<p>Retrieves and updates the current runtime configuration parameters of
the snapraidd service. Changes are applied instantly to memory and
persisted to the configuration file.
Note that certain networking and security settings are read-only and
require a manual edit and SIGHUP.
</p><p>Example:
</p><pre>
curl -X GET <a href="http://localhost:7627/snapraid/v1/config">http://localhost:7627/snapraid/v1/config</a> | jq
curl -X PATCH <a href="http://localhost:7627/snapraid/v1/config">http://localhost:7627/snapraid/v1/config</a> \
&nbsp;&nbsp;&nbsp;&nbsp;-d '{ "probe_interval_minutes": 10 }'
</pre>
</div>
</div>
<div class="manual-section-level-2">
<h2 id="sec7-4" class="manual-title-level-2">
Activity Control
</h2>
<p>All operations that modify the array state are asynchronous; they
return an HTTP 202 Accepted status and queue a task for background
execution.
</p><p>Because tasks run in the background, these endpoints are used to
monitor progress and manage the execution lifecycle.
</p><div class="manual-section-level-3">
<h3 id="sec7-4-1" class="manual-title-level-3">
/snapraid/v1/activity
</h3>
<p>Provides real-time telemetry for the currently executing task,
including a progress percentage, estimated time of completion (ETA),
and a live stream of the process log output.
If no task is in execution, it returns the last completed task.
</p><p>Example:
</p><pre>
curl -s <a href="http://localhost:7627/snapraid/v1/activity">http://localhost:7627/snapraid/v1/activity</a> | jq
</pre>
</div>
<div class="manual-section-level-3">
<h3 id="sec7-4-2" class="manual-title-level-3">
/snapraid/v1/tasks
</h3>
<p>Lists all tasks waiting, the task currently active, and the task
execution history. The response from this entry point can be very long,
as the history may span up to a month.
</p><p>Example:
</p><pre>
curl -s <a href="http://localhost:7627/snapraid/v1/tasks">http://localhost:7627/snapraid/v1/tasks</a> | jq
</pre>
</div>
<div class="manual-section-level-3">
<h3 id="sec7-4-3" class="manual-title-level-3">
/snapraid/v1/stop
</h3>
<p>Terminates the currently running task (such as sync or scrub) by
sending a SIGTERM signal to the background process.
</p><p>Example:
</p><pre>
curl -X POST <a href="http://localhost:7627/snapraid/v1/stop">http://localhost:7627/snapraid/v1/stop</a>
</pre>
</div>
</div>
<div class="manual-section-level-2">
<h2 id="sec7-5" class="manual-title-level-2">
State and Cache Management
</h2>
<p>To optimize performance and support lightweight monitoring (such as
desktop status bars), the daemon implements a state synchronization
mechanism via the /v1/state endpoint.
</p><div class="manual-section-level-3">
<h3 id="sec7-5-1" class="manual-title-level-3">
/snapraid/v1/state
</h3>
<p>The response provides a high-level summary of the daemon's current
operation and health, alongside a pulse object containing sequence
counters.
</p><p>The pulse object contains counters used for cache invalidation. Each
field corresponds directly to a data-heavy API entry point.
</p><p>If a counter has not changed since the last request, the corresponding
entry point is guaranteed to return the same data. If a counter is
different, the underlying subsystem state has evolved, and the entry
point will potentially return updated information.
</p><p>Note that the counters are not necessarily monotonically increasing
because they are reset if the daemon restarts. You should compare
them only for equality.
</p><p>Example:
</p><pre>
curl -X GET <a href="http://localhost:7627/snapraid/v1/state">http://localhost:7627/snapraid/v1/state</a> | jq
</pre>
</div>
</div>
<div class="manual-section-level-2">
<h2 id="sec7-6" class="manual-title-level-2">
Schedule
</h2>
<p>The schedule entry point allows batching multiple SnapRAID commands
into a single sequential session. Upon submission, the daemon executes
tasks in the order provided, maintaining a single-threaded execution
flow.
</p><p>The daemon enforces strict serialization for all operations. Only one
task can access the array at a time. All scheduled tasks are placed
in an execution queue and executed in their scheduled order.
</p><p>To ensure data safety, the daemon employs a fail-fast policy where any
command failure triggers the immediate cancellation of all subsequent
tasks within the same schedule request. This prevents operations from
running against an unstable or inconsistent array state while
preserving any independent tasks previously queued in the system.
</p><p>The only exception is the report command, which acts as a mandatory
finalizer. It will execute regardless of previous failures to ensure
the generation of a report that reflects the final state of the system.
</p><div class="manual-section-level-3">
<h3 id="sec7-6-1" class="manual-title-level-3">
/snapraid/v1/schedule
</h3>
<p>Queues a sequence of standard SnapRAID operations.
</p><p>Example:
</p><pre>
curl -X POST <a href="http://localhost:7627/snapraid/v1/schedule">http://localhost:7627/snapraid/v1/schedule</a> \
&nbsp;&nbsp;&nbsp;&nbsp;-d '{"tasks": [{"command": "diff"}, {"command": "report"}]}'
</pre>
<p>Supported Commands:
</p><div class="manual-tag-list">
<div class="manual-tag-entry">
<div class="manual-tag-name">
up
</div><div class="manual-tag-description">
Spins up all drives in the array.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
down
</div><div class="manual-tag-description">
Spins down array drives to save power.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
probe
</div><div class="manual-tag-description">
Verifies the power status of all configured disks and gathers
SMART information for those already spinning.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
smart
</div><div class="manual-tag-description">
Collects and parses SMART attributes from all drives to assess
physical health.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
diff
</div><div class="manual-tag-description">
Scans the array to identify changed, added, or deleted files
since the last sync.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
status
</div><div class="manual-tag-description">
Provides a summary of the array state, including parity
levels and data distribution.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
sync
</div><div class="manual-tag-description">
Updates the parity information to match the current state of
the data disks.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
scrub
</div><div class="manual-tag-description">
Verifies the integrity of the data and parity by recalculating
checksums for a portion of the array.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
check
</div><div class="manual-tag-description">
Performs a full verification of the array integrity without
modifying any data.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
fix
</div><div class="manual-tag-description">
Attempts to recover deleted files or repair corrupted data using
the parity information.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
report
</div><div class="manual-tag-description">
Generates a comprehensive summary of the last operations and
array statistics.
</div>
</div>
<div class="manual-tag-entry">
<div class="manual-tag-name">
down_idle
</div><div class="manual-tag-description">
Executes a conditional spindown operation of the disks that
have exceeded the <b>spindown_idle_minutes</b> threshold.
</div>
</div>
</div>
</div>
</div>
</div>
<div class="manual-section-level-1">
<h1 id="sec8" class="manual-title-level-1">
Signals
</h1>
<p>This section defines how the daemon responds to standard Unix signals,
allowing for external process control and graceful management of the
service lifecycle.
</p><div class="manual-section-level-3">
<h3 class="manual-title-level-3">
SIGHUP
</h3>
<p>Reloads the configuration file and resets the internal state.
It also reloads the Web UI. This is the recommended way to
apply changes to static&nbsp;&nbsp;&nbsp;&nbsp;parameters without restarting the
service.
</p></div>
<div class="manual-section-level-3">
<h3 class="manual-title-level-3">
SIGTERM, SIGINT
</h3>
<p>Initiates a graceful shutdown. If a task is currently
running, the daemon attempts to terminate the child process
before exiting.
</p></div>
<div class="manual-section-level-3">
<h3 class="manual-title-level-3">
SIGQUIT
</h3>
<p>Immediately terminates the process using the default signal
action and may generate a core dump. This signal is intended
for emergency debugging and post mortem analysis of a hung
or misbehaving daemon. No cleanup or graceful shutdown is
performed.
</p></div>
</div>
<div class="manual-section-level-1">
<h1 id="sec9" class="manual-title-level-1">
Files
</h1>
<p>The following list specifies the default filesystem paths used by the
daemon for configuration, data persistence, and inter-process communication.
</p><div class="manual-section-level-2">
<h2 id="sec9-1" class="manual-title-level-2">
Linux
</h2>
<p>On Linux and Unix-like systems:
</p><div class="manual-section-level-3">
<h3 id="sec9-1-1" class="manual-title-level-3">
$PREFIX/etc/snapraidd.conf
</h3>
<p>The primary configuration file location. The $PREFIX variable
represents the installation path chosen at build time (typically
via the <b>--prefix</b> argument to the configure script). Common
values include <b>/usr/local</b> or <b>/usr</b>. If this file does not
exist, the daemon falls back to <b>/etc/snapraidd.conf</b>.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec9-1-2" class="manual-title-level-3">
$PREFIX/share/snapraidd
</h3>
<p>The primary system data directory. This is the first location
searched for the web dashboard ZIP file (e.g., commander.zip).
If not found here, the daemon falls back to <b>/usr/share/snapraidd</b>.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec9-1-3" class="manual-title-level-3">
/etc/snapraidd.conf
</h3>
<p>The secondary/system-wide configuration file location, used if
the prefix-specific file is missing.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec9-1-4" class="manual-title-level-3">
/usr/share/snapraidd
</h3>
<p>The secondary/system-wide data directory, used as a fallback for
web assets.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec9-1-5" class="manual-title-level-3">
/run/snapraidd.pid
</h3>
<p>Default PID file location.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec9-1-6" class="manual-title-level-3">
/var/log/snapraid
</h3>
<p>Default directory for SnapRAID command execution logs. This
directory contains the output of the SnapRAID binary itself,
rather than the daemon's service logs.
If this directory does not exist, the daemon will attempt to create it
upon the first execution of a SnapRAID command.
</p></div>
</div>
<div class="manual-section-level-2">
<h2 id="sec9-2" class="manual-title-level-2">
Windows
</h2>
<p>On Windows systems:
</p><div class="manual-section-level-3">
<h3 id="sec9-2-1" class="manual-title-level-3">
snapraidd.conf
</h3>
<p>The configuration file is expected to be in the same directory
where the <b>snapraidd.exe</b> binary is located.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec9-2-2" class="manual-title-level-3">
log\
</h3>
<p>A subdirectory named <b>log</b> within the installation directory is
used to store the SnapRAID command execution logs. If this
directory does not exist, the service will attempt to create it
upon the first execution of a SnapRAID command.
</p></div>
<div class="manual-section-level-3">
<h3 id="sec9-2-3" class="manual-title-level-3">
commander.zip
</h3>
<p>The web dashboard assets are searched for in the same directory
as the executable.
</p></div>
</div>
</div>
</div>
</main>
</div>
<!-- Footer -->
<footer>
<div class="container footer-content">
<div class="footer-col">
<div class="logo">
<img src="android-chrome-192x192.png" width="32" height="32"/>
SnapRAID
</div>
<p>Copyright &copy; 2026 Andrea Mazzoleni</p>
<p class="license">Distributed under GPL v3 License</p>
</div>
<div class="footer-col">
</div>
</div>
</footer>
</body>
</html>