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.
Install (recommended: hash-locked)
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, and paste the token when it asks. The token is single-use, and it is read with the input hidden, so it stays out of your shell history and the process list.
ghostai-connect enroll \
--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
Without a terminal, pipe the token in with --token-file -, read it from a
file only you can read with --token-file PATH (it warns when other users can
read the file), or set GHOSTAI_CONNECT_ENROLL_TOKEN (least preferred: the
environment of a process is visible to the same user and to docker inspect).
These, and the prompt, need 0.2.9 or later. On 0.2.8 or earlier, put the token
last, after --: ghostai-connect enroll --base-url ... --relay-url ... -- <token>.
A token can begin with -, and without -- it is read as an option.
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.
Run at login or boot
ghostai-connect service install # start it now, at every login, and after it stops
ghostai-connect logs -n 100 -f # its recent output
ghostai-connect service uninstall # stop and remove it; the enrollment is kept
On macOS this is a launchd user agent
(~/Library/LaunchAgents/com.dymium.ghostai-connect.plist, output in
~/Library/Logs/ghostai-connect/connect.log). On Linux it is a systemd user
unit (~/.config/systemd/user/ghostai-connect.service, output in journald);
to start it at boot without logging in, turn on lingering with
loginctl enable-linger <you>, which service install reminds you of. The
service runs the ghostai-connect you installed it with, plus run, and
holds no token or key. When the connector was revoked or its key store refuses
its keys, run exits with code 78 and the systemd unit does not restart it.
Not available in a container (use --restart unless-stopped) or on Windows.
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 --base-url ... --relay-url ... -- <token>
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 --base-url ... --relay-url ... -- <token>,
then docker compose up -d. From 0.2.9, leave off -- <token> and
docker compose run asks for it, hidden.
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", "--base-url", "...", "--relay-url", "...", "--", "<token>"] (for
example as a Job, with the Deployment scaled to 0), then scale the Deployment
to 1. From 0.2.9 you can keep the token out of the pod spec: put it in a Secret,
drop "--", "<token>", and set GHOSTAI_CONNECT_ENROLL_TOKEN from the Secret
with valueFrom.secretKeyRef. Delete the Secret once enrolled.
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.9
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ghostai_connect-0.2.9.tar.gz | 151.5 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ghostai_connect-0.2.9-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 310.8 kB
Release files / ghostai_connect-0.2.9.tar.gz
| Download URL | ghostai_connect-0.2.9.tar.gz |
|---|---|
| Size | 151.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
edc7f71720605936f312e2398cd3bc9b54264f8ce9920b7dd68c79f2bb42f3d1
|
|
BLAKE2b-256 checksum How to use checksums |
4f661600af79dc0bbe07dbb284393377bd815b0928e829b2e78623f4c34ed833
|
| 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 17, 2026.
Transparency logRelease files / ghostai_connect-0.2.9-py3-none-any.whl
| Download URL | ghostai_connect-0.2.9-py3-none-any.whl |
|---|---|
| Size | 159.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a38b7fa0e319bc8dafa31343a17ae664255c443a7ea6ff6b6e9b62ecf28d51dc
|
|
BLAKE2b-256 checksum How to use checksums |
122d903b05e76d6293aab63c9615652c8c979239f62a91d705157bd4889f49cf
|
| 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 17, 2026.
Transparency logSecurity for ghostai-connect 0.2.9
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.
Attestation for ghostai_connect-0.2.9.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 17, 2026.
Transparency logA 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.