Alright, let’s talk about Samba. You know that feeling when you’re at a party and two groups of people just can’t seem to talk to each other? That’s your network. Over in the corner, you have the Unix-like systems (Linux, macOS) speaking the native tongue of POSIX permissions and NFS. And then there’s the Windows crowd, holding court in the center of the room, chatting away in a proprietary dialect called SMB. They don’t mean to be difficult; it’s just how they were raised.

Samba is the brilliant, multilingual friend who bridges this gap. It’s an open-source implementation of the Server Message Block (SMB) protocol—and its more modern, slightly-better-behaved cousin, the Common Internet File System (CIFS). In practice, SMB and CIFS are used interchangeably, and it mostly means “the thing that lets Windows machines share files and printers.” Samba lets your Linux box walk right up to that Windows party, introduce itself, and start sharing files like it’s been there all along. It pretends to be a Windows server for your Windows clients. The magic is that it’s not emulation; it’s a full-fledged, reverse-engineered reimplementation. It had to be, because for the longest time, Microsoft treated the SMB spec as a state secret. The Samba team did forensic analysis on network packets to get it right, which is the software equivalent of figuring out a recipe by only ever tasting the final dish.

The Absolute Basics: smb.conf and the smbd Daemon

Samba’s entire personality is defined by a single, deceptively simple-looking configuration file: /etc/samba/smb.conf. This file uses an INI-style format, which is a fancy way of saying it’s full of sections marked by [brackets] and key-value pairs. The two most important daemons are smbd, which handles file and print sharing, and nmbd, which deals with the NetBIOS name resolution nonsense that Windows still clings to for backward compatibility.

A minimal, bone-stupid smmb.conf to create a share might look like this:

[global]
   workgroup = WORKGROUP
   server string = My %h Samba Server
   security = user

[my_share]
   path = /srv/samba/share
   read only = no
   browsable = yes

You’d then create the directory, set the permissions (a topic we’ll scream about shortly), and fire it up with systemctl start smbd nmbd. But this is the “hello world” of Samba shares—functional, but missing about a hundred things you need for real use.

Authentication: The Usual Pain Point

Here’s where the designers, both at Microsoft and on the Samba team, have made choices. Questionable ones. Samba can authenticate users in two main ways:

  1. security = user: The sane default. The client (your Windows PC) must authenticate with a username and password that exists on the Samba server. This is where it gets fun. Samba users are backed by real Linux users. You can’t have a Samba user without a system user account. But crucially, their Samba password is set separately using the smbpasswd command.

    # First, create the Linux user (if they don't exist)
    sudo useradd -s /sbin/nologin myuser
    # Now, set their Samba password. This is what Windows will use.
    sudo smbpasswd -a myuser
    

    Why the separation? Because storing passwords is messy, and Samba needed its own database to handle the weird hashing requirements of the various SMB protocol versions. It’s a hassle, but it’s a necessary one.

  2. security = ads: This is for when you want to join a Windows Active Directory domain. Your Samba server becomes a member of the domain, and it lets the AD Domain Controllers handle authentication. It’s more complex to set up but is the “correct” way in a corporate environment. We’ll leave that for a more advanced chapter, lest we both start crying.

The most common pitfall? Permission denied errors because you forgot to run smbpasswd -a for a user after creating their Linux account. I’ve done it. You’ll do it. We all do it.

Permissions: The Layer Cake of Despair

This is the single most important concept to grasp. Windows and Linux have fundamentally different permission models. When Samba serves a file, it has to translate between them, and it uses two sets of rules to do it:

  1. Linux Filesystem Permissions: The absolute foundation. The smbd daemon runs as root, but it accesses files as the user it authenticated. If the Linux user myuser doesn’t have read permission on a file in /srv/samba/share, it doesn’t matter what you put in smb.conf—the kernel will say no. Always, always use ls -l on your share directory first when troubleshooting.

  2. Samba Share Permissions: These are defined in smb.conf and are processed after the Linux kernel has already said “yes.” You can have a directory world-readable on Linux (777) but set read only = yes in the share definition, making it read-only for Samba clients. Conversely, you can have read only = no but if the underlying file is mode 444, the user still can’t write to it. Samba’s settings can only restrict permissions further, not grant new ones.

The best practice? Decide on a ownership strategy. I prefer creating a dedicated Linux group (e.g., sambashare), adding my Samba users to it, and then setting the share directory to be owned by that group with the setgid bit to ensure new files inherit the group.

sudo groupadd sambashare
sudo chgrp sambashare /srv/samba/share
sudo chmod 2770 /srv/samba/share  # 2 = setgid, 770 = rwx for owner & group
sudo usermod -aG sambashare myuser

This way, any file myuser creates in the share is automatically owned by the sambashare group, allowing your other Samba users in that group to access it.

The Protocol Versions: SMB1 is a Historical Atrocity

You must, and I cannot stress this enough, forbid SMB1. Microsoft itself has declared it a legacy protocol. It’s slow, inefficient, and horrifyingly insecure (thanks, WannaCry). Modern Windows versions have it disabled by default. Samba will try to negotiate the highest version possible, but you should explicitly enforce a minimum of SMB2 in your [global] section to be safe.

[global]
   # ... other settings ...
   server min protocol = SMB2_02
   client min protocol = SMB2_02
   # Optionally, disable ancient and insecure auth
   ntlm auth = no

This tells both client and server to refuse to speak anything older than SMB2, saving you from yourself and any ancient clients you might have lying around. If you have something that genuinely requires SMB1, you need to have a long, hard talk with that device’s owner about their life choices.