by: Helge, published: Aug 23, 2025, in

Samba File Server With POSIX ACLs in a Docker Container

This article explains how to set up a Samba file server as an Active Directory domain member in a Docker container. This newer configuration differs from my earlier setup in one essential point: it uses POSIX instead of Windows ACLs, simplifying the administration and making it possible to modify files via other protocols than SMB. This post is part of my series on home automation, networking & self-hosting that shows how to install, configure, and run a home server with dockerized or virtualized services.

This article is part of a mini-series about running Samba Active Directory and a file server service in a Docker container on a home server:

Please read the previous articles of this mini-series before proceeding.

Planning

Why Not Windows ACLs?

In my initial implementation, I went to great lengths to configure ACL support that is fully compatible with Windows’ nuanced file system permission feature set. Using Windows ACLs on Linux does have a significant downside, though, that may or may not affect you: you can only ever provide write access to your files via SMB, never via an alternative protocol such as SFTP. This is because the Windows ACLs are maintained in extended file system attributes by Samba. If you create a new file on the Linux console, bypassing Samba, your file won’t have the necessary ACL info and, therefore, not be visible to Windows clients.

Another drawback of using Windows ACLs on Linux is that administration is quite complex and, therefore, error-prone. A well-architected solution should be easy to maintain.

As I realized belatedly, I don’t really need full Windows ACL support. I do, however, want to be flexible in how I can access my files and not be limited to SMB. Alternative file access methods like SFTP or a browser-based UI are high on my wish list. So I decided to rethink my file system permission strategy.

Traditional Unix UGO Permissions or POSIX ACLs?

Traditional Unix user/group/other (UGO) permissions have one significant limitation that affects almost every use case: you cannot grant different types of access to multiple groups. A common scenario where you’d want to do just that is a structure where you have one group that grants read+write permissions on a directory whereas another group only grants read permissions.

Such a structure is simple and versatile but, unfortunately, cannot be implemented with Unix UGO permissions because UGO only supports a single group. To bypass that limitation, we can turn to POSIX ACLs.

POSIX ACLs allow us to grant permissions to multiple groups as well as specify default permissions that apply to new files and directories. Exactly what is needed for most real-world use cases.

POSIX ACLs

POSIX vs. NFSv4 ACLs

POSIX ACLs are somewhat simplistic in nature. Other than NFSv4 ACLs, they cannot be used to mirror Windows ACLs in full fidelity but that isn’t necessary as long as we manage our permissions on Linux and refrain from using more exotic Windows ACL features (such as deny ACEs, which shouldn’t be used anyway).

As we’re using Linux, we’re limited to POSIX ACLs anyway, as Linux doesn’t come with NFSv4 ACLs.

Samba and POSIX ACLs

Samba supports POSIX ACLs and should apply them automatically. Frustratingly, that initially wasn’t the case. Only when I updated the container image to the August 2025 patch state of Ubuntu 24.04 and Samba 4.19.5 did POSIX ACLs work via SMB.

Contrary to popular belief, it’s not necessary to enable the acl_xattr VFS module in order to use POSIX ACLs with Samba.

Dockerized Samba File Server Installation

If you followed my Samba Active Directory domain controller installation guide, you already have a Samba file server in a Docker container. The only thing left to do is configure it.

Supervisord Config File supervisord.conf

Create config-fs1/supervisor/supervisord.conf with the following content:

[supervisord]
nodaemon=true
user=root
logfile=/dev/null
logfile_maxbytes=0

[program:smbd]
command=smbd --foreground --no-process-group --debug-stdout
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true
startretries=1
autorestart=false

[program:winbindd]
command=winbindd --foreground --no-process-group --debug-stdout
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
redirect_stderr=true
startretries=1
autorestart=false

Start the Fileserver Container

Verify that when you start the Samba containers you see the following when you inspect the logs with docker compose logs fs1:

No Samba config file found at: /etc/samba/config/smb.conf
Please exec into the container and join a domain by running the following commands:
  docker exec -it samba bash
  /usr/helpers/samba-join.sh

Domain Join

Exec into the FS container and run the domain join script:

docker exec -it fs1 bash
/usr/helpers/samba-join.sh

After the file server has joined the domain, restart the FS container to give my init script the chance to do its magic at container start:

docker compose stop fs1
docker compose start fs1

Inspect the container logs for errors with the command docker compose logs fs1. You should see the following:

INFO Set uid to user 0 succeeded
INFO supervisord started with pid 7
INFO spawned: 'smbd' with pid 11
INFO spawned: 'winbindd' with pid 12
smbd version 4.19.5-Ubuntu started.
Copyright Andrew Tridgell and the Samba Team 1992-2023
winbindd version 4.19.5-Ubuntu started.
Copyright Andrew Tridgell and the Samba Team 1992-2023
INFO success: smbd entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
INFO success: winbindd entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

