Local File Sharing in Linux
Would you like to share files among multiple users on the same Linux system?
Surprisingly, this is trickier to accomplish than it appears, so here is a method that works.
The problem: You would like to allow multiple users on the same Linux system to share files among themselves. Only users who are members of a special sharing group are allowed access to a common sharing directory, and any user may read, write, and modify the permissions or any file created by any other user. All other users are denied access. Additionally, we want to allow remote access to the shared directory for remote users who do not have a local account on the system.
Sounds simple, doesn’t it? However, unexpected surprises abound. Linux possesses an effective permission system to restrict who may do what with a file, and in order to achieve all of these goals, we must become creative in finding ways to work around the built-in permission system.
No magical program or mystical command exists that will enable local file sharing as described above. Various methods are possible, but all have drawbacks. The first thought that might come to mind is to create a share group of users allowed to share files with each other, create a shared directory, assign the Set Group ID (SGID) permission to it, and set the directory’s group to that of the share group. This works to a limited extent, but it poses problems when files are copied from an NTFS/FAT file system. Also, the default umask setting denies write permission to the share group, and only the owner may change file permissions.
What we need is a way to automatically assign default permissions to all files created within the shared directory and make each user see himself as the owner of every file so he may modify file permissions.
bindfs to the rescue!
Linux does not possess a built-in way to assign default permissions to a specified directory, so we will rely upon a program called bindfs to assign default permissions automatically and allow each user to become the owner of each file.
Sharing files among local users on the same computer
1. Install bindfs
sudo apt-get install bindfs
2. Create a shared directory
Create a common directory where users will share files.
sudo mkdir /var/share
For this example, the shared directory named share is created in /var. Place it anywhere outside of a user’s home directory. This prevents the shared directory from being accidentally deleted when a user is deleted from the system and eliminates any dependencies on a particular user.
For security, root should be the owner and group of share.
3. Change permissions on /var/share so only root has access
sudo chmod 0700 /var/share
There is no need to assign SGID or a share group since bindfs will handle that for us.
4. Create a share group
This is best managed from the Group settings GUI, but the command line will also work.
sudo groupadd share
Add all users to this group who are allowed access to the shared directory.
Add a single user:
sudo usermod -aG share inky
Add multiple users:
sudo sed -i '/^share:/s/\(.*\)/\1,inky,blinky,pinky/' /etc/group
Separate each username with a comma. No spaces.
5. Create a readme file
As root, create a readme.txt file inside /var/share that explains the purpose for the shared directory along with any other instructions, jokes, or pieces of advice you wish to include.
sudo gedit /var/share/readme.txt
This is intended to be a convenience feature for new users since the first thought they might have is “What is this directory used for?” A readme file will help explain.
However, there is a slight problem with readme.txt: Any user can delete or change it! Oh, no! To prevent this, set the immutable attribute on readme.txt. (Assuming you are in /var/share.)
sudo chattr +i readme.txt
Now, the readme.txt cannot be deleted or modified in any way, making it constantly present in /var/share. Not even root can change it. To make modifications, clear the immutable attribute first:
sudo chattr -i readme.txt
When the changes are complete, set the immutable attribute again. Only users with sudo privileges are allowed to change the immutable attribute, so make sure only trusted users on the system are allowed to use sudo. Regular users should be denied sudo privileges anyway and those users who are allowed to use sudo usually know what they are doing, so neither of these issues should be a problem.
6. Create symbolic links to the shared directory
For each user, create a soft link (symbolic link) named share to /var/share.
sudo ln -s /var/share /home/inky/share
This makes it more convenient for users to access the shared directory and shows that a shared directory is present on the system. The user simply clicks the share link and the shared directory is instantly available. This is much easier than navigating the file system to find /var/share.
To automatically add the share link to all new users at creation time, create a link in the skeleton directory /etc/skel.
sudo ln -s /var/share /etc/skel
All new users will be given a link to the shared directory within their home directories, but they will be denied access to share until added to the share group.
7. Mount the share
This is where the magic happens. Until /var/share is mounted, nobody can access it. We will mount it with bindfs as another file system so default permissions will be assigned to the files within it automatically.
sudo bindfs -o perms=0770,mirror-only=@share,group=share /var/share /var/share
perms=0770 The default permissions assigned to all new files
mirror=@share All users in the share group become owners
group=share The default group ownership assigned to files
/var/share The shares directory to mount
/var/share Where to mount /var/share
Notice that we are mounting /var/share in itself. This is not a typo. Doing this eliminates the need to create a separate mount point.
The argument mirror-only=@share tells which users will see themselves as owners of the files. This is important since only file owners may modify file permissions. This allows any user with access to share to see himself as a file owner, and thus, be allowed to modify file permissions.
The @share section tells bindfs to grab a list of users from those listed in the share group. While individual users may also be listed, this is more convenient. Only one list (the share group) must be maintained.
The group=share argument assigns the default group share to files within the shared directory. Only members of group share may access the files. All others are denied access.
If you are a member of the share group, then you should be able to access /var/share. Try creating files and directories. Copy a file from a FAT file system into the share directory. Now, view the permissions of the files created.
Each file shows that you are the owner, and the group is share with read and write permissions. Even files copied from a FAT/NTFS file system will contain these permissions.
Switch to another user (Inky, for example) who is a member of the share group and open the shared directory. Before doing anything, view the permissions of any file previously created by the other user. Notice that Inky is now the owner of the file even though Inky is not the one who created it. This is bindfs at work, and this is what we want. Since Inky is now seen as the owner, Inky may modify the permissions of the file. This includes changing the execute permission for scripts.
As Inky, create a new file, and then switch to another user (Blinky in this example). As Blinky, view the permissions of the file created by Inky and notice that Blinky is the file owner. Each user will see himself as the file’s owner, and each file will be assigned the share group ownership with read and write permissions.
By assigning default read and write permissions to the share group, there is no need to change the default umask for users.
Auto-Mounting the shared directory
For convenience, let us configure /etc/fstab so /var/share will mount automatically each time the system boots.
sudo gedit /etc/fstab
On a new line, enter this:
bindfs#/var/share /var/share fuse perms=0770,mirror-only=@share,group=share 0 0
The # after bindfs is not a typo. It must be included.
Users with accounts on the local machine may access the shared directory remotely by logging in via SSH. No surprise there. But what if we would like to allow users without local system accounts access to the shared directory?
One method is to create a local user specifically for this purpose. Simply share the username and password of this dedicated share account, and anyone may connect via SSH.
1. Creating the share account
The idea is to create a share user (named share) whose home directory is /var/share.
sudo useradd share -g share -M -d /var/share
-g share Make the share user a member of the share group
-M Do not create a home directory for this user
-d Set the default home directory to /var/share. When the user logs in, /var/share is his home directory
2. Assign a password to the share account
Remember this is the password you will give out to others in order to allow them to have access to /var/share. All remote users must log in as share using this password.
3. Change share’s UserID
To avoid local logins of the share account and to prevent it from appearing on the login screen, change share’s UID to a value of 999 or less. UIDs less than 1000 do not appear on the Ubuntu login screen, thus hiding them.
sudo usermod -u 999 share
Now, users may login under the share account using the share password.
sshfs will allow a remote user to mount the local /var/share into his file hierarchy and conveniently access the shared directory as if it were another drive on his system.
1. Install sshfs on the local system
sudo apt-get install sshfs
2. A remote user mounts the share like this
sshfs share@computer:/var/share local_mount_point
Users with local accounts may mount remotely using their own accounts, but this allows users without local accounts to mount the shared directory. In both cases, all network traffic is encrypted.
To unmount the sshfs share, the remote user must use this:
fusermount -u local_mount_point
This involves setting up an FTP server and configuring it to allow read and write access to the shared directory. Anonymous logins should be disabled. Instead, use an FTP share account with a password, and give this FTP account to remote users.
While FTP is unencrypted and some servers might pose a security risk, FTP offers file transfer limits, access policies, and quotas that can be configured for the share account. This provides a way to set quotas on the shared directory while the Linux file system does not.
Samba is another way to allow multiple users to share a directory. It functions similar to bindfs in that default permissions are applied to new files. So, why not use Samba instead of bindfs? Because symbolic links cannot be created for Samba shares.
Remember, the goal is to make sharing files as easy as possible, and providing a soft link in each user’s home directory allows easy access to the shared directory. Soft links cannot be created for Samba shares (or FTP shares).
To access the shared directory via Samba, the user would first need to enter smb://computer/var/share in Nautilus. The user must then create a bookmark in Nautilus to access the shared directory again or reenter the Samba address. This is an added step that some users may not have the knowledge to do. Plus, it is an inconvenience to manually enter an address to access a directory. Providing a pre-made soft link is much easier and automatically created for new users, minimizing maintenance.
Q. “These are a lot of steps. Why not just create a share group, assign SGID to the shared directory, and leave it at that?”
A. While this works, it is limited and presents three issues:
1. The default umask does not set the write permission for the share group.
This means the owner must manually set the group write permission for every file created. This is an extra step to remember. If a user forgets to assign the write permission on a file, then no other user may write to that file and all users must wait until the file owner allows writing.
We want file sharing to be as automatic and transparent as possible for simplicity and convenience. While we could change the default system umask, this would present a security risk. We want group write permissions for the shared directory only.
2. Only the file owner may modify file permissions.
We want any user to modify the permissions of any file. Members of the share group are assumed to trust each other, so this should not be a problem. All other users are denied access.
Suppose a script is created, but the owner forgets to set the execute bit. Another user needs to run the file, but he must wait until the owner sets the execute bit on the script. This involves contacting the file owner and waiting. What if the owner is on vacation? By allowing any user to modify file permissions on files within the shared directory, waiting is eliminated.
3. Files copied from FAT/NTFS file systems remove group permissions.
Suppose you copy a file from a USB thumb drive into the shared directory. Devices like these are often formatted in FAT. The typical Linux permission/SGID/group system will only allow the owner to access the FAT files. Group and others will be denied.
The user copying the files from the USB device is given ownership of those files while group and other permissions are stripped. No other user would be able to access those files until the owner manually assigns the share group and share permissions.
While this might not be problem for a few files, it requires an extra step to remember and quickly becomes tedious—especially if permissions must be set recursively. If something is tedious, people will avoid using it.
Linux has no built-in way to assign a default group and default permissions to files created in a specific directory. This is why we use bindfs. bindfs automatically assigns the default share group and read/write permissions to files created in /var/share no matter the file’s source. This way, when a file is copied from a FAT/NTFS device, the file will be “imported” into the ext4 file system with the proper permissions.
Q. “Help! One user is hogging the disk space. How can I enable quotas for the share?”
A. There is no way to set quotas on a specific directory. Only file systems. Even though bindfs mounts /var/share as a file system, the usrquota and grpquota options cannot be used with bindfs because bindfs does not recognize them.
One solution is to enable the quota system on the root file system containing /var/share, and then set quotas for the individual users. However, quotas will affect their file actions outside the shared directory as well.
Another idea is to create the shared directory on its own partition of limited size. This way, the share will never grow beyond its partition. However, this only limits the size of the entire shared directory and does not place limits on users allowed to access that directory.
Q. “I have removed a user from the share group, but he still has access to the shared directory. He is currently logged in. What can I do?”
A. You must either log him out manually or wait until he logs himself out because his group privileges will not change until he logs out and then logs back in. This is the way Linux works. If you change a user’s group membership while he still logged in, the changes will not take effect until the next time the user logs in. Current privileges remain in effect.