Deployment Examples

Container and orchestration examples for running Shelly CLI as a metrics exporter.

Examples for deploying shelly-cli as a Prometheus metrics exporter.

Deployment Options

MethodDirectoryDescription
Kuberneteskubernetes/Kustomize manifests for K8s deployment
Dockerdocker/Docker Compose with optional Prometheus/Grafana

Configuration

Generate a config file with shelly init or create one manually.

See example configs for reference.

Headless Init

Use shelly init flags to configure without interactive prompts:

1
2
3
4
5
6
7
8
# Register devices directly
shelly init --device kitchen=192.168.1.100 --device bedroom=192.168.1.101

# Device with authentication
shelly init --device secure=192.168.1.102:admin:secret

# Bulk import from JSON
shelly init --devices-json devices.json

See the Docker and Kubernetes READMEs for container-specific examples using init containers and run args.

Quick Start

Kubernetes (Kustomize)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Use as remote base with your config
cat <<EOF > kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - https://github.com/tj-smith47/shelly-cli//examples/deployments/kubernetes
configMapGenerator:
  - name: shelly-config
    behavior: replace
    files:
      - config.yaml=~/.config/shelly/config.yaml
EOF

kustomize build . | kubectl apply -f -

Docker Compose

1
2
cd docker/
docker compose up -d

Docker

1
2
3
4
5
6
docker run -d \
  -p 9090:9090 \
  -v ~/.config/shelly:/root/.config/shelly:ro \
  --name shelly-exporter \
  ghcr.io/tj-smith47/shelly-cli:latest \
  metrics prometheus --port 9090

Metrics Exported

MetricTypeDescription
shelly_device_onlinegaugeDevice reachability (0/1)
shelly_wifi_rssigaugeWiFi signal strength (dBm)
shelly_uptime_secondscounterDevice uptime
shelly_temperature_celsiusgaugeDevice temperature
shelly_switch_ongaugeSwitch state (0/1)
shelly_power_wattsgaugeActive power consumption
shelly_voltage_voltsgaugeVoltage reading
shelly_current_ampsgaugeCurrent reading
shelly_energy_wh_totalcounterTotal energy consumed
shelly_frequency_hzgaugeAC frequency
shelly_ram_free_bytesgaugeFree RAM
shelly_ram_total_bytesgaugeTotal RAM

Prometheus Configuration

Add to your prometheus.yml:

1
2
3
4
5
scrape_configs:
  - job_name: 'shelly'
    static_configs:
      - targets: ['shelly-exporter:9090']  # or localhost:9090
    scrape_interval: 30s

Docker Compose

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# Shelly CLI Prometheus Exporter
#
# Configuration: Generate config with `shelly init` or place manually at ~/.config/shelly/config.yaml
# Example configs: https://github.com/tj-smith47/shelly-cli/tree/master/examples/config

services:
  shelly-exporter:
    image: ghcr.io/tj-smith47/shelly-cli:latest
    container_name: shelly-exporter
    command: ["metrics", "prometheus", "--port", "9090"]
    ports:
      - "9090:9090"
    volumes:
      - ${XDG_CONFIG_HOME:-$HOME/.config}/shelly:/root/.config/shelly:ro
    restart: unless-stopped
    networks:
      - monitoring
    healthcheck:
      test: ["CMD", "wget", "-q", "--spider", "http://localhost:9090/metrics"]
      interval: 30s
      timeout: 10s
      retries: 3

  # Optional: Prometheus to scrape metrics
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - "9091:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention.time=15d'
    restart: unless-stopped
    networks:
      - monitoring
    depends_on:
      - shelly-exporter
    profiles:
      - full

  # Optional: Grafana for dashboards
  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    volumes:
      - grafana-data:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
      - GF_USERS_ALLOW_SIGN_UP=false
    restart: unless-stopped
    networks:
      - monitoring
    depends_on:
      - prometheus
    profiles:
      - full

networks:
  monitoring:
    driver: bridge

volumes:
  prometheus-data:
  grafana-data:

Run shelly-cli as a Prometheus metrics exporter using Docker or Docker Compose.

Prerequisites

  • Docker 20.10+
  • Docker Compose v2 (optional)
  • Shelly config at ~/.config/shelly/config.yaml (generate with shelly init)

Quick Start

Using Docker Compose

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Start just the exporter
docker compose up -d shelly-exporter

# Start with full monitoring stack (Prometheus + Grafana)
docker compose --profile full up -d

# View logs
docker compose logs -f shelly-exporter

# Stop services
docker compose down

Using Docker Directly

1
2
3
4
5
6
docker run -d \
  -p 9090:9090 \
  -v ~/.config/shelly:/root/.config/shelly:ro \
  --name shelly-exporter \
  ghcr.io/tj-smith47/shelly-cli:latest \
  metrics prometheus --port 9090

Configuration

Generate a config file with shelly init or create one manually.

See example configs for reference.

Container Init Setup

Initialize config inside the container using run args:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# One-liner: init then run metrics
docker run -d \
  -p 9090:9090 \
  -v shelly-config:/root/.config/shelly \
  --name shelly-exporter \
  ghcr.io/tj-smith47/shelly-cli:latest \
  sh -c 'shelly init --device=kitchen=192.168.1.100 --device=bedroom=192.168.1.101 --no-color && shelly metrics prometheus --port 9090'

# Or init first, then run
docker run --rm \
  -v shelly-config:/root/.config/shelly \
  ghcr.io/tj-smith47/shelly-cli:latest \
  init --device=kitchen=192.168.1.100 --no-color

docker run -d \
  -p 9090:9090 \
  -v shelly-config:/root/.config/shelly \
  --name shelly-exporter \
  ghcr.io/tj-smith47/shelly-cli:latest \
  metrics prometheus --port 9090

Import devices from a JSON file:

1
2
3
4
5
docker run --rm \
  -v shelly-config:/root/.config/shelly \
  -v ./devices.json:/config/devices.json:ro \
  ghcr.io/tj-smith47/shelly-cli:latest \
  init --devices-json /config/devices.json --no-color

Network Mode

For device discovery to work, you may need host network mode:

1
2
3
4
5
6
docker run -d \
  --network host \
  -v ~/.config/shelly:/root/.config/shelly:ro \
  --name shelly-exporter \
  ghcr.io/tj-smith47/shelly-cli:latest \
  metrics prometheus --port 9090

Files

FileDescription
docker-compose.ymlDocker Compose configuration
prometheus.ymlPrometheus scrape configuration (for full profile)

Profiles

The Docker Compose file supports profiles:

  • Default (no profile): Just the shelly-exporter
  • full: Includes Prometheus and Grafana
1
2
3
4
5
# Exporter only
docker compose up -d

# Full monitoring stack
docker compose --profile full up -d

Verification

1
2
3
4
5
6
7
8
# Check container status
docker compose ps

# Test metrics endpoint
curl http://localhost:9090/metrics

# View exporter logs
docker compose logs shelly-exporter

Grafana Setup

When using the full profile, Grafana is available at http://localhost:3000

  1. Login with admin/admin
  2. Add Prometheus data source: http://prometheus:9090
  3. Import or create dashboards for Shelly metrics

Kubernetes

Deploy shelly-cli as a Prometheus metrics exporter in Kubernetes using Kustomize.

Prerequisites

  • Kubernetes cluster (1.19+)
  • kubectl configured
  • kustomize (or kubectl with kustomize support)
  • Shelly config file (generate with shelly init)

Quick Start

Create an overlay that references this as a remote base:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# my-shelly/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - https://github.com/tj-smith47/shelly-cli//examples/deployments/kubernetes

# Provide your config file
configMapGenerator:
  - name: shelly-config
    behavior: replace
    files:
      - config.yaml=~/.config/shelly/config.yaml

Then apply:

1
kustomize build my-shelly/ | kubectl apply -f -

Local Clone

1
2
3
4
5
6
7
8
9
# Clone and provide your config
git clone https://github.com/tj-smith47/shelly-cli.git
cd shelly-cli/examples/deployments/kubernetes

# Copy your config (or symlink)
cp ~/.config/shelly/config.yaml .

# Apply
kustomize build . | kubectl apply -f -

Configuration

Generate a config file with shelly init or create one manually.

See example configs for reference.

Init Container Setup

Use an init container to configure devices at pod startup:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# In your deployment overlay
spec:
  template:
    spec:
      initContainers:
        - name: init-config
          image: ghcr.io/tj-smith47/shelly-cli:latest
          command:
            - shelly
            - init
            - --device=kitchen=192.168.1.100
            - --device=bedroom=192.168.1.101
            - --api-mode=local
            - --no-color
          volumeMounts:
            - name: shelly-config
              mountPath: /root/.config/shelly
      volumes:
        - name: shelly-config
          emptyDir: {}

Or import from a ConfigMap containing device JSON:

1
2
3
4
5
6
7
8
9
initContainers:
  - name: init-config
    image: ghcr.io/tj-smith47/shelly-cli:latest
    command: ["sh", "-c"]
    args:
      - shelly init --devices-json /config/devices.json --no-color
    volumeMounts:
      - name: devices-json
        mountPath: /config

Image Version

To use a specific version in your overlay:

1
2
3
images:
  - name: ghcr.io/tj-smith47/shelly-cli
    newTag: v1.0.0

Prometheus Operator

If you have Prometheus Operator installed, add the ServiceMonitor to your overlay:

1
2
3
resources:
  - https://github.com/tj-smith47/shelly-cli//examples/deployments/kubernetes
  - https://github.com/tj-smith47/shelly-cli//examples/deployments/kubernetes/servicemonitor.yaml

Files

FileDescription
kustomization.yamlKustomize configuration with configMapGenerator
namespace.yamlCreates the monitoring namespace
deployment.yamlExporter deployment
service.yamlClusterIP service for scraping
servicemonitor.yamlPrometheus Operator ServiceMonitor (optional)

Verification

1
2
3
4
5
6
7
8
9
# Check deployment status
kubectl get pods -n monitoring -l app=shelly-exporter

# View logs
kubectl logs -n monitoring -l app=shelly-exporter

# Test metrics endpoint
kubectl port-forward -n monitoring svc/shelly-exporter 9090:9090
curl http://localhost:9090/metrics

Prometheus Configuration

If not using Prometheus Operator, add this to your prometheus.yml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
scrape_configs:
  - job_name: 'shelly'
    kubernetes_sd_configs:
      - role: endpoints
        namespaces:
          names:
            - monitoring
    relabel_configs:
      - source_labels: [__meta_kubernetes_service_label_app_kubernetes_io_name]
        regex: shelly-exporter
        action: keep

Or use static config:

1
2
3
4
5
scrape_configs:
  - job_name: 'shelly'
    static_configs:
      - targets: ['shelly-exporter.monitoring.svc.cluster.local:9090']
    scrape_interval: 30s

deployment.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
apiVersion: apps/v1
kind: Deployment
metadata:
  name: shelly-exporter
  namespace: monitoring
  labels:
    app.kubernetes.io/name: shelly-exporter
    app.kubernetes.io/component: exporter
spec:
  replicas: 1
  selector:
    matchLabels:
      app: shelly-exporter
  template:
    metadata:
      labels:
        app: shelly-exporter
        app.kubernetes.io/name: shelly-exporter
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9090"
        prometheus.io/path: "/metrics"
    spec:
      containers:
        - name: shelly-exporter
          image: ghcr.io/tj-smith47/shelly-cli:latest
          args:
            - metrics
            - prometheus
            - --port
            - "9090"
          ports:
            - containerPort: 9090
              name: metrics
              protocol: TCP
          volumeMounts:
            - name: config
              mountPath: /root/.config/shelly
              readOnly: true
          resources:
            requests:
              cpu: 10m
              memory: 32Mi
            limits:
              cpu: 100m
              memory: 64Mi
          livenessProbe:
            httpGet:
              path: /metrics
              port: 9090
            initialDelaySeconds: 10
            periodSeconds: 30
          readinessProbe:
            httpGet:
              path: /metrics
              port: 9090
            initialDelaySeconds: 5
            periodSeconds: 10
          securityContext:
            readOnlyRootFilesystem: true
            runAsNonRoot: false
            allowPrivilegeEscalation: false
      volumes:
        - name: config
          configMap:
            name: shelly-config
      securityContext:
        seccompProfile:
          type: RuntimeDefault

service.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
apiVersion: v1
kind: Service
metadata:
  name: shelly-exporter
  namespace: monitoring
  labels:
    app.kubernetes.io/name: shelly-exporter
    app.kubernetes.io/component: exporter
spec:
  type: ClusterIP
  ports:
    - port: 9090
      targetPort: 9090
      name: metrics
      protocol: TCP
  selector:
    app: shelly-exporter

servicemonitor.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# ServiceMonitor for Prometheus Operator
# Only apply if you have Prometheus Operator installed
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: shelly-exporter
  namespace: monitoring
  labels:
    app.kubernetes.io/name: shelly-exporter
    app.kubernetes.io/component: monitoring
spec:
  selector:
    matchLabels:
      app: shelly-exporter
  namespaceSelector:
    matchNames:
      - monitoring
  endpoints:
    - port: metrics
      interval: 30s
      path: /metrics
      scrapeTimeout: 10s