DEV Community

Cover image for The Superior way to share files over a LAN
Shoban Chiddarth
Shoban Chiddarth

Posted on

The Superior way to share files over a LAN

GitHub: @ShobanChiddarth/openssh-server


You need to send a file to another machine on your network. It should be a solved problem. It is not.

Every method people actually reach for is either insecure, annoying to set up, or leaves something running on your machine long after you needed it. This post is about the one approach that gets all three things right - and it takes about two minutes to set up.


What You're Probably Doing (And Why It's Bad)

Let's go through the common options honestly.

Python HTTP server

python3 -m http.server 8080
Enter fullscreen mode Exit fullscreen mode

Everyone knows this one. It works, and that's roughly where the positives end. Traffic is completely unencrypted. Anyone on the same network can see every byte in transit. There's no authentication - anyone who can reach the port can download anything you're serving.

Netcat

# sender
nc -l 9999 < file.txt

# receiver
nc 192.168.1.x 9999 > file.txt
Enter fullscreen mode Exit fullscreen mode

Same problem. Cleartext, no auth, one shot if you're lucky. It's basically a raw pipe over TCP dressed up as a tool.

Installing openssh-server on your machine

This one at least solves the encryption problem. But now you've installed a permanent service on your host OS. sshd is running all the time, listening on port 22, attached to your actual system - its users, its filesystem, its everything. You wanted to share one folder for five minutes. You now have a permanently expanded attack surface.

And if you give the other person SSH credentials? They have a shell into your real machine. Full access. That's a lot of trust for a quick file transfer.

Samba / NFS

Heavy to configure, plenty of surface area, and definitely not something you spin up for a quick transfer and tear down cleanly.


The Actual Problem

The core issue with all of these is that they either skip encryption entirely, or they go too far in the other direction and give the other party more access than a file transfer requires.

What you actually want is:

  • Encrypted transfer
  • Auth (so not just anyone on the LAN can connect)
  • Access scoped to exactly one directory, nothing else
  • Zero footprint when you're done

The Solution: OpenSSH Inside a Docker Container

Here's the idea: run an SSH server inside a Docker container. Mount only the specific directory you want to share into that container. The other party connects over SSH, lands in that directory, and that's all they can see - not your home folder, not your system files, not anything else on your machine. When the transfer is done, you stop the container and it's completely gone.

The host OS never has sshd installed. No permanent service. No lingering open port. The container is the entire blast radius.

I built and published this as a ready-to-use Docker image with two variants: one based on Alpine Linux (smaller, recommended) and one based on Ubuntu Noble. The image handles user creation, password setup, and public key injection entirely through environment variables.


How It Works

When the container starts, the entrypoint script does the following:

  1. Reads SSH_USER, SSH_PASSWORD, and SSH_PUBLIC_KEY from environment variables
  2. Creates a low-privilege user inside the container with those credentials
  3. Writes the public key to that user's ~/.ssh/authorized_keys
  4. Starts sshd in the foreground

The user's home directory inside the container is whatever you bind-mount from your host. They can read and write files there. That's the full extent of what they can touch.


Step-by-Step: Running It

Prerequisites: Docker installed and running. That's it.

1. Pull the image

docker pull shobanchiddarth/openssh-server:alpine-1.0.0
Enter fullscreen mode Exit fullscreen mode

Or if you prefer the Ubuntu variant:

docker pull shobanchiddarth/openssh-server:ubuntu-noble-1.0.0
Enter fullscreen mode Exit fullscreen mode

2. Create the directory you want to share

mkdir -p /tmp/myshare
Enter fullscreen mode Exit fullscreen mode

Put whatever files you want to transfer in here, or leave it empty for the other party to upload into.

3. Set up your environment variables

Grab the sample.env from the repo and copy it:

cp sample.env .env
Enter fullscreen mode Exit fullscreen mode

Edit .env:

SSH_USER=USERNAME
SSH_PASSWORD=PASSWORD
SSH_PUBLIC_KEY=ssh-ed25519 AAAA... you@yourmachine
Enter fullscreen mode Exit fullscreen mode

SSH_PUBLIC_KEY is optional in practice - if the other party doesn't have a key pair, they'll just use the password. But public key is always preferable.

4. Run the container

docker run -d \
  --name myshare \
  -p 0.0.0.0:2222:22 \
  --env-file .env \
  -v /tmp/myshare:/home/USERNAME \
  shobanchiddarth/openssh-server:alpine-1.0.0
Enter fullscreen mode Exit fullscreen mode

The -v flag is the key part. /tmp/myshare is the folder on your machine. /home/USERNAME is where the SSH user lands inside the container. Those two are linked - anything written to one appears in the other. The username in the path should match SSH_USER in your .env.

Your LAN IP is whatever ip a (Linux) or ipconfig (Windows) shows for your network interface - typically something like 192.168.1.x.

