[root tip] [How To] Samba Server From Scratch

Difficulty: ★★★★☆

What is SAMBA

Samba is the standard Windows interoperability suite of programs for Linux and Unix.

Samba File Server From Scratch

Source: Samba From Scratch | root.nix.dk

The bar is set high as the configuration is done from scratch using a SSH terminal session to the target system.


The exercise is to setup Samba to share different content for different audiences using an Arch Linux based OS and with consideration of how we pre-emptively secure the system against unauthorized access and changes to the content.

It will also require understanding of the Access Control List in a GNU/Linux system as well as networking concepts.

The final setup will provide the following features

Users and groups

username groups home shell
admin admin yes yes
hans users,office no no
grete users,admin no no


  • public share
    • authenticated users can edit files
    • guests can read files
  • document share
    • stored on local root partition accessible to authenticated users
    • files may be edited by users belonging to the admin group
    • office users can only read the documents
  • music library (administrated by the dedicated admin)
    • stored on external partition - in this case an USB stick


A minmal Arch Linux based server - with a valid network configuration accessible using SSH.

The Samba documentation at Arch Wiki.

On your workstation add a hosts entry to simplify connection - I use a Raspberry Pi named filebox so throughout this document uses filebox as a reference to the Samba server.

If you don’t know the IP of your device - you can find it using nmap to scan network for devices exposing an open port 22

nmap -p 22 --open ip.x.y.z/24

Depending on your network and your device IP and name - adapt the following to your usecase

echo "ip.x.y.z filebox" | sudo tee -a /etc/hosts


Create a new ssh session to your server system.

ssh username@filebox

Run a full system update and install the following packages samba, firewalld and micro

sudo pacman -Syu samba firewalld micro

Enable firewalld and configure the service for the home zone

sudo systemctl enable --now firewalld
sudo firewall-cmd --set-default-zone=home
sudo firewall-cmd --permanent --add-service={samba,ssh} --zone=home

Restart the system


root context

All the following configuration is assuming your are using ssh shell with non-root user operating in the context of root - so remember switch to root context.

su -l root

data tree

On the server we will store data in a designated tree starting from our system root (/)

mkdir -p /data/{office,media/music,public}

Visualised using tree

# tree /data
├── media
│   └── music
├── office
└── public



The office folder’s permission should allow modify/write by group with no access for other - including guests.

The office group doesn’t exist - so we create it and assign the group to the documents folder.

groupadd office

Assign the documents folder to the group

chgrp office /data/office


The content of /data/media/music is stored on an external USB device, so initially there is no data. The device may or may not be attached, we will handle that later as this pose a challenge.

The media folder has suitable permissions - no need to change.


The public folder is writable by group and readable for other

chmod g+w /data/public

For the public folder we decided that authenticated users are allowed to write - guests are not. The default users group is perfect for this.

chgrp users /data/public

If you list the content of the data folder - you should now get a similar result

# ls -l /data
drwxr-xr-x 3 root root   4096 Aug 10 01:29 media
drwxrwx--- 2 root office 4096 Oct 16 10:40 office
drwxrwxr-x 2 root users  4096 Oct 16 09:48 public

data protection

To ensure we do not accidental enable folder traversel outside the shares we will expose the data in second structure mapping in the data by the use bind mounts.

Mounting using bind is a simple and efficient method of making data from one folder available from another folder on the same system. The function is similar to symlink but you cannot create folder traversal using dots.

We will create some corresponding folders in /srv and bind our data there.

mkdir -p /srv/samba/{data,public}

Open the file /etc/fstab with micro

micro /etc/fstab

Append the following lines

/data             /srv/samba/data none bind 0 0
/data/public      /srv/samba/public none bind 0 0

Now execute a reload and mount everything

systemctl daemon-reload
mount -a

When we list the /srv/samba, we see how our changes to the data folders is reflected in share tree

# ls -l /srv/samba
drwxr-xr-x 5 root root  4096 Oct 16 10:40 data
drwxrwxr-x 2 root users 4096 Oct 16 09:48 public

