Auto update

This commit is contained in:
Andrea Mazzoleni 2026-02-23 23:59:05 +01:00
parent da1d84091d
commit ba8cd74f03
3 changed files with 139 additions and 87 deletions

View file

@ -1,10 +1,12 @@
<!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">
<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>How SnapRAID Works</title>
<link rel="stylesheet" href="style.css">
<link rel="apple-touch-icon" sizes="180x180" href="/beta/apple-touch-icon.png">
@ -13,51 +15,55 @@
<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());
<!-- 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>
gtag('config', 'G-W1Z5FKHYQ4');
</script>
<!-- Google Universal Analytics -->
<script type="text/javascript">
<!-- Google Universal Analytics -->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-21967501-1']);
_gaq.push(['_trackPageview']);
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>
(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="favicon-32x32.png"/>
<img src="favicon-32x32.png" />
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>
<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="index">Home</a></li>
<li><a href="ui">UI & Daemon</a></li>
<li><a href="howitworks" class="active">How it Works</a></li>
<li><a href="design" >Design</a></li>
<li><a href="compare" >Compare</a></li>
<li><a href="manual" >Manual</a></li>
<li><a href="faq" >FAQ</a></li>
<li><a href="support" >Support</a></li>
<li><a href="design">Design</a></li>
<li><a href="compare">Compare</a></li>
<li><a href="manual">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>
</ul>
</nav>
@ -73,10 +79,12 @@
<h2 class="section-title">Understanding Data Parity</h2>
<div style="max-width: 800px; margin: 0 auto 3rem auto; text-align: center;">
<p style="font-size: 1.1rem; color: var(--text-primary);">
Parity is a mathematical "summary" of data that allows for the reconstruction of lost information without requiring a full 1:1 copy of every file.
Parity is a mathematical "summary" of data that allows for the reconstruction of lost information
without requiring a full 1:1 copy of every file.
</p>
<p style="font-size: 1rem; color: var(--text-secondary);">
Traditional mirroring (copying) requires 100% extra space. Parity allows for protection using significantly less overhead by storing a mathematical relationship between files instead.
Traditional mirroring (copying) requires 100% extra space. Parity allows for protection using
significantly less overhead by storing a mathematical relationship between files instead.
</p>
</div>
@ -86,9 +94,11 @@
<h3 style="color: var(--text-accent);">The Basic Logic</h3>
<p class="card-subtitle">"Filling in the Blanks"</p>
<p>Imagine three boxes: two for data (numbers) and one for Parity (the sum of the first two).</p>
<div style="background: rgba(0,0,0,0.3); padding: 1rem; border-radius: var(--radius); margin: 1.5rem 0; font-family: var(--font-mono); text-align: center;">
<div style="display: flex; justify-content: center; gap: 1rem; align-items: center;">
<div
style="background: rgba(0,0,0,0.3); padding: 1rem; border-radius: var(--radius); margin: 1.5rem 0; font-family: var(--font-mono); text-align: center;">
<div
style="display: flex; justify-content: center; gap: 1rem; align-items: center; flex-wrap: wrap;">
<div style="text-align: center;">
<div style="color: var(--text-secondary); font-size: 0.8rem;">Disk 1</div>
<div style="font-size: 1.5rem; font-weight: bold;">10</div>
@ -107,8 +117,9 @@
</div>
<p>
If <strong>Disk 1</strong> is destroyed, the system solves the remaining equation:
<code style="background: rgba(255,255,255,0.1); padding: 2px 5px; border-radius: 4px;">[?] + 15 = 25</code>.
If <strong>Disk 1</strong> is destroyed, the system solves the remaining equation:
<code
style="background: rgba(255,255,255,0.1); padding: 2px 5px; border-radius: 4px;">[?] + 15 = 25</code>.
The system identifies the missing value (10) and restores it to a new disk.
</p>
</div>
@ -118,35 +129,48 @@
<h3 style="color: var(--text-accent);">Single Parity</h3>
<p class="card-subtitle">RAID 5 Logic</p>
<p>
The most common form of protection, allowing an array to survive the loss of any <strong>single</strong> disk.
The most common form of protection, allowing an array to survive the loss of any
<strong>single</strong> disk.
</p>
<p>
<strong>Mechanism:</strong> It uses the <strong>XOR</strong> (Exclusive OR) operation. XOR compares bits across multiple disks to create a "map" that can reverse-engineer any single missing piece of the puzzle.
<strong>Mechanism:</strong> It uses the <strong>XOR</strong> (Exclusive OR) operation. XOR
compares bits across multiple disks to create a "map" that can reverse-engineer any single
missing piece of the puzzle.
</p>
<div style="border-left: 3px solid var(--warning); padding-left: 1rem; margin-top: 1.5rem;">
<p style="margin-bottom: 0; font-size: 0.9rem;">
<strong>Limitation:</strong> Single parity can only solve for one unknown variable. If two disks fail simultaneously, the mathematical equation becomes unsolvable (e.g., <code style="font-size: 0.85rem;">X + Y = 25</code> has too many possibilities).
<strong>Limitation:</strong> Single parity can only solve for one unknown variable. If two
disks fail simultaneously, the mathematical equation becomes unsolvable (e.g., <code
style="font-size: 0.85rem;">X + Y = 25</code> has too many possibilities).
</p>
</div>
</div>
</div>
<div class="grid grid-2-cols" style="margin-top: 2rem;">
<!-- Multiple Parity -->
<div class="card">
<!-- Multiple Parity -->
<div class="card">
<h3>Multiple Parity Levels</h3>
<p>Used to survive multiple simultaneous disk failures by employing more complex mathematical formulas.</p>
<p>Used to survive multiple simultaneous disk failures by employing more complex mathematical
formulas.</p>
<ul style="list-style: none; padding: 0; margin-top: 1.5rem;">
<li style="margin-bottom: 1.5rem;">
<strong style="color: var(--text-primary); display: block; margin-bottom: 0.25rem;">Dual Parity (RAID 6)</strong>
<p style="font-size: 0.95rem; margin-bottom: 0.5rem;">Survives <strong>2</strong> simultaneous failures.</p>
<p style="font-size: 0.85rem; color: var(--text-secondary);">Requires two separate equations: an addition-based sum (XOR) and a polynomial-based formula (Reed-Solomon) where disks are treated as coordinates on a geometric curve.</p>
<strong style="color: var(--text-primary); display: block; margin-bottom: 0.25rem;">Dual
Parity (RAID 6)</strong>
<p style="font-size: 0.95rem; margin-bottom: 0.5rem;">Survives <strong>2</strong>
simultaneous failures.</p>
<p style="font-size: 0.85rem; color: var(--text-secondary);">Requires two separate
equations: an addition-based sum (XOR) and a polynomial-based formula (Reed-Solomon)
where disks are treated as coordinates on a geometric curve.</p>
</li>
<li>
<strong style="color: var(--text-primary); display: block; margin-bottom: 0.25rem;">Triple to Hexa Parity</strong>
<p style="font-size: 0.95rem; margin-bottom: 0.5rem;">Survives <strong>3 to 6</strong> failures.</p>
<p style="font-size: 0.85rem; color: var(--text-secondary);">Essential for large arrays (20+ disks) where the statistical risk of multiple failures during a rebuild is higher.</p>
<strong style="color: var(--text-primary); display: block; margin-bottom: 0.25rem;">Triple
to Hexa Parity</strong>
<p style="font-size: 0.95rem; margin-bottom: 0.5rem;">Survives <strong>3 to 6</strong>
failures.</p>
<p style="font-size: 0.85rem; color: var(--text-secondary);">Essential for large arrays (20+
disks) where the statistical risk of multiple failures during a rebuild is higher.</p>
</li>
</ul>
</div>
@ -156,10 +180,13 @@
<div class="card" style="border-color: var(--warning); background: rgba(245, 158, 11, 0.05);">
<h3 style="color: var(--warning);">The "Largest Disk" Rule</h3>
<p>
The Parity Disk must be <strong>at least as large</strong> as the largest Data Disk in the array.
The Parity Disk must be <strong>at least as large</strong> as the largest Data Disk in the
array.
</p>
<p style="margin-bottom: 0;">
<strong>Reason:</strong> Parity is calculated on a "sector-by-sector" basis. To protect the 1,000th gigabyte of a data drive, the parity drive must have a 1,000th gigabyte available to store that specific calculation. Without that space, the data is left unprotected.
<strong>Reason:</strong> Parity is calculated on a "sector-by-sector" basis. To protect the
1,000th gigabyte of a data drive, the parity drive must have a 1,000th gigabyte available to
store that specific calculation. Without that space, the data is left unprotected.
</p>
</div>
</div>
@ -169,31 +196,37 @@
<!-- The Role of Integrity Checksums Section -->
<div style="margin-top: 5rem; margin-bottom: 5rem;">
<h2 class="section-title">The Role of Integrity Checksums in Data Repair</h2>
<!-- Introduction: The Silent Error Problem -->
<div style="max-width: 800px; margin: 0 auto 3rem auto; text-align: center;">
<h3 style="color: var(--text-accent); margin-bottom: 1rem;">The "Silent Error" Problem</h3>
<p style="font-size: 1.1rem; color: var(--text-primary);">
Physical disk failure is obvious: the drive disappears. However, "Silent Corruption" (bit-rot) is invisible.
Physical disk failure is obvious: the drive disappears. However, "Silent Corruption" (bit-rot) is
invisible.
A single bit flips from a 0 to a 1, but the disk still appears "healthy" to the computer.
</p>
</div>
<div class="grid grid-2-cols" style="align-items: stretch;">
<!-- Why Parity Alone Fails -->
<div class="card">
<h3 style="color: var(--danger);">Why Parity Alone is Not Enough</h3>
<p class="card-subtitle">"Parity can fix a hole, but it cannot find a lie."</p>
<p>Recall our simple math: <code>Disk A (5) + Disk B (3) = Parity (8)</code>.</p>
<div style="background: rgba(239, 68, 68, 0.1); padding: 1.5rem; border-radius: var(--radius); margin: 1.5rem 0; border: 1px solid var(--danger);">
<p style="margin-bottom: 0.5rem; font-weight: bold; color: var(--danger);">Scenario: Bit-Rot on Disk A</p>
<div
style="background: rgba(239, 68, 68, 0.1); padding: 1.5rem; border-radius: var(--radius); margin: 1.5rem 0; border: 1px solid var(--danger);">
<p style="margin-bottom: 0.5rem; font-weight: bold; color: var(--danger);">Scenario: Bit-Rot on
Disk A</p>
<div style="font-family: var(--font-mono); font-size: 0.95rem;">
<div>Original: 5 + 3 = 8 <span style="color: var(--success);">✓</span></div>
<div style="margin-top: 0.5rem;">Rotten: &nbsp;<span style="text-decoration: underline; font-weight: bold;">9</span> + 3 = 12 <span style="color: var(--danger);">✗</span></div>
<div style="margin-top: 0.5rem; color: var(--text-secondary); border-top: 1px dashed var(--danger); padding-top: 0.5rem;">
<div style="margin-top: 0.5rem;">Rotten: &nbsp;<span
style="text-decoration: underline; font-weight: bold;">9</span> + 3 = 12 <span
style="color: var(--danger);">✗</span></div>
<div
style="margin-top: 0.5rem; color: var(--text-secondary); border-top: 1px dashed var(--danger); padding-top: 0.5rem;">
Mismatch! 12 ≠ 8 (Parity)
</div>
</div>
@ -213,7 +246,8 @@
</ul>
<p style="font-size: 0.95rem; font-style: italic; color: var(--text-secondary);">
Without knowing the culprit, parity is useless. If you try to "fix" the array blindly, you might overwrite good data with bad data.
Without knowing the culprit, parity is useless. If you try to "fix" the array blindly, you might
overwrite good data with bad data.
</p>
</div>
@ -221,52 +255,71 @@
<div class="card" style="border-color: var(--success);">
<h3 style="color: var(--success);">The Solution: Integrity Checksums</h3>
<p class="card-subtitle">"Digital Fingerprints"</p>
<p>A checksum is a mathematical fingerprint for a specific file or block of data.</p>
<div style="margin: 1.5rem 0;">
<h4 style="font-size: 1rem; color: var(--text-primary); margin-bottom: 1rem;">The Repair Workflow</h4>
<h4 style="font-size: 1rem; color: var(--text-primary); margin-bottom: 1rem;">The Repair
Workflow</h4>
<div style="display: flex; flex-direction: column; gap: 1rem;">
<!-- Step 1 -->
<div style="display: flex; align-items: center; gap: 1rem; padding: 0.75rem; background: rgba(255,255,255,0.03); border-radius: var(--radius);">
<div style="min-width: 24px; height: 24px; background: var(--danger); color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 0.8rem; font-weight: bold;">1</div>
<div
style="display: flex; align-items: center; gap: 1rem; padding: 0.75rem; background: rgba(255,255,255,0.03); border-radius: var(--radius);">
<div
style="min-width: 24px; height: 24px; background: var(--danger); color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 0.8rem; font-weight: bold;">
1</div>
<div>
<div style="font-weight: bold; color: var(--text-primary);">Check Fingerprint A</div>
<div style="font-size: 0.9rem; color: var(--danger);">"Does not match." (Culprit Found!)</div>
<div style="font-weight: bold; color: var(--text-primary);">Check Fingerprint A
</div>
<div style="font-size: 0.9rem; color: var(--danger);">"Does not match." (Culprit
Found!)</div>
</div>
</div>
<!-- Step 2 -->
<div style="display: flex; align-items: center; gap: 1rem; padding: 0.75rem; background: rgba(255,255,255,0.03); border-radius: var(--radius);">
<div style="min-width: 24px; height: 24px; background: var(--success); color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 0.8rem; font-weight: bold;">2</div>
<div
style="display: flex; align-items: center; gap: 1rem; padding: 0.75rem; background: rgba(255,255,255,0.03); border-radius: var(--radius);">
<div
style="min-width: 24px; height: 24px; background: var(--success); color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 0.8rem; font-weight: bold;">
2</div>
<div>
<div style="font-weight: bold; color: var(--text-primary);">Check Fingerprint B</div>
<div style="font-size: 0.9rem; color: var(--success);">"Matches." (Data is safe.)</div>
<div style="font-weight: bold; color: var(--text-primary);">Check Fingerprint B
</div>
<div style="font-size: 0.9rem; color: var(--success);">"Matches." (Data is safe.)
</div>
</div>
</div>
<!-- Step 3 -->
<div style="display: flex; align-items: center; gap: 1rem; padding: 0.75rem; background: rgba(255,255,255,0.03); border-radius: var(--radius);">
<div style="min-width: 24px; height: 24px; background: var(--success); color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 0.8rem; font-weight: bold;">3</div>
<div
style="display: flex; align-items: center; gap: 1rem; padding: 0.75rem; background: rgba(255,255,255,0.03); border-radius: var(--radius);">
<div
style="min-width: 24px; height: 24px; background: var(--success); color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 0.8rem; font-weight: bold;">
3</div>
<div>
<div style="font-weight: bold; color: var(--text-primary);">Check Parity</div>
<div style="font-size: 0.9rem; color: var(--success);">"Matches." (Parity is safe.)</div>
<div style="font-size: 0.9rem; color: var(--success);">"Matches." (Parity is safe.)
</div>
</div>
</div>
</div>
</div>
<p style="margin-top: 1.5rem;">
<strong>Result:</strong> We know with 100% certainty that <strong>Disk A</strong> is the liar. We can now safely use the math (<code>Parity 8 - Disk B 3</code>) to recalculate the original <strong>5</strong> and repair the corruption.
<strong>Result:</strong> We know with 100% certainty that <strong>Disk A</strong> is the liar.
We can now safely use the math (<code>Parity 8 - Disk B 3</code>) to recalculate the original
<strong>5</strong> and repair the corruption.
</p>
</div>
</div>
<!-- Final Thought Banner -->
<div style="margin-top: 3rem; background: linear-gradient(90deg, rgba(59, 130, 246, 0.1) 0%, rgba(16, 185, 129, 0.1) 100%); padding: 2rem; border-radius: var(--radius); text-align: center; border: 1px solid rgba(255,255,255,0.1);">
<div
style="margin-top: 3rem; background: linear-gradient(90deg, rgba(59, 130, 246, 0.1) 0%, rgba(16, 185, 129, 0.1) 100%); padding: 2rem; border-radius: var(--radius); text-align: center; border: 1px solid rgba(255,255,255,0.1);">
<p style="font-size: 1.25rem; color: var(--text-primary); margin: 0; font-weight: 500;">
"Integrity checksums provide the <strong>Identity</strong> of the error, while Parity provides the <strong>Medicine</strong>. You need both to perform a successful surgery on your data."
"Integrity checksums provide the <strong>Identity</strong> of the error, while Parity provides the
<strong>Medicine</strong>. You need both to perform a successful surgery on your data."
</p>
</div>
</div>
@ -291,6 +344,5 @@
</div>
</footer>
</body>
</html>
</html>

View file

@ -54,8 +54,8 @@ body {
gap: 2rem;
}
.grid-2-cols { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid-3-cols { grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.grid-2-cols { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grid-3-cols { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grid-4-cols { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
/* --- Typography --- */
@ -770,7 +770,7 @@ footer {
.donation-card { border-color: var(--warning); background: rgba(245, 158, 11, 0.05); }
/* UI Gallery */
.ui-gallery { display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: 1rem; margin-top: 2rem; }
.ui-gallery { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1rem; margin-top: 2rem; }
.ui-shot {
border: 1px solid var(--border-color);
border-radius: var(--radius);

View file

@ -85,7 +85,7 @@
<p>Move your management from the terminal to the browser. The integrated Web UI provides a high-fidelity command center that is served natively by the daemon, no complex web server setup required.</p>
</div>
</div>
<div class="ui-shot" data-large="dashboard.png" style="width: 110%; min-height: 450px;">
<div class="ui-shot" data-large="dashboard.png" style="min-height: 450px;">
<img src="dashboard.png" alt="Daemon Dashboard">
<div class="ui-shot-caption">Daemon Dashboard</div>
</div>