Secure, encrypted file transfer via QR codes
Xfer enables seamless file sharing between devices using QR codes and end-to-end encryption. Send files from your desktop to your phone, or vice versa, with complete privacy.
- π Mandatory end-to-end encryption (AES-256-GCM)
- π Optional password protection for sensitive files
- π± QR code transfers - scan and go
- π Works across networks - NAT and firewall friendly
- π Zero-knowledge server - relay never sees plaintext
- β Automatic checksum verification
- π§Ύ Strict completion semantics (sender succeeds only after receiver finalizes)
- π Real-time progress tracking
- ποΈ Transfer history with privacy controls
- π¨ Modern, friendly UI
# Quick install (Linux/macOS)
curl -fsSL https://raw.githubusercontent.com/thecodefreak/xfer/main/install.sh | bash
# With Go
go install github.com/thecodefreak/xfer/cmd/xfer@latest
# Or download pre-built binaries from releases
# https://github.com/thecodefreak/xfer/releases# Run interactive setup wizard
xfer setup
# Or manually configure
xfer config set server https://xfer.example.comxfer send photo.jpg
# With password protection
xfer send --password document.pdf
# Send multiple files (auto-zipped)
xfer send file1.txt file2.txt folder/
# Send a directory
xfer send my-folder/xfer receive
# Receive to specific directory
xfer receive ~/Downloads/- Sender runs
xfer send file.txt - CLI generates encryption keys and displays a QR code
- Receiver scans the QR code with their phone
- File transfers encrypted through the relay server
- Browser decrypts locally and downloads the file
Mobile Browser ββHTTPS/E2EβββΊ Relay Server βββWSS/E2Eββ CLI Client
(decrypt) (blind relay) (encrypt)
- AES-256-GCM encryption with HKDF-SHA256 key derivation
- 256-bit cryptographic tokens for session security
- SHA-256 checksums verify file integrity
- Zero-knowledge server - cannot access file contents or metadata
- Optional Argon2id password protection for extra security
See SECURITY.md for detailed security analysis.
Configuration file: ~/.config/xfer/config.yaml
server: "https://xfer.example.com"
timeout: 10m
output-dir: "."
progress: true
history: true
hide-filenames: falsexfer send <files...> # Send files
xfer receive [path] # Receive files
xfer config <get|set|list|reset> # Manage configuration
xfer version # Show versiondocker run -d \
-e XFER_BASE_URL=https://xfer.example.com \
-p 127.0.0.1:8080:8080 \
ghcr.io/thecodefreak/xfer:latestservices:
xfer:
image: ghcr.io/thecodefreak/xfer:latest
environment:
XFER_BASE_URL: https://xfer.example.com
XFER_PORT: 8080
XFER_SESSION_TTL: 5m
XFER_MAX_SIZE: 209715200 # 200MB
ports:
- "127.0.0.1:8080:8080"
restart: unless-stoppedServer images now run on distroless as non-root. If you are upgrading from an older image, remove any explicit xfer user setting and recreate the container.
For Compose, avoid user: xfer; use user: "65532:65532" only if you need explicit user mapping.
unable to find user xfer: no matching entries in passwd file- Cause: old container config still forces
xferuser, but new image uses distrolessnonroot - Fix: remove
--user xfer/user: xfer, recreate container, then start again
- Cause: old container config still forces
Note: Server requires HTTPS reverse proxy (nginx/Traefik/Caddy) for production.
Docker release tags are published as v* and latest.
See ARCHITECTURE.md for technical details.
# Clone repository
git clone https://github.com/thecodefreak/xfer.git
cd xfer
# Install dependencies
go mod download
# Build
go build ./cmd/xfer
go build ./cmd/xfer-server
# Run tests
go test ./...MIT License - see LICENSE for details.
Contributions welcome! Please read CONTRIBUTING.md first.
Inspired by qrcp and similar tools, reimagined with security-first design.