# ls -l /srv/samba/data
drwxr-xr-x 3 root root   4096 Aug 10 01:29 media
drwxr-xr-x 2 root office 4096 Oct 16 10:40 office
drwxrwxr-x 2 root users  4096 Oct 16 09:48 public

And the tree

├── data
│   ├── media
│   │   └── music
│   ├── office
│   └── public
└── public

Basic samba configuration

Navigate to the samba configuration folder on your server system

cd /etc/samba

A Samba service is always configured from scratch - there is no default config, it must be created before you can start the service.

My favorite terminal editor is micro due to the support for copy/paste as well as other editor shortcuts e.g. Ctrl+s.

In the samba configuration folder start micro and create the required configuration smb.conf

micro smb.conf

We start by defining two sections global configuration and public share configuration - you are free to use your own text for ‘workgroup’ and ‘server string’ settings

   workgroup = WORKGROUP
   server string = Samba File Server
   server role = standalone server
   log file = /var/log/samba/log.%m
   max log size = 50
   guest account = nobody
   map to guest = Bad Password

Run the command testparm to ensure your smb.conf is free from spelling errors then start the service.

testparm -s

If you are curios about smb.conf - try this

testparm -s -v > ~/smb-defaults.txt | micro

Enable and start the service smb

systemctl enable --now smb

Enhance network discovery

The following is not strictly necessary but to some it is a necessity.

To locate your service by name enable and start the nmb service

systemctl enable --now nmb

You can further enhance discovery using avahi

systemctl enable --now avahi-daemon

Now test the connect from your workstation - you should see something similar

 $ smbclient -L filebox
Password for [WORKGROUP\fh]:

        Sharename       Type      Comment
        ---------       ----      -------
        IPC$            IPC       IPC Service (Samba File Server)
SMB1 disabled -- no workgroup available

public share

Edit the smb.conf file and append the following to create the public share

   path = /srv/samba/public
   public = yes
   writable = yes
   printable = no

Save the file and test the configuration

testparm -s

If all is good, restart services

systemctl restart smb nmb

Verify the public share by opening the file manager on your workstation.

Use Ctrl+L and input smb://ip.x.y.z/public then press Enter

Login using the anonymous method. Try creating new file - you should expect access denied.

Go back to your shell and create an empty text file in public folder.

touch /data/public/test.txt

Go back to your file manager press F5 to reveal the new file.

All good - now unmount the public share from the file manager and reopen the share - this time login using the username and credentials from your ssh session - this time edit the file and save it.

Did you get access denied once more? Good - this is expected behavior as there is no users in the samba trust database. Unmount the public share using the eject button in the file manager.

user - samba vs. system

It is very important to remember

  • a system user is not a samba user
  • a samba user requires a system user

If you change your user password you either remember two passwords or change using smbpasswd for your username.

To enable passwd sync maintenance from samba to system - add this to the global section of smb.conf

   obey pam restrictions = yes
   unix password sync = yes
   passwd program = /usr/bin/passwd %u
   passwd chat = *New*UNIX*password* %n\n *ReType*new*UNIX*password* %n\n *passwd:*all*authentication*tokens*updated*successfully*
   pam password change = yes

Any changes to smb.conf requires the service to be restarted and as a precaution always test the config before restarting.

Using this command will prevent samba from restarting if the testparm command fails

testparm -s

If all is good, restart services

systemctl restart smb nmb

anonymous user

Anonymous users is a security risk.
You have no control over the content on your share. This is bad - very, very bad - think ransomware - you don’t wannacry :sob: If you - despite all warnings - must create a public share with no restrictions refer to Samba Usage on Arch Wiki.

authenticated user

Remember the leading sentence for this section - a system user is not a samba user. Since our service should allow authenticated users to create content in the public folder - let us start easy with your ssh username.

In your file manager mount the share again - this time using your ssh user and the samba password. Open the empty file - enter some text and save it. Try creating some new content on the public share. You should expect - access denied.

You are an authenticated user - why should you expect access denied?

Back in the shell, let us look at the permissions for the public folder

 $ ls -l /data
[ ... ]
drwxrwxr-x  2 root users  4096 12 mar 11:38 public

Note the group users, then check which groups your username is member of

 $ groups <username>
wheel lp sys network power username

