| |

LFCE 66 ๐Ÿง NFS Server โ€” Installation and Config

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

NFS (Network File System) is the standard protocol for sharing directories across a Unix-like network. The server exports a directory from its local filesystem, and clients mount it over the network as if it were a local filesystem. The previous chapters covered web servers and mail servers, both of which provide application-level services; NFS provides filesystem-level access, and its configuration is built around the /etc/exports file that defines which directories are shared with which clients. The LFCE exam objectives explicitly include providing and configuring network shares via NFS .

The installation is a package manager command, but the configuration requires attention to the export syntax, the client specification, and the permission mapping. The default export options are read-only and root-squashed, which are safe defaults but may not match the intended use. The exportfs command applies the configuration, and the showmount command verifies it. The firewall rules differ between NFSv4, which uses a single port, and NFSv3, which uses several auxiliary services.

Key point: NFSv4 uses TCP port 2049 exclusively and does not require the portmapper or the mountd service for basic operation . NFSv3 requires port 111 for rpcbind, an additional port for mountd, and the lock and stat services. The /etc/exports entry defines the directory, the clients, and the options in parentheses. The root_squash option maps the client’s root user to nobody, which prevents a client root from having root access on the server; the no_root_squash option disables this mapping and should be used only for diskless clients .


Why NFS configuration requires careful export syntax

The client-specification problem.

The /etc/exports file uses a specific syntax: the directory, followed by a whitespace-separated list of clients, each with an optional parenthesized list of options. The client can be a hostname, an IP address, a network in CIDR notation (192.168.1.0/24), or a wildcard (*.example.com) . A space between the client and the opening parenthesis changes the meaning: client (rw) applies the default options to client and exports to a different client named (rw), while client(rw) applies the rw option to client. The no-space form is the correct one.

The permission-mapping problem.

NFS identifies users by UID and GID, not by username. A file owned by UID 1000 on the server is owned by the user with UID 1000 on the client, regardless of the username. If the UIDs do not match, the file appears to be owned by a different user or by nobody. The root_squash option maps the client’s root to nobody, which is the default and the safe choice . For environments where the UIDs are not synchronized, the idmapd service and the Domain setting in /etc/idmapd.conf provide the mapping, but the simplest solution is to ensure the UIDs match across the server and the clients .

The firewall problem.

NFSv4 uses TCP port 2049 for all operations, which makes the firewall rule simple . NFSv3 uses rpcbind on port 111, mountd on a dynamically assigned port, and the lock and stat services on additional ports. The dynamic ports are a problem for firewall rules, and the standard solution is to set static ports in /etc/nfs.conf and open those ports explicitly . A server that supports both versions must open all the ports that the older version requires.


a. Installing the packages

The NFS server package is named nfs-kernel-server on Debian and Ubuntu, and nfs-utils on RHEL, Rocky Linux, and Fedora.

# Debian / Ubuntu
sudo apt update
sudo apt install nfs-kernel-server

# RHEL / Rocky / Fedora
sudo dnf install nfs-utils

# Verify the installation
rpcinfo -p | grep nfs
# Output shows the NFS program and its version

The rpcinfo -p command lists the RPC programs that are registered with the portmapper. The NFS program appears with its version and port . On a system that uses only NFSv4, the portmapper may not be running, and the command produces no output for NFS; the systemctl status nfs-server command confirms that the server is active.


b. Configuring the exports file

The /etc/exports file defines the shared directories. Each line contains the directory path, the clients, and the options.

# /etc/exports
/srv/nfs/shared 192.168.1.0/24(rw,sync,no_subtree_check)
/srv/nfs/readonly 192.168.1.0/24(ro,sync)

The first line exports /srv/nfs/shared to the 192.168.1.0/24 network with read-write access. The sync option tells the server to commit the changes to disk before replying, which is slower but safer than the async option. The no_subtree_check option disables the subtree check, which is a performance optimization that is safe when the entire directory is exported . The second line exports a read-only directory.

The root_squash option is the default and maps the client’s root to nobody. To allow the client’s root to have root access on the server, the no_root_squash option is used, but this is a security risk and should be limited to trusted clients.

