Skip to main content

GhostAI Connect

GhostAI Connect links an inference server you run yourself (Ollama, vLLM, or any OpenAI-compatible server) to GhostAI. It opens one outbound WebSocket connection to the GhostAI relay, so you never open an inbound firewall port.

Each release from 0.2.7 attaches ghostai-connect-<version>-install.lock to its GitHub release. It lists the sha256 of every file the connector installs: each dependency, including PyCA cryptography, and the ghostai-connect wheel itself. pip then refuses any file whose hash does not match, wherever it came from. RELEASE_SIGNING.md shows how to verify the lock's signature first.

Python 3.10 or later:

python3 -m venv ~/.local/share/ghostai-connect
~/.local/share/ghostai-connect/bin/pip install --require-hashes --no-deps --only-binary :all: \
  -r ghostai-connect-<version>-install.lock
ln -sf ~/.local/share/ghostai-connect/bin/ghostai-connect ~/.local/bin/ghostai-connect
ghostai-connect --version

On Windows, create the environment with py -m venv %LOCALAPPDATA%\ghostai-connect and run %LOCALAPPDATA%\ghostai-connect\Scripts\pip with the same arguments.

  • --require-hashes: every file must match a hash in the lock.
  • --no-deps: install exactly what the lock lists and resolve nothing else.
  • --only-binary :all:: never build from source. A source build downloads its build tools without checking hashes. Every supported platform has wheels; if pip finds none for yours, contact support rather than dropping the flag.

To upgrade, delete ~/.local/share/ghostai-connect and repeat these steps with the new version's lock. Your enrollment and key are not in that directory, so they are kept.

pipx cannot install with hash checking. It upgrades pip in its own shared environment and installs the package name you give it, neither of which has a hash, so --pip-args="--require-hashes ..." makes both steps fail. Use a virtual environment as above for the hash-locked install; the other ways below do not check hashes.

Install

Python 3.10 or later:

pipx install ghostai-connect      # or: pip install ghostai-connect
ghostai-connect --version

Or use the container image for linux/amd64 and linux/arm64: ghcr.io/dymium-io/ghostai-connect:<version>.

Verify before you run it

The container image is signed keyless with Sigstore by this repository's release workflow. With cosign v2 or later:

cosign verify \
  --certificate-identity-regexp '^https://github\.com/dymium-io/ghostai-connect/\.github/workflows/publish-image\.yml@refs/tags/v' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  ghcr.io/dymium-io/ghostai-connect:<version>

The PyPI files carry PEP 740 attestations from the same repository. With pipx install pypi-attestations:

pypi-attestations verify pypi \
  --repository https://github.com/dymium-io/ghostai-connect \
  pypi:ghostai_connect-<version>-py3-none-any.whl

RELEASE_SIGNING.md in the source repository has the details.

Enroll and run

Use the enrollment command shown in the GhostAI admin console. The token is single-use.

ghostai-connect enroll <token> \
  --base-url https://your-ghostai-instance.example.com \
  --relay-url wss://relay-connector.your-ghostai-instance.example.com/connector/ws

ghostai-connect run      # runs until stopped; reconnects automatically
ghostai-connect doctor   # last heartbeat, registration status, last error

Both URLs must be https:// and wss://; http:// and ws:// are accepted only for localhost, or with --allow-insecure for local development.

The enrolled credential and the call-signing key are kept in your operating system's credential store: the macOS login keychain, the Linux Secret Service (GNOME Keyring or KWallet, through secret-tool), or Windows DPAPI. Where no store is usable (a server without a desktop session) they stay in ~/.config/ghostai-connect/config.json with mode 0600, and enroll and run say so. Set GHOSTAI_CONNECT_KEYSTORE to keychain or file to choose explicitly. Do not restore this key from a backup or copy it to another computer: GhostAI treats an older copy as stolen and revokes the connector. Run one ghostai-connect run per enrollment.

Environment variable Meaning Default
GHOSTAI_CONNECT_LOCAL_URL Your local inference server http://localhost:11434
GHOSTAI_CONNECT_MAX_CONCURRENCY Concurrent requests forwarded to it 4
GHOSTAI_CONNECT_MAX_RECONNECT_ATTEMPTS Give up after this many consecutive failed reconnects retry forever
GHOSTAI_CONNECT_KEYSTORE Where the key is kept: auto, keychain, sealed or file auto (sealed in the image)

