Shell-Level ACL Management in Linux: Complete Guide

 

Shell-Level ACL Management in Linux: Complete Guide

Part 5 of 8 —Shell-Level ACL Management in Linux: Complete Guide

👁️
getfacl — View
✏️
setfacl — Modify
🔄
Backup & Restore

The two main shell commands for working with ACLs are getfacl (read/display ACL) and setfacl (create/modify/delete ACL entries). These are the tools you’ll use every day when managing file access on a Linux system. Understanding all their options gives you complete control over ACLs from the command line.

Command Options Reference

getfacl -dgetfacl -Rgetfacl –omit-header setfacl -msetfacl -xsetfacl -b setfacl -dsetfacl -ksetfacl -R setfacl -Msetfacl -nsetfacl –set setfacl –restore

getfacl — View ACL

getfacl Options Reference
Option What It Does Example
(no options) Show access ACL with file/owner/group header getfacl file.txt
-d Show default ACL instead of access ACL (directories only) getfacl -d dir/
–omit-header Hide the # file/owner/group comment lines getfacl --omit-header file.txt
-R Recursive — show ACL for all files in directory tree getfacl -R /project/
-n Show UID/GID numbers instead of names getfacl -n file.txt
-p Don’t strip leading “/” — for absolute paths in backup getfacl -Rp /data/ > backup.txt
-e Show all effective rights comments getfacl -e file.txt
# Basic: view access ACL with header
getfacl myfile.txt
# file: myfile.txt
# owner: ravi
# group: users
user::rw-
user:alice:r-x
group::r--
mask::r-x
other::---

# Clean output without header (useful in scripts)
getfacl --omit-header myfile.txt
user::rw-
user:alice:r-x
group::r--
mask::r-x
other::---

# Show with numeric UID/GID (useful when users may not exist on target)
getfacl -n myfile.txt
# user::rw-
# user:1001:r-x
# group::r--
# mask::r-x
# other::---

# View default ACL of a directory
getfacl -d mydir/

setfacl — Modify ACL

setfacl Options Reference
Option What It Does Example
-m entries Add or modify ACL entries (short form) setfacl -m u:bob:r-- file
-M file Read ACL entries to add/modify from a file setfacl -M acl.txt file
-x entries Remove specific ACL entries (no permissions needed) setfacl -x u:bob file
-X file Read entries to remove from a file setfacl -X remove.txt file
-b Remove ALL extended entries (leaves minimal ACL: user/group/other) setfacl -b file
-k Remove default ACL from a directory setfacl -k mydir/
-d Apply to default ACL instead of access ACL setfacl -d -m u:bob:r-- dir/
-R Apply recursively to all files in directory tree setfacl -R -m u:bob:r-- dir/
-n Don’t auto-recalculate ACL_MASK after changes setfacl -n -m u:bob:r-- file
–set spec Completely replace ACL (all old entries removed first) setfacl --set u::rw,g::r,o::- file
–restore file Restore ACLs from a getfacl backup file setfacl --restore=backup.txt

Step-by-Step Shell Examples

Example 1: Full ACL workflow from scratch
# Step 1: Set umask and create file
umask 022
touch project.c
getfacl project.c
# file: project.c   (minimal ACL — rw-r--r--)

# Step 2: Add a named user entry
setfacl -m u:alice:rwx project.c
getfacl --omit-header project.c
# user::rw-
# user:alice:rwx   <-- new entry
# group::r--
# mask::rwx        <-- auto-created by setfacl
# other::r--

# Step 3: Add a named group entry
setfacl -m g:devteam:rw- project.c
getfacl --omit-header project.c
# user::rw-
# user:alice:rwx
# group::r--
# group:devteam:rw-  <-- new entry
# mask::rwx          <-- auto-updated to union of alice+devteam+group
# other::r--

# Step 4: Tighten the mask
setfacl -m m::rw- project.c
getfacl --omit-header project.c
# user:alice:rwx   #effective:rw-  <-- execute removed by mask!

