Setting Up Samba

The steps we’ve looked at so far around setting up a home server are, in a sense, just a warmup. The ultimate step that brings the server to life is to set up Samba, the Linux software suite for serving files to Windows clients.

Choosing a Security Mode

Samba offers several security modes. The default is basic user-level security. Under this mode, you allow certain Linux users to connect to a Samba instance by creating passwords for them with smbpasswd.

I had no reason to deviate from this default, and I like that it associates actions taken within a share with a specific Linux user (rather than a general “share user”).

Selecting Share Directories

While I wanted to associate actions, and files themselves, with Linux users, I didn’t want to enforce security within the circle of Samba-enabled Linux users. Rather, any Samba user was to have access to any Samba-accessible file, whether it was her own, someone else’s, or a public file.

This desire led me away from setting up sharing within the /home hierarchy and toward  new top-level directories–two, to be exact.

User-Originated Data vs. Other Stuff

Why two top-level directories? Well, user data on a PC is typically a mix of user-originated files and files sourced from elsewhere, digital music being a prime example. Traditional Windows directory structures combine the two on a single volume, which is unfortunate: it’s easiest to do backups at the volume level, but they’re much less important for stuff we could simply re-download than for items we create.

To promote better backup practices, then, I created one top-level directory (creatively, /data1) for data that is user-originated and should be frequently backed up, and another (/data2) for sourced-elsewhere files that could be backed up less often.

Since /home data is definitely worth backing up frequently, I took the step of moving it into /data1 as linux-home (and implementing a /home > /data1/linux-home symlink). I didn’t want to provide Samba access to that data, so a /data1/all-os directory became the top-level /data1 share, with a /data2/all-os counterpart on /data2.

Putting Linux Permissions to Work

With a security mode chosen and share directories in place, the next step was to negotiate with the Linux permissions system and put it to work for me. I had the concept of the “core users” of the server being the only ones having Samba access, so I created a core-users Linux group and made it the primary group for that subset of users. I also made it the group of /data1/all-os and /data2/all-os.

Making Future Files and Directories Group-Writeable

A user’s “umask” sets the permissions on files and directories he creates. Users’ umask on my system, 0022, gives read privileges to a file’s group and read-execute privileges to a directory’s group. So far, so good: those permissions enable a file or directory created on the Samba share by one user to be viewed by other users. However, that umask denies write privileges to groups, which isn’t so hot in this context: it would prevent users from changing each others’ files.

Luckily, Samba offers force create mode (for files) and force directory mode, which override the permissions set based on umask. By setting those options to 0774 and 0775, respectively, files and directories created through Samba would be group-writeable.

Getting SELinux Types Right

There’s one final, critical piece to the puzzle. Originally, I didn’t realize this step was needed, and leaving it out had brought this project to its knees–as in, my Samba share just did not work! …And I was dumbfounded as to why.

The critical step was to get the types right in my SELinux contexts.

By default, new top-level directories, like /data1 and /data2, as well as directories created under them, are given type etc_runtime_t. In a typical SELinux configuration, Samba cannot access the etc_runtime_t type.

To get things working, I had to set up file specifications to apply the samba_share_t type to /data1/all-os, to /data2/all-os, and to any files and directories that would get created under them. The syntax, which was taken from the samba_selinux man page (snapshot available on Dan Walsh’s blog), was as follows:

semanage fcontext -a -t samba_share_t "/data1/all-os(/.*)?"
semanage fcontext -a -t samba_share_t "/data2/all-os(/.*)?"
restorecon -R -v /data1/all-os
restorecon -R -v /data2/all-os

Samba shares have samba_share_t type

It’s Alive!

Once this range of steps was addressed, our Samba server came to life!

From Windows: Mapping drive letter to Samba share, copying up a file, reading it back

The end product works so seamlessly with Windows clients, one could easily forget there’s a Linux machine at the other end of the connection.

Appendix: Relevant Sections of smb.conf, as Written Out by SWAT

        workgroup = MYGROUP
        server string = Samba Server Version %v
        log file = /var/log/samba/log.%m
        max log size = 50
        force create mode = 0774
        force directory mode = 0775
        cups options = raw

        comment = Frequently backed-up data
        path = /data1/all-os
        read only = No

        comment = Infrequently backed-up data
        path = /data2/all-os
        read only = No

Battling “new-host,” Round Two

With the home server‘s hostname problem apparently resolved, I was able to access its Samba shares from Windows machines using the desired syntax (\\jtown\...). (Configuring the shares will be the topic of the next posting.) However, I had difficulties connecting to the server by name with SSH.

Router identifies server as “new-host”

A check of the administration GUI on my Verizon FiOS router, which also functions as a DNS and DHCP server, uncovered the issue: The router was still calling the server “new-host”! As a result, DNS lookups on “jtown,” the desired hostname, were failing.

DHCP request omits hostname

Wireshark review of traffic between the server and the router confirmed the underlying problem: the server was not including its hostname in its DHCP request for an IP address. So, the router was choosing to continue calling it “new-host.”

The Red Hat documentation looked like it would guide me to a solution. It includes a section on DHCP client configuration, which talks about a promising DHCP_HOSTNAME option. The only problem was, the option belongs in a device configuration file in /etc/sysconfig/network-scripts, but with NetworkManager handling my networking, there was no such file! How, then, to proceed?

The Fix

The information in Red Hat bug #723374 put me on the path to a fix. If you’re facing the same problem I did, hopefully this approach will work for you, too.

If you’re using a networking device other than wired Ethernet on eth0, you’ll want to change the filename in step #1 accordingly.

  1. Create an /etc/dhclient-eth0.conf file. (Putting the file in /etc/dhcp works, too, but unlike /etc, non-root users can’t list that directory’s contents.) Creating the file while su‘ed to root will give non-root users privileges to read it but not write to it, which is desirable.
  2. Setting up the file per the dhclient.conf man page, write out a send host-name statement with the desired hostname (comments are supported with #):
    # Added by D. Manchester, 2 May 2012
    send host-name "jtown";
  3. Restart the NetworkManager service (sudo service NetworkManager restart).

DHCP request includes hostname

With that additional configuration file in place, Wireshark indicates that the server includes its hostname in its DHCP request. And indeed, the router now identifies the server correctly, and DNS lookups on “jtown” work!

Router identifies server as “jtown”

Shares Accessible Even Without Fix?

The fact that the home server’s Samba shares were accessible via “jtown” even without this fix offers a useful reminder: While it apparently can work with DNS, SMB/CIFS, the protocol implemented by Samba, does not require DNS for name resolution. Rather, a client can discover a server via NetBIOS broadcast, and indeed, responding to such broadcasts is the primary purpose of Samba’s nmbd daemon.

Next: Configuring Samba!