← Week 2: SPIRE Internals and Attestation

Day 12: Installing and Running SPIRE Locally (Docker Compose)

Phase 4 · August 16, 2026

← Week 2: SPIRE Internals and Attestation

Agenda (2–3 hours)

  • Setup (30 min): Pull SPIRE Docker images; review the quickstart config
  • Deploy (60 min): Run SPIRE server + agent with Docker Compose
  • Verify (60 min): Use spire-server and spire-agent CLI to confirm setup
← Week 2: SPIRE Internals and Attestation

Docker Compose Setup

# docker-compose.yml
version: "3.8"
services:
  spire-server:
    image: ghcr.io/spiffe/spire-server:1.9.6
    hostname: spire-server
    volumes:
      - ./config/server:/etc/spire/server
      - spire-server-data:/opt/spire/data/server
    command: ["-config", "/etc/spire/server/server.conf"]
    ports:
      - "8081:8081"

  spire-agent:
    image: ghcr.io/spiffe/spire-agent:1.9.6
    hostname: spire-agent
    depends_on: [spire-server]
    volumes:
      - ./config/agent:/etc/spire/agent
      - spire-agent-socket:/tmp/spire-agent/public
      - spire-agent-data:/opt/spire/data/agent
    command: ["-config", "/etc/spire/agent/agent.conf"]
    pid: "host"     # required for unix workload attestation

volumes:
  spire-server-data:
  spire-agent-data:
  spire-agent-socket:
← Week 2: SPIRE Internals and Attestation

Server Config (Local Dev)

# config/server/server.conf
server {
  bind_address = "0.0.0.0"
  bind_port = "8081"
  socket_path = "/tmp/spire-server/private/api.sock"
  trust_domain = "example.org"
  data_dir = "/opt/spire/data/server"
  log_level = "DEBUG"
  ca_ttl = "168h"
  default_svid_ttl = "1h"
}

plugins {
  DataStore "sql" {
    plugin_data { database_type = "sqlite3"
                  connection_string = "/opt/spire/data/server/datastore.sqlite3" }
  }
  NodeAttestor "join_token" { plugin_data {} }
  KeyManager "memory" { plugin_data {} }
}

Using join_token node attestation — simplest for local dev (no AWS needed).

← Week 2: SPIRE Internals and Attestation

Agent Config (Local Dev)

# config/agent/agent.conf
agent {
  data_dir = "/opt/spire/data/agent"
  log_level = "DEBUG"
  trust_domain = "example.org"
  server_address = "spire-server"
  server_port = "8081"
  socket_path = "/tmp/spire-agent/public/api.sock"
  trust_bundle_path = "/etc/spire/agent/bootstrap.crt"
  insecure_bootstrap = true   // only for local dev — no bootstrap cert needed
}

plugins {
  NodeAttestor "join_token" { plugin_data {} }
  KeyManager "memory" { plugin_data {} }
  WorkloadAttestor "unix" { plugin_data {} }
}
← Week 2: SPIRE Internals and Attestation

Bringing It Up

# Start server
docker compose up -d spire-server

# Generate a join token for the agent to use
docker compose exec spire-server \
  spire-server token generate -spiffeID spiffe://example.org/spire/agent/local

# Output: Token: abc123def456 (copy this)

# Start agent with the join token
SPIRE_JOIN_TOKEN=abc123def456 docker compose up -d spire-agent

# Verify agent connected
docker compose exec spire-server spire-server agent list
# Should show: spiffe://example.org/spire/agent/join_token/abc123def456
← Week 2: SPIRE Internals and Attestation

Verifying the Deployment

# List registered entries (should be empty initially)
docker compose exec spire-server spire-server entry show

# Check agent health
docker compose exec spire-agent spire-agent healthcheck
# Output: Agent is healthy.

# Check server health
docker compose exec spire-server spire-server healthcheck
# Output: Server is healthy.

# Inspect the trust bundle
docker compose exec spire-server spire-server bundle show
# Prints the JWK Set for example.org
← Week 2: SPIRE Internals and Attestation

Challenge Assignment

Get SPIRE running locally:

  1. Create the directory structure:
    spiffe-demo/
    ├── docker/
    │   ├── docker-compose.yml
    │   ├── config/server/server.conf
    │   └── config/agent/agent.conf
    
  2. Start server + agent; verify both are healthy
  3. Run spire-server agent list and paste the output in your notes
  4. Run spire-server bundle show — save the JWK Set to a file (you'll use it in Day 17)
  5. Answer: what does the trust bundle JWK Set contain? (How many keys? What algorithm?)
  6. What is the trust bundle's spiffe_refresh_hint? What does it mean?

Document any errors you encountered and how you fixed them.

← Week 2: SPIRE Internals and Attestation

Resources

  • SPIRE quickstart: spiffe.io/docs/latest/try/getting-started-linux-macos-x
  • SPIRE Docker images: ghcr.io/spiffe/spire-server, ghcr.io/spiffe/spire-agent
  • SPIRE examples: github.com/spiffe/spire-examples
  • join_token attestor: github.com/spiffe/spire/blob/main/doc/plugin_server_nodeattestor_jointoken.md