# Allow root access from a specific trusted host
/srv/nfs/diskless 192.168.1.50(rw,sync,no_root_squash)

The exportfs command applies the configuration without restarting the service.

# Apply the exports
sudo exportfs -ra

# Show the active exports
sudo exportfs -v

The -r flag re-exports all directories, and the -a flag applies to all entries. The -v flag shows the active exports with their options . A syntax error in /etc/exports produces an error message from exportfs, and the previous configuration remains in effect.


c. Starting the server and opening the firewall

The NFS server is a systemd service. It must be started and enabled, and the firewall must permit the NFS traffic.

# Start and enable the server
sudo systemctl enable --now nfs-server

# Check the status
sudo systemctl status nfs-server

# Open the firewall for NFSv4 (TCP 2049)
sudo firewall-cmd --permanent --add-service=nfs
sudo firewall-cmd --reload

The systemctl enable --now nfs-server command starts the service and configures it to start at boot. The firewall-cmd --add-service=nfs command opens the ports that the NFS service definition includes, which for NFSv4 is TCP port 2049 . On a system that uses ufw, the command is sudo ufw allow nfs.

For NFSv3, the firewall must also permit port 111 for rpcbind and the mountd port. The mountd port is dynamic by default, and the standard solution is to set a static port in /etc/nfs.conf.

# /etc/nfs.conf
[mountd]
port=20048

[statd]
port=32765

[lockd]
port=32766
udp-port=32766

The [mountd], [statd], and [lockd] sections set the static ports. The firewall rules must open these ports, and the rpcinfo -p command confirms the ports that are actually in use .


Complete Example Session

# ============================================
# PART 1: INSTALL THE NFS SERVER PACKAGE
# ============================================
sudo apt install nfs-kernel-server

# ============================================
# PART 2: CREATE THE SHARED DIRECTORY
# ============================================
sudo mkdir -p /srv/nfs/shared
sudo chown nobody:nogroup /srv/nfs/shared
sudo chmod 777 /srv/nfs/shared

# ============================================
# PART 3: CONFIGURE THE EXPORTS
# ============================================
sudo tee /etc/exports > /dev/null <<'EOF'
/srv/nfs/shared 192.168.1.0/24(rw,sync,no_subtree_check)
EOF

# ============================================
# PART 4: APPLY THE EXPORTS
# ============================================
sudo exportfs -ra
sudo exportfs -v
# Output shows the exported directory and its options

# ============================================
# PART 5: START AND ENABLE THE SERVER
# ============================================
sudo systemctl enable --now nfs-server
sudo systemctl status nfs-server
# Output: active (running)

# ============================================
# PART 6: OPEN THE FIREWALL
# ============================================
sudo firewall-cmd --permanent --add-service=nfs
sudo firewall-cmd --reload

# ============================================
# PART 7: VERIFY THE EXPORTS FROM THE SERVER
# ============================================
sudo showmount -e localhost
# Output: Export list for localhost:
#         /srv/nfs/shared 192.168.1.0/24

# ============================================
# PART 8: CHECK THE LISTENING PORTS
# ============================================
sudo ss -tlnp | grep :2049
# Output: LISTEN 0 64 *:2049 *:* users:(("nfsd",pid=...))

# ============================================
# PART 9: TEST FROM A CLIENT
# ============================================
# On a client on the 192.168.1.0/24 network:
# sudo mkdir -p /mnt/nfs
# sudo mount -t nfs 192.168.1.10:/srv/nfs/shared /mnt/nfs
# ls /mnt/nfs

# ============================================
# PART 10: CLEAN UP
# ============================================
# On the client: sudo umount /mnt/nfs
# On the server: sudo exportfs -ua
# sudo systemctl stop nfs-server

The ten parts demonstrate the complete NFS server setup: installation, directory creation, exports configuration, applying the exports, starting the service, opening the firewall, verifying the exports, checking the listening port, testing from a client, and cleanup. The critical verification is Part 7: showmount -e lists the exported directory and the clients that are allowed to mount it.