Verification

Test Samba Configuration

Test the Samba config file by running testparm.

DNS Record

Make sure that the file server’s name can be resolved on other machines on the network:

host fs1.ad.internal

Winbindd

Run the following commands to verify that Winbindd is able to connect to the AD DC:

wbinfo --ping-dc
# Expected output: checking the NETLOGON for domain[AD] dc connection to "dc1.ad.internal" succeeded

wbinfo -u
# Expected output: [list of users in the domain]

wbinfo -g
# Expected output: [list of groups in the domain]

wbinfo -i administrator
# Expected output: [passwd entry for administrator]

getent passwd administrator
# Expected output: [passwd entry for administrator]

getent group "AD\Domain Users"
# Expected output: domain users:x:10513:

Re-Join

Before you can re-join a machine to AD you need to delete its DNS record or dynamic DNS updates will fail because only the previous machine SID has permissions to update the existing record.

Run the following on the DC:

# Usage
samba-tool dns delete <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV|TXT> <data>
# Example
samba-tool dns delete localhost ad.internal fs1 A 192.168.0.6 -U administrator

Group Membership Structure

We’ll use a simple but flexible group structure to assign permissions to individual areas on the file server.

Working With Samba AD Groups

  • Create and modify groups on the DC.
  • Nested AD groups work correctly with POSIX ACLs.
  • After making group membership changes, the file server container needs to be stopped and restarted.

Directory Structure

/srv/samba/data/		<<-- top-level directory (shared folder)
 ├── Family-Data/		<<-- second-level directory in shared folder
 ├── Pictures/			<<-- second-level directory in shared folder
 └── Videos/			<<-- second-level directory in shared folder

Groups for Directory Permissions

  • For each second-level directory we assign one group read+write permissions and another only read permissions, e.g.:
    • FS_Data_Pictures_RW: read+write
    • FS_Data_Pictures_R: read
  • One “global” group to provide access to everything:
    • FS_Data_RW

Group Membersip

Add the global group to each second-level directory group as member, e.g.:

# Read+write
samba-tool group addmembers FS_Data_Pictures_RW FS_Data_RW

# Read only
samba-tool group addmembers FS_Data_Pictures_R FS_Data_R

Add users to the global group or to individual directory groups as needed, e.g.:

samba-tool group addmembers FS_Data_Pictures_RW userA

File Shares

Create a File Share

  1. Create a directory in the file system:
mkdir /srv/samba/data
  1. Add the share definition as a new stanza to config/smb.conf:
[Data]
	path = /srv/samba/data
	read only = no

	inherit acls = yes
	inherit owner = yes
  1. Reload the Samba configuration:
smbcontrol all reload-config

Set Unix UGO Permissions

# Change the owner and group to root
chown -R root:root /srv/samba/data

# Full access for root
chmod -R 770 /srv/samba/data

Set POSIX ACLs

Top-Level Directory

# Read permissions for everybody
setfacl -m group:"Domain Users":r-x /srv/samba/data

Second-Level Directory

# Read and read+write permissions for R and RW groups, respectively
setfacl -R -m group:"FS_Data_Pictures_RW":rwx,group:"FS_Data_Pictures_R":r-x /srv/samba/data/Pictures

# Default permissions for new files/directories: same command but with "-d"
setfacl -R -d -m group:"FS_Data_Pictures_RW":rwx,group:"FS_Data_Pictures_R":r-x /srv/samba/data/Pictures

Map (Mount) a File Share From Windows

To map a Samba file share on a Windows machine it’s not necessary for the Windows machine to be joined to the Samba domain. Run the following command to map the Data share on any Windows PC connected to the same network:

# When prompted, enter:
# 1) The user name in the format: ad.internal\USERNAME
# 2) The user's password
# Optionally replace S: with a different drive letter
net use s: \\fs1.ad.internal\data /savecred /p:yes

Note: The password is stored securely in Windows Credential Manager (open GUI with control keymgr.dll). The stored credentials persist reboots; they are automatically re-used when the network drive is being re-connected.

Additional Features & Optimizations

Recycle Bin

Samba comes with a recycle bin feature that moves files to a .recycle directory instead of deleting them. This feature is independent of the Windows File Explorer recycle bin.

Notes

  • With Samba’s recycle bin enabled, there is no way to “really” delete files (e.g., with Shift+Del) without moving them to the .recycle directory.
  • Just like the Windows original, Samba’s recycle bin is not emptied automatically.
  • The .recycle directory is created with the hidden attribute so that’s it’s not visible in Windows File Explorer by default.

