Building a 4TB Video Storage Stack on Fedora (Transmission + SMB)

Posted on Feb 7, 2026

I recently added a 4TB Seagate IronWolf HDD to my ThinkCentre Server to serve as a dedicated video storage and torrenting machine. To get the most out of the spinning rust, I needed a setup that minimizes fragmentation and network latency.

Here is the complete, non-interactive configuration guide for Fedora 43 Server, moving from a raw disk to a fully tuned streaming stack. All commands are executed as root.

The Hardware

  • Disk: Seagate IronWolf 4TB (SATA, 5400RPM)
  • OS: Fedora Linux 43 (Server Edition)
  • Mount Point: /srv/TORRENT

Step 1: Partitioning & Formatting

Since the drive is larger than 2TB, we must use GPT. We use sgdisk for non-interactive partitioning and mkfs.ext4 with specific flags to optimize for large video files.

Key Flags:

  • -m 0: Sets reserved blocks to 0% (reclaiming ~200GB of space usually reserved for root).
  • -T largefile4: Reduces inode count, optimizing the filesystem structure for large files rather than millions of tiny ones.
# 1. Wipe existing filesystem signatures to prevent conflicts
wipefs -a /dev/sdb

# 2. Create a new GPT table with a single partition filling the disk
# -n 1:0:0 (New partition 1, start default, end default)
# -t 1:8300 (Type Linux Filesystem)
sgdisk -n 1:0:0 -t 8300 /dev/sdb

# 3. Inform the kernel of changes
partprobe /dev/sdb

# 4. Format with Large File optimization
mkfs.ext4 -m 0 -T largefile4 /dev/sdb1

Step 2: Persistent Mount

We mount the drive to /srv/TORRENT using its UUID to ensure it survives reboots and cable swaps.

# 1. Create the mount point
mkdir -p /srv/TORRENT

# 2. Capture the UUID and append to fstab
# We use 'noatime' to prevent write-wear during reads
DISK_UUID=$(blkid -s UUID -o value /dev/sdb1)
echo "UUID=${DISK_UUID} /srv/TORRENT ext4 defaults,noatime,lazytime,data=ordered 0 2" >> /etc/fstab
systemctl daemon-reload

# 3. Mount the drive
mount -a

# 4. FIX PERMISSIONS (Critical Step)
# By default, the mount point is owned by root. We must give it to transmission.
chown -R transmission:transmission /srv/TORRENT
chmod 775 /srv/TORRENT

# 5. Create directory structure
# Since we just changed ownership, these will be created as transmission:transmission
mkdir -p /srv/TORRENT/{inbox,new,family}

Step 3: Transmission Daemon Setup

We are using the system-wide transmission-daemon. By default, the configuration directory might be empty, so we will generate a full, optimized settings.json file.

Optimizations:

  • preallocation: 2 (Full): Allocates full file space on download start. Essential to prevent fragmentation on HDDs.
  • cache-size-mb: 256: Increases write cache to smooth out I/O spikes.
# 1. Stop the service to allow config editing
systemctl stop transmission-daemon

# 2. Ensure the configuration directory exists
mkdir -p /var/lib/transmission/.config/transmission-daemon/

