Skip to content
Muslu Yüksektepe

ntcp (nettransfer)

A single-binary Go tool that moves files and folders between two servers quickly, securely and with resume support.

nettransfer is a command-line tool I built for moving files and folders between two servers. The command is called ntcp. Transfers are encrypted with TLS 1.3, resume from where they stopped if interrupted, and skip files that were already delivered in full. The tool is written in Go using only the standard library and ships as a single executable.

Purpose

People usually move files between servers with scp or with rsync over SSH. These tools work well, but they need SSH access on the other server. When I only wanted to let a build server or a CI pipeline drop files somewhere, opening an SSH account felt like too much. scp, on the other hand, cannot resume an interrupted transfer.

I wrote ntcp to fill that gap. My aim was a transfer tool that runs as a service on the receiving side, is authorised with a time-limited or permanent token instead of SSH, survives interruptions and installs with a single command.

How it works

On the receiving server, ntcp install installs the tool as a service, generates the first token and prints it once. ntcp init chooses whether tokens are permanent or expire after a set time. On the sending machine, a transfer is started by giving the local path, the server address, the token and optionally a target directory.

Once connected, the client first sends a manifest, a summary listing the files to be sent with their sizes and modification times. For each file the server replies with one of three answers: the file is already complete, the file does not exist, or the file is partial. For partial files the server sends a bitmap showing which blocks it already has, and the client sends only the missing blocks.

Data moves in fixed 4 MiB blocks. Each block travels with a 20-byte header made up of the file index, offset, length and a CRC32C checksum. The checksum is used to detect whether the data was damaged on the way. The state of an unfinished transfer is kept on the server in temporary files with the .emr and .emr.bm extensions, and running the same command again continues from them.

The target path rules resemble rsync. If the local path ends with a slash, only the folder's contents are sent; otherwise the folder itself is sent. A relative target puts the files under the server's data directory. An absolute target can write anywhere the service has permission to write.

Key features

  • An interrupted transfer resumes at block level when the same command is run again.
  • Files with the same size and modification time are skipped, while files whose content changed are sent again.
  • Connections are encrypted with TLS 1.3 and the server certificate is pinned with TOFU. TOFU means recording the certificate fingerprint seen on the first connection and refusing later connections that present a different certificate.
  • For CI environments, the expected certificate fingerprint can be supplied in advance through an environment variable.
  • Tokens are generated from 32 random bytes and only their SHA-256 hashes are stored on the server.
  • Tokens are checked with a constant-time comparison, which prevents information from leaking through response times.
  • When time-limited tokens expire, the service removes them automatically every 10 minutes.
  • Newly generated tokens take effect without restarting the service.
  • A limit of 60 attempts per minute per IP and at most 100 concurrent connections is enforced.
  • Paths containing .. are rejected on both the sending and the receiving side.
  • The optional --delete-after flag deletes the local source after a successful transfer.
  • When the terminal supports it, a coloured interface and an animated progress bar are shown.

Technical stack

ntcp is written in Go with no external dependencies, using only the standard library. All of the code lives in a single source file. TCP connections use keep-alive, NoDelay to reduce latency and 2 MiB buffers. The server generates a self-signed certificate, and the certificate, private key and token file are stored with owner-only permissions.

The service is installed with systemd on Linux, launchd on macOS and the Windows service manager on Windows. The systemd unit on Linux comes with hardening settings that protect system directories and prevent privilege escalation. The tool is built for six platforms across Linux, macOS and Windows. GitHub Actions checks and builds every change, and when a version tag is pushed, binaries for all platforms are published automatically. There are shell install scripts for Linux and macOS and a PowerShell script for Windows. The project is MIT licensed.

Use cases

  • Sending a website's built files to the publishing directory on a server.
  • Moving database backups to another server and deleting the local copy once the transfer is complete.
  • Dropping files on a server from CI/CD pipelines with only a token, without opening an SSH account.
  • Transferring files of tens of gigabytes completely even when the connection drops along the way.
  • Quickly re-sending a single changed file, such as a stylesheet, to its place on the server.

Status

I released the first version in 2026 and developed it up to version 0.4.0 on the same day. The latest version added absolute target paths, an rsync-like trailing slash rule and the option to delete the local source after a transfer.

Category
Networking, servers & infrastructure
Year
2026

Technologies

  • Go
  • TLS 1.3
  • CLI
  • Open Source

Links

  • GitHub https://github.com/muslu/nettransfer

Back to all projects