Fransys

Tech blog — Architecture, Cloud & DevOps

BlogServicesContactAbout

Follow me

githubGitHublinkedinLinkedinmailMail

© 2026 Fransys • Fransys

Fransys

Categories

  • All posts
  • Tags
  • productivity10
  • nas10
  • ai8
  • security7
  • self-hosting7
  • linux6
  • claude-code6
  • neovim5
  • docker5
  • editor4
  • networking4
  • mcp3
  • vpn3
  • lua2
  • terminal2
naslinuxstoragesynology

Migrating Synology data to a Debian NAS without losing anything

Published on
February 3, 2026·5 min read
Avatar François GUERLEZFrançois GUERLEZ

Where I started

I spent years on a Synology DS918+. Good product. Really solid. But eventually the limitations pile up. No custom kernel. Packages locked to Synology's release schedule. And this creeping vendor lock-in that makes leaving progressively harder.

The trigger? Control. With Debian, you pick the hardware. You own every layer. You automate with Ansible. But first, you need to get your data back. That's where it gets messy.

What Synology actually uses

Good news: Synology didn't invent anything exotic. DSM runs on standard Linux technologies:

  • mdadm for software RAID (their SHR is just mdadm RAID 5)
  • LVM for logical volumes
  • Btrfs as the filesystem
  • eCryptFS for shared folder encryption

Bad news: Synology added a custom flag to Btrfs, the caseless flag. Makes filenames case-insensitive (SMB/Windows compatibility). The vanilla Linux kernel? No idea what that is.

The Btrfs patch: caseless flag support

Without this patch, kernel screams:

BTRFS error: unrecognized feature flag: caseless

Simple refusal. So: compile a patched Btrfs module that knows about this flag. I built an Ansible role btrfs_synology that handles everything:

  1. Install kernel headers and build tools
  2. Fetch kernel sources matching your running version
  3. Apply the patch adding caseless support
  4. Compile btrfs.ko and install via DKMS

The patch itself? Minimal. Few lines declaring the flag as known, read-only. You don't need to create new caseless files, just read existing ones. Once the patched module loads, kernel accepts Synology Btrfs partitions happily.

Detecting and mounting the RAID

Synology uses mdadm normally. Detection is automatic:

# Scan for existing RAID arrays
mdadm --assemble --scan

# Check RAID status
mdadm --detail /dev/md2

Typical output for SHR (RAID 5) across 4 drives:

/dev/md2:
        Version : 1.2
  Creation Time : Fri Mar 15 10:22:18 2024
     Raid Level : raid5
     Array Size : 5860270080 (5.46 TiB)
  Used Dev Size : 1953423360 (1.82 TiB)
   Raid Devices : 4
  Total Devices : 4
    Persistence : Superblock is persistent
          State : clean
    Active Devices : 4
   Working Devices : 4
    Failed Devices : 0
     Spare Devices : 0
            Layout : left-symmetric
        Chunk Size : 64K

Next, activate LVM:

# Scan and activate volume groups
vgscan
vgchange -ay

# List logical volumes
lvs
  LV   VG   Attr       LSize Pool Origin Data%  Meta%
  lv   vg1  -wi-a----- 5.46t

The logical volume /dev/vg1/lv contains our Btrfs filesystem. Mount it:

mount -t btrfs /dev/vg1/lv /mnt/data

Making it permanent

For everything to mount automatically on boot:

# /etc/fstab - Synology RAID mount
/dev/vg1/lv  /mnt/data  btrfs  defaults,noatime,autodefrag  0  0

The Ansible role also configures mdadm for automatic assembly via /etc/mdadm/mdadm.conf.

eCryptFS: unlocking encrypted folders

If you had encryption on your Synology shared folders, each encrypted folder is a directory with eCryptFS files underneath. Two-step decryption:

# Mount the eCryptFS layer
mount -t ecryptfs /mnt/data/@Famille /mnt/data/Famille \
  -o ecryptfs_cipher=aes,ecryptfs_key_bytes=32,\
ecryptfs_passthrough=no,ecryptfs_enable_filename_crypto=no

