Skip to content

Your own private cloud file share with Samba, Alpine Linux, and Nebula

Image

There is a certain kind of person who looks at services like Dropbox or OneDrive and thinks: "Why would I let someone else hold my files when I can spend three hours on a Saturday doing it myself and have something objectively cooler?" If you are that kind of person, welcome. This article is for you.*

What we are building here is a private Samba file server running on Alpine Linux, accessible exclusively through a Nebula overlay network. The end result is a share that behaves like a classic network drive but lives on your own infrastructure and is, by design, invisible to the rest of the internet. No open ports. No exposed services. No surprises.


Why Nebula?

Nebula is a scalable, peer-to-peer overlay network built by Slack. It uses WireGuard-style cryptography, certificate-based authentication, and punches through NAT without needing a central relay. Nodes on a Nebula network can communicate directly with each other regardless of where they physically are, on a VPS, behind a home router, or on a laptop in a coffee shop.

The relevant property for this setup is that a service bound exclusively to a Nebula interface is simply not reachable from the public internet. There is no firewall rule to forget, no accidental exposure. If you are not on the Nebula network with a valid certificate, the service does not exist as far as you are concerned. That is not security through obscurity, that is just topology.


Prerequisites

  • A server running Alpine Linux (this was tested on Alpine 3.23.2)
  • Nebula installed and running on that server with a static Nebula IP (we will use 10.x.x.1 as the example throughout)
  • A client machine also connected to the same Nebula network
  • Basic comfort with the command line

Step 1: Install Samba

apk add samba

Alpine's package manager pulls in both smbd (the file sharing daemon) and nmbd (the name resolution daemon). After installation, /etc/samba/ exists and is ready to be configured.


Step 2: Create a system user

Each person who gets a share needs a corresponding system user. Samba relies on the underlying OS user database for file ownership, but we do not want these accounts to have any actual access to the server itself.

adduser -D -H -s /sbin/nologin alice

Breaking this down:

  • -D — do not set a system password. The account cannot be used for system login regardless, but this makes that explicit.
  • -H — do not create a home directory under /home/. There is no reason for one.
  • -s /sbin/nologin — assign /sbin/nologin as the shell. This is not a real shell. It is a small binary that prints "This account is currently not available" and terminates the session immediately. SSH, console login, su --> all blocked. The user exists purely as a system principal so that file ownership works correctly.

You can verify the effect yourself:

cat /etc/shells        # lists all valid login shells on the system
cat /etc/passwd        # shows every user and their assigned shell

/sbin/nologin is not listed in /etc/shells, which is what prevents it from being used as a login shell.


Step 3: Set a Samba password

Linux and Samba maintain completely separate password databases. The system uses /etc/shadow. Samba uses its own TDB (Trivial Database) file at /var/lib/samba/private/passdb.tdb. You can have a system account with no password and a perfectly valid Samba password, which is exactly what we want.

smbpasswd -a alice

The -a flag adds the user to Samba's password database and prompts you to set a password. This is what alice will use when mounting the share from her client.


Step 4: Create the user's directory

mkdir -p /mnt/alice
chown alice:alice /mnt/alice
chmod 700 /mnt/alice
  • mkdir -p creates the directory, and the -p flag means it will not complain if the directory already exists.
  • chown alice:alice sets both the owner and the group to alice. This is what ties the filesystem permissions to the Samba user.
  • chmod 700 means the owner can read, write, and traverse the directory. Nobody else can see it, let alone touch it.

Step 5: Check your Nebula interface name

Before writing the Samba configuration, identify the name of your Nebula network interface:

ip link show

Look for an interface with your Nebula IP. It will typically be nebula0 or nebula1, and its type will show as POINTOPOINT. Note the name — you will need the IP address in the next step.

ip a | grep nebula

In this setup the interface was nebula1 with the address 10.x.x.1/24.


Step 6: Configure Samba

cat > /etc/samba/smb.conf << 'EOF'
[global]
   workgroup = WORKGROUP
   server string = My Samba Server
   security = user
   map to guest = never
   passdb backend = tdbsam

   interfaces = lo 10.x.x.1/24
   bind interfaces only = yes

   disable netbios = yes
   smb ports = 445

[alice]
   path = /mnt/alice
   valid users = alice
   read only = no
   browseable = yes
EOF

What each directive does and why it matters

[global] section:

  • security = user — clients must authenticate with a username and password. No anonymous access.
  • map to guest = never — if authentication fails, the connection is dropped. There is no fallback to a guest session.
  • passdb backend = tdbsam — use Samba's built-in TDB password database, which is what smbpasswd writes to.
  • interfaces = lo 10.x.x.1/24 — instruct Samba to listen only on the loopback interface and the Nebula interface. The /24 subnet notation is important here: Nebula uses a POINTOPOINT tunnel interface, and without the subnet mask Samba may fail to bind to it correctly. This was the root cause of the issue encountered during this setup, without /24, Samba stubbornly listened only on 127.0.0.1.
  • bind interfaces only = yes — enforce the interface restriction strictly. Samba will not listen on any interface not listed above.
  • disable netbios = yes — NetBIOS is a legacy broadcast-based name resolution protocol from the 1980s. We do not need it. Disabling it reduces noise and removes an unnecessary attack surface.
  • smb ports = 445 — modern SMB runs on TCP port 445. Port 139 (the old NetBIOS session port) is not needed.

[alice] section:

  • path — the filesystem path being shared.
  • valid users — only the named user can access this share. Even if someone else on the Nebula network knows the share exists, they cannot authenticate into it.
  • read only = no — the user can read and write. Self-explanatory.
  • browseable = yes — the share appears in the share list when browsing to the server. Since the server is only reachable via Nebula and all Nebula nodes are trusted, hiding the share name provides no real benefit.

You can verify the configuration is syntactically valid before restarting anything:

testparm

Step 7: Start Samba and enable it on boot

Alpine uses OpenRC as its init system:

rc-service samba start
rc-update add samba default
  • rc-service samba start — starts both smbd and nmbd immediately.
  • rc-update add samba default — registers Samba in the default runlevel so it comes back up after a reboot without any manual intervention.

Verify that Samba is actually listening on the Nebula IP:

netstat -tlnp | grep 445

You want to see 10.x.x.1:445 in the output. If you only see 127.0.0.1:445, double-check that you included the /24 subnet mask in the interfaces line and restart.


Step 8: Connect from a client

From a macOS client connected to the same Nebula network, open Finder and press ⌘K, then enter:

smb://10.x.x.1/alice

On Windows, open File Explorer and go to:

\\10.x.x.1\alice

Authenticate with the Samba username and the password set in step 3. The share mounts as a regular network drive. You can map it permanently if you want it available at every login.


Adding more users

The process is entirely repeatable. For each new user:

adduser -D -H -s /sbin/nologin bob
smbpasswd -a bob
mkdir -p /mnt/bob
chown bob:bob /mnt/bob
chmod 700 /mnt/bob

Add a corresponding block to /etc/samba/smb.conf:

[bob]
   path = /mnt/bob
   valid users = bob
   read only = no
   browseable = yes

Then reload:

rc-service samba restart

Each user can see their own share and nothing else. Users cannot traverse into each other's directories due to the chmod 700 permissions, and the valid users directive in Samba provides an additional layer on top of that.


A note on backups

If you are running a backup job that archives /mnt/ (like I do) and you should be, all user shares under /mnt/ are automatically included without any changes to the backup configuration. There is nothing special about the Samba directories from the filesystem's perspective. They are just directories.


Why this is actually a private cloud share

The key property of this setup is that the Samba service is bound exclusively to a Nebula interface. No firewall rule is required to block access from the public internet because the service is not listening on any public interface in the first place. A port scanner hitting your server's public IP will find nothing on port 445.

Access requires two things: a valid Nebula certificate (issued by your Nebula certificate authority) and a valid Samba password. Both are required. One without the other is useless.

The result is a file share that is accessible from anywhere your Nebula nodes can reach each other, which is effectively anywhere with an internet connection, while remaining completely invisible to everyone else. That is a private cloud file share in the most literal sense of the word, without a third party holding your data, without a subscription, and without a monthly bill reminding you that convenience has a price.

The only thing it costs is a Saturday afternoon. Some would call that a bargain.