# 3. Write the FULL optimized configuration
# Note: We change 'umask' to 2 (002) to allow group write permissions for SMB
cat <<EOF > /var/lib/transmission/.config/transmission-daemon/settings.json
{
    "alt-speed-down": 50,
    "alt-speed-enabled": false,
    "alt-speed-time-begin": 540,
    "alt-speed-time-day": 127,
    "alt-speed-time-enabled": false,
    "alt-speed-time-end": 1020,
    "alt-speed-up": 50,
    "announce-ip": "",
    "announce-ip-enabled": false,
    "anti-brute-force-enabled": false,
    "anti-brute-force-threshold": 100,
    "bind-address-ipv4": "0.0.0.0",
    "bind-address-ipv6": "::",
    "blocklist-date": 0,
    "blocklist-enabled": false,
    "blocklist-updates-enabled": true,
    "blocklist-url": "[http://www.example.com/blocklist](http://www.example.com/blocklist)",
    "cache-size-mb": 64,
    "compact-view": false,
    "default-trackers": "",
    "dht-enabled": true,
    "download-dir": "/srv/TORRENT/new",
    "download-queue-enabled": true,
    "download-queue-size": 5,
    "encryption": 1,
    "idle-seeding-limit": 30,
    "idle-seeding-limit-enabled": false,
    "incomplete-dir": "/srv/TORRENT/inbox",
    "incomplete-dir-enabled": true,
    "lpd-enabled": true,
    "message-level": 2,
    "peer-congestion-algorithm": "",
    "peer-limit-global": 200,
    "peer-limit-per-torrent": 50,
    "peer-port": 51413,
    "peer-port-random-high": 65535,
    "peer-port-random-low": 49152,
    "peer-port-random-on-start": false,
    "peer-socket-tos": "le",
    "pex-enabled": true,
    "port-forwarding-enabled": true,
    "preallocation": 2,
    "prefetch-enabled": true,
    "queue-stalled-enabled": true,
    "queue-stalled-minutes": 30,
    "ratio-limit": 2,
    "ratio-limit-enabled": true,
    "rename-partial-files": true,
    "rpc-authentication-required": false,
    "rpc-bind-address": "0.0.0.0",
    "rpc-enabled": true,
    "rpc-host-whitelist": "",
    "rpc-host-whitelist-enabled": true,
    "rpc-port": 9091,
    "rpc-url": "/transmission/",
    "rpc-username": "",
    "rpc-whitelist": "0.0.0.0",
    "rpc-whitelist-enabled": false,
    "scrape-paused-torrents-enabled": true,
    "script-torrent-done-enabled": false,
    "script-torrent-done-filename": "",
    "speed-limit-down": 100,
    "speed-limit-down-enabled": false,
    "speed-limit-up": 100,
    "speed-limit-up-enabled": false,
    "start-added-torrents": true,
    "trash-original-torrent-files": false,
    "umask": 2,
    "upload-slots-per-torrent": 14,
    "utp-enabled": false,
    "watch-dir": "/srv/TORRENT/inbox",
    "watch-dir-enabled": true
}
EOF

# 4. Fix permissions
# The system daemon runs as 'transmission', so it needs ownership of the config and data
chown -R transmission:transmission /var/lib/transmission
chown -R transmission:transmission /srv/TORRENT

# 5. Start the service
systemctl enable --now transmission-daemon

Step 4: Samba (SMB) Configuration

We configure Samba to share the directory as Read-Only.

Note: We set force user = transmission to ensure that you can access files created by the torrent client without permission errors.

# 1. Backup existing config
cp /etc/samba/smb.conf /etc/samba/smb.conf.bak

# 2. Append the Read-Only share definition
# Note: We use 'aio' (Asynchronous I/O) settings to improve read performance for large files.
cat <<EOF >> /etc/samba/smb.conf

[VideoArchive]
   path = /srv/TORRENT
   browseable = yes
   read only = yes
   guest ok = yes
   force user = transmission
   aio read size = 16384
   aio write size = 16384
EOF

# 3. Restart Samba
systemctl enable --now smb

Verification

Run lsblk to confirm the mount and check the service status.

lsblk
systemctl status transmission-daemon

Step 5: SELinux & Permissions (Fedora Specific)

Fedora enforces strict security. By default, it will block Samba from accessing /srv. We must update the security context and ensure user permissions allow directory traversal.

# 1. Allow Samba to read/write the torrent directory in SELinux
# (Requires policycoreutils-python-utils)
semanage fcontext -a -t samba_share_t "/srv/TORRENT(/.*)?"
restorecon -R -v /srv/TORRENT
setsebool -P allow_transmission_anon_write 1

# 2. Add your user to the transmission group for easy access
usermod -a -G transmission think

# 3. Create a Samba password for your user (required for private shares)
smbpasswd -a think

Step 6: Migrating Old Data (Optional)

If you are moving data from an old drive (e.g., /srv/TORRENT_OLD), do not use cp. Standard copy commands do not pre-allocate space, which will immediately fragment your fresh drive.

Instead, use rsync with the --preallocate flag to ensure large video files are written contiguously.

# 1. Stop Transmission to release file locks
systemctl stop transmission-daemon

# 2. Copy with Preallocation
# -a: Archive mode (preserves permissions/times)
# -h: Human readable numbers
# -W: Whole file (faster for local copies)
# --preallocate: The magic flag to prevent fragmentation
# --info=progress2: Shows a single total progress bar
rsync -ahW --info=progress2 --preallocate /srv/TORRENT_OLD/ /srv/TORRENT/

# 3. Restart Transmission
systemctl start transmission-daemon