Enable Recycle Bin

To enable Samba’s recycle bin, add the following lines to a share configuration in smb.conf:

	# VFS modules (make sure to include all modules - this is not cumulative to a global definition but replaces it instead)
	vfs objects = recycle
	
	# Recycle bin configuration
	recycle:directory_mode = 775
	recycle:keeptree = yes
	recycle:versions = yes

Set Permissions

  • Directories:
    • Apparently, recycle bin directories are created in the context of the user deleting a file.
    • If the user who’s deleting a file doesn’t have write permissions on the recycle bin directories, files aren’t moved to the .recycle directory but deleted instead.
  • Files:
    • “Deleted” files retain their POSIX ACLs.
  • Conclusion:
    • All users need write permissions on the recycle bin directory hierarchy.
    • The directory structure is, therefore, revealed to any user.
    • The contents of files, on the other hand, remain protected by their original permissions.

Set (top-level) permissions:

# Write permissions for everybody on directories.
# The recursion is only necessary if you have existing directories in the bin.
setfacl -R -m g:"Domain Users":rwx /srv/samba/data/.recycle
setfacl -R -d -m g:"Domain Users":rwx /srv/samba/data/.recycle

Delete Files After 60 Days

To prevent the recycle bin from growing indefinitely we’ll set up a script on the Docker host that runs daily and deletes files and directories in the bin after 60 days.

Create the file /usr/local/bin/samba-recycle-cleanup.sh with the following content:

#!/bin/bash
RecyclePath=/rpool/encrypted/docker/samba/shares-fs1/data/.recycle
MaxDays=60
# Delete all files created earlier than MaxDays
find $RecyclePath -name "*" -ctime +$MaxDays -type f -delete
# Delete empty directories
find $RecyclePath -name "*" -empty -type d -delete

Make the script executable:

chmod +x /usr/local/bin/samba-recycle-cleanup.sh

Create a cron job to run the script daily one minute after midnight:

crontab -e

Paste the following into the file that opens:

1 0 * * * /usr/local/bin/samba-recycle-cleanup.sh

Access-Based Enumeration (ABE)

What is Access-Based Enumeration (ABE)?

Access-based enumeration is a popular Microsoft technology that has existed in Windows Server since 2003. ABE displays only those files and folders a user has permission to access. It does this by filtering directory listings when a network share is accessed via SMB, removing files or folders the user doesn’t have read permissions for.

Enabling Access-Based Enumeration (ABE) in Samba

Samba has an equivalent to ABE that can be enabled by adding the following to the share definition stanza in smb.conf:

	# Enable access-based enumeration
	hide unreadable = yes

Disable the Print Service

To disable print server functionality, add the following to the [global] stanza of the machine’s config/smb.conf file:

load printers = no
printing = bsd
printcap name = /dev/null
disable spoolss = yes

Note: this is also a useful configuration for domain controllers.

Backup

My backup solution based on restic works with this Samba file server setup very well, indeed.

Running Samba in an Unprivileged Container

This configuration doesn’t require a privileged Docker container because it doesn’t use Windows permissions (which are stored in the security.NTACL extended attribute, which is only accessible as root).

Note: As of Samba 4.18, an alternative location can be specified via the acl_xattr:security_acl_name configuration option (docs).

Migration from Windows to POSIX ACLs

This section lists the changes for those of you who’re migrating from my earlier setup with Windows ACL.

Remove Settings from smb.conf

global Stanza

  • map acl inherit: change from yes to no (default) or remove the line altogether.
    • With this setting enabled, Samba would attempt to map Windows ACL protection flags to user.SAMBA_PAI extended attributes.

Per-Share Stanza

  • vfs objects: remove acl_xattr
    • We’re not storing Windows ACLs anymore but rely solely on POSIX ACLs.
  • acl_xattr:ignore system acls = yes
    • Remove this line. It’s not honored when the acl_xattr VFS module is disabled.

Add Settings to smb.conf

We’re adding settings the either are not necessary or automatically enabled if the acl_xattr VFS module is enabled.

Per-Share Stanza

  • inherit acls = yes
    • Always use and propagate default directory ACLs.
    • This sets the Unix mode to 0777 on new files and directories.
  • inherit owner = yes
    • The owner of new files and directories is set to the owner of the parent directory.
  • inherit permissions = yes
    • The Unix UGO permissions of new files and directories are inherited from the parent directory.

Remove Samba’s Windows ACL Extended Attributes

find /path/to/samba/share -exec setfattr -x security.NTACL {} \;

Previous Article Samba & SMB Web Access Through Filestash With Passthrough Auth