Quick Reference

Installation Packages

DistributionPackage
Debian / Ubuntunfs-kernel-server
RHEL / Rocky / Fedoranfs-utils

Exports Syntax

ElementExample
Directory/srv/nfs/shared
Client (CIDR)192.168.1.0/24
Client (host)client.example.com
Client (wildcard)*.example.com
Options(rw,sync,no_subtree_check)

Common Export Options

OptionMeaning
rwRead-write access
roRead-only access
syncCommit to disk before replying
asyncReply before committing
root_squashMap client root to nobody (default)
no_root_squashAllow client root to be root
no_subtree_checkDisable subtree checking

Commands

CommandPurpose
exportfs -raRe-export all directories
exportfs -vShow active exports
showmount -e <server>List exports from a client
rpcinfo -pShow RPC programs and ports
systemctl status nfs-serverCheck service state

Firewall Ports

VersionPorts
NFSv4TCP 2049
NFSv3TCP/UDP 111, 2049, mountd, statd, lockd

Best Practices

โœ… Do This:

# Use no_subtree_check for exported directories
/srv/nfs/shared 192.168.1.0/24(rw,sync,no_subtree_check)      # โœ…

# Keep root_squash for security
/srv/nfs/shared 192.168.1.0/24(rw,sync,root_squash)           # โœ…

# Apply exports without restarting
exportfs -ra                                                   # โœ…

# Verify the exports
exportfs -v                                                    # โœ…

# Open only the required ports
firewall-cmd --add-service=nfs                                 # โœ…

# Use NFSv4 to simplify the firewall
# Only TCP 2049 is required                                     # โœ…

โŒ Don’t Do This:

# Use no_root_squash for untrusted clients
/srv/nfs/shared *(rw,sync,no_root_squash)    # Security risk    # โŒ

# Put a space between the client and the options
192.168.1.0/24 (rw)    # The options apply to a different client # โŒ

# Forget to apply the exports
# The new directory is not shared                               # โŒ

# Open all ports for NFSv3 without static port configuration
# The mountd port changes on every restart                      # โŒ

# Export a directory without setting the permissions
# The client cannot write to the share                          # โŒ

Common Pitfalls

PitfallWhy It HappensFix
Client cannot mountFirewall blocks port 2049Open the NFS service
Permission deniedUID mismatch or root_squashMatch UIDs; check export options
Export not visibleexportfs not runexportfs -ra
NFSv3 mount failsDynamic mountd port blockedSet static ports in nfs.conf
Write fails despite rwDirectory permissions on the serverchmod and chown the directory
Service not startingMissing package or port conflictCheck systemctl status nfs-server

Real-World Examples

1. Install the package

apt install nfs-kernel-server    # Debian
dnf install nfs-utils            # RHEL

2. Create the shared directory

mkdir -p /srv/nfs/shared && chown nobody:nogroup /srv/nfs/shared

3. Basic export

/srv/nfs/shared 192.168.1.0/24(rw,sync,no_subtree_check)

4. Read-only export

/srv/nfs/readonly 192.168.1.0/24(ro,sync)

5. Apply the exports

exportfs -ra

6. Show the exports

exportfs -v

7. Start the server

systemctl enable --now nfs-server

8. Open the firewall

firewall-cmd --permanent --add-service=nfs && firewall-cmd --reload

9. Verify from the server

showmount -e localhost

10. Mount from a client

mount -t nfs 192.168.1.10:/srv/nfs/shared /mnt/nfs

Visual

