Skip to content

Repository files navigation

Bitsend

Bitsend cover art

Files, where they belong. A fast, native Rust file drop for computers, devices, and programs.

Project website / Program integration guide / MIT License

Bitsend has a host GUI, a client GUI, a CLI, and two threaded HTTP servers on the same host IP.

Two-server design

Server Default port Used by Authentication Purpose
Host/control server 8787 Host GUI, bitsend-cli, admin automation Static host token Program/device records, API-key generation, kick/restore/regenerate, host status/config
Client/data server 8788 Bitsend Client and programs Per-device 16-character API key Status, heartbeat, file listing, streaming upload/download

Both servers bind to 0.0.0.0 and therefore work over Ethernet, Wi-Fi, and Tailscale. They use separate Tokio multi-threaded runtimes. The data server never accepts the host token, and the control server never accepts a device API key.

For a remote program, use:

http://HOST_TAILSCALE_IP:8788 + X-Bitsend-Api-Key: YOUR_16_CHARACTER_KEY

A program needs both the host's Tailscale IP and its own API key to use the client/data server. See md/agent.md for the full program-integration contract and request examples.

Features

  • Native cross-platform GUI built with egui/eframe.
  • Google Material Symbols Rounded icons bundled for the native GUI and landing page.
  • Pastel flat UI with lightweight status animations and no gradients.
  • Async Rust HTTP APIs built with Axum and Tokio.
  • Separate threaded control and data servers for responsive administration during transfers.
  • Streaming uploads and downloads; uploads are limited to 10 GiB by default.
  • Configurable host drop folder.
  • Host GUI shows local IP, Tailscale IP, both ports, static host token, JSON path, and devices/programs.
  • Generate a persistent 16-character API key for every program or device.
  • Kick without deleting; restore later or regenerate a replacement key.
  • Device/program records and authorization state survive restarts in JSON.
  • Client GUI requires an API key before displaying host information or files.
  • CLI for pairing programs, generating keys, checking status, listing, uploading, downloading, and administration.
  • No database or external service is required.

GitHub presentation

The website/ directory is a dependency-free GitHub Pages landing page with the same pastel, flat visual system as the native GUI. It includes responsive animation, no gradients, and a bundled Google Material Symbols font with no JavaScript library dependency. Use website/assets/bitsend-cover.svg as the repository's 1280x640 social-preview artwork. The included .github/workflows/pages.yml publishes the site from GitHub Actions; replace YOUR_GITHUB_USERNAME in the website links before publishing.

Platform guides

The packaging scripts are packaging/build-deb.sh and packaging/build-windows.ps1. The Linux package contains the host, client, and CLI binaries. A Linux host and Windows client are protocol-compatible. For a CLI-only build without the native GUI stack, use cargo build --release --locked --no-default-features --bin bitsend-cli. A verified Linux Mint package and matching Linux binaries are in artifacts/linux/; Windows .exe packages are produced by the GitHub Actions release workflow.

Requirements

Install a current stable Rust toolchain using rustup. Rust 1.80 or newer is recommended.

Linux GUI dependencies

On Debian/Ubuntu:

sudo apt update
sudo apt install build-essential pkg-config libx11-dev libxcb1-dev \
  libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev \
  libxkbcommon-dev libwayland-dev

Linux needs a working X11 or Wayland desktop session.

Windows

Install the MSVC Rust toolchain and Visual Studio Build Tools with the Desktop C++ workload. Windows Defender Firewall may ask whether bitsend-host.exe should accept private-network connections; allow it for networks where the host should be reachable.

Build and run

cd bitsend
cargo fmt
cargo test --lib --locked -j 1
cargo build --release --locked -j 1

Release binaries are written to target/release/:

  • bitsend-host / bitsend-host.exe
  • bitsend-client / bitsend-client.exe
  • bitsend-cli / bitsend-cli.exe

Start the host computer:

cargo run --release --bin bitsend-host

Start a GUI client:

cargo run --release --bin bitsend-client

The host remains running while its GUI process is running. It starts both API servers in the background.

Host CLI options

bitsend-host --port 8787 --client-port 8788 --data-file /path/to/bitsend-host.json

Aliases: --admin-port is the same as --port.

On Windows PowerShell:

bitsend-host.exe --port 8787 --client-port 8788 `
  --data-file "$env:APPDATA\Bitsend\host.json"

If no options are supplied, the host uses ports 8787 and 8788.

The default host JSON path is:

  • Linux: $XDG_CONFIG_HOME/bitsend/host.json, or $HOME/.config/bitsend/host.json
  • Windows: %APPDATA%\Bitsend\host.json

The default drop folder is BitsendDrop in the directory from which the host was first launched. Change it from the host GUI.

With UFW on Linux, allow both private-network ports if needed:

sudo ufw allow 8787/tcp
sudo ufw allow 8788/tcp

Pair a program and generate its API key

Host GUI

  1. Start Bitsend Host.
  2. Confirm the Tailscale client/data address shown in the connection details.
  3. Enter a program name and type, such as backup-agent and program.
  4. Click Add + generate API key.
  5. Give the program the displayed 16-character API key.
  6. Configure the program with the host Tailscale IP and client/data port 8788.

CLI

The static host token is visible in the host GUI. Use it only against the host/control port:

bitsend-cli keygen \
  --admin http://HOST_TAILSCALE_IP:8787 \
  --host-token STATIC_HOST_TOKEN \
  --name backup-agent \
  --kind program

The command prints the persistent API key. The alias pair performs the same operation.

For automation, use --json:

bitsend-cli keygen --admin http://HOST_TAILSCALE_IP:8787 \
  --host-token STATIC_HOST_TOKEN --name backup-agent \
  --kind program --json

A kicked device can be paired again with its existing --device-id; this creates a fresh key and reauthorizes that record.

Program CLI examples

Use the client/data port and API key for every program data operation:

# Check that the authenticated data server is working
bitsend-cli status \
  --server http://HOST_TAILSCALE_IP:8788 \
  --api-key PROGRAM_API_KEY

# Keep the program marked online
bitsend-cli heartbeat \
  --server http://HOST_TAILSCALE_IP:8788 \
  --api-key PROGRAM_API_KEY

# List the drop folder
bitsend-cli list \
  --server http://HOST_TAILSCALE_IP:8788 \
  --api-key PROGRAM_API_KEY

# Send a file
bitsend-cli upload \
  --server http://HOST_TAILSCALE_IP:8788 \
  --api-key PROGRAM_API_KEY \
  --file ./state.db

# Download a file
bitsend-cli download \
  --server http://HOST_TAILSCALE_IP:8788 \
  --api-key PROGRAM_API_KEY \
  --name state.db \
  --output ./state-copy.db

Use bitsend-cli help for all commands. admin-status, list, status, upload, and the other administration commands support --json where useful.

Tailscale

Install and sign in to Tailscale on both computers and ensure they are in the same tailnet. In the host GUI, use the displayed Tailscale client API address, for example:

http://100.64.12.34:8788

If the host GUI says Tailscale was not detected, start the Tailscale service and wait for its network scan or reopen Bitsend Host.

HTTP API

Host/control server

All control endpoints require either:

X-Bitsend-Host-Token: STATIC_HOST_TOKEN

or:

Authorization: Bearer STATIC_HOST_TOKEN

Endpoints:

Method Path Purpose
GET /api/v1/admin/status Control status, both ports, detected IPs, and remembered devices
GET /api/v1/admin/config Current host/control and client/data configuration
GET /api/v1/admin/devices List programs/devices and their keys
POST /api/v1/admin/devices Create a program/device key
POST /api/v1/admin/api-keys Alias for key generation
POST /api/v1/admin/devices/{id}/kick Disable a device without deleting it
POST /api/v1/admin/devices/{id}/restore Reauthorize a kicked device with its existing key
POST /api/v1/admin/devices/{id}/regenerate Replace its key and authorize it
POST /api/v1/pair JSON host-token pairing alias

Create a key directly:

curl -sS -X POST http://HOST_TAILSCALE_IP:8787/api/v1/admin/api-keys \
  -H 'X-Bitsend-Host-Token: STATIC_HOST_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"name":"backup-agent","kind":"program"}'

Client/data server

All data endpoints require:

X-Bitsend-Api-Key: 16_CHARACTER_PROGRAM_KEY

or Authorization: Bearer 16_CHARACTER_PROGRAM_KEY.

Method Path Purpose
GET /api/v1/info Authenticated server/device information and file list
GET /api/v1/status Authenticated working/status response
POST /api/v1/heartbeat Mark a program online
GET /api/v1/files List files
POST /api/v1/files Multipart upload with field name file
GET /api/v1/files/{filename} Stream a file from the drop folder

Example upload:

curl -X POST http://HOST_TAILSCALE_IP:8788/api/v1/files \
  -H 'X-Bitsend-Api-Key: PROGRAM_API_KEY' \
  -F 'file=@./state.db'

Security notes

  • Bitsend is intended for a trusted LAN or a Tailscale network, not direct public-Internet exposure.
  • Plain HTTP sends credentials over the local network without TLS. Tailscale encrypts tailnet traffic. Use an HTTPS reverse proxy if TLS is required outside Tailscale.
  • The static host token can create keys and administer all devices. Protect it like an administrator password.
  • Per-program API keys grant access to the client/data server and should be kept secret.
  • The host JSON contains the host token and API keys. Protect it with operating-system file permissions.
  • The API rejects path traversal and refuses symlink entries when downloading.
  • Kicking blocks a key immediately. Regenerate if a key may have been copied.

Development

cargo fmt
cargo test --lib --locked -j 1
cargo clippy --all-targets --all-features
cargo build --release --locked -j 1

About

Send files via LAN or tailnet, with an api that any program can use!

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages