| |

LFCE 118 ๐Ÿง mdadm โ€” Creating Arrays

โฑ๏ธ Estimated read: 13 min | |

mdadm is the userspace tool that manages Linux software RAID. It creates arrays from block devices, assembles them at boot, monitors their health, and handles the replacement of failed disks. Creating an array is a single command, but the command carries decisions that affect capacity, performance, and recoverability: the RAID level, the number of devices, the chunk size, and the metadata version. Each of these has consequences that are easier to understand before the array exists than after it has been formatted and filled with data.

This chapter covers the creation of RAID arrays with mdadm: the prerequisite of preparing the member devices, the --create command and its essential options, the meaning of chunk size and metadata version, the persistence step that makes the array survive a reboot, and the post-creation verification. It also covers the creation of arrays with a missing member, which is how a degraded array is built when a replacement disk is not yet available. By the end, you will be able to create RAID 0, 1, 5, 6, and 10 arrays, verify their status, and ensure they are recognized at boot.

Key point: An array created with mdadm --create is not persistent until mdadm --detail --scan output is written to /etc/mdadm.conf (or the array is otherwise configured for assembly). The array exists in the kernel immediately; it survives a reboot only if the assembly configuration is saved.


Why creation has these parameters

The level and device count problem. The RAID level determines how many devices are required and what the usable capacity will be. RAID 0 requires at least two devices and has no redundancy. RAID 1 requires at least two and uses one device’s capacity. RAID 5 requires at least three and loses one device’s worth to parity. RAID 6 requires at least four and loses two. RAID 10 requires at least four and uses half the raw capacity. The --raid-devices count must match the number of devices supplied, or mdadm will refuse to create the array.

The chunk size problem. Chunk size is the amount of data written to one disk before the next disk in the stripe is used. A smaller chunk spreads data across disks more frequently, which can improve performance for small random I/O but increases the number of disk operations for large sequential I/O. A larger chunk favors sequential throughput. The kernel documentation suggests 32 KB as a reasonable starting point for most arrays, while noting that a 4 KB chunk with a 16 KB write across three disks results in 4 KB to each disk . The default in modern mdadm is 512 KB, which is large and may not suit all workloads .

The metadata version problem. mdadm stores array metadata in a superblock on each member device. Metadata version 1.2 is the modern default and places the superblock 4 KB from the start of the device, which is compatible with most bootloaders when the array is used for data but not necessarily for /boot. Version 0.90 is the legacy format, placed at the end of the device, and is sometimes required for boot partitions on older systems. The creation command accepts --metadata= to pin the version; if omitted, mdadm uses 1.2 and prints a note .

The persistence problem. mdadm --create assembles the array in the running kernel. The kernel knows about the array until the next reboot. At boot, the mdmonitor service reads /etc/mdadm.conf to determine which arrays to assemble . Without an entry in that file, the array does not come back automatically. The --detail --scan output produces the correct ARRAY line, and appending it to the configuration file is the standard persistence step .


a. Preparing the member devices

The member devices can be entire disks (/dev/sdb) or partitions (/dev/sdb1). Using partitions is more flexible because it allows different partitions on the same disk to serve different purposes, but using entire disks is simpler and avoids alignment issues. In either case, the devices must not be mounted, must not contain data that needs to be preserved, and should be of the same size. mdadm uses the smallest device’s capacity for the array, so mismatched sizes waste the extra space on larger devices.

# Identify the target devices
lsblk

# If using partitions, create them with fdisk or parted
# Set the partition type to Linux RAID autodetect (fd)
sudo fdisk /dev/sdb
# n (new partition), t (type), fd (Linux RAID), w (write)

The creation command will overwrite the superblock on each member device, which destroys any existing filesystem or data on that device. Confirm the device names before proceeding.

b. The create command and its essential options

The syntax is mdadm --create <device> --level=<level> --raid-devices=<count> <members>. The <device> is the array device, typically /dev/md0 or a named device like /dev/md/data. The --level accepts numeric or named values: 0 or raid0, 1 or raid1, 5 or raid5, 6 or raid6, 10 or raid10 .

# RAID 1 from two partitions
sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb1 /dev/sdc1

# RAID 5 from three partitions
sudo mdadm --create /dev/md0 --level=5 --raid-devices=3 /dev/sdb1 /dev/sdc1 /dev/sdd1

# RAID 6 from four partitions
sudo mdadm --create /dev/md0 --level=6 --raid-devices=4 /dev/sdb1 /dev/sdc1 /dev/sdd1 /dev/sde1

# RAID 10 from four partitions
sudo mdadm --create /dev/md0 --level=10 --raid-devices=4 /dev/sdb1 /dev/sdc1 /dev/sdd1 /dev/sde1

The command prompts for confirmation before creating the array. The --verbose flag prints the details of what is being created. After creation, the array may begin a background resynchronization (rebuild), which is expected for parity-based levels and for mirrors. The array is usable during this process, but performance is reduced until it completes.

c. Chunk size and metadata version

Chunk size is specified with --chunk= in kilobytes. The default is 512 KB in modern mdadm. For a workload that does many small random writes, a smaller chunk (32 KB or 64 KB) may perform better because each write touches fewer disks. For sequential throughput, a larger chunk allows each disk to write more data before seeking. The kernel documentation suggests 32 KB as a starting point .

# Create with an explicit 64 KB chunk
sudo mdadm --create /dev/md0 --level=5 --raid-devices=3 --chunk=64 \
  /dev/sdb1 /dev/sdc1 /dev/sdd1

The metadata version is specified with --metadata=. The default is 1.2. If the array will be used for /boot on a system with an older bootloader, 0.90 may be required. The creation output notes when the default metadata is used and whether it is suitable for boot .

d. Creating with a missing device

mdadm can create an array with fewer devices than the level requires by declaring a missing member. This is useful when a disk has failed and the replacement has not arrived, or when building an array incrementally. The missing device is specified with the keyword missing in the member list, and the --raid-devices count includes it.

# Create a degraded RAID 5 with two devices and one missing
sudo mdadm --create /dev/md0 --level=5 --raid-devices=3 \
  /dev/sdb1 /dev/sdc1 missing

The array is created in degraded state. When a replacement disk is added with mdadm --add, the array rebuilds onto it. This is the standard recovery path for a failed member.

e. Persistence and verification

The array must be recorded in /etc/mdadm.conf for automatic assembly at boot. The --detail --scan command produces the correct configuration line, and appending it to the file saves the array’s UUID and metadata version .

# Save the array configuration
sudo mdadm --detail --scan | sudo tee -a /etc/mdadm.conf

# Verify the entry
cat /etc/mdadm.conf
# ARRAY /dev/md0 metadata=1.2 name=hostname:0 UUID=...

The array status is checked with --detail, and the kernel’s view of all arrays is in /proc/mdstat.

# Detailed status
sudo mdadm --detail /dev/md0

# Brief status of all arrays
cat /proc/mdstat

After creation, the array is a raw block device. It must be formatted with a filesystem before it can be mounted. For parity-based arrays, the filesystem’s stride and stripe-width should be calculated from the chunk size and the number of data disks to align I/O with the RAID geometry .


Complete Example Session

# ============================================
# PART 1: IDENTIFY TARGET DEVICES
# ============================================
lsblk

# Confirm the devices are not mounted and contain no data
# /dev/sdb, /dev/sdc, /dev/sdd are the targets
# ============================================
# PART 2: CREATE A RAID 1 ARRAY
# ============================================
sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 \
  /dev/sdb1 /dev/sdc1