NFS Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  SERVER EXPORTS; CLIENT MOUNTS                                โ”‚
โ”‚                                                              โ”‚
โ”‚  NFS Server                                                  โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ /etc/exports                                           โ”‚  โ”‚
โ”‚  โ”‚ /srv/nfs/shared 192.168.1.0/24(rw,sync)                โ”‚  โ”‚
โ”‚  โ”‚                                                        โ”‚  โ”‚
โ”‚  โ”‚ exportfs -ra โ†’ kernel NFS server                       โ”‚  โ”‚
โ”‚  โ”‚ TCP 2049 (NFSv4)                                       โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                             โ”‚                                โ”‚
โ”‚                             โ”‚ Network                        โ”‚
โ”‚                             โ–ผ                                โ”‚
โ”‚  NFS Client                                                  โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ mount -t nfs server:/srv/nfs/shared /mnt/nfs           โ”‚  โ”‚
โ”‚  โ”‚ โ†’ /mnt/nfs is the server's /srv/nfs/shared             โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Exports Syntax

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  DIRECTORY  CLIENT(OPTIONS)                                  โ”‚
โ”‚                                                              โ”‚
โ”‚  /srv/nfs/shared 192.168.1.0/24(rw,sync,no_subtree_check)     โ”‚
โ”‚  โ”‚                โ”‚              โ”‚                            โ”‚
โ”‚  โ”‚                โ”‚              โ””โ”€โ”€ Options in parentheses  โ”‚
โ”‚  โ”‚                โ””โ”€โ”€ Client specification                   โ”‚
โ”‚  โ””โ”€โ”€ Directory to share                                     โ”‚
โ”‚                                                              โ”‚
โ”‚  NO SPACE between client and (options).                      โ”‚
โ”‚  A space changes the meaning.                                โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

NFSv4 vs NFSv3 Firewall

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  NFSv4 IS SIMPLER FOR FIREWALLS                              โ”‚
โ”‚                                                              โ”‚
โ”‚  NFSv4:                                                      โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ TCP 2049 only                                          โ”‚  โ”‚
โ”‚  โ”‚ No rpcbind, no mountd                                  โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                                                              โ”‚
โ”‚  NFSv3:                                                      โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ TCP/UDP 111 (rpcbind)                                  โ”‚  โ”‚
โ”‚  โ”‚ TCP/UDP 2049 (nfs)                                     โ”‚  โ”‚
โ”‚  โ”‚ mountd port (dynamic by default)                       โ”‚  โ”‚
โ”‚  โ”‚ statd port (dynamic)                                   โ”‚  โ”‚
โ”‚  โ”‚ lockd port (dynamic)                                   โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Debian packagenfs-kernel-server
RHEL packagenfs-utils
Configuration file/etc/exports
Apply exportsexportfs -ra
Show exportsexportfs -v
Verify from clientshowmount -e <server>
Servicenfs-server
NFSv4 portTCP 2049
NFSv3 ports111, 2049, mountd, statd, lockd
Default permission mappingroot_squash
Firewall servicenfs

Key takeaways:

  • The /etc/exports file defines the shares. Each line contains the directory, the clients, and the options in parentheses. The client can be a hostname, an IP address, a CIDR network, or a wildcard. A space between the client and the options changes the meaning .
  • NFSv4 uses TCP 2049 only. The firewall rule is simple, and the portmapper and mountd are not required for basic NFSv4 operation. NFSv3 requires the additional services and their ports .
  • root_squash is the default and the safe choice. It maps the client’s root user to nobody, preventing a client root from having root access on the server. no_root_squash should be limited to trusted clients .
  • The exportfs command applies the configuration. The -ra flags re-export all directories, and the -v flag shows the active exports. A syntax error in the file produces an error message, and the previous configuration remains in effect.
  • UIDs must match for correct ownership. NFS identifies users by UID and GID, not by username. If the UIDs differ between the server and the client, the files appear to be owned by the wrong user or by nobody .
  • The showmount -e command verifies the exports. It lists the exported directories and the clients that are allowed to mount them. A client that cannot see the export cannot mount it, regardless of the firewall rules.

Remember: NFS shares a directory from the server and mounts it on the client. The /etc/exports file defines the directory, the clients, and the options. The exportfs command applies the configuration, and the nfs-server service serves it. NFSv4 uses a single port, which simplifies the firewall; NFSv3 requires the portmapper and the mountd service. The root_squash option is the default and should be kept unless a trusted client needs root access. The showmount command verifies the exports, and the mount command on the client confirms that the share is accessible.


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!