# Step 5: ls -l shows extended ACL with '+'
ls -l project.c
# -rw-rw-r--+ 1 ravi users 0 Jan 1 10:00 project.c
#      ^^^
#  This is ACL_MASK (rw-), NOT ACL_GROUP_OBJ (r--)
Example 2: Removing ACL entries
# Remove a specific named user entry
setfacl -x u:alice project.c
# Note: no permissions needed when removing — just tag:qualifier
getfacl --omit-header project.c
# mask auto-adjusts to union of remaining entries

# Remove a named group entry
setfacl -x g:devteam project.c

# Remove ALL extended entries at once (-b = blank/clean)
setfacl -b project.c
getfacl --omit-header project.c
# user::rw-
# group::r--
# other::r--
# (Back to minimal ACL! No mask, no named user/group entries)

# ls -l no longer shows '+'
ls -l project.c
# -rw-r--r-- 1 ravi users 0 Jan 1 10:00 project.c
Example 3: Apply ACL recursively to a directory tree
# Set ACL on all files and dirs in /project/ recursively
setfacl -R -m u:contractor:r-x /project/

# Check a few files
getfacl --omit-header /project/main.c
getfacl --omit-header /project/src/utils.c

# You can combine: set default ACL for new files AND access ACL for existing
# First, set default ACL on the directory (for future files)
setfacl -d -m u:contractor:r-x /project/
# Then, apply access ACL to all existing files
setfacl -R -m u:contractor:r-x /project/

# Remove default ACL from directory
setfacl -k /project/
Example 4: Backup and restore ACLs
<code">#!/bin/bash
# acl_backup_restore.sh

PROJECT_DIR="/home/ravi/project"
BACKUP_FILE="/backup/project_acls_$(date +%Y%m%d).txt"

echo "=== Backing up ACLs ==="
# -R recursive, output goes to backup file
getfacl -R "$PROJECT_DIR" > "$BACKUP_FILE"
echo "Saved to: $BACKUP_FILE"

echo ""
echo "=== Restoring ACLs ==="
# --restore reads the backup file
# Must be run from / for correct path resolution
cd /
setfacl --restore="$BACKUP_FILE"
echo "Restore complete."

# Verify a sample file
echo ""
echo "=== Verification ==="
getfacl "$PROJECT_DIR/main.c"
Example 5: Completely replace ACL using –set
<code"># --set REPLACES the entire ACL (unlike -m which adds/modifies)
# --set must include owner, group, other entries (the three base entries)

# Completely set a new ACL
setfacl --set "u::rw-,u:bob:r--,g::r--,g:devs:rw-,m::rw-,o::---" project.c

# Verify the complete replacement
getfacl --omit-header project.c

# Difference: -m vs --set
# -m: adds/updates specified entries, leaves others untouched
# --set: wipes everything, then sets exactly what you specify

# Example: file currently has user:alice entry
# After setfacl -m u:bob:r-- file → alice entry still there, bob added
# After setfacl --set "u::rw-,u:bob:r--,g::r--,m::r--,o::---" file
#   → alice entry is GONE, only bob remains
Example 6: Practical shell script — set up a project directory with ACLs
<code">#!/bin/bash
# setup_project_acl.sh — Configure ACLs for a team project directory
# Usage: ./setup_project_acl.sh /path/to/project

PROJECT="$1"
OWNER="ravi"
TEAM_GROUP="devteam"
REVIEWER="alice"
AUDITOR="charlie"

if [ -z "$PROJECT" ]; then
    echo "Usage: $0 /path/to/project"
    exit 1
fi

if [ ! -d "$PROJECT" ]; then
    echo "Error: $PROJECT is not a directory"
    exit 1
fi

echo "Setting up ACLs for: $PROJECT"

# 1. Set access ACL on the directory itself
setfacl -m "u:$REVIEWER:r-x,u:$AUDITOR:r--,g:$TEAM_GROUP:rwx,m::rwx,o::---" "$PROJECT"

