{"id":20485,"date":"2026-07-29T02:14:34","date_gmt":"2026-07-29T02:14:34","guid":{"rendered":"https:\/\/www.sandbox.backupassist.com\/blog\/?p=20485"},"modified":"2026-07-29T02:26:14","modified_gmt":"2026-07-29T02:26:14","slug":"ubiquiti-nas-snapshots-against-ransomware-methodology","status":"publish","type":"post","link":"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology","title":{"rendered":"Ubiquiti UNAS \u2014 Experimental testing methodology"},"content":{"rendered":"<p><!-- TITLE (paste into WP Title field): Ubiquiti UNAS \u2014 Experimental testing methodology --><\/p>\n<p><em>Companion document to the <a target=\"_blank\" href=\"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware\">Snapshots for ransomware resilience &#8211; research report<\/a>. It documents the full experimental procedure and screenshot evidence behind that report&#8217;s scorecard, in enough detail to reproduce the tests. Device under test: Ubiquiti UNAS (&#8220;NAS 8TB&#8221;), UniFi Drive. Filesystem: Btrfs on MDADM, RAID1, 7.99 TB pool. Test client: Windows 10. Test tool: <code>nas_snaptest.py<\/code>.<\/em><\/p>\n<p>All tests were run with the test tool (<code>nas_snaptest.py<\/code>) executing <strong>on the Windows client, against the mapped SMB share, using the share-only account<\/strong>. The tool never logs into the NAS. Snapshots are taken, and pool\/drive space is read, from the NAS admin interface at the checkpoints where the tool pauses. This separation is deliberate: the modelled &#8220;attacker&#8221; holds the backup share&#8217;s credentials and nothing else.<\/p>\n<h2 id=\"test-group-1\">Test group 1 \u2014 Device capability exploration &amp; setup<\/h2>\n<h3 id=\"test-1-1\">Test 1.1 \u2014 Test share and baseline configuration<\/h3>\n<p>The test drive <code>Snapshot_Test<\/code> was created in UniFi Drive with the following configuration:<\/p>\n<ul>\n<li><strong>Storage pool:<\/strong> Pool 1 (8 TB, RAID1).<\/li>\n<li><strong>Enforced storage limit:<\/strong> 50 GB. (This becomes the quota used to reach &#8220;full&#8221; quickly.)<\/li>\n<li><strong>Snapshot limit:<\/strong> 64 (the platform default; the field accepts 1\u2013256).<\/li>\n<li><strong>Snapshot schedule:<\/strong> Daily at 12:00 AM for this test (the platform&#8217;s scheduling is finer-grained than &#8220;daily&#8221; suggests \u2014 see the note below).<\/li>\n<li><strong>SMB Trash:<\/strong> initially enabled at creation, <strong>later disabled<\/strong> for the test. This was a deliberate configuration change so that deletes free blocks immediately rather than routing to a recycle area.<\/li>\n<\/ul>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_1.1_add_shared_drive.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Add Shared Drive \u2014 Snapshot_Test, 50 GB enforced limit, snapshot limit 64, daily schedule, SMB Trash<\/figcaption><\/figure>\n<p>Although &#8220;Daily&#8221; is the finest option shown, the platform&#8217;s scheduling is finer-grained still than the label suggests. With Daily, Weekly or Monthly selected, a snapshot can be taken <strong>At<\/strong> a fixed time or <strong>Between<\/strong> a start and end time, and when a window is used an <strong>Interval<\/strong> can be chosen down to <strong>hourly<\/strong> (or every 2, 3, 4, 6, 8 or 12 hours). Snapshots can therefore be scheduled as frequently as once an hour, not merely once a day.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_1.1_schedule_daily.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Schedule set to Daily \u2014 a 12:00 AM to 11:45 PM window with an hourly interval<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_1.1_schedule_monthly.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Schedule set to Monthly \u2014 a day-of-month selector with the same time-window and hourly interval options<\/figcaption><\/figure>\n<p>The pool was nearly empty of <em>our<\/em> test data at the start (~902 GB used of 7.99 TB, from unrelated existing shares such as <code>Linus_Dev_Backup<\/code>). Note: partway through the test campaign, additional unrelated data was added to other shares on the same NAS. From that point on the <strong>pool<\/strong> usage figure is contaminated for our purposes, so later tests rely on the drive&#8217;s own <code>\/ 50 GB<\/code> usage figure and on the snapshot list, both of which are scoped to <code>Snapshot_Test<\/code>.<\/p>\n<h3 id=\"test-1-2\">Test 1.2 \u2014 Creating the share-only account<\/h3>\n<p>UniFi Drive separates two distinct secrets, which is central to the credential-separation question:<\/p>\n<ul>\n<li>The <strong>UniFi account identity<\/strong> (email + UniFi\/SSO login), which grants access to the console and the Drive admin UI, including snapshot controls.<\/li>\n<li>The <strong>File Services &amp; Time Machine credentials<\/strong> \u2014 a separate local username\/password used only for SMB\/Time Machine access to shares.<\/li>\n<\/ul>\n<p>Creating the share-only account is a specific six-step sequence. The password field does not appear on the initial &#8220;Create New User&#8221; form; it is exposed only after enabling <strong>File Services &amp; Time Machine Credentials<\/strong> on the user&#8217;s settings (gear) tab.<\/p>\n<ol>\n<li>\n<p>Open the Users screen and click <strong>Create New<\/strong>.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_1.2_add_user_6.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>User list before creating the test user<\/figcaption><\/figure>\n<\/li>\n<li>\n<p>Fill in the user details and click <strong>Create<\/strong>. Note the File Services &amp; Time Machine Credentials checkbox is not yet enabled at this stage, so there is no password field.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_1.2_add_user_5.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Create New User form \u2014 no password field yet<\/figcaption><\/figure>\n<\/li>\n<li>\n<p>Click the newly created user, then the gear icon, then enable <strong>File Services &amp; Time Machine Credentials<\/strong>.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_1.2_add_user_4.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Enabling File Services &amp; Time Machine Credentials reveals the username\/password fields<\/figcaption><\/figure>\n<\/li>\n<li>\n<p>Enter a fresh username and password. (Username can only contain <code>[a-z] [A-Z] [0-9] . _ -<\/code>, cannot be changed once the profile is created; password is case-sensitive, 12\u201364 characters.)<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_1.2_add_user_1.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Username snapshot_tester and password set<\/figcaption><\/figure>\n<\/li>\n<li>\n<p>Click <strong>Shared Drives<\/strong> and check the drive just created (<code>Snapshot_Test<\/code>), set as <strong>Editor<\/strong>.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_1.2_add_user_2.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Assigning the Snapshot_Test shared drive as Editor<\/figcaption><\/figure>\n<\/li>\n<li>\n<p>Click <strong>Apply Changes<\/strong>.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_1.2_add_user_3.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Final state \u2014 snapshot_tester, Admin unchecked, Editor on Snapshot_Test only<\/figcaption><\/figure>\n<\/li>\n<\/ol>\n<p><strong>Result \u2014 criterion #2 (separate credentials): Yes.<\/strong> The File Services SMB credential (<code>snapshot_tester<\/code>) is a genuinely distinct secret from the UniFi admin login \u2014 not the same identity with different permissions. The account was created with <strong>Admin unchecked<\/strong> and only <strong>Editor<\/strong> rights on the single <code>Snapshot_Test<\/code> drive, matching the threat model of &#8220;the credentials the backup software holds, and nothing more.&#8221;<\/p>\n<p>The share was then mapped from the Windows client to drive letter <code>S:<\/code>:<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_1.3_map_network_drive.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Mapping the network drive with net use, authenticating as snapshot_tester<\/figcaption><\/figure>\n<p>The mapping used the interactive password prompt rather than placing the password on the command line, so the credential is not persisted in shell history \u2014 consistent with the threat model&#8217;s requirement not to store the share credential persistently.<\/p>\n<h2 id=\"test-group-2\">Test group 2 \u2014 Attack &amp; recovery: does the snapshot survive a share-credentials attack?<\/h2>\n<p>This is the central test: it simulates ransomware that has compromised the workstation and reached the mapped backup drive, but does <strong>not<\/strong> hold NAS admin credentials.<\/p>\n<p><strong>Step 1 \u2014 Build the clean dataset and take the clean recovery point.<\/strong><\/p>\n<pre><code>python nas_snaptest.py init --share S:\\snaptest --files 20 --file-size-mib 100<\/code><\/pre>\n<p>The tool wrote 20 \u00d7 100 MiB = 1.95 GiB of incompressible data and built a SHA-256 manifest, then paused at a checkpoint. A manual snapshot was taken on the NAS admin side as the clean recovery point.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_2.1_results.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>init run complete \u2014 20 files written, manifest built, checkpoint reached<\/figcaption><\/figure>\n<p>Baseline figures recorded from the drive panel: usage <strong>2.10 GB \/ 50 GB<\/strong> (the NAS&#8217;s decimal 2.10 GB equals the 1.95 GiB written), <strong>Snapshot Count 1\/64<\/strong>, with no snapshot-exclusive space pinned yet (nothing had changed since the snapshot).<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_2.1_disk_usage.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Drive panel baseline \u2014 2.10 GB \/ 50 GB, snapshot count 1\/64<\/figcaption><\/figure>\n<p><strong>Step 2 \u2014 The attack: overwrite all files over the share.<\/strong><\/p>\n<pre><code>python nas_snaptest.py churn --share S:\\snaptest --percent 100 --no-pause<\/code><\/pre>\n<p>Acting as <code>snapshot_tester<\/code> (share access only), all 20 <code>data_*.bin<\/code> files were overwritten in place with fresh junk \u2014 what ransomware does to a backup set. The client free-space delta was 0.00 B, as expected for in-place overwrite of same-size files; the live backup set is now destroyed.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_2.2_overwrite_results.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>churn complete \u2014 all 20 files overwritten with junk<\/figcaption><\/figure>\n<p>The drive usage panel still showed <strong>2.10 GB \/ 50 GB<\/strong> with the snapshot intact. This is consistent with Btrfs copy-on-write: the overwritten blocks now exist only inside the snapshot (pinned), and that retention is accounted for on the pool rather than against the 50 GB live-data figure.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_2.2_overwrite_disk_usage.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Drive panel after churn \u2014 usage unchanged, snapshot retained<\/figcaption><\/figure>\n<p>The drive&#8217;s snapshot-count tooltip clarifies the count is a global figure (&#8220;2 of 4,096 snapshots used across all drives&#8221;):<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_2.2_snapshot_count_popover.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Snapshot count info popover \u2014 global figure across all drives<\/figcaption><\/figure>\n<p><strong>Step 3 \u2014 Attacker visibility checks (share side only).<\/strong><\/p>\n<ul>\n<li>\n<p><strong>Previous Versions:<\/strong> right-clicking a file \u2192 Properties \u2192 Previous Versions showed <em>no<\/em> versions. UniFi Drive does not expose snapshots to SMB clients via the Windows Previous Versions \/ VSS shadow-copy interface, so the client-side &#8220;restore previous version&#8221; path some ransomware targets does not exist here.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_2.2_snapshot_is_invisible_to_attacker.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Previous Versions tab \u2014 &#8220;There are no previous versions available&#8221;<\/figcaption><\/figure>\n<\/li>\n<li>\n<p><strong>Hidden snapshot directory:<\/strong> <code>dir \/a<\/code> (which lists hidden and system entries) on <code>S:\\snaptest<\/code> showed only the 20 <code>data_*.bin<\/code> files and <code>_manifest.csv<\/code> \u2014 no <code>~snapshot<\/code> \/ <code>#snapshot<\/code> directory exposed over SMB.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_2.2_no_hidden_files_in_directory.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>dir \/a on the share \u2014 no hidden snapshot folder present<\/figcaption><\/figure>\n<\/li>\n<\/ul>\n<p>The attacker, holding only the share credential, could neither see nor enumerate nor reach the snapshots.<\/p>\n<p><strong>Step 4 \u2014 Restore from the NAS admin side.<\/strong><\/p>\n<p>From the admin snapshot browser, the snapshot can be navigated into and inspected. The options offered are <strong>Lock<\/strong>, <strong>Restore<\/strong>, and (for individual files) <strong>Download<\/strong> \/ <strong>Delete<\/strong>.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_2.3_options_in_NAS_admin_console.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Snapshot browser \u2014 Lock \/ Restore \/ Delete options on the clean snapshot<\/figcaption><\/figure>\n<p>Navigating into the snapshot confirmed it held the clean dataset: 21 files (20 data + manifest), each with the original pre-attack modified time, owner shown as &#8220;Snapshot Tester&#8221;.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_2.3_correct_file_times_on_snapshots.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Inside the snapshot \u2014 clean file times confirm it predates the attack<\/figcaption><\/figure>\n<p>Clicking <strong>Restore<\/strong> produced a clear, descriptive confirmation dialog: &#8220;This past version of the data will replace the current version in UniFi Drive. To restore a specific file, please select individual files and restore them.&#8221; The dialog also offers an optional &#8220;Create a current snapshot of the drive before restoration&#8221; safety net, and warns that file operations may fail while the drive is being restored.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_2.3_what_restore_does.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Restore confirmation dialog \u2014 whole-drive rollback, selective-file alternative, pre-restore snapshot option<\/figcaption><\/figure>\n<p>This establishes the UNAS restore model:<\/p>\n<ul>\n<li><strong>Restore<\/strong> = whole-drive rollback (destructive to the current\/live state).<\/li>\n<li><strong>Download<\/strong> = non-destructive per-file pull through the browser. Practical for a few small files, but impractical for backup-scale image files (e.g. multi-hundred-GB VHDX), where pulling data back through a browser tab is not viable. For real backup recovery, whole-drive Restore is the realistic path. (This is distinct from criterion #6, which asks specifically whether a snapshot can be <em>mounted as a share<\/em> for a backup product to recover against \u2014 which the UNAS does not offer.)<\/li>\n<\/ul>\n<p>The restore completed and reported success:<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_2.3_snapshot_restored.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Restore completed notification<\/figcaption><\/figure>\n<p><strong>Step 5 \u2014 Verify the recovery is byte-perfect.<\/strong><\/p>\n<pre><code>python nas_snaptest.py verify --share S:\\snaptest<\/code><\/pre>\n<pre><code>[verify] matched=20  changed=0  missing=0\n[verify] PASS - restored dataset is identical to the clean original.<\/code><\/pre>\n<p>All 20 files matched their original SHA-256 hashes, and an independent <code>dir \/a<\/code> showed every file back at its clean pre-attack timestamp.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_2.3_successful.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>verify PASS \u2014 20 matched, 0 changed, 0 missing; dir confirms clean file times<\/figcaption><\/figure>\n<p><strong>Result \u2014 Test group 2: PASS (criterion #3: Yes).<\/strong> A share-only attacker destroyed the live backup set, could not see or touch the snapshot, and the snapshot fully recovered the clean data byte-for-byte from the admin side.<\/p>\n<h2 id=\"test-group-3\">Test group 3 \u2014 Snapshot lock behaviour<\/h2>\n<p>Having confirmed snapshots survive a share-only attacker, the next question is whether they can be protected from automatic deletion and from an administrator. UniFi Drive offers a per-snapshot <strong>Lock<\/strong>.<\/p>\n<p><strong>No scheduled \/ policy lock.<\/strong> The drive&#8217;s snapshot settings panel exposes Snapshot Limit, Schedule, Time, Create a Snapshot, and Delete All Snapshots \u2014 but no option to lock new snapshots automatically or apply a retention-lock policy.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_3.1_no_scheduled_lock_option.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Snapshot settings panel \u2014 no scheduled\/automatic lock option<\/figcaption><\/figure>\n<p><strong>Lock is manual and per-snapshot,<\/strong> applied via the <strong>Lock<\/strong> link in the snapshot browser.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_3.2_manual_lock_per_snapshot_1.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Per-snapshot Lock link in the snapshot browser<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_3.2_manual_lock_per_snapshot_2.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>A locked snapshot shown with the padlock icon in the snapshot dropdown<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_3.3_snapshot_list.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Snapshot list showing locked vs unlocked snapshots<\/figcaption><\/figure>\n<p><strong>Lock is one-click reversible.<\/strong> A locked snapshot offers an immediate <strong>Unlock<\/strong> action, so an administrator can remove the lock instantly.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_3.4_unlock_action.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>A locked snapshot showing the one-click Unlock action<\/figcaption><\/figure>\n<p><strong>Lock protects against ordinary &#8220;Delete All,&#8221; but is overridable.<\/strong> A fresh snapshot was created and locked.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_3.5_create_snapshot.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Creating a new snapshot to test lock behaviour<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_3.6_lock_snapshot.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>The new snapshot, locked<\/figcaption><\/figure>\n<p>The &#8220;Delete All Snapshots&#8221; dialog includes an <strong>&#8220;Include Locked Snapshots&#8221;<\/strong> checkbox. Deleting without ticking it removed only the unlocked snapshots and left the locked one in place; ticking it would remove locked snapshots as well.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_3.7_delete_all_options.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Delete All Snapshots dialog with the &#8220;Include Locked Snapshots&#8221; checkbox<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_3.9_only_locked_remains.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>After deleting unlocked snapshots, only the locked one remains<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_3.8_delete_all_behaviour.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Delete All behaviour<\/figcaption><\/figure>\n<p><strong>Result \u2014 Lock characterisation:<\/strong><\/p>\n<ul>\n<li><strong>Criterion #7 (lockable against automatic deletion): Yes<\/strong> \u2014 confirmed further in Test group 6 below.<\/li>\n<li><strong>Criterion #8 (locking automatable \/ scheduled): No<\/strong> \u2014 manual, per-snapshot only; scheduled snapshots are always created unlocked.<\/li>\n<li><strong>Criterion #4 (safe from administrator): No<\/strong> \u2014 Lock is one-click reversible (Unlock) and bypassable via &#8220;Delete All \u2192 Include Locked Snapshots.&#8221; Lock is a guard against the NAS&#8217;s own automatic maintenance, not a guarantee of immutability against a deliberate administrator.<\/li>\n<li><strong>Criterion #5 (fixed immutability period): No<\/strong> \u2014 Lock has no time-bound retention window or expiry.<\/li>\n<\/ul>\n<h2 id=\"test-group-4\">Test group 4 \u2014 Throughput with snapshots (write and churn)<\/h2>\n<p><strong>Internal (on-NAS) measurements.<\/strong> The question is whether enabling snapshots, and accumulating a deep history, slows the NAS. This was tested directly on the NAS (writes issued locally over SSH), which removes network variability and isolates the filesystem behaviour. Every write was <code>fsync<\/code>&#8216;d so the reported rate reflects data committed to the pool, not data cached in RAM \u2014 verified independently with <code>iostat<\/code>, which showed ~250 MB\/s genuinely reaching both mirror disks during a large write, ruling out cache inflation.<\/p>\n<p>Two write patterns were measured, because they exercise different paths:<\/p>\n<ul>\n<li><strong>Fresh write<\/strong> \u2014 new data into free space, no copy-on-write contention.<\/li>\n<li><strong>Churn<\/strong> \u2014 overwrite-in-place of an existing 32 GiB dataset. This triggers copy-on-write against any snapshot sharing those blocks, and is the worst case for snapshot overhead.<\/li>\n<\/ul>\n<p>Three states were compared: (1) snapshot feature <strong>off<\/strong>; (2) feature <strong>on, zero snapshots<\/strong>; (3) feature <strong>on<\/strong>, taking a snapshot after each churn to build depth from 0 to 12.<\/p>\n<p><strong>Findings:<\/strong><\/p>\n<ul>\n<li><strong>Fresh writes show no penalty.<\/strong> Feature-off vs. feature-on (zero snapshots) write throughput were indistinguishable within run-to-run noise.<\/li>\n<li><strong>Churn with deep history plateaus, and does not degrade with depth.<\/strong> Two independent 12-round depth sweeps both settled at <strong>~153\u2013156 MiB\/s<\/strong> once a handful of snapshots existed, and the rate was flat from ~5 snapshots through 12. The two runs agreed to within ~1 MiB\/s at every depth \u22655. Twelve snapshots churn no slower than five \u2014 the common belief that Btrfs slows down as snapshots accumulate did not occur on this NAS.<\/li>\n<\/ul>\n<table>\n<thead>\n<tr>\n<th>Snapshot depth<\/th>\n<th>Run 1 (MiB\/s)<\/th>\n<th>Run 2 (MiB\/s)<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>0\u20134 (early, noisy)<\/td>\n<td>176, 128, 156, 225, 181<\/td>\n<td>226, 228, 187, 159, 158<\/td>\n<\/tr>\n<tr>\n<td>5\u201311 (settled)<\/td>\n<td>156, 157, 155, 155, 155, 152, 154<\/td>\n<td>157, 156, 156, 154, 153, 152, 153<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<ul>\n<li><strong>The early-round scatter is background NAS activity, not a snapshot effect.<\/strong> The two runs disagree wildly at low depth (depth 1: 128 vs. 228) but converge from depth 5 on. An <code>iostat<\/code> capture during run 2 caught the cause: a one-off ~32 GiB sequential read burst (disks pinned at ~280 MB\/s for ~2 minutes) from an unrelated background task, which landed on that run&#8217;s initial write phase. In run 1 an equivalent background task evidently landed on an early churn instead. Because the disturbance falls at a different point each run, it shows up as non-reproducible early scatter \u2014 it is not tied to snapshot depth. (An earlier single-run reading of a &#8220;~12% step at the first snapshot&#8221; did <strong>not<\/strong> survive this re-run and was retracted.)<\/li>\n<li><strong>Any steady-state penalty vs. no-snapshots is modest and within noise.<\/strong> No-snapshot churn measured 172\u2013226 MiB\/s across trials; the with-snapshot plateau (~155) sits at or just below that band. A small penalty (\u227215%) is plausible but cannot be pinned precisely, because the run-to-run variance is dominated by the NAS&#8217;s own background I\/O rather than by snapshots.<\/li>\n<\/ul>\n<p><strong>Baseline throughput is bursty even without snapshots.<\/strong> Each file is written with an <code>fsync<\/code>, so the write blocks until the NAS confirms the data is durably on disk. Over SMB this produces a sawtooth: each file streams at close to line rate, then the send rate drops to near zero during the per-file commit round-trip before the next file starts, so the effective average sits well below the ~1 Gbps peaks. This cadence is a property of the durable write pattern \u2014 present with or without snapshots \u2014 and is distinct from the run-to-run background variability discussed above.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_4.1_throughput_without_snapshots.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Client-side (over-SMB) send throughput during a no-snapshot baseline write. The rate sawtooths between near-line-rate bursts (~1 Gbps peaks), while a file streams to the NAS, and brief stalls toward zero at each per-file <code>fsync<\/code>, where the client waits for the NAS to commit that file to disk before the next begins.<\/figcaption><\/figure>\n<p><strong>Mechanism note.<\/strong> <code>btrfs qgroup show<\/code> confirmed the drive&#8217;s storage limit is enforced via flat, per-subvolume qgroups (level <code>0\/N<\/code>, no parent\/child rollup). There is no hierarchical accounting that would grow more expensive as snapshots accumulate \u2014 consistent with the observed flat-with-depth throughput. Each 100%-churn snapshot pins a full 32 GiB of exclusive retention on the pool, matching the space model in Test group 5.<\/p>\n<p><strong>Verdict (criterion #1): Yes.<\/strong> Enabling snapshots imposes no meaningful slowdown: fresh writes are unaffected, overwrite-heavy churn takes at most a modest bounded penalty, and \u2014 the property that matters for a backup target accumulating history \u2014 throughput does not degrade as snapshot count grows. The largest source of throughput variation on this NAS is its own background maintenance, not snapshots.<\/p>\n<p><em>Scope note: these are internal measurements that isolate filesystem behaviour from the network. The over-SMB rate a backup product actually sees is network-bound: the pool-flood test (Test group 7) confirmed a sustained ~117 MB\/s writing large incompressible files over gigabit ethernet \u2014 comfortably below the ~155 MiB\/s internal churn plateau, meaning the network is the limit and any snapshot overhead is fully masked in practice.<\/em><\/p>\n<h2 id=\"test-group-5\">Test group 5 \u2014 Foundational space-model tests<\/h2>\n<h3 id=\"test-5-1\">Test 5.1 \u2014 Natural space pressure (fill to full)<\/h3>\n<p>The drive was filled with junk (no churn) until writes failed, to observe behaviour as the drive reaches its limit.<\/p>\n<pre><code>python nas_snaptest.py fill --share S:\\snaptest --yes<\/code><\/pre>\n<p>The fill proceeded until the write failed with <code>[Errno 28] No space left on device<\/code> at ~50 GB of live data. The NAS <strong>refused the write<\/strong> rather than deleting anything.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.1_after_command_line.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>fill command \u2014 WRITE FAILED, No space left on device at ~50 GB<\/figcaption><\/figure>\n<p>The drive had filled to its <strong>50 GB enforced limit<\/strong> (49,999,513,400 bytes of live data), while the underlying <strong>pool had terabytes free<\/strong> (~902 GB \/ 7.99 TB used). The 50 GB drive quota \u2014 not the pool \u2014 is the effective limit.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.1_after_NAS_disk_usage.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Pool usage during fill \u2014 pool nowhere near full while the 50 GB drive quota was reached<\/figcaption><\/figure>\n<p>The snapshots present before the fill were still present afterward (the count did not drop). Note, however, that this fill only <em>added<\/em> files; it did not overwrite or delete anything, so the pre-fill snapshots pinned no exclusive blocks and there was no space to be reclaimed by deleting them. This run therefore confirms the <strong>50 GB quota is the effective limit and writes fail safely at it<\/strong>, but it does not by itself test snapshot auto-deletion.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.1_after_snapshots_available.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Snapshots still present after the fill<\/figcaption><\/figure>\n<h3 id=\"test-5-2-5-3\">Test 5.2\u20135.3 \u2014 Where does snapshot retention live? (delete and write tests)<\/h3>\n<p>To locate snapshot retention (against the 50 GB drive quota, or on the 8 TB pool), a snapshot was taken of the drive in its ~50 GB-full state (pinning all the fill data), and then all fill files were deleted from the share.<\/p>\n<pre><code>del *      (on S:\\snaptest)<\/code><\/pre>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.2_after_command_line.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Deleting all fill files from the share; dir then shows the share empty<\/figcaption><\/figure>\n<p>Immediately after the delete, the share reported almost no free space. <strong>This was the NAS taking time to update its space bookkeeping<\/strong> \u2014 the figure had not yet refreshed.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.2_after_snapshots_available.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Snapshot list after the delete<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.2_NAS_disk_usage.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Pool usage view during the delete test<\/figcaption><\/figure>\n<p>After waiting a few minutes, a fresh 2 GB dataset was written to confirm the true state:<\/p>\n<pre><code>python nas_snaptest.py init --share S:\\snaptest --files 20 --file-size-mib 100<\/code><\/pre>\n<p>The write <strong>succeeded<\/strong>, and the drive then reported ~48 GB free (50 GB less the ~2 GB just written). The NAS had completed its bookkeeping and returned the ~50 GB of space.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.3_after_command_line.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Write succeeded; ~48 GB free reported on the share<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.3_after_NAS_disk_usage.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Drive panel after the write \u2014 space returned<\/figcaption><\/figure>\n<p><strong>Result.<\/strong> Snapshot-exclusive retention does <strong>not<\/strong> count against the 50 GB drive quota \u2014 it is counted against the 8 TB pool. The snapshot taken while the drive held ~50 GB of (subsequently deleted) fill data pinned that data on the pool, yet the drive&#8217;s 50 GB allowance was fully returned for live use. The 50 GB quota governs <strong>live referenced data<\/strong>; copy-on-write retention accrues on the <strong>pool<\/strong>.<\/p>\n<p>A new clean recovery-point snapshot (09:58) was then taken of the fresh dataset for the subsequent tests, deliberately left <strong>unlocked<\/strong>.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.3_after_created_snapshot.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>New clean recovery-point snapshot created (09:58)<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.3_after_new_snapshots_available.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Snapshot list including the new clean recovery point<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.3_after_snapshots_available.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Snapshot list state<\/figcaption><\/figure>\n<h3 id=\"test-5-4-5-5\">Test 5.4\u20135.5 \u2014 Churn rounds: space cost of churn, and where it lands<\/h3>\n<p>Two full-dataset churn rounds were run, taking a snapshot after each, to measure the space cost of churn and confirm where churn retention is counted.<\/p>\n<p><strong>Round 1 (Test 5.4):<\/strong><\/p>\n<pre><code>python nas_snaptest.py churn --share S:\\snaptest --percent 100 --csv tD_churn.csv<\/code><\/pre>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.4_after_command_line.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Churn round 1 command output<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.4_after_take_snapshot.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Snapshot created after churn round 1<\/figcaption><\/figure>\n<p>After the churn and snapshot: drive usage <strong>2.10 GB \/ 50 GB (unchanged)<\/strong>, pool <strong>up ~2.1 GB<\/strong>, snapshot count incremented.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.4_after_NAS_drive_usage.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Drive usage after churn round 1 \u2014 unchanged at 2.10 GB \/ 50 GB<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.4_after_NAS_disk_usage.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Pool usage after churn round 1 \u2014 up ~2.1 GB<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.4_after_new_snapshots_available.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Snapshot list after churn round 1<\/figcaption><\/figure>\n<p><strong>Round 2 (Test 5.5):<\/strong> same command. Drive usage again <strong>2.10 GB \/ 50 GB unchanged<\/strong>; pool again <strong>+~2.1 GB<\/strong>.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.5_after_command_line.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Churn round 2 command output<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.5_after_take_snapshot.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Snapshot created after churn round 2<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.5_after_NAS_drive_usage.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Drive usage after churn round 2 \u2014 still 2.10 GB \/ 50 GB<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.5_after_NAS_disk_usage.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Pool usage after churn round 2 \u2014 up another ~2.1 GB<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_5.5_after_new_snapshots_available.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Snapshot list after churn round 2<\/figcaption><\/figure>\n<p><strong>Result (Test 5.4\u20135.5 figure).<\/strong> A full-dataset churn (overwriting ~1.95 GiB in place) snapshotted costs <strong>~2.1 GB of pool retention per round<\/strong>, with the drive&#8217;s live-data figure staying constant. Churn retention is counted against the pool, exactly as deletion retention is (Test 5.2\u20135.3). Consequently, the drive&#8217;s 50 GB quota can never accumulate snapshot-exclusive blocks and therefore can never itself trigger snapshot deletion.<\/p>\n<h2 id=\"test-group-6\">Test group 6 \u2014 Snapshot-cap deletion and whether Lock is enforced<\/h2>\n<p>Because the snapshot limit is a per-drive setting (1\u2013256), deletion can be triggered cheaply by the <strong>snapshot count limit<\/strong> rather than by space. Starting from 6 snapshots (two of which were locked: the original 8:20 PM, and a second one locked mid-test at 10:09 AM), the limit was lowered step by step and the snapshot list observed.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_6.1_original.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Starting state for the reduction test<\/figcaption><\/figure>\n<p>Setting the limit to 7 (above the current count) confirmed no existing snapshot is removed when the limit is merely set above the count:<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_6.2_7_snapshots.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Limit set to 7 \u2014 count 6\/7, nothing removed<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_6.3_6_snapshots.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>6\/6 state<\/figcaption><\/figure>\n<p>Lowering the limit below the current count triggers a confirmation that names the behaviour explicitly: <strong>&#8220;1 of your oldest unlocked snapshots will be deleted to meet the new limit.&#8221;<\/strong><\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_6.4_reduce_to_5_snapshots.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Reduce-to-5 confirmation \u2014 &#8220;oldest unlocked snapshots will be deleted&#8221;<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_6.5_5_snapshots.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>5 snapshots remaining<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_6.6_4_snapshots.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>4 snapshots remaining<\/figcaption><\/figure>\n<p>A second snapshot was locked partway through to observe its behaviour under continued reduction:<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_6.7_lock_another_snapshot.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Locking a second snapshot during the reduction<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_6.8_reduce_to_3_snapshots.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Reduce-to-3 step<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_6.9_3_snapshots.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>3 snapshots remaining<\/figcaption><\/figure>\n<p>When the reduction reached the point where only locked snapshots remained as the oldest, the NAS <strong>could not honour the limit<\/strong>: it displayed a <strong>3\/2<\/strong> state (count exceeding the limit) with the warning &#8220;You&#8217;ve reached the maximum number of snapshots, and all existing snapshots are locked and cannot be overwritten.&#8221; The NAS sits <em>over<\/em> its configured limit rather than auto-delete a locked snapshot.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_6.10_reduce_to_2_snapshots.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Reduce-to-2 attempt<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_6.11_2_snapshots.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>3\/2 over-limit state \u2014 locked snapshots cannot be auto-deleted to meet the limit<\/figcaption><\/figure>\n<p><strong>Result \u2014 cap deletion and whether Lock is enforced:<\/strong><\/p>\n<ul>\n<li>Cap-driven deletion is <strong>oldest-unlocked-first<\/strong>, and it is <strong>clearly announced<\/strong> in the UI (the warning pre-announces &#8220;The oldest snapshot and excess versions will be deleted when a new one is created&#8221;). This is genuine oldest-first automatic deletion \u2014 the &#8220;dangerous default&#8221; behaviour \u2014 but it only ever touches <strong>unlocked<\/strong> snapshots, and it is not silent.<\/li>\n<li><strong>Lock is effective against automatic\/cap deletion (criterion #7: Yes).<\/strong> The NAS will sit over its own limit rather than auto-delete a locked snapshot.<\/li>\n<li>The clean recovery-point snapshot (09:58) used earlier was <strong>never locked<\/strong>, and was therefore correctly deleted as an oldest-unlocked snapshot during the reduction \u2014 confirming the deletion order and that unlocked snapshots are always vulnerable to automatic deletion.<\/li>\n<\/ul>\n<p>The combination of Test group 3 and Test group 6 gives the precise Lock verdict:<\/p>\n<table>\n<thead>\n<tr>\n<th>Threat to the snapshot<\/th>\n<th>Does Lock protect it?<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Automatic deletion to honour the snapshot count limit (cap deletion)<\/td>\n<td><strong>Yes<\/strong> \u2014 box refuses, sits over-limit rather than delete a locked snapshot<\/td>\n<\/tr>\n<tr>\n<td>The NAS auto-deleting under pool space pressure<\/td>\n<td><strong>Yes (moot)<\/strong> \u2014 pool pressure deletes <em>neither<\/em> locked nor unlocked snapshots; the NAS refuses writes instead (see Test group 7)<\/td>\n<\/tr>\n<tr>\n<td>A deliberate administrator action (Unlock, or Delete All \u2192 Include Locked)<\/td>\n<td><strong>No<\/strong> \u2014 one click \/ one checkbox defeats it<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2 id=\"test-group-7\">Test group 7 \u2014 Pool-flood snapshot deletion (criterion #9)<\/h2>\n<p>The question is whether filling the pool via a <em>different<\/em> share deletes snapshots on <code>Snapshot_Test<\/code>. This is the self-inflicted scenario: an operational accident (or a second compromised share) consuming pool space until another drive&#8217;s snapshots are deleted unintentionally.<\/p>\n<p><strong>Precondition setup.<\/strong> <code>Snapshot_Test<\/code> was reconfigured with a 105 GB quota and a 64-snapshot limit. A 97 GiB dataset was written to the drive (the <code>init<\/code> run was interrupted by the quota limit at ~97 files rather than 100 \u2014 the partial file was deleted and the interrupted manifest noted). Two tracer snapshots were then established:<\/p>\n<ul>\n<li><strong>Locked tracer<\/strong> \u2014 taken immediately after the initial write (Jul 6, 11:40 AM). This is the control: if pool pressure deletes locked snapshots, that would be new information for the Lock verdict table (Test group 6).<\/li>\n<li><strong>Unlocked tracer<\/strong> \u2014 taken after a full 97 GiB churn round (Jul 6, 12:27 PM). This is the at-risk tracer: the decisive question is whether pool pressure deletes unlocked snapshots.<\/li>\n<\/ul>\n<p>At this point the pool stood at <strong>7.11 TB \/ 7.99 TB<\/strong> (~880 GB free). A third churn round was attempted to produce a second unlocked tracer, but the pool was already tight enough that the snapshot creation failed (&#8220;We were unable to create a snapshot of Snapshot_Test. Please try again later&#8221;) \u2014 the NAS had insufficient pool metadata space to commit a new snapshot. The two existing tracers were unaffected. This failure is itself a finding: at high pool pressure the NAS <strong>refuses to create new snapshots rather than deleting existing ones<\/strong>.<\/p>\n<p>This failure was also <strong>silent<\/strong>. With no category or event filter applied, the event log recorded the surrounding activity at the time \u2014 snapshot creations, a <em>Shared Drive Almost Full<\/em> warning for <code>Snapshot_Test<\/code> (104 GB \/ 105 GB), and a <em>Storage Pool Almost Full<\/em> warning \u2014 but <strong>no <em>Snapshot Creation Failed<\/em> entry<\/strong> for the failed attempt itself. The only indication was the transient on-screen toast; nothing in the log identifies the snapshot as having failed. (Both this failure point and its logging are revisited in Test group 8, where snapshot creation instead succeeded at far lower free space \u2014 so the ~880 GB \/ ~11% figure here is best read as a one-off observation rather than a reliable threshold.)<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_setup_snapshot_failure_not_logged.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Event log spanning the failed snapshot \u2014 surrounding pool and snapshot activity is recorded, with no &#8220;Snapshot Creation Failed&#8221; entry for the failed attempt<\/figcaption><\/figure>\n<p><strong>Setup evidence.<\/strong> The 97 GiB precondition dataset was written across three rounds (the 105 GB quota interrupts each pass), with pool, drive-usage and snapshot-list checkpoints captured after each:<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_initial_state_NAS.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Starting state \u2014 NAS dashboard before reconfiguring Snapshot_Test<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_initial_state_Snapshot_Test_drive.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Starting state \u2014 Snapshot_Test drive before the test<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_precondition_no_snapshots.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Precondition \u2014 Snapshot_Test reconfigured to a 105 GB quota, no snapshots yet<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_precondition_empty_drive.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Precondition \u2014 Snapshot_Test drive empty at the new quota<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_setup_round_1_write.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Round 1 \u2014 writing the dataset over SMB<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_setup_out_of_space_post_round_1.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Round 1 \u2014 write halted at the 105 GB quota limit (out of space)<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_setup_NAS_storage_usage_post_round_1.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Post round 1 \u2014 NAS storage usage<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_setup_Snapshot_Test_snapshots_post_round_1.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Post round 1 \u2014 Snapshot_Test snapshot list (locked tracer taken 11:40 AM)<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_setup_Snapshot_Test_usage_post_round_1.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Post round 1 \u2014 Snapshot_Test drive usage<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_setup_churn_post_round_2.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Post round 2 \u2014 churn round complete<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_setup_NAS_storage_usage_post_round_2.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Post round 2 \u2014 NAS storage usage<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_setup_Snapshot_Test_snapshots_post_round_2.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Post round 2 \u2014 Snapshot_Test snapshot list (unlocked tracer taken 12:27 PM)<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_setup_Snapshot_Test_usage_post_round_2.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Post round 2 \u2014 Snapshot_Test drive usage<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_setup_churn_post_round_3.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Post round 3 \u2014 churn round complete<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_setup_NAS_storage_usage_post_round_3.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Post round 3 \u2014 NAS storage usage<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_setup_unable_to_take_snapshot.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Third snapshot attempt failed \u2014 &#8220;unable to create a snapshot&#8221; at high pool pressure<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_setup_log_message.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Log event \u2014 &#8220;Storage Pool 1 is 7.19 TB of 7.99 TB and almost full&#8221;<\/figcaption><\/figure>\n<p><strong>The flood.<\/strong> The share <code>Fill_Me_Up<\/code> (no quota, no snapshots) was mapped from the Windows client and flooded using <code>nas_snaptest.py fill --chunk-mib 1024 --stop-free-mib 51200<\/code>. The flood was run <strong>over SMB<\/strong> (share credentials only, consistent with the threat model) and wrote at a sustained ~117 MB\/s, consuming ~680 GiB over approximately 1 hour 45 minutes. The pool was driven to <strong>7.96 TB \/ 7.99 TB<\/strong> (~30 GB free) at the stop threshold.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_flood_other_share_in_progress_1.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Cross-drive flood in progress \u2014 writing 1 GiB chunks to Fill_Me_Up over SMB<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_flood_other_share_in_progress_but_screenshot_taken_well_after.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Flood run \u2014 client view (screenshot taken well after the run began)<\/figcaption><\/figure>\n<p>Both tracer snapshots on <code>Snapshot_Test<\/code> were checked at the stop point and after an overnight period: both remained intact. The NAS surfaced a <em>&#8220;Storage Pool 1 is almost full&#8221;<\/em> log event during the flood, and the <code>Snapshot_Test<\/code> drive panel continued to display the &#8220;approaching storage limit&#8221; advisory \u2014 but no automatic snapshot deletion occurred.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_after_flood_NAS_storage_usage.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>After the flood \u2014 NAS storage usage (~30 GB free)<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_after_flood_Snapshot_Test_usage.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>After the flood \u2014 Snapshot_Test drive usage unchanged<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_after_flood_Snapshot_Test_snapshots.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>After the flood \u2014 both tracer snapshots still present on Snapshot_Test<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_after_flood_full_dashboard.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>After the flood \u2014 full NAS dashboard<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_after_flood_command_line.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>After the flood \u2014 command-line view<\/figcaption><\/figure>\n<p><strong>Driving to absolute full.<\/strong> A second flood run (<code>fill<\/code> with no <code>--stop-free-mib<\/code> threshold) was then run against a new subdirectory on <code>Fill_Me_Up<\/code>, driving the pool to <strong>65.5 KB free<\/strong> \u2014 effectively zero. The fill script wrote 34 \u00d7 1 GiB chunks before failing with <code>[Errno 28] No space left on device<\/code>. The failure took 5\u201310 minutes to propagate back to the client, consistent with Btrfs stalling internally when it has exhausted metadata space. The dashboard confirmed <strong>7.99 TB \/ 7.99 TB<\/strong> with 65.5 KB available.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_max_flood_in_progress_NAS_dashboard.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Second flood in progress \u2014 NAS dashboard approaching absolute full<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_max_flood_in_progress_client_machine.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Second flood in progress \u2014 client machine writing chunks<\/figcaption><\/figure>\n<p>At absolute pool full, both tracer snapshots on <code>Snapshot_Test<\/code> remained present and intact:<\/p>\n<ul>\n<li>Jul 6, 12:27 PM \u2014 <strong>unlocked<\/strong> \u2014 present \u2713<\/li>\n<li>Jul 6, 11:40 AM \u2014 <strong>locked<\/strong> \u2014 present \u2713<\/li>\n<li>Snapshot Count: <strong>2\/64<\/strong> \u2014 unchanged \u2713<\/li>\n<li>Drive usage: <strong>104.15 GB \/ 105 GB<\/strong> \u2014 unchanged \u2713<\/li>\n<\/ul>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_max_flood_complete_NAS_dashboard.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>At absolute pool full \u2014 NAS dashboard (65.5 KB free)<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_max_flood_complete_Snapshot_Test.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>At absolute pool full \u2014 Snapshot_Test with both tracers intact, 2\/64<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_max_flood_complete_client_machine.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>At absolute pool full \u2014 client machine<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_max_flood_complete_client_failed.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Fill script failed with [Errno 28] No space left on device<\/figcaption><\/figure>\n<p><strong>Snapshot integrity verification.<\/strong> With the pool at absolute full, <code>data_00000.bin<\/code> was downloaded from each snapshot and the current version via the admin UI and hashed with <code>certutil -hashfile<\/code>. All three SHA1 hashes were distinct, confirming each snapshot genuinely preserves a different point-in-time version of the data rather than sharing blocks:<\/p>\n<table>\n<thead>\n<tr>\n<th>Version<\/th>\n<th>SHA1<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Current (post-churn)<\/td>\n<td><code>3eaacf97c4f92093f31e393d9cec38f7a5bb8994<\/code><\/td>\n<\/tr>\n<tr>\n<td>11:40 AM snapshot (locked, original)<\/td>\n<td><code>de40ebb7c486ab713100cdf9a42af668c8e95b88<\/code><\/td>\n<\/tr>\n<tr>\n<td>12:27 PM snapshot (unlocked, post-churn)<\/td>\n<td><code>3d1ab43ed5d4f750886012d12cb422a005bb7449<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The admin UI remained responsive throughout, with no sluggishness observed at 65.5 KB free.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_verify_download_snapshots.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Downloading data_00000.bin from each snapshot for hashing<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.1_verify_checksum_snapshots.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>SHA1 checksums of the three versions \u2014 all distinct<\/figcaption><\/figure>\n<p><strong>Same-share churn flood.<\/strong> To confirm the finding holds when the pressure originates from the backup share itself \u2014 the more direct attacker path \u2014 a further test was run. <code>Snapshot_Test<\/code> was restored to the Jul 6, 12:27 PM snapshot (returning ~100 GB of pool space), an additional 50 GB was written to <code>Fill_Me_Up<\/code> to tighten the pool back to ~104 GB free, and both tracer snapshots were confirmed present:<\/p>\n<ul>\n<li>Jul 6, 2026 at 12:27 PM \u2014 <strong>unlocked<\/strong> \u2713<\/li>\n<li>Jul 6, 2026 at 11:40 AM \u2014 <strong>locked<\/strong> \u2713<\/li>\n<\/ul>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.2_full_storage.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Test 7.2 start \u2014 pool at absolute full (7.99\/7.99 TB, 65.5 KB free), carried over from Test 7.1<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.2_restore_to_snapshot_confirmation.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Restore confirmation \u2014 rolling Snapshot_Test back to the 12:27 PM snapshot<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.2_restore_to_snapshot_complete.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Restore complete \u2014 Snapshot_Test view<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.2_restore_to_snapshot_complete_NAS_dashboard.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Restore complete \u2014 NAS dashboard, ~100 GB of pool space returned<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.2_setup_50GB_left_on_NAS.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Tightening the pool \u2014 50 GB left on the NAS after topping up Fill_Me_Up<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.2_setup_writing_50GB.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Writing the additional 50 GB to Fill_Me_Up<\/figcaption><\/figure>\n<p>A full 100% churn of the 97 GiB dataset was then run against <code>Snapshot_Test<\/code> via SMB (share credentials only). With only ~104 GB of pool headroom, each GiB of in-place overwrite pins a further GiB of copy-on-write retention on the pool; the churn was expected to exhaust the pool at roughly the halfway point. The churn failed mid-run with <code>OSError: [Errno 28] No space left on device<\/code>, driving the pool to <strong>7.99 TB \/ 7.99 TB<\/strong> (65.5 KB available) \u2014 absolute full. Both tracer snapshots remained intact:<\/p>\n<ul>\n<li>Jul 6, 2026 at 12:27 PM \u2014 <strong>unlocked<\/strong> \u2014 present \u2713<\/li>\n<li>Jul 6, 2026 at 11:40 AM \u2014 <strong>locked<\/strong> \u2014 present \u2713<\/li>\n<li>Snapshot Count: <strong>2\/64<\/strong> \u2014 unchanged \u2713<\/li>\n<li>Drive usage: <strong>103.38 GB \/ 105 GB<\/strong> (slight reduction reflecting the partial churn before failure) \u2713<\/li>\n<\/ul>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.2_churn_main_share_until_out_of_space.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Same-share churn driven until the pool is out of space<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.2_after_complete_NAS_dashboard.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>After the same-share churn flood \u2014 NAS dashboard<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_7.2_after_complete_Snapshot_Test_snapshots.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>After the same-share churn flood \u2014 both tracers still present on Snapshot_Test<\/figcaption><\/figure>\n<p><strong>Result \u2014 criterion #9: Yes \u2014 confirmed under all conditions.<\/strong> Neither cross-drive flooding nor same-share churn flooding deletes snapshots, even at absolute pool full. The NAS&#8217;s response to pool exhaustion is consistent: refuse new writes rather than delete existing snapshots. This is the safe failure mode, and it holds regardless of which share is the source of pressure.<\/p>\n<p>The Lock verdict table from Test group 6 can now be completed:<\/p>\n<table>\n<thead>\n<tr>\n<th>Threat to the snapshot<\/th>\n<th>Does Lock protect it?<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Automatic deletion to honour the snapshot count limit (cap deletion)<\/td>\n<td><strong>Yes<\/strong> \u2014 the NAS refuses rather than delete a locked snapshot<\/td>\n<\/tr>\n<tr>\n<td>The NAS auto-deleting under pool space pressure<\/td>\n<td><strong>Yes (moot)<\/strong> \u2014 pool pressure deletes <em>neither<\/em> locked nor unlocked snapshots; the NAS refuses writes instead<\/td>\n<\/tr>\n<tr>\n<td>A deliberate administrator action (Unlock, or Delete All \u2192 Include Locked)<\/td>\n<td><strong>No<\/strong> \u2014 one click \/ one checkbox defeats it<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2 id=\"test-group-8\">Test group 8 \u2014 Retest: where snapshot creation fails, and possible silent failures<\/h2>\n<p>This group is a deliberate retest. Several of the most important findings above rest on only a handful of observations, so they are replicated here under controlled conditions \u2014 both to confirm they are reproducible and, where possible, to characterise them more precisely. For completeness, four items are revisited:<\/p>\n<ol>\n<li>Automatic snapshot deletion driven by the maximum-snapshot-count limit (first observed in Test group 6).<\/li>\n<li>The point at which snapshot creation begins to fail as free space runs low \u2014 re-examining the single Test group 7 observation of a failure at roughly 11% free.<\/li>\n<li>Whether scheduled snapshots behave any differently from manual ones.<\/li>\n<li>Confirmation of the earlier observation that a snapshot which fails for lack of disk space does so silently, with no notification to the administrator.<\/li>\n<\/ol>\n<h3 id=\"test-8-1\">Test 8.1 \u2014 Notification channels: can the NAS alert on a failure?<\/h3>\n<p>Before testing whether a snapshot failure caused by low disk space is silent, the available notification channels were investigated \u2014 because a failure that is recorded or alerted is not silent, whereas one that passes with no signal is.<\/p>\n<p>The NAS offers two notification channels: email (SMTP) and push notifications through the UniFi mobile app. Push was not available here, as the mobile app had not been paired with this deployment, which left email as the only channel to configure. The NAS can send email either through its own hosted &#8220;UI Mail Server&#8221; or through a custom SMTP server; the hosted option was unavailable in this deployment, so a custom SMTP server was configured (SSL, port 465, authenticated):<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_8.1_email_notification_setup.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Email Services \u2014 custom SMTP server, SSL on port 465, authentication enabled<\/figcaption><\/figure>\n<p>The built-in <strong>Send Test Email<\/strong> consistently failed with a generic error, and \u2014 importantly \u2014 produced no diagnostic detail and no corresponding entry in any log:<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_8.1_email_notification_test_failed.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Test email result \u2014 &#8220;Unable to Send Email. Please confirm your SMTP settings and try again.&#8221;<\/figcaption><\/figure>\n<p>Roughly 20 minutes was spent verifying the settings. The same mailbox and credentials were confirmed working independently from an Apple Mail client, both sending and receiving, which rules out the mailbox, the credentials, and server reachability as the cause. The conclusion is that the NAS fails to send through this mail server for a reason it does not report: the test-email failure is itself a silent failure, with no log entry to diagnose it. Email notification could not be established.<\/p>\n<p>The NAS does, however, maintain an <strong>event log<\/strong> for snapshots, and that log records snapshot failures. The log below includes a <strong>Snapshot Creation Failed<\/strong> event \u2014 &#8220;A scheduled snapshot for Snapshot_Test failed because existing snapshots are locked&#8221; (28 June) \u2014 alongside the routine created, deleted, and restored events:<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_8.1_snapshot_event_logs.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Snapshot event log \u2014 a &#8220;Snapshot Creation Failed&#8221; entry appears among the created\/deleted\/restored events<\/figcaption><\/figure>\n<p>This matters for the silent-failure question. It establishes that at least one class of scheduled-snapshot failure \u2014 the count limit being reached while all existing snapshots are locked \u2014 is written to the event log, even though it could not be delivered by email. For the remainder of this group, therefore, the test for a &#8220;silent&#8221; failure is whether an equivalent <strong>event-log entry<\/strong> appears, since the event log, not email, is the notification channel that actually works on this NAS. The specific open question carried into the next test is whether a snapshot that fails for lack of disk space is recorded in the same way, or passes with no entry at all.<\/p>\n<h3 id=\"test-8-2\">Test 8.2 \u2014 How far can the pool be filled before snapshot creation fails?<\/h3>\n<p>To find where snapshot creation fails, a fresh share (<code>Fine_Snapshot_Test<\/code>) was created and grown in steps: add data (by duplicating a file or folder), check the pool on the NAS dashboard, take a manual snapshot, then repeat \u2014 continuing until the pool was completely full.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_8.2_00_create_new_share.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Creating the Fine_Snapshot_Test share<\/figcaption><\/figure>\n<p>A snapshot succeeded at <strong>every<\/strong> step. As the drive grew from ~3 GB to ~151 GB and the pool&#8217;s available space fell from ~156 GB to ~2 GB, each manual snapshot was created without error and the snapshot count climbed steadily (1, 2, 3 \u2026 9). Two points from that descent \u2014 snapshots still succeeding at ~27 GB and then ~2 GB of pool space remaining:<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_8.2_28_dashboard.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Pool dashboard with ~27 GB available \u2014 snapshot still succeeding<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_8.2_36_dashboard.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Pool dashboard with ~2 GB available \u2014 snapshot still succeeding<\/figcaption><\/figure>\n<p>Creation failed <strong>only<\/strong> once the pool reached genuine full \u2014 7.99 TB \/ 7.99 TB, zero bytes free:<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_8.2_38_snapshot_creation_failed.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Snapshot creation failed at absolute pool full \u2014 &#8220;We were unable to create a snapshot\u2026 Please try again later&#8221;<\/figcaption><\/figure>\n<p>Unlike the failures seen elsewhere, this one was <strong>logged<\/strong>: the event log carried both a <strong>Snapshot Creation Failed<\/strong> entry and a <strong>Storage Pool Full<\/strong> event at the same time.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_8.2_39_event_log_pool_full.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Event log at pool full \u2014 &#8220;Snapshot Creation Failed&#8221; and &#8220;Storage Pool 1 is full&#8221;<\/figcaption><\/figure>\n<p>The full step-by-step series is captured in <code>Test_8.2_01<\/code> through <code>Test_8.2_39<\/code>. The key result: contrary to the single observation in Test group 7, snapshot creation did <strong>not<\/strong> fail at ~10% free \u2014 it succeeded down to a few GB free and failed only at absolute pool exhaustion.<\/p>\n<h3 id=\"test-8-3\">Test 8.3 \u2014 Recovering snapshot capability by freeing pool space<\/h3>\n<p>With the pool left at absolute full by Test 8.2, the next question was whether the <em>original<\/em> <code>Snapshot_Test<\/code> drive could be snapshotted again, and how much free space that takes. Pool space was recovered by deleting data from <code>Fill_Me_Up<\/code> (which holds no snapshots, so its deletes free pool space directly), with a manual snapshot of <code>Snapshot_Test<\/code> attempted after each deletion. <code>Snapshot_Test<\/code>&#8216;s own usage stayed at 103.38 GB \/ 105 GB throughout, so every change in free space came from <code>Fill_Me_Up<\/code>.<\/p>\n<table>\n<thead>\n<tr>\n<th>Attempt<\/th>\n<th>Pool free<\/th>\n<th>Snapshot of <code>Snapshot_Test<\/code><\/th>\n<th>Event-log entry<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>1 (starting state)<\/td>\n<td>2.37 GB<\/td>\n<td><strong>Failed<\/strong><\/td>\n<td>none \u2014 silent<\/td>\n<\/tr>\n<tr>\n<td>2 (after deleting ~2.4 GB)<\/td>\n<td>4.84 GB<\/td>\n<td><strong>Failed<\/strong><\/td>\n<td>none \u2014 silent<\/td>\n<\/tr>\n<tr>\n<td>3 (after deleting ~32 GB)<\/td>\n<td>34.55 GB<\/td>\n<td><strong>Succeeded<\/strong><\/td>\n<td>logged (&#8220;Snapshot Created&#8221;)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_8.3_02_snapshot_attempt1_failed.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Attempt 1 failed at 2.37 GB free \u2014 &#8220;We were unable to create a snapshot of Snapshot_Test&#8221;<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_8.3_07_delete_32_files_confirm.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Freeing pool space by deleting the next batch from Fill_Me_Up<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_8.3_10_snapshot_attempt3_success.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Attempt 3 succeeded at 34.55 GB free \u2014 &#8220;Snapshot_Test Snapshot Created&#8221;<\/figcaption><\/figure>\n<figure><img decoding=\"async\" src=\"https:\/\/ba-web-content.sfo3.cdn.digitaloceanspaces.com\/nas-snapshots\/ubiquiti-nas\/Test_8.3_11_event_log.png\" alt=\"\" style=\"max-width: 800px;width: 100%;height: auto;margin: 0 auto\" \/><figcaption>Event log \u2014 the successful Snapshot_Test snapshot is recorded; neither failed attempt appears<\/figcaption><\/figure>\n<p>Two observations. First, <code>Snapshot_Test<\/code> required roughly <strong>35 GB free<\/strong> to snapshot, yet in Test 8.2 <code>Fine_Snapshot_Test<\/code> \u2014 a <em>larger<\/em> drive with <em>more<\/em> snapshots \u2014 succeeded at ~2 GB free. The free space a snapshot needs is therefore not a single fixed figure; it varies with the drive and its state. Second, both failed attempts (at 2.37 GB and 4.84 GB free) produced <strong>no event-log entry<\/strong>, while the success was logged \u2014 confirming, again, that a failure short of absolute pool-full is silent.<\/p>\n<h3 id=\"test-group-8-findings\">Test group 8 \u2014 findings<\/h3>\n<p><strong>1. Snapshots can fail, but not at a predictable point.<\/strong> The single ~11%-free observation from Test group 7 did not reproduce. Snapshot creation succeeded down to ~2 GB free on one drive (Test 8.2), required ~35 GB free on another (Test 8.3), and the same drive failed twice at 2\u20135 GB free before succeeding once ~35 GB was available. The determinant is unclear \u2014 it may involve data or drive-state dependence, or the timing of background maintenance running on the NAS over time. The important point is the <strong>lack of repeatability<\/strong>: an operator cannot rely on a known free-space margin, and that non-determinism is itself the risk for anyone who needs guarantees.<\/p>\n<p><strong>2. Some failures are silent.<\/strong> This was observed repeatedly. A snapshot failure short of absolute pool-full produced no event-log entry in every case seen \u2014 Test group 7 at ~880 GB free, and Test 8.3 twice at 2\u20135 GB free. Only a failure at genuine zero-free generated a <strong>Snapshot Creation Failed<\/strong> \/ <strong>Storage Pool Full<\/strong> pair (Test 8.2), and email notification could not be established at all (Test 8.1). So an operator may not be told that recovery points have stopped being created.<\/p>\n<p><em>Scope note: two of the four replications planned for this group were not carried out \u2014 count-limit automatic deletion (already established in Test group 6) and any difference between scheduled and manual snapshots. Neither is expected to change the report&#8217;s conclusions.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Companion document to the Snapshots for ransomware resilience &#8211; research report. It documents the full experimental procedure and screenshot evidence behind that report&#8217;s scorecard, in enough detail to reproduce the tests. Device under test: Ubiquiti UNAS (&#8220;NAS 8TB&#8221;), UniFi Drive. Filesystem: Btrfs on MDADM, RAID1, 7.99 TB pool. Test client: Windows 10. Test tool: nas_snaptest.py. &#8230; <a title=\"Ubiquiti UNAS \u2014 Experimental testing methodology\" class=\"read-more\" href=\"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology\">Read more <span class=\"screen-reader-text\">Ubiquiti UNAS \u2014 Experimental testing methodology<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":20487,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[764,757,1],"tags":[274,840,829,832,213,837,823,841,838,125,839,831],"class_list":["post-20485","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-best-practices","category-cyber-resilience","category-uncategorized","tag-backup-strategy","tag-backup-testing","tag-btrfs","tag-cyber-resilience-2","tag-data-recovery","tag-experimental-testing","tag-nas-snapshots","tag-performance-testing","tag-ransomware-testing","tag-smb","tag-snapshot-validation","tag-ubiquiti-unas"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.9 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Ubiquiti UNAS Experimental Testing Methodology | BackupAssist<\/title>\n<meta name=\"description\" content=\"Explore the experimental methodology behind our Ubiquiti UNAS snapshot research, including reproducible ransomware, recovery, performance, and snapshot validation tests.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Ubiquiti UNAS Experimental Testing Methodology | BackupAssist\" \/>\n<meta property=\"og:description\" content=\"Explore the experimental methodology behind our Ubiquiti UNAS snapshot research, including reproducible ransomware, recovery, performance, and snapshot validation tests.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology\" \/>\n<meta property=\"og:site_name\" content=\"Cyber Resilience Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-07-29T02:14:34+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-07-29T02:26:14+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.sandbox.backupassist.com\/app\/uploads\/sites\/3\/2026\/07\/magic_editTUFIUXVtVnVSS0UjMSM0ZDdkZDdiYzMwMTRhZWUxYTM5YzA1MzcwYTg2ZWExYiMxMzc2IyNUUkFOU0ZPUk1BVElPTl9SRVFVRVNU.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1376\" \/>\n\t<meta property=\"og:image:height\" content=\"768\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Linus Chang\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Linus Chang\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"53 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology\"},\"author\":{\"name\":\"Linus Chang\",\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/#\/schema\/person\/523a9a01769da254de228dbd4b1328d3\"},\"headline\":\"Ubiquiti UNAS \u2014 Experimental testing methodology\",\"datePublished\":\"2026-07-29T02:14:34+00:00\",\"dateModified\":\"2026-07-29T02:26:14+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology\"},\"wordCount\":6152,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.sandbox.backupassist.com\/app\/uploads\/sites\/3\/2026\/07\/magic_editTUFIUXVtVnVSS0UjMSM0ZDdkZDdiYzMwMTRhZWUxYTM5YzA1MzcwYTg2ZWExYiMxMzc2IyNUUkFOU0ZPUk1BVElPTl9SRVFVRVNU.jpg\",\"keywords\":[\"backup strategy\",\"Backup Testing\",\"Btrfs\",\"Cyber Resilience\",\"data recovery\",\"Experimental Testing\",\"NAS Snapshots\",\"Performance Testing\",\"Ransomware Testing\",\"SMB\",\"Snapshot Validation\",\"Ubiquiti UNAS\"],\"articleSection\":[\"Best practices\",\"Cyber Resilience\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology\",\"url\":\"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology\",\"name\":\"Ubiquiti UNAS Experimental Testing Methodology | BackupAssist\",\"isPartOf\":{\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.sandbox.backupassist.com\/app\/uploads\/sites\/3\/2026\/07\/magic_editTUFIUXVtVnVSS0UjMSM0ZDdkZDdiYzMwMTRhZWUxYTM5YzA1MzcwYTg2ZWExYiMxMzc2IyNUUkFOU0ZPUk1BVElPTl9SRVFVRVNU.jpg\",\"datePublished\":\"2026-07-29T02:14:34+00:00\",\"dateModified\":\"2026-07-29T02:26:14+00:00\",\"description\":\"Explore the experimental methodology behind our Ubiquiti UNAS snapshot research, including reproducible ransomware, recovery, performance, and snapshot validation tests.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology#primaryimage\",\"url\":\"https:\/\/www.sandbox.backupassist.com\/app\/uploads\/sites\/3\/2026\/07\/magic_editTUFIUXVtVnVSS0UjMSM0ZDdkZDdiYzMwMTRhZWUxYTM5YzA1MzcwYTg2ZWExYiMxMzc2IyNUUkFOU0ZPUk1BVElPTl9SRVFVRVNU.jpg\",\"contentUrl\":\"https:\/\/www.sandbox.backupassist.com\/app\/uploads\/sites\/3\/2026\/07\/magic_editTUFIUXVtVnVSS0UjMSM0ZDdkZDdiYzMwMTRhZWUxYTM5YzA1MzcwYTg2ZWExYiMxMzc2IyNUUkFOU0ZPUk1BVElPTl9SRVFVRVNU.jpg\",\"width\":1376,\"height\":768,\"caption\":\"A NAS dashboard visualizing snapshot history, storage usage, backup validation, and recovery checkpoints to support cyber resilience and rapid data recovery.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.sandbox.backupassist.com\/blog\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Ubiquiti UNAS \u2014 Experimental testing methodology\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/#website\",\"url\":\"https:\/\/www.sandbox.backupassist.com\/blog\/\",\"name\":\"Cyber Resilience Blog\",\"description\":\"Protect Your Cloud Data with BackupAssist\",\"publisher\":{\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.sandbox.backupassist.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/#organization\",\"name\":\"Cyber Resilience Blog\",\"url\":\"https:\/\/www.sandbox.backupassist.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.sandbox.backupassist.com\/app\/uploads\/sites\/3\/2019\/09\/BA-Logo-Full-Logo.svg\",\"contentUrl\":\"https:\/\/www.sandbox.backupassist.com\/app\/uploads\/sites\/3\/2019\/09\/BA-Logo-Full-Logo.svg\",\"caption\":\"Cyber Resilience Blog\"},\"image\":{\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/#\/schema\/person\/523a9a01769da254de228dbd4b1328d3\",\"name\":\"Linus Chang\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.sandbox.backupassist.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/58a69ed0d0b9928d91dec6132dccfb646cc4230839af779f185531c722b0d017?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/58a69ed0d0b9928d91dec6132dccfb646cc4230839af779f185531c722b0d017?s=96&d=mm&r=g\",\"caption\":\"Linus Chang\"},\"description\":\"*Founder &amp; Creator, BackupAssist* Linus Chang has been writing software since he was eight years old. He founded BackupAssist in 2002 \u2014 making him one of the longest-standing voices in Windows backup and data protection \u2014 and has spent the decades since talking to IT administrators around the world about what actually goes wrong, and why. His interest in data loss isn't abstract. Early in his career, he was working at the Monash University help desk when a student came in with a floppy disk that wouldn't read. They tried everything. None of their drives could read it either. The disk held her entire PhD dissertation \u2014 years of work \u2014 and it was the only copy. She broke down in tears. There was nothing he could do. Five years later, he wrote the first version of BackupAssist. Linus holds a Bachelor of Science in Computer Science and has held Microsoft Certified Solution Developer and Sun Certified Java Programmer credentials. More recently, he has completed digital forensics and cyber-security courses through the Black Hat Conference. He has spoken on information security and cryptography at Infosecurity Europe, addressed politicians and policymakers at Australian Parliament House, presented to SMB IT administrators at the IT Pro Experts Conference, and served as a guest lecturer to Cyber Security master's students at the University of Melbourne. On this blog, Linus writes about backup strategy and the technical side of cyber-resilience \u2014 drawing on 24 years of product development and direct conversation with the IT professionals BackupAssist is built for. [Connect with Linus on LinkedIn](https:\/\/www.linkedin.com\/in\/linuschang\/)\",\"url\":\"https:\/\/www.sandbox.backupassist.com\/blog\/author\/linus-chang\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Ubiquiti UNAS Experimental Testing Methodology | BackupAssist","description":"Explore the experimental methodology behind our Ubiquiti UNAS snapshot research, including reproducible ransomware, recovery, performance, and snapshot validation tests.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology","og_locale":"en_US","og_type":"article","og_title":"Ubiquiti UNAS Experimental Testing Methodology | BackupAssist","og_description":"Explore the experimental methodology behind our Ubiquiti UNAS snapshot research, including reproducible ransomware, recovery, performance, and snapshot validation tests.","og_url":"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology","og_site_name":"Cyber Resilience Blog","article_published_time":"2026-07-29T02:14:34+00:00","article_modified_time":"2026-07-29T02:26:14+00:00","og_image":[{"width":1376,"height":768,"url":"https:\/\/www.sandbox.backupassist.com\/app\/uploads\/sites\/3\/2026\/07\/magic_editTUFIUXVtVnVSS0UjMSM0ZDdkZDdiYzMwMTRhZWUxYTM5YzA1MzcwYTg2ZWExYiMxMzc2IyNUUkFOU0ZPUk1BVElPTl9SRVFVRVNU.jpg","type":"image\/jpeg"}],"author":"Linus Chang","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Linus Chang","Est. reading time":"53 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology#article","isPartOf":{"@id":"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology"},"author":{"name":"Linus Chang","@id":"https:\/\/www.sandbox.backupassist.com\/blog\/#\/schema\/person\/523a9a01769da254de228dbd4b1328d3"},"headline":"Ubiquiti UNAS \u2014 Experimental testing methodology","datePublished":"2026-07-29T02:14:34+00:00","dateModified":"2026-07-29T02:26:14+00:00","mainEntityOfPage":{"@id":"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology"},"wordCount":6152,"commentCount":0,"publisher":{"@id":"https:\/\/www.sandbox.backupassist.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology#primaryimage"},"thumbnailUrl":"https:\/\/www.sandbox.backupassist.com\/app\/uploads\/sites\/3\/2026\/07\/magic_editTUFIUXVtVnVSS0UjMSM0ZDdkZDdiYzMwMTRhZWUxYTM5YzA1MzcwYTg2ZWExYiMxMzc2IyNUUkFOU0ZPUk1BVElPTl9SRVFVRVNU.jpg","keywords":["backup strategy","Backup Testing","Btrfs","Cyber Resilience","data recovery","Experimental Testing","NAS Snapshots","Performance Testing","Ransomware Testing","SMB","Snapshot Validation","Ubiquiti UNAS"],"articleSection":["Best practices","Cyber Resilience"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology","url":"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology","name":"Ubiquiti UNAS Experimental Testing Methodology | BackupAssist","isPartOf":{"@id":"https:\/\/www.sandbox.backupassist.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology#primaryimage"},"image":{"@id":"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology#primaryimage"},"thumbnailUrl":"https:\/\/www.sandbox.backupassist.com\/app\/uploads\/sites\/3\/2026\/07\/magic_editTUFIUXVtVnVSS0UjMSM0ZDdkZDdiYzMwMTRhZWUxYTM5YzA1MzcwYTg2ZWExYiMxMzc2IyNUUkFOU0ZPUk1BVElPTl9SRVFVRVNU.jpg","datePublished":"2026-07-29T02:14:34+00:00","dateModified":"2026-07-29T02:26:14+00:00","description":"Explore the experimental methodology behind our Ubiquiti UNAS snapshot research, including reproducible ransomware, recovery, performance, and snapshot validation tests.","breadcrumb":{"@id":"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology#primaryimage","url":"https:\/\/www.sandbox.backupassist.com\/app\/uploads\/sites\/3\/2026\/07\/magic_editTUFIUXVtVnVSS0UjMSM0ZDdkZDdiYzMwMTRhZWUxYTM5YzA1MzcwYTg2ZWExYiMxMzc2IyNUUkFOU0ZPUk1BVElPTl9SRVFVRVNU.jpg","contentUrl":"https:\/\/www.sandbox.backupassist.com\/app\/uploads\/sites\/3\/2026\/07\/magic_editTUFIUXVtVnVSS0UjMSM0ZDdkZDdiYzMwMTRhZWUxYTM5YzA1MzcwYTg2ZWExYiMxMzc2IyNUUkFOU0ZPUk1BVElPTl9SRVFVRVNU.jpg","width":1376,"height":768,"caption":"A NAS dashboard visualizing snapshot history, storage usage, backup validation, and recovery checkpoints to support cyber resilience and rapid data recovery."},{"@type":"BreadcrumbList","@id":"https:\/\/www.sandbox.backupassist.com\/blog\/ubiquiti-nas-snapshots-against-ransomware-methodology#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.sandbox.backupassist.com\/blog"},{"@type":"ListItem","position":2,"name":"Ubiquiti UNAS \u2014 Experimental testing methodology"}]},{"@type":"WebSite","@id":"https:\/\/www.sandbox.backupassist.com\/blog\/#website","url":"https:\/\/www.sandbox.backupassist.com\/blog\/","name":"Cyber Resilience Blog","description":"Protect Your Cloud Data with BackupAssist","publisher":{"@id":"https:\/\/www.sandbox.backupassist.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.sandbox.backupassist.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.sandbox.backupassist.com\/blog\/#organization","name":"Cyber Resilience Blog","url":"https:\/\/www.sandbox.backupassist.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sandbox.backupassist.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.sandbox.backupassist.com\/app\/uploads\/sites\/3\/2019\/09\/BA-Logo-Full-Logo.svg","contentUrl":"https:\/\/www.sandbox.backupassist.com\/app\/uploads\/sites\/3\/2019\/09\/BA-Logo-Full-Logo.svg","caption":"Cyber Resilience Blog"},"image":{"@id":"https:\/\/www.sandbox.backupassist.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.sandbox.backupassist.com\/blog\/#\/schema\/person\/523a9a01769da254de228dbd4b1328d3","name":"Linus Chang","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sandbox.backupassist.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/58a69ed0d0b9928d91dec6132dccfb646cc4230839af779f185531c722b0d017?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/58a69ed0d0b9928d91dec6132dccfb646cc4230839af779f185531c722b0d017?s=96&d=mm&r=g","caption":"Linus Chang"},"description":"*Founder &amp; Creator, BackupAssist* Linus Chang has been writing software since he was eight years old. He founded BackupAssist in 2002 \u2014 making him one of the longest-standing voices in Windows backup and data protection \u2014 and has spent the decades since talking to IT administrators around the world about what actually goes wrong, and why. His interest in data loss isn't abstract. Early in his career, he was working at the Monash University help desk when a student came in with a floppy disk that wouldn't read. They tried everything. None of their drives could read it either. The disk held her entire PhD dissertation \u2014 years of work \u2014 and it was the only copy. She broke down in tears. There was nothing he could do. Five years later, he wrote the first version of BackupAssist. Linus holds a Bachelor of Science in Computer Science and has held Microsoft Certified Solution Developer and Sun Certified Java Programmer credentials. More recently, he has completed digital forensics and cyber-security courses through the Black Hat Conference. He has spoken on information security and cryptography at Infosecurity Europe, addressed politicians and policymakers at Australian Parliament House, presented to SMB IT administrators at the IT Pro Experts Conference, and served as a guest lecturer to Cyber Security master's students at the University of Melbourne. On this blog, Linus writes about backup strategy and the technical side of cyber-resilience \u2014 drawing on 24 years of product development and direct conversation with the IT professionals BackupAssist is built for. [Connect with Linus on LinkedIn](https:\/\/www.linkedin.com\/in\/linuschang\/)","url":"https:\/\/www.sandbox.backupassist.com\/blog\/author\/linus-chang"}]}},"_links":{"self":[{"href":"https:\/\/www.sandbox.backupassist.com\/blog\/wp-json\/wp\/v2\/posts\/20485","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sandbox.backupassist.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sandbox.backupassist.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sandbox.backupassist.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sandbox.backupassist.com\/blog\/wp-json\/wp\/v2\/comments?post=20485"}],"version-history":[{"count":3,"href":"https:\/\/www.sandbox.backupassist.com\/blog\/wp-json\/wp\/v2\/posts\/20485\/revisions"}],"predecessor-version":[{"id":20490,"href":"https:\/\/www.sandbox.backupassist.com\/blog\/wp-json\/wp\/v2\/posts\/20485\/revisions\/20490"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.sandbox.backupassist.com\/blog\/wp-json\/wp\/v2\/media\/20487"}],"wp:attachment":[{"href":"https:\/\/www.sandbox.backupassist.com\/blog\/wp-json\/wp\/v2\/media?parent=20485"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sandbox.backupassist.com\/blog\/wp-json\/wp\/v2\/categories?post=20485"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sandbox.backupassist.com\/blog\/wp-json\/wp\/v2\/tags?post=20485"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}