ghostai-connect run first checks that it can save its state, and refuses to start if it cannot: every connection advances a counter it must save.

Interactive mode

Run ghostai-connect with no arguments in a terminal (or ghostai-connect interactive) for a numbered menu covering enroll, run, status, and local MCP targets. Each item runs the same command with the same checks. The enrollment token is read without echo, and removing or replacing something asks you to type a word to confirm. Set NO_COLOR to turn off color. The menu opens only when both input and output are a terminal: in a container, a service unit, a script, or CI, ghostai-connect with no arguments prints its usage as before.

Running in Docker / Kubernetes

The image ghcr.io/dymium-io/ghostai-connect:<version> runs ghostai-connect run as user 1000. A container has no keychain, so the image seals the connector's keys (AES-256-GCM) under a key-encryption key (KEK) you give it, and keeps the sealed keys and the rest of its state on a volume. It needs two things:

  • A writable state volume at /home/connect/.config/ghostai-connect, one per running connector. Never share one between two containers, start a second container from a copy, or restore one from a backup: the state advances with every connection, and GhostAI quarantines a connector that comes back with an older copy until an admin approves the restore.
  • A KEK: 32 random bytes, base64, mounted read-only as a secret at /run/secrets/ghostai-connect-kek, or wrapped with AWS KMS (below). Keep it out of the volume and out of the image: the volume alone is then useless to whoever copies it.

The connector refuses to enroll (before it uses the token) or to start when its keys would be in plaintext, when its state is in the container's writable layer instead of a volume, when the KEK file is in the writable layer or in the state volume, or when the state cannot be written.

Environment variable Meaning
GHOSTAI_CONNECT_KEK_FILE The KEK secret file (default /run/secrets/ghostai-connect-kek)
GHOSTAI_CONNECT_KEK_KMS_CIPHERTEXT_FILE The KEK as AWS KMS ciphertext, instead of a KEK file
GHOSTAI_CONNECT_KEK_KMS_KEY_ID The KMS key ARN; KMS refuses ciphertext made under any other key
GHOSTAI_CONNECT_KEK_KMS_REGION The KMS key's region (default AWS_REGION)
GHOSTAI_CONNECT_ALLOW_PLAINTEXT_SECRETS 1 keeps the keys in plaintext anyway, with a warning. Throwaway tests only

The KEK is never read from an environment variable: docker inspect shows those.

Docker

# Once. Store this file like a password, outside the volume.
head -c 32 /dev/urandom | base64 > ghostai-connect-kek
sudo chown 1000 ghostai-connect-kek && chmod 400 ghostai-connect-kek

docker run --rm \
  -v ghostai-connect:/home/connect/.config/ghostai-connect \
  -v "$PWD/ghostai-connect-kek:/run/secrets/ghostai-connect-kek:ro" \
  ghcr.io/dymium-io/ghostai-connect:<version> \
  enroll <token> --base-url ... --relay-url ...

docker run -d --name ghostai-connect --restart unless-stopped --read-only \
  -v ghostai-connect:/home/connect/.config/ghostai-connect \
  -v "$PWD/ghostai-connect-kek:/run/secrets/ghostai-connect-kek:ro" \
  -e GHOSTAI_CONNECT_LOCAL_URL=http://ollama:11434 \
  ghcr.io/dymium-io/ghostai-connect:<version>

--read-only is optional; it leaves the connector no writable layer at all.

Docker Compose

services:
  ghostai-connect:
    image: ghcr.io/dymium-io/ghostai-connect:<version>
    restart: unless-stopped
    read_only: true
    environment:
      GHOSTAI_CONNECT_LOCAL_URL: http://ollama:11434
    volumes:
      - ghostai-connect:/home/connect/.config/ghostai-connect
    secrets:
      - ghostai-connect-kek   # mounted at /run/secrets/ghostai-connect-kek
secrets:
  ghostai-connect-kek:
    file: ./ghostai-connect-kek
volumes:
  ghostai-connect:

Enroll once with docker compose run --rm ghostai-connect enroll <token> --base-url ... --relay-url ..., then docker compose up -d.

Kubernetes

The KEK is a Secret, mounted read-only (Kubernetes keeps Secret volumes on tmpfs). Mount it outside /run/secrets, where it would hide the service account token. The state is a PersistentVolumeClaim. Use one replica with the Recreate strategy, so two pods never run at once.

kubectl create secret generic ghostai-connect-kek \
  --from-literal=ghostai-connect-kek="$(head -c 32 /dev/urandom | base64)"
apiVersion: v1
kind: PersistentVolumeClaim
metadata: {name: ghostai-connect-state}
spec:
  accessModes: [ReadWriteOnce]
  resources: {requests: {storage: 16Mi}}
---
apiVersion: apps/v1
kind: Deployment
metadata: {name: ghostai-connect}
spec:
  replicas: 1
  strategy: {type: Recreate}
  selector: {matchLabels: {app: ghostai-connect}}
  template:
    metadata: {labels: {app: ghostai-connect}}
    spec:
      securityContext: {runAsUser: 1000, runAsGroup: 1000, fsGroup: 1000}
      containers:
        - name: connect
          image: ghcr.io/dymium-io/ghostai-connect:<version>
          args: ["run"]
          env:
            - {name: GHOSTAI_CONNECT_LOCAL_URL, value: "http://ollama:11434"}
            - {name: GHOSTAI_CONNECT_KEK_FILE, value: /etc/ghostai-connect-kek/ghostai-connect-kek}
          securityContext: {readOnlyRootFilesystem: true, allowPrivilegeEscalation: false}
          volumeMounts:
            - {name: state, mountPath: /home/connect/.config/ghostai-connect}
            - {name: kek, mountPath: /etc/ghostai-connect-kek, readOnly: true}
      volumes:
        - name: state
          persistentVolumeClaim: {claimName: ghostai-connect-state}
        - name: kek
          secret: {secretName: ghostai-connect-kek, defaultMode: 0400}

To enroll, run the same pod spec once with args: ["enroll", "<token>", "--base-url", "...", "--relay-url", "..."] (for example as a Job, with the Deployment scaled to 0), then scale the Deployment to 1.

AWS KMS with a workload identity (EKS IRSA, ECS, EC2)

Instead of a KEK secret, keep only KMS ciphertext of the KEK beside the connector. The workload's own AWS identity decrypts it at startup, so the plaintext KEK is never stored anywhere, a copy of the volume and the ciphertext is useless without that identity, and every use is in CloudTrail.

aws kms encrypt --key-id alias/ghostai-connect \
  --plaintext fileb://<(head -c 32 /dev/urandom) \
  --encryption-context ghostai-connect=kek \
  --query CiphertextBlob --output text > ghostai-connect-kek.kms
kubectl create configmap ghostai-connect-kek-kms --from-file=ghostai-connect-kek.kms

Give the pod's IAM role (IRSA) kms:Decrypt on that key, with the condition "kms:EncryptionContext:ghostai-connect": "kek". In the Deployment above, use that service account, mount the ConfigMap at /etc/ghostai-connect-kek instead of the Secret, and replace GHOSTAI_CONNECT_KEK_FILE with:

          env:
            - {name: GHOSTAI_CONNECT_KEK_KMS_CIPHERTEXT_FILE, value: /etc/ghostai-connect-kek/ghostai-connect-kek.kms}
            - {name: GHOSTAI_CONNECT_KEK_KMS_KEY_ID, value: "arn:aws:kms:<region>:<account>:key/<key-id>"}
            - {name: GHOSTAI_CONNECT_KEK_KMS_REGION, value: "<region>"}

The connector uses, in order: AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY, a web identity token (IRSA), the container credentials endpoint (ECS task roles, EKS Pod Identity), then EC2 instance metadata (IMDSv2 only). It does not read ~/.aws. AWS_ENDPOINT_URL_KMS selects a VPC or FIPS endpoint. For other clouds, deliver the KEK as a file from your secret manager (for example its Kubernetes CSI driver) and use GHOSTAI_CONNECT_KEK_FILE.

TPM passthrough

