Achieving full fidelity during server migration: -A to preserve POSIX ACLs, -X for extended attributes including SELinux security contexts, -H for hardlinks, plus caution about SELinux policy mismatches on the destination server.

In episode 11 we migrated with rsync -avHAX --numeric-ids. Episode 15 dissects those last three letters — A, X, H — because that's the difference between "files moved" and "applications run normally on the new server". Every system with a web server, database, or fine-grained permission setup depends on this metadata layer.
Why does it matter? Imagine the migration is done, but the application refuses to start: on the old server the permissions were set via ACLs (not just basic rwx), and the SELinux labels changed. Without -A and -X, that metadata is lost — and "migration done" becomes "production down".
ACLs (Access Control Lists) extend the basic Unix permission model — allowing multiple users/groups with different permissions on a single file (for example, the web user can read, the backup user can write, while the owner has full control). -A (--acls) preserves them:
getfacl /var/www/app/config.php
rsync -avA /var/www/ root@new-server:/var/www/
getfacl /var/www/app/config.phpWithout -A, only basic permissions (rwxr-xr-x) are carried; additional ACL entries are silently lost. On the destination server, check with getfacl to confirm the ACLs came along. Note: -A also covers default ACLs on directories — important for directories written by other users.
Extended attributes (xattr) are additional metadata beyond permissions and timestamps — for example, user.* labels created by applications, and the most critical for modern distributions: security.selinux. -X (--xattrs) preserves them:
rsync -avAX /var/www/ root@new-server:/var/www/Note
-X copies all xattr namespaces including security.*, which normally only root can write. That's why -X often has to be run as root. If you see a setxattr failed error, it's almost certainly permissions or the destination filesystem not supporting xattrs (e.g. old NFS).
Already covered in episode 11, but worth repeating in the fidelity context: -H (--hard-links) preserves the relationships between files sharing an inode. Two files that were hardlinks at the source must remain hardlinks after migration — without -H they become two separate copies:
rsync -avHAX --numeric-ids /srv/ root@new-server:/srv/The -avHAX combination is the standard high-fidelity migration recipe: archive + hardlinks + ACL + xattr. Add --numeric-ids to preserve UID/GID. Memorize this combination — you'll use it again and again.
On systems with SELinux (RHEL/Fedora/CentOS), every file has a security.selinux security label — e.g. system_u:object_r:httpd_sys_content_t. This label determines whether a process (e.g. httpd) may access a file. -X carries those labels as-is:
ls -Z /var/www/index.html
rsync -avAX /var/www/ root@new-server:/var/www/
ls -Z /var/www/index.htmlIf the context is lost, files on the new server get the default label automatically (default_t) — and httpd can be denied access even though the rwx permissions are correct. That's why so many CentOS/RHEL migrations end with "new server, application not working": it isn't a code problem, it's the SELinux context.
There's a cautionary side: -X copies contexts raw, but SELinux at the destination only allows labels matching its own policy. If the policy on the new server differs (e.g. a different distro, or a different SELinux version), there are two possibilities:
restorecon may change it to the default.setxattr fails (an error in the log), the file is already processed.restorecon -Rv /var/wwwRecommended practice: after migrating to an SELinux system, run restorecon -Rv on the migrated directories to align labels with the local policy, then verify with ls -Z. Never rely on -X alone on systems with SELinux enabled.
Warning
Two common mistakes: (1) migrating from SELinux to a system without SELinux — the labels are still carried by -X and become metadata junk; (2) migrating to SELinux without -X, then wondering why the application is denied. Determine the SELinux status on both sides (getenforce) first before deciding whether to use -X or restorecon.
Not all filesystems support these three features equally well:
| Filesystem | ACL | xattr | Notes |
|---|---|---|---|
| ext4 | Yes | Yes | Standard |
| xfs | Yes | Yes | RHEL standard |
| btrfs/zfs | Yes | Yes | May have special namespaces |
| NFS v3 | Limited | No | NFS migration: use --no-xattrs if needed |
| FAT/NTFS | No | Limited | Not a target for Linux data |
Before a large migration, test small: rsync -avAX one directory, then getfacl/getfattr/ls -Z at the destination. Better to discover limitations on a test file than on the whole dataset.
After migrating with -avHAX, verify all three:
getfacl /var/www/index.html
getfattr -d /var/www/index.html
ls -Z /var/www/index.html
stat -c '%h' /var/www/share/file1These three commands show what was preserved: ACLs (getfacl), xattrs (getfattr), and the hardlink count (stat -c '%h'). If the output on the new server matches the old one, fidelity is achieved.
In this episode you've achieved full fidelity in migration.
Key takeaways:
-A preserves ACLs (including default ACLs); check with getfacl.-X preserves xattrs including security.selinux; may need root.-H preserves hardlink relationships.-X + restorecon -Rv after migration; watch for policy mismatches.In episode 16 we build the verification habit: testing & dry-run workflow — -n (dry-run) + -i (itemize) to see changes before execution, --checksum (-c) for validation, and --ignore-times when you doubt the timestamps. See you in episode 16!