# 2. Set default ACL so new files inherit these permissions
setfacl -d -m "u::rwx,u:$REVIEWER:r-x,u:$AUDITOR:r--,g:$TEAM_GROUP:rwx,m::rwx,o::---" "$PROJECT"

# 3. Apply to existing files recursively
setfacl -R -m "u:$REVIEWER:r-x,u:$AUDITOR:r--,g:$TEAM_GROUP:rwx,m::rwx,o::---" "$PROJECT"

# 4. Show results
echo ""
echo "=== Directory ACL ==="
getfacl "$PROJECT"
echo ""
echo "=== Default ACL ==="
getfacl -d "$PROJECT"

echo ""
echo "Done! New files created in $PROJECT will inherit these ACLs."

Common setfacl Patterns

<code"># Pattern 1: Give one user read access
setfacl -m u:username:r-- filename

# Pattern 2: Give one group read+write access
setfacl -m g:groupname:rw- filename

# Pattern 3: Block all access for a user (even if they're in a group)
# (Tricky: you can't really "deny" with POSIX ACLs — user match wins)
# Best approach: don't add the user to any permissive group

# Pattern 4: Give user read-only on entire directory tree
setfacl -R -m u:auditor:r-x /sensitive/

# Pattern 5: Remove one user's special access
setfacl -x u:username filename

# Pattern 6: Remove all ACL extensions (reset to chmod-only)
setfacl -b filename

# Pattern 7: Copy ACL from one file to another
getfacl source.txt | setfacl --set-file=- dest.txt

# Pattern 8: Set a very restrictive mask (limits all group class to read)
setfacl -n -m m::r-- filename

# Pattern 9: Set default ACL on directory for future files
setfacl -d -m u:alice:rwx,g:team:rw-,m::rwx,o::--- /shared/

# Pattern 10: Remove default ACL from directory
setfacl -k /shared/

Interview Questions

Q1. What is the difference between setfacl -m and setfacl –set?

-m (modify) adds or updates specific entries, leaving all other existing entries untouched. --set completely replaces the entire ACL — first removes all entries, then applies exactly what you specify. With --set, you must include the three mandatory entries (user, group, other) otherwise the ACL will be invalid.

Q2. What does setfacl -b do and when would you use it?

setfacl -b removes all “extended” ACL entries (ACL_USER, ACL_GROUP, and ACL_MASK), leaving only the three base entries (ACL_USER_OBJ, ACL_GROUP_OBJ, ACL_OTHER) — a minimal ACL equivalent to traditional permissions. Use it when you want to completely remove per-user/per-group access control and revert to standard chmod permissions.

Q3. How do you apply the same ACL to all files in a directory including new files created later?

Two steps: (1) Use setfacl -d -m ... to set a default ACL on the directory — this is inherited by all future files. (2) Use setfacl -R -m ... to apply the ACL to all existing files recursively. Default ACL handles future files; -R handles existing ones.

Q4. When removing an ACL entry with setfacl -x, do you need to specify the permissions?

No. When removing, you only specify the tag type and qualifier (for named user/group), not the permissions. Example: setfacl -x u:bob filename — no permissions needed. This makes sense because you’re identifying which entry to remove, not what to change it to.

Q5. How do you back up and restore all ACLs in a directory tree?

Backup: getfacl -R /directory/ > acls_backup.txt
Restore: cd / && setfacl --restore=acls_backup.txt
The restore must be run from / because getfacl records relative paths and the restore uses them to find the correct files.

Q6. What does the + sign at the end of ls -l permissions indicate?

It means the file has an extended ACL (has ACL_USER or ACL_GROUP entries beyond the three minimal entries). The group permission bits shown in ls -l reflect the ACL_MASK value, not ACL_GROUP_OBJ. Use getfacl filename to see the full ACL.
Next: Default ACLs & File Creation →

Understand how directories pass ACLs to newly created files and subdirectories

Continue → ← Back

Leave a Reply

Your email address will not be published. Required fields are marked *