# Output:
# mdadm: Note: this array has metadata at the start and
#     may not be suitable as a boot device.
# Continue creating array? yes
# mdadm: array /dev/md0 started.
# ============================================
# PART 3: CREATE A RAID 5 ARRAY WITH CHUNK SIZE
# ============================================
sudo mdadm --create /dev/md1 --level=5 --raid-devices=3 \
  --chunk=64 /dev/sdb2 /dev/sdc2 /dev/sdd1

# The array starts and begins background resync.
# Check progress with cat /proc/mdstat.
# ============================================
# PART 4: CREATE A DEGRADED ARRAY
# ============================================
sudo mdadm --create /dev/md2 --level=5 --raid-devices=3 \
  /dev/sdd2 /dev/sde1 missing

# The array is created with two active devices.
# State is "degraded" until a replacement is added.
# ============================================
# PART 5: VERIFY CREATION
# ============================================
sudo mdadm --detail /dev/md0

# Look for:
# Raid Level : raid1
# Array Size : ...
# State : clean, resyncing (or active)
# Active Devices : 2
# ============================================
# PART 6: CHECK RESYNC PROGRESS
# ============================================
cat /proc/mdstat

# Example output:
# md0 : active raid1 sdc1[1] sdb1[0]
#       976630272 blocks super 1.2 [2/2] [UU]
#       [=>...................]  resync =  5.2% ...
# ============================================
# PART 7: SAVE CONFIGURATION FOR PERSISTENCE
# ============================================
sudo mdadm --detail --scan | sudo tee -a /etc/mdadm.conf

# Verify the ARRAY line
grep ARRAY /etc/mdadm.conf
# ============================================
# PART 8: FORMAT THE ARRAY
# ============================================
# For a RAID 5 array, calculate stride and stripe-width
# chunk = 64 KB, block = 4 KB, data disks = 2
# stride = 64 / 4 = 16
# stripe-width = 2 * 16 = 32

sudo mkfs.ext4 -v -b 4096 -E stride=16,stripe-width=32 /dev/md1
# ============================================
# PART 9: MOUNT AND TEST
# ============================================
sudo mkdir -p /mnt/raid5
sudo mount /dev/md1 /mnt/raid5
df -h /mnt/raid5
# ============================================
# PART 10: ADD A REPLACEMENT TO A DEGRADED ARRAY
# ============================================
sudo mdadm /dev/md2 --add /dev/sdf1

# The array begins rebuilding onto the new device.
# Monitor with cat /proc/mdstat.

The ten parts covered device identification, RAID 1 creation, RAID 5 creation with chunk size, degraded array creation, verification, resync monitoring, persistence, filesystem formatting with stride, mounting, and adding a replacement member.


Quick Reference

Create command syntax

ElementExample
Array device/dev/md0 or /dev/md/data
Level--level=5 or --level=raid5
Device count--raid-devices=3
Chunk size--chunk=64 (KB)
Metadata--metadata=1.2 (default)
Members/dev/sdb1 /dev/sdc1 /dev/sdd1
Missing membermissing keyword

Minimum devices by level

LevelMinimum devicesUsable capacity
RAID 02N ร— disk
RAID 121 ร— disk
RAID 53(Nโˆ’1) ร— disk
RAID 64(Nโˆ’2) ร— disk
RAID 104(N/2) ร— disk

Verification commands

CommandPurpose
mdadm --detail /dev/md0Detailed array status
cat /proc/mdstatAll arrays, resync progress
lsblkBlock device view including md devices
mdadm --detail --scanConfiguration line for mdadm.conf

Persistence

StepCommand
Save configurationmdadm --detail --scan >> /etc/mdadm.conf
Verify entrygrep ARRAY /etc/mdadm.conf
Test assemblymdadm --assemble --scan (after reboot or manually)

Best Practices

โœ… Do This:

# Use --verbose to see creation details
mdadm --create --verbose /dev/md0 --level=5 --raid-devices=3 ... # โœ…
# Choose chunk size deliberately
--chunk=64                                                       # โœ…
# Save configuration immediately after creation
mdadm --detail --scan >> /etc/mdadm.conf                         # โœ…
# Verify with /proc/mdstat after creation
cat /proc/mdstat                                                 # โœ…
# Calculate stride and stripe-width for parity arrays
mkfs.ext4 -E stride=16,stripe-width=32 /dev/md0                  # โœ…

โŒ Don’t Do This:

# Create an array on devices that contain data
mdadm --create /dev/md0 ... /dev/sdb1                            # โŒ (destroys data)
# Omit the persistence step
mdadm --create /dev/md0 ...                                      # โŒ (not persistent)
# Use mismatched device sizes without understanding the waste
# (mdadm uses the smallest device's size)                        # โŒ
# Ignore metadata version for boot arrays
--metadata=1.2 for /boot                                         # โŒ (may not boot)
# Assume the array is ready immediately
# Resync may still be running                                      # โŒ

Common Pitfalls

PitfallWhy It HappensFix
Array not present after rebootNo entry in /etc/mdadm.confRun mdadm --detail --scan >> /etc/mdadm.conf
mdadm: cannot open /dev/sdb1: Device or resource busyDevice is mounted or in useUnmount the device first
Array size smaller than expectedMismatched member sizesUse same-sized devices; mdadm uses the smallest
Boot fails after creating /boot on RAIDMetadata version incompatible with bootloaderUse --metadata=0.90 for boot arrays on older systems
Resync takes hoursLarge disks and background rebuildExpected; monitor with /proc/mdstat
Filesystem performance poor on RAID 5Stride and stripe-width not alignedReformat with calculated stride/stripe-width

Real-World Examples

1. Create RAID 1 from two disks

mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb /dev/sdc

2. Create RAID 5 with 64 KB chunk

mdadm --create /dev/md0 --level=5 --raid-devices=3 --chunk=64 /dev/sdb1 /dev/sdc1 /dev/sdd1

3. Create RAID 6 from four disks

mdadm --create /dev/md0 --level=6 --raid-devices=4 /dev/sdb1 /dev/sdc1 /dev/sdd1 /dev/sde1

4. Create RAID 10 from four disks

mdadm --create /dev/md0 --level=10 --raid-devices=4 /dev/sdb1 /dev/sdc1 /dev/sdd1 /dev/sde1

5. Create degraded RAID 5

mdadm --create /dev/md0 --level=5 --raid-devices=3 /dev/sdb1 /dev/sdc1 missing

6. Save configuration

mdadm --detail --scan >> /etc/mdadm.conf

7. Check status

mdadm --detail /dev/md0

8. Check resync progress

cat /proc/mdstat

9. Format with stride

mkfs.ext4 -E stride=16,stripe-width=32 /dev/md0

10. Add replacement to degraded array

mdadm /dev/md0 --add /dev/sdf1

Visual

The create command structure

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  MDADM --CREATE                                              โ”‚
โ”‚                                                              โ”‚
โ”‚  mdadm --create /dev/md0 \                                  โ”‚
โ”‚        --level=5 \           โ† RAID level                   โ”‚
โ”‚        --raid-devices=3 \    โ† device count                 โ”‚
โ”‚        --chunk=64 \          โ† chunk size (KB)              โ”‚
โ”‚        /dev/sdb1 /dev/sdc1 /dev/sdd1  โ† members             โ”‚
โ”‚                                                              โ”‚
โ”‚  The array device is created and assembled.                 โ”‚
โ”‚  Members are overwritten with superblocks.                  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Creation and persistence flow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  CREATE โ”€โ”€โ–บ ASSEMBLE โ”€โ”€โ–บ SAVE โ”€โ”€โ–บ PERSIST                   โ”‚
โ”‚                                                              โ”‚
โ”‚  mdadm --create                                              โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  Array exists in kernel (/dev/md0)                           โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  mdadm --detail --scan >> /etc/mdadm.conf                    โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  At boot: mdmonitor reads mdadm.conf                         โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  Array assembled automatically                               โ”‚
โ”‚                                                              โ”‚
โ”‚  Without the save step, the array disappears on reboot.      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Degraded array creation

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  CREATE WITH MISSING DEVICE                                  โ”‚
โ”‚                                                              โ”‚
โ”‚  mdadm --create /dev/md0 --level=5 --raid-devices=3 \      โ”‚
โ”‚        /dev/sdb1 /dev/sdc1 missing                           โ”‚
โ”‚                                                              โ”‚
โ”‚  Result:                                                     โ”‚
โ”‚    Active devices: 2                                         โ”‚
โ”‚    State: degraded                                           โ”‚
โ”‚    Redundancy: none (waiting for replacement)                โ”‚
โ”‚                                                              โ”‚
โ”‚  Later:                                                      โ”‚
โ”‚    mdadm /dev/md0 --add /dev/sdd1                            โ”‚
โ”‚    Array rebuilds onto the new device.                       โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

