NAS
a home storage box that looks after itself
Network folders, S3 buckets, a photo library from phones and iCloud, disk health and a third place for our projects' backups — on one box at home, next to TrueNAS. Two weeks from the first release to daily use.
- engine
- Rust
- backend
- PythonFastAPI
- data
- PostgreSQL
- frontend
- ReactFlutter
- infrastructure
- nginxDocker
- also
- ZFSTrueNAS
At home there is a box with six disks and TrueNAS. It stores, but tells nothing: how the disks are, where the space went, whether the copies arrived. Photos live in iCloud, old archives on flash drives, backups of our projects only at cloud providers. We needed one panel that keeps all of it and says by itself when something is wrong.
NAS grew from the core of our platform: the same panel, roles, pushes, backups, monitoring. On top — its own part: a ZFS pool, buckets, a photo library. It installs next to TrueNAS and takes nothing from it — everything of its own lives in one dataset, and the pool is unlocked and mounted by TrueNAS.
Object storage compatible with S3: a file on disk and a row in the database. Compatibility is checked with real clients — boto3, aws cli, rclone; the signature is verified against AWS reference vectors. Keys carry rights per bucket and prefix, rights change without reissuing, immutable buckets refuse to overwrite.
Our own Flutter app with a Rust core uploads iPhone photos in the background. The iCloud transfer took 95,203 files — and changed nothing in iCloud: write methods are disabled, the key layout matches the app's, so there are no duplicates. Old camera photos come in through import: the date from EXIF, duplicates by sha256 across the whole library, RAW and JPEG of one frame glued into one photo.
The feed works like on a phone: Live photos, edits, deletion into "Recently deleted" for 30 days. Rotation and crop with straightening never touch the original: the box renders a copy next to it, and going back is one button.
Every five minutes a collector snapshots the pool, SMART and what TrueNAS knows. The panel explains in words and gives the command. The box remembers counter history: an alert is not about "36 errors in a lifetime" but about growth over a week — cable errors growing means it is time to reseat the cable. For Seagate disks it compares SMART hours with the FARM log: a reset counter gives away a refurbished disk. A pool scrub is a progress bar: how much is verified and when it ends.
The box sits at home behind NAT, and project servers cannot reach it. So the box opens the tunnel itself: on the server it is a plain S3 address, and the box's key there can only do this forward — no login, no commands. Four production projects send encrypted copies here next to the cloud ones. When two tunnels pointed at one server under different names, the box showed exactly that — before a copy was ever needed.
CPU, cores, memory, network, temperatures — over a socket every 2–3 seconds, a Live mode on any chart. "Resources" split CPU, disk and network by consumer: iCloud transfer, import, pool scrub, system. Updates are a button: only a released version and only forward, and the panel shows what is coming and what is installed.
14 days from the first release to a box that holds family photos and project copies. 74 releases, each checked on a test stand with real clients. The box survived a reboot in the middle of writing: the pool intact, jobs resumed where they stopped, and the SMART history pointed to the cable to check.
The library
photos from phones and iCloud, by day
Disks
a pool scrub and an alert on growing cable errors
Editing a photo without losing the original
Importing old cameras
date from EXIF, duplicates by sha256
Temperatures
CPU, NVMe and disks





