> For the complete documentation index, see [llms.txt](https://docs.palliora.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.palliora.org/participate/run-palliora-node-on-a-tee.md).

# Run Palliora Node on a TEE

This document walks Palliora node operators through running their infrastructure inside a hardware‑backed Trusted Execution Environment (TEE) using Dstack.

The goal is to move from “ordinary Docker deployment” to a setup where every Palliora node runs inside an Intel TDX Confidential VM, with **hardware‑enforced isolation and remotely verifiable attestations**. Instead of trusting a generic cloud VM or Kubernetes cluster, operators will be able to show cryptographic proof that their node—and its configuration—ran in a specific, measured environment.

Dstack acts as the bridge between Palliora’s existing Docker‑based node stack and low‑level TEE features. It lets us:

* Take the standard Palliora `docker-compose.yml`.
* Run it inside a dedicated, attested CVM per deployment.
* Expose the same networking interfaces node operators expect.
* Generate TDX quotes directly from inside the node container for downstream verification.

This guide focuses on three practical outcomes:

1. **Provisioning a TEE‑ready host**\
   Renting an Intel TDX‑capable machine from a cloud provider and preparing it to run confidential workloads.
2. **Running Palliora under Dstack**\
   Installing Dstack’s components on the host, adapting Palliora’s `docker-compose.yml` for this environment, and deploying via Dstack’s UI.
3. **Proving and observing execution**\
   Pulling TDX attestation reports and node logs from inside the TEE, so operators and verifiers can build higher‑level trust tools (e.g., a Palliora trust dashboard) on top.

By the end of this document, Palliora community members should be able to reproducibly launch their own TEE‑protected nodes, without relying on a specific managed cloud, while keeping the operational model as close as possible to “just run Docker Compose.”

***

### 1. What Dstack Is <a href="#id-1-what-dstack-is" id="id-1-what-dstack-is"></a>

Dstack is an SDK and orchestration layer that runs your existing Docker apps inside **Confidential VMs (CVMs)** backed by hardware TEEs (Intel TDX, etc.).

### Core Components

* **dstack‑vmm**\
  Runs on the bare‑metal TDX host. Manages CVMs: creates, boots and stops them. Provides CVM orchestration and monitoring service right out of the box.
* **dstack‑gateway**\
  Reverse proxy on the host. Terminates TLS and routes `https://<id>-<port>.<base_domain>` to services inside CVMs.
* **dstack‑kms**\
  Key Management Service. Generates and seals keys; only unseals them inside attested CVMs, secluded from the host (prevents host/operator access). **Serves key derivation requests** from `dstack-guest-agent` inside running CVMs via RPC.
* **dstack‑guest‑agent**\
  Runs inside each CVM. Handles key derivation, remote attestation, and exposes `/var/run/dstack.sock` so containers can request TDX quotes.&#x20;
* **meta‑dstack (Yocto layer)**\
  Builds the minimal, hardened Linux image that runs inside CVMs and hosts Docker + guest‑agent. This uses the Yokto Linux guest image and provides dedicated memory/resources (secluded from the host) for confidentiality guarantees.

### Key Features

* **Drop‑in for Docker**: Use your existing `docker-compose.yml`, no app code changes.
* **Per‑app CVM isolation**: Each compose app runs in its own TDX CVM with encrypted memory.
* **Remote attestation**: Containers can request TDX quotes via `dstack.sock` and prove they ran in the expected environment.
* **Network ingress out of the box**: Gateway gives you HTTPS endpoints for node RPCs, APIs, etc., without manual nginx.

> See “[Dstack – Getting Started](https://docs.phala.com/dstack/getting-started)” for architecture and concepts.​

***

### 2. Renting an Intel TDX Machine <a href="#id-2-renting-an-intel-tdx-machine" id="id-2-renting-an-intel-tdx-machine"></a>

To self‑host Dstack, you need a VM that supports Intel TDX Confidential VMs (C3‑class or similar) on your cloud provider.

### Typical Requirements

* **Machine family**: Intel Sapphire Rapids with TDX enabled (for example, C3 `c3-standard-*` on some providers).
* **vCPU/RAM**: At least 8 vCPU, 32–64 GB RAM for comfortable Dstack builds and CVMs.
* **Disk**: 200+ GB SSD (Balanced PD/NVMe).
* **OS**: Recent Linux with TDX‑capable kernel (e.g., Ubuntu 24.04 LTS with `TDX_CAPABLE` flag).
* **Security:** Enable Confidential VM service > Intel TDX under security menu.

### Checklist When Creating the Host VM

* Enable **Confidential VM / Intel TDX** in the provider’s UI.
* Use a **TDX‑capable** OS image (check provider docs for “TDX\_CAPABLE” images).
* Ensure firewall/security groups allow:
  * SSH: 22 (admin access)
  * Dstack‑vmm UI: 9080
  * Dstack‑gateway HTTP/HTTPS: 80, 443, and optionally 9070 for the gateway dashboard.\[[docs.phala](https://docs.phala.com/dstack/getting-started)]​

Example firewall rule (conceptually):

```bash
bash# conceptual: open needed ports to your IP or trusted ranges
allow tcp:22,tcp:80,tcp:443,tcp:9070,tcp:9080 to host_ip
```

***

### 3. Installing and running Dstack (vmm, gateway, kms) <a href="#id-3-installing-dstack-vmm-gateway-kms" id="id-3-installing-dstack-vmm-gateway-kms"></a>

On your Intel TDX host VM, follow the[ upstream Dstack- Get started guide](https://docs.phala.com/dstack/getting-started#install-dependencies).

### 3.1 Summary of Dstack setup

```bash
bash# Install build deps (example for Ubuntu)
sudo apt update
sudo apt install -y build-essential chrpath diffstat lz4 wireguard-tools xorriso

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Clone meta-dstack
git clone https://github.com/Dstack-TEE/meta-dstack.git --recursive
cd meta-dstack
mkdir build && cd build

# Generate config template
../build.sh hostcfg
# Edit build-config.sh to match your environment (domain, ports, etc.)
vim ./build-config.sh

# Re-run host build
../build.sh hostcfg
# You should now see artifacts:
ls
# certs images dstack-kms kms.toml run dstack-vmm vmm.toml dstack-gateway gateway.toml
```

You can either **download a prebuilt CVM guest image**:

```bash
../build.sh dl 0.5.2
```

or **build it from source**:

```bash
../build.sh guest
```

### 3.2 Run Core Services

Run three terminals on the host:

```bash
./dstack-kms -c kms.toml
```

```bash
sudo ./dstack-gateway -c gateway.toml
```

```bash
./dstack-vmm -c vmm.toml
```

* `dstack-vmm` UI: `http://<host-ip>:9080`
* `dstack-gateway` dashboard: `https://<host-domain-or-ip>:9070` (if configured)

***

### 4. Preparing Palliora’s docker-compose for Dstack <a href="#id-4-preparing-pallioras-docker-compose-for-dstack" id="id-4-preparing-pallioras-docker-compose-for-dstack"></a>

Palliora’s existing compose uses host‑mounted genesis config and private ECR images. For TDX+Dstack we’ll make it **TEE‑friendly and easy for operators**.

### 4.a Genesis Config from Remote

Instead of mounting a local path like:

```
volumes:
    - "./palliora-manas.json:/root/palliora-manas.json"
```

Publish the Palliora genesis config in a **public Google Drive/GitHub repo/Gist**, then adjust compose to fetch it on container start.

Example pattern:

```
services:
  # New service to fetch the config file
  fetch-config:
    image: alpine:3.19
    volumes:
      - palliora-config-data:/root
    working_dir: /root
    command: wget -O /root/palliora-manas.json "https://drive.google.com/uc?export=download&id=1VX0Ei12kvGU2nnjXlzjMfAd53tVAaF42"
    restart: "no"
    
  palliora-node:
    image: public-registry/palliora-node:latest
    entrypoint: ["/bin/sh", "-c"]
    volumes:
      - palliora-config-data:/root/
volumes:
  palliora-config-data:
```

I've hosted one on Google Drive at <https://drive.google.com/uc?export=download&id=1VX0Ei12kvGU2nnjXlzjMfAd53tVAaF42>

### 4.b Switch to Public Images

To avoid ECR auth complexity for community operators we've pushed Palliora images to a **public registry** on public AWS ECR and reference them directly in compose:

```
services:
  palliora-node:
    image: public.ecr.aws/palliora/palliora/node:latest
```

This removes the need for AWS credentials or ECR login inside TEEs.

### 4.c Mount `/var/run/dstack.sock` for Attestation

To allow the node container to request TDX quotes, mount the Dstack socket as documented.

Example Palliora service snippet:

```
palliora-node:
    image: public.ecr.aws/palliora/palliora/node:latest
    working_dir: /
    volumes:
      - /var/run/dstack.sock:/var/run/dstack.sock
      - palliora-config-data:/root/
```

The `/var/run/dstack.sock` path is provided by the dstack guest‑agent inside the CVM; the mount just passes it into your container.

Here's the compiled changes to Palliora's docker-compose.yml

{% file src="/files/NZqKAxISIo34usmGP8cX" %}

***

### 5. Deploying Palliora via Dstack UI <a href="#id-5-deploying-palliora-via-dstack-ui-no-phala-mentio" id="id-5-deploying-palliora-via-dstack-ui-no-phala-mentio"></a>

For the community doc, describe deployment entirely via the generic Dstack‑vmm UI.

### 5.1 Open Dstack-vmm

Navigate to:

```
http://<your-tdx-host-ip>:9080
```

You’ll see the **dstack‑vmm web interface**.

### 5.2 Upload and Deploy docker-compose

* Click **“Deploy App”** (or equivalent button).
* Paste or upload the Palliora `docker-compose.yml` prepared in section 4.
* (Optional) Configure **Encrypted Environment Variables** if Palliora needs secrets, incase of using private ECR images — they are encrypted client‑side and only decrypted inside the CVM.
* Click **Deploy**.

Dstack will:

1. Create a new TDX CVM.
2. Boot the Yocto guest image with guest‑agent.
3. Pull the public Palliora node image.
4. Start the Palliora containers inside the CVM.

### 5.3 Checking Status

In the vmm UI:

* **Logs**: For CVM boot logs and container startup; use the **\[Logs]** button.
* **Dashboard**: See container status, resource usage, and guest‑agent health.

{% hint style="info" %}
On shutdown, TEE setup will wipe away the ollama and model installations to enable a clean slate boot expected from the TEE. In order to persist it, we need to move the ollama dir into the persistent storage of the TEE.
{% endhint %}

5.4 Palliora Setup

Once you have the Palliora client running, next up is setting up:\
1\. Ollama

2. Installing models
3. Creating a Palliora account
4. Staking
5. Finally joining as a guardian

For the above steps, you can follow our [Becoming a Guardian](/participate/become-a-guardian.md) guide.

***

### 6. Getting TDX Attestations and Logs from the TEE <a href="#id-6-getting-tdx-attestations-and-logs-from-the-tee" id="id-6-getting-tdx-attestations-and-logs-from-the-tee"></a>

Once the Palliora node is running inside the TDX CVM, operators can generate attestation reports and fetch logs programmatically or use the Trust-Centre to verify attestations automatically.

### 6.1 Trust Centre

A comprehensive open-source platform for managing and verifying Trusted Execution Environment (TEE) attestations in the dstack ecosystem. The Trust Center provides end-to-end verification of hardware attestation, OS integrity, source code authenticity, and domain ownership for TEE-protected applications.

Repo: <https://github.com/Phala-Network/trust-center>

\
The following is verified automatically by the Trust Centre client:

* **Verify Hardware Authenticity**: Cryptographically prove your app runs on genuine Intel TDX and Nvidia CC hardware
* **Confirm Code Integrity**: Verify the exact Docker compose configuration deployed matches your source code
* **Validate OS Security**: Ensure the operating system hasn’t been tampered with
* **Prove Zero Trust**: For gateway deployments, verify domain certificates are managed entirely within the TEE

For automated verification of your application’s attestation, see the [Trust Centre Technical Documentation](https://docs.phala.com/dstack/trust-center-technical) which explains how to use these quotes with the Trust Centre verification platform.

### 6.2 Requesting a TDX Quote from the Container

With `/var/run/dstack.sock` mounted, use the documented curl command from inside the Palliora container:

```bash
# inside the palliora-node container
curl -X POST --unix-socket /var/run/dstack.sock \
  -H 'Content-Type: application/json' \
  -d '{
        "reportData": "0x1234deadbeef00000000000000000000000000000000000000000000000000"
      }' \
  http://dstack/GetQuote | jq .
```

Or, with the newer interface

```bash
curl --unix-socket /var/run/dstack.sock \
  "http://localhost/GetQuote?report_data=0x1234deadbeef" | jq .
```

### Code integrity verification

* `reportData` is a **64‑byte app‑defined field** (hex string) that is hashed into the TDX report; Palliora can use it to bind the quote to a particular genesis hash or config version.
* The response JSON contains:
  * The TDX quote (base64)
  * The embedded `report_data`
  * Measurement fields and signatures

***

### Recap

* You rented a TDX‑capable machine.
* Installed and ran Dstack (vmm, gateway, kms).
* Adapted Palliora’s `docker-compose.yml` for Dstack (remote genesis, public images, `dstack.sock` mount).
* Deployed via the Dstack UI.
* Verified attestation through Trust Centre/Retrieved TDX quotes from inside the TEE.
