Sign inSign up

marcusholtz/i2p-party-line

By marcusholtz

Updated about 6 hours ago

Encrypted push-to-talk voice and group party line over I2P.

Image
Networking
Security
0

160

marcusholtz/i2p-party-line repository overview

I2P Party Line


Built for I2P License: MIT Source: GitLab Source: GitHub

marcusholtz/i2p-party-line

Encrypted push-to-talk voice and group party line over I2P. No accounts, no phone numbers, no servers, no open ports.

Supported Architectures

ArchitectureTag
x86-64amd64

Quick Start: Interactive Calling

Pull and run the interactive menu. Make calls, listen for calls, set secrets, test audio.

Save as docker-compose.yml, then run docker compose run --rm partyline:

services:
  partyline:
    image: marcusholtz/i2p-party-line:latest
    container_name: i2p-party-line
    restart: unless-stopped
    stdin_open: true
    security_opt:
      - label:disable
    devices:
      - /dev/snd:/dev/snd
    volumes:
      - ./data/docker/partyline:/data/.partyline
      - ./secrets:/run/secrets:ro
      - ${XDG_RUNTIME_DIR:-/run/user/1000}/pulse:/run/user/${UID:-1000}/pulse
    environment:
      - TERM=${TERM:-xterm-256color}
      - SHARED_SECRET_FILE=/run/secrets/shared_secret.txt
      - PULSE_SERVER=unix:/run/user/${UID:-1000}/pulse/native
      - XDG_RUNTIME_DIR=/run/user/${UID:-1000}
docker cli
docker run -it --rm \
  --name i2p-party-line \
  --security-opt label:disable \
  --device /dev/snd:/dev/snd \
  -v ./data/docker/partyline:/data/.partyline \
  -v ./secrets:/run/secrets:ro \
  -v ${XDG_RUNTIME_DIR}/pulse:/run/user/$(id -u)/pulse \
  -e TERM=${TERM} \
  -e SHARED_SECRET_FILE=/run/secrets/shared_secret.txt \
  -e PULSE_SERVER=unix:/run/user/$(id -u)/pulse/native \
  -e XDG_RUNTIME_DIR=/run/user/$(id -u) \
  marcusholtz/i2p-party-line:latest
First run
  1. i2pd reseeds and builds tunnels (~23 s for relay, ~86 s for calls from cold start)
  2. Your .b32.i2p address appears (no ports needed; I2P routes through tunnel gateways)
  3. Press 1 to set a shared secret (both sides need the same one)
  4. Share your address + secret, one side listens, the other calls

Your destination key persists in ./data/docker/partyline/ across restarts.

Quick Start: Always-On Relay

Run a persistent group bridge. Callers dial your .b32.i2p and are bridged together.

docker-compose

Using the same docker-compose.yml above:

# Start relay in background (i2pd builds tunnels, group bridge opens)
docker compose up -d

# Watch live activity
docker compose logs -f

# Stop
docker compose down
docker cli
docker run -d \
  --name i2p-party-line-relay \
  --restart unless-stopped \
  --security-opt label:disable \
  -v ./data/docker/partyline:/data/.partyline \
  -v ./secrets:/run/secrets:ro \
  -e SHARED_SECRET_FILE=/run/secrets/shared_secret.txt \
  marcusholtz/i2p-party-line:latest \
  relay

No audio mounts needed for relay mode (it forwards encrypted blobs, never decodes audio).

Parameters

ParameterFunction
-e SHARED_SECRET_FILEPath to secret file inside container. Default: /run/secrets/shared_secret.txt
-e OPUS_BITRATE=16Opus encoding bitrate in kbps
-e LISTEN_PORT=7777TCP listen port
-e I2P_SOCKS_PORT=4457i2pd SOCKS proxy port (loopback-only)
-e CIPHER=aes-256-cbcEncryption cipher (21 options)
-e HMAC_AUTH=1HMAC-sign protocol messages (0/1)
-e SINGLE_HOP=0Faster, less anonymous (0/1)
-e AUTO_LISTEN=0Auto-listen when i2pd is ready (0/1)
-e ALSA_DEVICE=Force ALSA capture device, e.g. plughw:2,0
-e ALSA_PLAY_DEVICE=Force ALSA playback device, e.g. plughw:0,0
-e PULSE_SERVERPulseAudio/PipeWire socket path
-v /data/.partylineConfig, I2P key, encrypted secret (persistent)
-v /run/secretsShared secret file (read-only mount)
-v /run/user/$UID/pulseHost audio socket
--device /dev/sndALSA fallback for bare-ALSA hosts

Shared Secret

The secret is not an environment variable. It is a bind-mounted file:

mkdir -p secrets
echo -n 'your-shared-secret' > secrets/shared_secret.txt
chmod 600 secrets/shared_secret.txt

Per-run override: docker compose run --rm partyline call <addr> --secret 'my-secret'

A relay does not need a secret.

Audio

Audio routes through the host's PulseAudio/PipeWire socket. ALSA direct (/dev/snd) is the fallback.

arecord -l    # find capture devices on the host
aplay -l      # find playback devices on the host

Security

PropertyDetail
EncryptionAES-256-CBC + PBKDF2 + HMAC-SHA256
RelayZero-knowledge: forwards blobs, never has the secret
Authentication.b32.i2p address + pre-shared secret
Forward secrecyNone; rotate secrets between conversations
SourceSingle bash script, no binaries, no telemetry

The Party Line Trifecta

Three networks, same app, same encryption:

ProjectTransportImage
Tor Party LineTor hidden servicesmarcusholtz/tor-party-line
I2P Party LineI2P garlic routingmarcusholtz/i2p-party-line
Reticulum Party LineReticulum meshmarcusholtz/reticulum-party-line

License

MIT

Tag summary

Content type

Image

Digest

sha256:92ded772c

Size

61.2 MB

Last updated

about 6 hours ago

docker pull marcusholtz/i2p-party-line