Skip to main content

Bootstrapping Secrets

Bootstrap tokens authenticate edge agents during initial registration with Expanso Cloud. These tokens establish trust and should be provisioned securely before deploying the edge agent.

Assumption

This guide assumes you have already obtained a bootstrap token from Expanso Cloud. The examples focus on how to provision and mount the token securely, not on token generation.


Why Bootstrap Tokens Matter

  • First Authentication: Bootstrap tokens are used only during initial agent startup
  • Node Registration: Tokens authorize the edge agent to register with Expanso Cloud
  • One-Time Use: After successful registration, agents use long-lived certificates for subsequent authentication
  • High Value: Compromised tokens could allow unauthorized agents to join your fleet

Local File Storage (Linux)

Store bootstrap tokens as files with restrictive permissions.

Create Token File

# Create directory with root ownership
sudo mkdir -p /etc/expanso

# Write token with restricted permissions
echo "YOUR_BOOTSTRAP_TOKEN" | sudo tee /etc/expanso/bootstrap.token > /dev/null
sudo chmod 600 /etc/expanso/bootstrap.token
sudo chown root:root /etc/expanso/bootstrap.token

Permissions:

  • 600 ensures only owner (root) can read/write
  • No group or world access

Use Token File

# Read token from file during bootstrap
expanso-edge bootstrap --token "$(sudo cat /etc/expanso/bootstrap.token)"

# Then run the agent
expanso-edge run --config /etc/expanso/edge-config.yaml

Environment Variables (Systemd)

Use environment files for systemd-managed services.

Create Environment File

# Create environment file
echo "EXPANSO_EDGE_BOOTSTRAP_TOKEN=YOUR_BOOTSTRAP_TOKEN" \
| sudo tee /etc/expanso/bootstrap.env > /dev/null

# Restrict permissions
sudo chmod 600 /etc/expanso/bootstrap.env
sudo chown root:root /etc/expanso/bootstrap.env

Systemd Service Configuration

/etc/systemd/system/expanso-edge.service
[Unit]
Description=Expanso Edge Node
After=network.target

[Service]
# Load environment variables from file
EnvironmentFile=-/etc/expanso/bootstrap.env

# Use environment variable in bootstrap command
ExecStart=/usr/local/bin/expanso-edge bootstrap \
--token ${EXPANSO_EDGE_BOOTSTRAP_TOKEN} \
run --config /etc/expanso/edge-config.yaml

Restart=unless-stopped
User=root

[Install]
WantedBy=multi-user.target

Enable and Start

sudo systemctl daemon-reload
sudo systemctl enable expanso-edge
sudo systemctl start expanso-edge

# Check status
sudo systemctl status expanso-edge

Docker Secrets

Docker Swarm secrets provide secure distribution to containers.

Create Docker Secret

# Create secret from file
echo "YOUR_BOOTSTRAP_TOKEN" > bootstrap.token
docker secret create expanso_bootstrap_token bootstrap.token

# Remove local file
rm bootstrap.token

Use in Docker Service

docker service create \
--name expanso-edge \
--secret expanso_bootstrap_token \
ghcr.io/expanso-io/expanso-edge:latest \
bootstrap --token /run/secrets/expanso_bootstrap_token run

Docker secret location: /run/secrets/expanso_bootstrap_token (mounted automatically)

Permissions: Docker manages permissions; only the container can read


Kubernetes Secrets

Use native Kubernetes Secrets for pod-based deployments.

Create Kubernetes Secret

# Create secret from literal value
kubectl create secret generic expanso-bootstrap-token \
--from-literal=bootstrap.token=YOUR_BOOTSTRAP_TOKEN \
--namespace=expanso-system

Or from a file:

echo "YOUR_BOOTSTRAP_TOKEN" > bootstrap.token

kubectl create secret generic expanso-bootstrap-token \
--from-file=bootstrap.token=bootstrap.token \
--namespace=expanso-system

rm bootstrap.token

Mount Secret in Pod

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: expanso-edge
namespace: expanso-system
spec:
replicas: 1
selector:
matchLabels:
app: expanso-edge
template:
metadata:
labels:
app: expanso-edge
spec:
containers:
- name: expanso-edge
image: ghcr.io/expanso-io/expanso-edge:latest
args:
- bootstrap
- --token-file
- /etc/expanso/bootstrap.token
- run
volumeMounts:
- name: bootstrap-token
mountPath: /etc/expanso
readOnly: true
volumes:
- name: bootstrap-token
secret:
secretName: expanso-bootstrap-token
defaultMode: 0400 # Read-only for owner

Secret location in container: /etc/expanso/bootstrap.token


Best Practices

1. Restrict File Permissions

Always use chmod 600 for local token files:

sudo chmod 600 /etc/expanso/bootstrap.token

2. Rotate Bootstrap Tokens

  • Generate new tokens periodically
  • Revoke old tokens after rotation
  • Use short-lived tokens when possible

3. Separate Bootstrap from Pipeline Secrets

  • Don't reuse bootstrap tokens for pipeline authentication
  • Use different storage mechanisms for different secret types

4. Audit Token Usage

  • Monitor which nodes use which tokens
  • Track token lifecycle in Expanso Cloud
  • Alert on suspicious registration attempts

5. Secure Token Distribution

  • Don't send tokens via email or chat
  • Use secure channels (SSH, secure file transfer)
  • Consider using configuration management tools (Ansible, Terraform)

Troubleshooting

Token Not Found

Symptom: Error: bootstrap token file not found

Solution: Verify file exists and has correct path:

ls -la /etc/expanso/bootstrap.token

Permission Denied

Symptom: Error: permission denied reading bootstrap token

Solution: Check file permissions and ownership:

sudo chmod 600 /etc/expanso/bootstrap.token
sudo chown root:root /etc/expanso/bootstrap.token

Invalid Token

Symptom: Error: invalid bootstrap token

Solution:

  • Verify token hasn't expired in Expanso Cloud
  • Check for extra whitespace in token file
  • Regenerate token if necessary

Next Steps