System prompts for the passphrase (the one you set in DSM). I automated this in an Ansible role ecryptfs_synology that:

  • Stores the passphrase in a secured file (600 permissions, root owner)
  • Auto-mounts encrypted folders at boot via systemd script
  • Handles multiple encrypted folders with different passphrases

Samba: recreating the shares

Data is mounted. Now put it on the network. I recreated the same share names as on the Synology so Windows/Mac clients found everything unchanged:

# /etc/samba/smb.conf (excerpt)
[Famille]
    path = /mnt/data/Famille
    valid users = @famille
    read only = no
    create mask = 0664
    directory mask = 0775

[Images]
    path = /mnt/data/Images
    valid users = @famille
    read only = no

[Musiques]
    path = /mnt/data/Musiques
    valid users = @famille
    read only = no

[Vidéos]
    path = /mnt/data/Vidéos
    valid users = @famille
    read only = no

Migrated shares: Coco, Famille, Images, Lalitha, Logiciels, Matthias, Musiques, Videos, Telechargements. Proper group-based permissions on each.

New app directories

Beyond migrated data, I created directories for new services:

# Directories for Docker applications
mkdir -p /mnt/data/apps
mkdir -p /mnt/data/media/{movies,tv,music}
mkdir -p /mnt/data/downloads/{complete,incomplete}
mkdir -p /mnt/data/photos

chown -R nasadmin:nasadmin /mnt/data/apps /mnt/data/media /mnt/data/downloads /mnt/data/photos

Everything on the RAID, same Btrfs volume.

Watch out: Btrfs subvolumes

Btrfs organizes data into subvolumes. Synology creates one per shared folder. The gotcha: moving a file between subvolumes isn't a rename - it's a full copy then delete. Multi-gigabyte files? Very slow. Temporarily consumes double space.

# List subvolumes
btrfs subvolume list /mnt/data

So if you need to move large files between shares, use rsync instead of mv. You get a progress bar. You can resume if interrupted.

Swap file on Btrfs

Creating a swap file on Btrfs requires one thing: disable copy-on-write on the file, or kernel refuses:

# Create the swap file
truncate -s 0 /mnt/data/swapfile
chattr +C /mnt/data/swapfile
fallocate -l 4G /mnt/data/swapfile
chmod 600 /mnt/data/swapfile
mkswap /mnt/data/swapfile
swapon /mnt/data/swapfile

# fstab entry
# /mnt/data/swapfile  none  swap  sw  0  0

The chattr +C disables CoW before allocating. Non-negotiable.

Monthly scrub for integrity

Btrfs has a scrub mechanism that verifies all data integrity by checking checksums. I run it monthly:

# /etc/systemd/system/btrfs-scrub.timer
[Unit]
Description=Monthly Btrfs scrub on /mnt/data

[Timer]
OnCalendar=monthly
Persistent=true
RandomizedDelaySec=3600

[Install]
WantedBy=timers.target
# /etc/systemd/system/btrfs-scrub.service
[Unit]
Description=Btrfs scrub /mnt/data

[Service]
Type=oneshot
ExecStart=/usr/bin/btrfs scrub start -B /mnt/data
Nice=19
IOSchedulingClass=idle

The Nice=19 and IOSchedulingClass=idle ensure scrub doesn't interfere with normal operations.

That's it

Synology to Debian migration is totally feasible, even with encrypted folders. The main hurdle is that Btrfs caseless flag - patch the kernel and everything else flows naturally. mdadm, LVM, Btrfs, eCryptFS: standard Linux tools Synology just assembled with a web UI on top. Manipulate them directly and you gain control, flexibility, and keep every last byte of your data.


Debian NAS from scratch series — This article is part of a complete series on building a Debian NAS.

Next: Installing Debian on a NAS in fully automated mode

Previous post

← Hardening your NAS Linux kernel to CIS Level 2 standards

Next post

Telescope, Treesitter and essential coding plugins for Neovim→
← Back to blog

Table of Contents

  • Where I started
  • What Synology actually uses
  • The Btrfs patch: caseless flag support
  • Detecting and mounting the RAID
  • Making it permanent
  • eCryptFS: unlocking encrypted folders
  • Samba: recreating the shares
  • New app directories
  • Watch out: Btrfs subvolumes
  • Swap file on Btrfs
  • Monthly scrub for integrity
  • That's it