Skip to content

Docker Deployment

Privitty Edge ships as a minimal scratch-based container image. The image contains fully static Rust binaries — no shell, no package manager, no OS-level CVE surface.

Included binaries:

Binary Role
privitty-edged Daemon (container entrypoint)
privitty-edge CLI for docker exec and health checks

Pull the image

docker pull privitty/edge:latest
docker pull ghcr.io/privitty/edge:latest

See Registries for all available tags and platforms.


Run (minimal)

docker run -d \
  --name privitty-edged \
  --restart unless-stopped \
  -e PRIVITTY_PROFILE=gateway01 \
  -p 127.0.0.1:7200:7200 \
  -v privitty-data:/var/lib/privitty \
  privitty/edge:latest

Run (production recommendations)

docker run -d \
  --name privitty-edged \
  --restart unless-stopped \
  -e PRIVITTY_PROFILE=factory-gw-01 \
  -e PRIVITTY_LICENSE_URL="https://plm.privittytech.com/v1/license/YOUR_TOKEN" \
  -e PRIVITTY_LISTEN=0.0.0.0:7200 \
  -e PRIVITTY_ACCOUNTS=/var/lib/privitty \
  -e RUST_LOG=info \
  -p 127.0.0.1:7200:7200 \
  -v privitty-data:/var/lib/privitty \
  --memory=512m \
  --cpus=1 \
  privitty/edge:latest
Recommendation Why
Bind to 127.0.0.1 on the host Keeps the JSON-RPC API off the public network
Named volume for /var/lib/privitty Persists keys, DB, blobs, and license across restarts
PRIVITTY_LICENSE_URL at start Activates license before HTTP — no restart needed
--restart unless-stopped Survives host reboots
Resource limits Prevents runaway memory on constrained gateways

Security

Do not expose port 7200 on 0.0.0.0 without a reverse proxy, firewall, or mTLS in front. The API has no built-in authentication layer — it is designed for localhost or trusted network segments.


Volumes

Mount Purpose
/var/lib/privitty Required for persistence. Account keys, SQLite DB, file blobs, privitty.lic
/etc/privitty/privitty-edged.toml Optional reference config (documentation only — see Configuration)

Volume ownership (Docker Desktop)

Fresh named volumes on macOS/Windows are often root-owned. The image entrypoint starts as root, chowns /var/lib/privitty to UID 1000, then drops privileges before writing account data. You do not need --user root or a manual alpine chown step on current images.

The daemon process runs as UID 1000 (privitty) for all runtime operations after startup.

Backup example:

docker run --rm \
  -v privitty-data:/data:ro \
  -v "$(pwd)":/backup \
  alpine tar czf /backup/privitty-backup.tar.gz -C /data .

Health check

The image includes a built-in Docker HEALTHCHECK:

HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
  CMD ["/usr/local/bin/privitty-edge", "health"]

Manual check from the host:

curl -s http://127.0.0.1:7200/health

Or inside the container (via exec on a debug sidecar — the scratch image has no shell):

docker exec privitty-edged /usr/local/bin/privitty-edge health

Start period

First boot provisioning can take up to 60 seconds. The health check start-period accounts for this.


Using the CLI inside the container

# Account status
docker exec privitty-edged \
  privitty-edge --accounts /var/lib/privitty status

# List chats
docker exec privitty-edged \
  privitty-edge --accounts /var/lib/privitty chats

# License management
docker exec privitty-edged \
  privitty-edge --accounts /var/lib/privitty license status

Always pass --accounts /var/lib/privitty when using CLI subcommands that touch the filesystem (license, etc.).


Sending files from the host

privitty_send_file and privitty-edge send-file require the file at a path inside the container. Host paths like /Users/.../Desktop/file.pdf are not visible to the daemon.

Option 1 — Bind mount (production)

Mount a host directory when you create the container:

mkdir -p ~/privitty-outbox

docker run -d \
  --name privitty-edged \
  --restart unless-stopped \
  -e PRIVITTY_PROFILE=factory-gw-01 \
  -e PRIVITTY_LICENSE_URL="https://plm.privittytech.com/v1/license/YOUR_TOKEN" \
  -p 127.0.0.1:7200:7200 \
  -v privitty-data:/var/lib/privitty \
  -v ~/privitty-outbox:/data \
  privitty/edge:latest

Drop files on the host — they appear in the container at /data/:

cp ~/Desktop/env/environmental_monitoring.pdf ~/privitty-outbox/

Use /data/environmental_monitoring.pdf in RPC or CLI calls. The mount must be writable (encryption creates .prv files in the same directory).

Cannot add a bind mount to a running container

If you started without -v ~/privitty-outbox:/data, use docker cp (Option 2) or recreate the container with the mount added. Your privitty-data volume persists across recreate.

Option 2 — docker cp (container already running)

docker cp ~/Desktop/env/environmental_monitoring.pdf privitty-edged:/data/

Option 3 — Send with CLI (encrypt + deliver in one command)

docker exec privitty-edged \
  privitty-edge --accounts /var/lib/privitty send-file \
  --chat 12 \
  --file /data/environmental_monitoring.pdf \
  --message "Sending a CDR file" \
  --allow-forward \
  --duration 40

See Example C · Send a File and the Curl Cookbook.

curl / JSON-RPC

There is no single RPC that encrypts and sends together — use two calls or the CLI above. See Curl Cookbook · Send an encrypted file.


Image variants

Tag Contents
privitty/edge:latest Daemon + CLI
privitty/edge:latest-viewer Daemon + CLI + privitty-viewer

Next steps