5. Transfer files from the other machine

# Upload a file
scp -P 2222 /path/to/file.txt USERNAME@192.168.1.x:~/

# Download a file
scp -P 2222 USERNAME@192.168.1.x:~/file.txt ./

# Interactive session
sftp -P 2222 USERNAME@192.168.1.x
Enter fullscreen mode Exit fullscreen mode

This works from Linux, macOS, and Windows (via PowerShell with OpenSSH, WSL, or Git Bash - all ship with scp and sftp).

6. Tear it down

docker stop myshare
docker rm myshare
Enter fullscreen mode Exit fullscreen mode

Port closed. No service running. Nothing left behind.


Windows Host Note

If you're running Docker Desktop on Windows, the volume mount path uses Windows-style paths:

docker run -d `
  --name myshare `
  -p 0.0.0.0:2222:22 `
  --env-file .env `
  -v C:\Users\YourName\myshare:/home/USERNAME `
  shobanchiddarth/openssh-server:alpine-1.0.0
Enter fullscreen mode Exit fullscreen mode

Everything else - the scp/sftp commands from the client side - is identical.


Security Properties at a Glance

Property Behavior
Encryption SSH - all traffic encrypted in transit
Authentication Password + public key
Host filesystem Completely inaccessible from inside the container
Shell access Scoped to the container only
Host SSH daemon Never installed
Persistence after use Zero - stop the container, it's gone

One thing worth being explicit about: bind the port to 0.0.0.0 only on trusted networks. That makes the container reachable on all your local interfaces. If you want to lock it down to a specific interface, replace 0.0.0.0 with that interface's IP (e.g., 192.168.1.5:2222:22). Either way, don't forward port 2222 through your router - this is a LAN tool.


Why This Is Better

The Python HTTP server is convenient. This is only marginally less convenient - one docker run command instead of one python3 command - and in exchange you get encryption, authentication, proper access scoping, and a completely clean teardown.

If you have Docker, there's no good reason to reach for the HTTP server anymore.

The repo has both Alpine and Ubuntu variants, a sample.env template, and full usage documentation. Pull it, try it, and stop sharing files over cleartext.


The known_hosts problem

Let's say you want your friend to share a file to you. So you ask him his public ssh key and spin up a container with port and volume mapped. And then he tries to ssh into your container. Then he gets hit with this

ssh test@192.168.1.2
The authenticity of host '192.168.1.2 (192.168.1.2)' can't be established.
ED25519 key fingerprint is SHA256:9d8pzTNQ1vLi2laKIqHnzOG+QdgNv8bDQVz67sNJi1E.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? 
Enter fullscreen mode Exit fullscreen mode

This is the unknown host warning, it is what ssh usually does to make sure you are accessing the machine you think you are accessing by showing the host key of the machine. So since your friend knows he is accessing your machine and trusts is, he types yes and then the host key gets added to ~/.ssh/known_hosts file. He then finishes the file sharing work and then closes the connection so you stop the container and delete it. Some time later if he wants to do another file sharing work, you spin up another container and if you are in the same LAN with the same private IP, ssh client on his machine sees your host with a different ssh host key when he is trying to access it. So it prints a message like this

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ED25519 key sent by the remote host is
SHA256:s9QoffY4cHer0u66A9s57WzN3/ufOfCBGTq/v9fhr5w.
Please contact your system administrator.
Add correct host key in /home/mint/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/mint/.ssh/known_hosts:3
  remove with:
  ssh-keygen -f '/home/mint/.ssh/known_hosts' -R '[192.168.56.1]:2222'
Host key for [192.168.56.1]:2222 has changed and you have requested strict checking.
Host key verification failed.
Enter fullscreen mode Exit fullscreen mode

But this can be ignored since it is true that the host key has changed and he has to remove the old known hosts entry with

ssh-keygen -f '/home/mint/.ssh/known_hosts' -R '[192.168.56.1]:2222'
Enter fullscreen mode Exit fullscreen mode

as said in that message. If it is unsure whether or not SOMEONE is doing SOMETHING NASTY you should send your host key to your friend and ask him to compare. You can do it by

docker exec -it myshare /bin/sh # or /bin/bash if ubuntu
cd /etc/ssh
ls *host*.pub # to see the host public key names
ssh-keygen -lf ssh_host_ecdsa_key.pub 
ssh-keygen -lf ssh_host_ed25519_key.pub 
ssh-keygen -lf ssh_host_rsa_key.pub
Enter fullscreen mode Exit fullscreen mode

Now send the output of the last 3 commands to him and tell him to enter the fingerprint of the algorithm (ecdsa or ed25519 or rsa) he is seeing in his screen and if it matches the host will be added to known_hosts (with the current host public key, so he will have to remove it later by following the above instructions) and the connection will happen.


GitHub: @ShobanChiddarth/openssh-server

Top comments (0)