In this case the user we added to samba is not member of users, thus we are denied writing.

Add your ssh username to the users group

gpasswd -a <username> users

Restart services and retry the edit operation

systemctl restart smb nmb

This time you are authenticated and you are member of the users group and thus allowed to make changes.

Remove your test content from the share and unmount.

creating users - add to samba

Our server is a file server only and as such - besides the admin - users has no use for home folder and they don’t need shell access.

Our challenge includes and administrator and two distinct authenticated users with access to the documents folder.

  • users group can read/write public content
  • office group can read documents
  • admin group can read/write all content

As we configured samba using unix password sync = yes samba will sync the password back to the system.

creating users

A designated administrator of shared content. The user has system login permissions and a home folder and we use smbpasswd to assign password as we have enabled password syncronisation from samba to system.

useradd --create-home --user-group --groups office,users --shell /bin/bash admin
smbpasswd -a admin

Add a user named hans in group office with no shell, no home and no personal group

useradd --no-create-home --no-user-group --groups office  -s /bin/nologin hans
smbpasswd -a hans

Now add the office user - name grete with no shell, no home, no personal group but a supplementary group admin - thus allowing the user to additionally edit documents

useradd --no-create-home --no-user-group --groups admin --shell /bin/nologin grete
smbpasswd -a grete

admin user permissions

When you list the content of the /data folder, root is listed as owner - but we have our dedicated admin.

Let’s change the group for /data root to admin - allowing admin to create new folders

chgrp admin /data

Next we change the owner of content inside /data/ - you did remove the test files - right? Otherwise the owner will change for those as well.

chown admin /data/* -R

the data share

Edit your samba configuration and add the following section

  path = /srv/samba/data
  public = no
  writable = yes
  printable = no
  guest ok = no

Test the config

testparm -s

If all is good, restart services

systemctl restart smb nmb

On your workstation open a terminal and run

smbclient -L filebox -U admin
Password for [WORKGROUP\admin]:

        Sharename       Type      Comment
        ---------       ----      -------
        public          Disk
        data            Disk
        IPC$            IPC       IPC Service (Samba File Server)
SMB1 disabled -- no workgroup available

the media share

The media share resides on a removable device and we want the device to be mounted all times. The problem with removable devices is - they are removable - which is a challenge to be solved.

We will face this challenge using systemd units.

We need the UUID of the partition we want to mount - so attach the device to the Raspberry Pi and list the available block devices

# lsblk -A
lsblk -A
sda            8:0    1  28,8G  0 disk 
└─sda1         8:1    1  28,8G  0 part 
mmcblk0      179:0    0  14,6G  0 disk 
├─mmcblk0p1  179:1    0 457,8M  0 part /boot
└─mmcblk0p2  179:2    0  14,1G  0 part /srv/samba/public

The partition is /dev/sda1 - let’s get the UUID and pipe it to the unit file.

lsblk -no UUID  /dev/sda1 > /etc/systemd/system/data-media-music.mount

systemd mount unit naming convention is to use the mountpoint as filename replacing / with -.

In our case we have placed the music files in the folder /data/media/music so this is where we mount the partition.

Open the unit file using micro

micro /etc/systemd/system/data-media-music.mount

Alter the content to match below - arrange for you UUID which is unique for my system to end the line What=/dev/disk/by-uuid/. (do not add spaces before or after the equal sign = and observe the casing of properties)

Description=USB stick with music files



Now we create unit which takes care of mount the partition when it is needed. The same rule on filename applies - but the extension is .automount

micro /etc/systemd/system/data-media-music.automount

The content of the automount is as follow

Description=USB stick with music files



All that is left now is to enable the automount unit

systemctl enable --now data-media-music.automount

To share the music folder on a common sharepoint - edit your smb.conf and add the following section

  path = /srv/samba/data/media/music
  public = yes
  printable = no
  guest ok = yes

Test your configuration

testparm -s

If all is good, restart services

systemctl restart smb nmb

:no_entry_sign: This is not a support thread - so don’t ask questions - instead create a new topic with your question - refer back to this topic.

:ok: If you spot an error - please do comment so the error can be fixed.

1 Like