RAID geometry and filesystem alignment

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  STRIDE AND STRIPE-WIDTH                                     โ”‚
โ”‚                                                              โ”‚
โ”‚  chunk = 64 KB                                               โ”‚
โ”‚  block = 4 KB                                                โ”‚
โ”‚  data disks (RAID 5, 3 devices) = 2                          โ”‚
โ”‚                                                              โ”‚
โ”‚  stride = chunk / block = 64 / 4 = 16                        โ”‚
โ”‚  stripe-width = data disks ร— stride = 2 ร— 16 = 32            โ”‚
โ”‚                                                              โ”‚
โ”‚  mkfs.ext4 -E stride=16,stripe-width=32 /dev/md0             โ”‚
โ”‚                                                              โ”‚
โ”‚  Aligns filesystem blocks with RAID stripes.                 โ”‚
โ”‚  Reduces read-modify-write overhead on parity arrays.        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Create commandmdadm --create /dev/mdX --level=N --raid-devices=C members
Default metadata1.2
Default chunk (modern)512 KB
Recommended chunk (kernel doc)32 KB starting point
Minimum devicesLevel-dependent (2, 2, 3, 4, 4)
Missing member keywordmissing
Persistence commandmdadm --detail --scan >> /etc/mdadm.conf
Status commandmdadm --detail /dev/mdX
Progress commandcat /proc/mdstat

Key takeaways:

  • The create command overwrites member devices. Confirm device names and back up any data before running it. The superblock written by mdadm destroys the previous contents.
  • Chunk size is a performance decision. Smaller chunks favor small random I/O; larger chunks favor sequential throughput. The kernel documentation suggests 32 KB as a starting point, not a universal default.
  • The array is not persistent until saved. mdadm --create assembles the array in the running kernel. /etc/mdadm.conf is what makes the array reappear after a reboot.
  • Degraded arrays can be created intentionally. The missing keyword allows an array to be built with fewer devices than the level requires, which is useful for recovery or incremental expansion.
  • The array is usable during resync. Parity-based levels and mirrors begin a background rebuild after creation. The array can be formatted and mounted immediately, but performance is reduced until the rebuild completes.
  • Filesystem alignment matters for parity arrays. Calculating stride and stripe-width from the chunk size and data disk count aligns filesystem I/O with the RAID geometry and avoids unnecessary read-modify-write cycles.

Remember: mdadm --create is one command, but it encodes several decisions: the level determines the failure tolerance and capacity overhead; the device count determines the minimum hardware requirement; the chunk size determines the I/O pattern the array handles best; the metadata version determines whether the array can be used for boot; and the persistence step determines whether the array survives a restart. Get the level and device count right first, because they cannot be changed without rebuilding. Choose the chunk size with the workload in mind. Save the configuration immediately. And verify with /proc/mdstat that the array is not still resyncing before treating it as fully redundant.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!