On a Linux host with a TPM 2.0, the connector can keep its device identity key in the TPM, where it cannot be copied at all (see the keys section above). The published image does not include tpm2-tools, so that it stays small and reproducible; build a derived image and pass the TPM resource manager in:

FROM ghcr.io/dymium-io/ghostai-connect:<version>
USER root
RUN apt-get update && apt-get install -y --no-install-recommends tpm2-tools \
    && rm -rf /var/lib/apt/lists/*
USER connect:connect
docker run ... --device /dev/tpmrm0 --group-add "$(stat -c %g /dev/tpmrm0)" <your-image>

Enroll with the TPM present. The state volume then holds only a reference to the TPM key, so a copy of the volume and the KEK still cannot act as the connector on another machine. Keep the KEK as well: the call keys and the connection counter are still sealed under it.

Upgrading a 0.2.6 container

0.2.6 kept the keys in plaintext in the volume, and its enrollment does not carry over to 0.2.7. Enroll 0.2.7 into a new volume with a KEK, then delete the old volume. (Started on a plaintext volume with a KEK, 0.2.7 seals the keys in place, but the old plaintext can linger on the volume's disk.)

Laptops and sleep

Close the lid whenever you like. From 0.2.7 the connector notices a wake or a network change within a second, drops the dead connection and connects again within a second or two of the network being back, retrying every second while Wi-Fi rejoins. While the computer sleeps, anything that uses the connector fails at once with connector offline rather than waiting for a timeout.

If the credential store is locked after a wake (a keychain set to lock on sleep, or a Linux keyring that locks on suspend), the connector waits and ghostai-connect doctor shows waiting for keystore unlock; it never moves the key somewhere less protected. Other statuses you may see between connections: reconnecting after sleep, reconnecting after a network change and waiting for network.

Upgrade

pipx upgrade ghostai-connect      # or: pip install --upgrade ghostai-connect

Your enrollment is kept across upgrades from 0.2.4 on. Restart ghostai-connect run after upgrading; on its first start 0.2.6 moves an existing key out of config.json into your credential store, where there is one.

GhostAI accepts 0.2.6 and later only. Everything between GhostAI and the connector is encrypted end to end with fresh keys for every connection, so the relay sees only which connector a message is for and how large it is. Every call is also signed with a key issued at enrollment, and the connector refuses anything that does not decrypt or check out; GhostAI does the same with every reply. If two computers use the same key, or an old copy of it connects, GhostAI revokes the connector and alerts your admins. The key can be rotated without enrolling again. Versions before 0.2.4 have no key: enroll again with a new token after upgrading.

License

Proprietary. Copyright (c) 2026 Dymium, Inc. All rights reserved. Use requires an active GhostAI subscription, under your agreement with Dymium, Inc.; see the LICENSE file included with the package. Questions: support@dymium.io.

Metadata

Release files for ghostai-connect 0.2.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ghostai-connect 0.2.7
File Size Uploaded Provenance
ghostai_connect-0.2.7.tar.gz 112.9 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for ghostai-connect 0.2.7
File Interpreter ABI Platform
ghostai_connect-0.2.7-py3-none-any.whl Python 3 none any Details

Total release size: 230.7 kB

Release files / ghostai_connect-0.2.7.tar.gz

Download URL ghostai_connect-0.2.7.tar.gz
Size 112.9 kB
Tags Source
SHA-256 checksum
How to use checksums
4bdc118135fe496443a6e6b6fbf7268dad021116d5b36120a5bf28f2ec252993
BLAKE2b-256 checksum
How to use checksums
4acc097a1cd06553faada06d2ea813e4225a2a04628475cfd0dbf8ebb08c3cc9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release files / ghostai_connect-0.2.7-py3-none-any.whl

Download URL ghostai_connect-0.2.7-py3-none-any.whl
Size 117.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a5afae333be082a0ad802896ccc6869e27aba016ad68400e25d35ca92c4693a0
BLAKE2b-256 checksum
How to use checksums
5389df85b49cd399e4b5efa2932bafbf9e34c1845182d913a54d187d5f4759a3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Security for ghostai-connect 0.2.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for ghostai_connect-0.2.7.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page