{"id":33918437,"url":"https://github.com/crstian19/prometheus-storagebox-exporter","last_synced_at":"2026-04-01T21:45:04.228Z","repository":{"id":328022070,"uuid":"1111835873","full_name":"crstian19/prometheus-storagebox-exporter","owner":"crstian19","description":"Modern Prometheus exporter for Hetzner Storage Box with comprehensive metrics","archived":false,"fork":false,"pushed_at":"2026-03-21T11:21:47.000Z","size":290,"stargazers_count":40,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-21T11:25:44.054Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/crstian19.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-07T18:11:28.000Z","updated_at":"2026-03-21T11:21:21.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/crstian19/prometheus-storagebox-exporter","commit_stats":null,"previous_names":["crstian19/prometheus-storagebox-exporter"],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/crstian19/prometheus-storagebox-exporter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crstian19%2Fprometheus-storagebox-exporter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crstian19%2Fprometheus-storagebox-exporter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crstian19%2Fprometheus-storagebox-exporter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crstian19%2Fprometheus-storagebox-exporter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/crstian19","download_url":"https://codeload.github.com/crstian19/prometheus-storagebox-exporter/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crstian19%2Fprometheus-storagebox-exporter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31292510,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T21:15:39.731Z","status":"ssl_error","status_checked_at":"2026-04-01T21:15:34.046Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-12T08:22:17.657Z","updated_at":"2026-04-01T21:45:04.210Z","avatar_url":"https://github.com/crstian19.png","language":"Go","funding_links":["https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=MUW2XFMQB2782"],"categories":["Tools"],"sub_categories":["Rust"],"readme":"# Prometheus Hetzner Storage Box Exporter\n\n\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"https://cdn.crstian.me/storage-box-exporter-logo.png\" alt=\"Storage Box Exporter Logo\" width=\"200\"\u003e\n\n**Modern Prometheus exporter for Hetzner Storage Box with comprehensive metrics**\n\n![CI](https://img.shields.io/github/actions/workflow/status/crstian19/prometheus-storagebox-exporter/ci.yml?label=CI\u0026logo=github\u0026logoColor=white\u0026style=for-the-badge\u0026branch=main)\n![Go Report Card](https://goreportcard.com/badge/github.com/crstian19/prometheus-storagebox-exporter?style=for-the-badge\u0026logo=go\u0026logoColor=white)\n![License](https://img.shields.io/github/license/crstian19/prometheus-storagebox-exporter?style=for-the-badge\u0026logo=unlicense\u0026logoColor=white)\n![Docker](https://img.shields.io/badge/docker-ghcr.io-blue?style=for-the-badge\u0026logo=docker\u0026logoColor=white)\n![GitHub Release](https://img.shields.io/github/release/crstian19/prometheus-storagebox-exporter?style=for-the-badge\u0026logo=github\u0026logoColor=white\u0026label=release)\n![Go Version](https://img.shields.io/github/go-mod/go-version/crstian19/prometheus-storagebox-exporter?style=for-the-badge\u0026logo=go\u0026logoColor=white\u0026label=go)\n\n[Quick Start](#-quick-start) • [Metrics](#-metrics) • [Installation](#-installation) • [Grafana Dashboard](#-grafana-dashboard) • [Configuration](#%EF%B8%8F-configuration)\n\n\u003c/div\u003e\n\n---\n\n## 📋 Overview\n\nA Prometheus exporter for [Hetzner Storage Box](https://www.hetzner.com/storage/storage-box) using the modern Hetzner Cloud API.\n\n- ✅ **15+ comprehensive metrics** - Storage usage, access settings, snapshots, and protection status\n- 🐳 **Multi-architecture Docker** - Images for amd64 and arm64\n- ☸️ **Kubernetes ready** - Pre-built manifests included\n- 🎯 **Lightweight** - Under 50MB memory usage\n- 📈 **Grafana dashboard** - 21-panel dashboard ready to import ([download](grafana-provisioning/dashboards/grafana-dashboard.json))\n- 🔒 **Bearer token auth** - Secure API authentication\n\n### Key Features\n\n- **All-in-one solution** - Includes Docker images, K8s manifests, and Grafana dashboard\n- **Additional metrics** - Access settings (SSH, Samba, WebDAV, ZFS), snapshot plans, and delete protection\n- **Production ready** - Health checks, structured logging, and comprehensive error handling\n\n### 📊 Dashboard Preview\n\n\u003cdiv align=\"center\"\u003e\n\n\u003ca href=\"grafana-provisioning/dashboards/grafana-dashboard.json\"\u003e\n  \u003cimg src=\"https://cdn.crstian.me/storagebox-dashboard.png\" alt=\"Dashboard Overview - Click to download\" width=\"800\"\u003e\n\u003c/a\u003e\n\n\n\u003cp\u003e\u003cem\u003eClick on dashboard image to download the JSON file for import \u003c/em\u003e\u003c/p\u003e\n\n\u003c/div\u003e\n\n---\n\n## 🚀 Quick Start\n\n### Prerequisites\n\nYou need a Hetzner API token with read permissions:\n\n1. Log in to [Hetzner Cloud Console](https://console.hetzner.cloud/)\n2. Navigate to **Security** → **API Tokens**\n3. Create a new token with **Read** permissions\n4. Copy the token for configuration\n\n### Docker Compose (Recommended)\n\n\n```bash\ndocker-compose up -d\n```\n\n### Docker\n\n```bash\ndocker run -d \\\n  --name storagebox-exporter \\\n  -p 9509:9509 \\\n  -e HETZNER_TOKEN=\"your-api-token\" \\\n  ghcr.io/crstian19/prometheus-storagebox-exporter:latest\n\n# With token file (recommended for NixOS)\necho \"your-api-token\" \u003e /run/secrets/hetzner-token\ndocker run -d \\\n  --name storagebox-exporter \\\n  -p 9509:9509 \\\n  -v /run/secrets/hetzner-token:/run/secrets/hetzner-token:ro \\\n  -e HETZNER_TOKEN_FILE=\"/run/secrets/hetzner-token\" \\\n  ghcr.io/crstian19/prometheus-storagebox-exporter:latest\n```\n\n**🐳 Multi-Architecture Docker Images**\n\nOur Docker images are built for multiple architectures with automatic platform detection:\n\n```bash\n# Automatically pulls the right image for your platform:\ndocker pull ghcr.io/crstian19/prometheus-storagebox-exporter:latest\n\n# Available architectures:\n# - Linux amd64 (Intel/AMD)\n# - Linux arm64 (ARM 64-bit)\n# - macOS amd64 (Intel Mac)\n# - macOS arm64 (Apple Silicon)\n```\n\n**🏷️ Available Tags:**\n- `latest` - Latest release (multi-arch)\n- `v0.x.x` - Specific version (multi-arch)\n- `latest-amd64` - Intel/AMD specific\n- `latest-arm64` - ARM specific\n\n### Binary\n\n```bash\n# Linux amd64\nwget https://github.com/crstian19/prometheus-storagebox-exporter/releases/latest/download/prometheus-storagebox-exporter_linux_x86_64.tar.gz\ntar xzf prometheus-storagebox-exporter_linux_x86_64.tar.gz\n\n# Run with environment variable\nexport HETZNER_TOKEN=\"your-api-token\"\n./prometheus-storagebox-exporter\n\n# Or with token file (recommended for NixOS)\necho \"your-api-token\" \u003e /run/secrets/hetzner-token\nexport HETZNER_TOKEN_FILE=\"/run/secrets/hetzner-token\"\n./prometheus-storagebox-exporter\n```\n\n### Access Metrics\n\nOpen http://localhost:9509/metrics to view the exported metrics.\n\n---\n\n---\n\n## ⚙️ Configuration\n\n### Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `HETZNER_TOKEN` | *required* | Hetzner API token (mutually exclusive with HETZNER_TOKEN_FILE) |\n| `HETZNER_TOKEN_FILE` | *optional* | Path to file containing Hetzner API token (mutually exclusive with HETZNER_TOKEN) |\n| `LISTEN_ADDRESS` | `:9509` | Address to listen on |\n| `METRICS_PATH` | `/metrics` | Path for metrics endpoint |\n| `LOG_LEVEL` | `info` | Log level (debug, info, warn, error) |\n| `CACHE_TTL` | `0` | Cache TTL in seconds, 0 to disable (default: disabled) |\n| `CACHE_MAX_SIZE` | `0` | Cache maximum size in bytes, 0 for unlimited |\n| `CACHE_CLEANUP_INTERVAL` | `0` | Cache cleanup interval in seconds, 0 for 10s default |\n| `CACHE_STORAGE_TYPE` | `memory` | Cache storage type (memory, redis) |\n\n### Command-line Flags\n\n```bash\n./prometheus-storagebox-exporter --help\n\nFlags:\n  --hetzner-token string           Hetzner API token (can also be set via HETZNER_TOKEN env var)\n  --hetzner-token-file string      Path to file containing Hetzner API token (can also be set via HETZNER_TOKEN_FILE env var)\n  --listen-address string          Address to listen on for HTTP requests (default \":9509\")\n  --metrics-path string            Path under which to expose metrics (default \"/metrics\")\n  --log-level string               Log level (debug, info, warn, error) (default \"info\")\n  --cache-ttl int                  Cache TTL in seconds, 0 to disable (can also be set via CACHE_TTL env var, default: 0 - disabled)\n  --cache-max-size int64           Cache maximum size in bytes, 0 for unlimited (can also be set via CACHE_MAX_SIZE env var, default: 0 - unlimited)\n  --cache-cleanup-interval int     Cache cleanup interval in seconds, 0 for default (can also be set via CACHE_CLEANUP_INTERVAL env var, default: 0 - 10s)\n  --cache-storage-type string      Cache storage type (memory, redis) (can also be set via CACHE_STORAGE_TYPE env var, default: memory)\n  --version                        Show version information and exit\n```\n\n### Cache Configuration (Optional)\n\n\u003e ⚠️ **Cache is disabled by default** following Prometheus best practices. Use `scrape_interval` in Prometheus instead of caching for most use cases.\n\n#### When to Enable Cache\n\n- **Multiple Prometheus instances**: Prevent duplicate API calls\n- **Rate limiting concerns**: Reduce API request frequency\n- **Development/Testing**: Minimize API calls during testing\n\n#### Cache Configuration Examples\n\n```bash\n# Enable cache with 60s TTL, 1MB size limit\nexport CACHE_TTL=60\nexport CACHE_MAX_SIZE=1048576\nexport CACHE_CLEANUP_INTERVAL=30\n\n# Enable with memory limit only (10s cleanup interval)\nexport CACHE_TTL=120\nexport CACHE_MAX_SIZE=5242880\n\n# Enable with custom cleanup interval\nexport CACHE_TTL=300\nexport CACHE_CLEANUP_INTERVAL=60\n```\n\n#### Prometheus Configuration (Recommended Alternative)\n\n```yaml\n# prometheus.yml\nscrape_configs:\n  - job_name: 'storagebox-exporter'\n    scrape_interval: 5m    # Control scraping frequency\n    scrape_timeout: 30s\n    static_configs:\n      - targets: ['localhost:9509']\n```\n\n---\n\n## 📊 Metrics\n\nThe exporter exposes 15+ metrics organized in 4 categories:\n\n### Core Storage Metrics\n\n| Metric | Type | Description | Labels |\n|--------|------|-------------|--------|\n| `storagebox_disk_quota_bytes` | Gauge | Total storage quota in bytes | id, name, server, location |\n| `storagebox_disk_usage_bytes` | Gauge | Total used diskspace in bytes | id, name, server, location |\n| `storagebox_disk_usage_data_bytes` | Gauge | Diskspace used by files in bytes | id, name, server, location |\n| `storagebox_disk_usage_snapshots_bytes` | Gauge | Diskspace used by snapshots in bytes | id, name, server, location |\n\n### Information \u0026 Status Metrics\n\n| Metric | Type | Description | Labels |\n|--------|------|-------------|--------|\n| `storagebox_info` | Info | Storage box information (value always 1) | id, name, username, server, location, storage_type, system |\n| `storagebox_status` | Gauge | Current status (1=active, 0=inactive) | id, name, status |\n| `storagebox_created_timestamp` | Gauge | Unix timestamp of creation | id, name |\n\n### Access Settings Metrics\n\n| Metric | Type | Description | Labels |\n|--------|------|-------------|--------|\n| `storagebox_access_ssh_enabled` | Gauge | SSH access enabled (1=yes, 0=no) | id, name |\n| `storagebox_access_samba_enabled` | Gauge | Samba/CIFS access enabled (1=yes, 0=no) | id, name |\n| `storagebox_access_webdav_enabled` | Gauge | WebDAV access enabled (1=yes, 0=no) | id, name |\n| `storagebox_access_zfs_enabled` | Gauge | ZFS access enabled (1=yes, 0=no) | id, name |\n| `storagebox_reachable_externally` | Gauge | External reachability (1=yes, 0=no) | id, name |\n\n### Protection \u0026 Snapshot Metrics\n\n| Metric | Type | Description | Labels |\n|--------|------|-------------|--------|\n| `storagebox_snapshot_plan_enabled` | Gauge | Automatic snapshots configured (1=yes, 0=no) | id, name |\n| `storagebox_protection_delete` | Gauge | Delete protection status (1=protected, 0=no) | id, name |\n\n### Exporter Metrics\n\n| Metric | Type | Description |\n|--------|------|-------------|\n| `storagebox_exporter_scrape_duration_seconds` | Gauge | Duration of the scrape in seconds |\n| `storagebox_exporter_scrape_errors_total` | Counter | Total number of scrape errors |\n| `storagebox_exporter_up` | Gauge | Exporter health status (1=healthy, 0=unhealthy) |\n| `storagebox_exporter_cache_hits_total` | Counter | Total number of cache hits (0 when cache disabled) |\n| `storagebox_exporter_cache_misses_total` | Counter | Total number of cache misses (increments every scrape when cache disabled) |\n\n---\n\n\n### Dashboard Features\n\n- **📊 Overview Section**: Gauges for disk usage percentage and disk space distribution\n- **📈 Time Series Graphs**:\n  - Disk usage over time with quota visualization\n  - Usage breakdown (Data vs Snapshots) with dual Y-axes\n  - Disk usage percentage trends\n  - Storage growth rate analysis (1h intervals)\n- **📋 Detailed Table**: Complete storage box details with all metrics\n- **🔧 Access Status**: Visual indicators for SSH, Samba, WebDAV, and ZFS access\n- **🛡️ Configuration Info**: Snapshot plan and delete protection status\n- **📊 Multi-box Support**: Variable to filter by specific storage box or view all\n\n### Quick test with Docker Compose\n\nThe repository includes a complete Docker Compose test with pre-configured dashboard:\n\n```bash\n# Start all services (Exporter + Prometheus + Grafana)\n./test-env.sh\n\n# Or manually:\ndocker-compose -f docker-compose.dev.yml up -d\n```\n\nAccess points:\n- 🎯 **Grafana Dashboard**: http://localhost:3000 (admin/admin) - *Dashboard is pre-imported*\n- 📈 **Prometheus**: http://localhost:9090\n- 🔧 **Exporter**: http://localhost:9509/metrics\n\n\u003e **💡 For production**: Import the dashboard manually using [grafana-dashboard.json](grafana-provisioning/dashboards/grafana-dashboard.json)\n\n### Dashboard Panels\n\nThe dashboard includes:\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003ctd width=\"50%\"\u003e\n\n- Disk Usage Percentage (Gauge)\n- Disk Space Distribution (Pie)\n- Total Quota (Stat)\n- Total Used (Stat)\n- Free Space (Stat)\n- Data Files Usage (Stat)\n\n\u003c/td\u003e\n\u003ctd width=\"50%\"\u003e\n\n- Snapshots Usage (Stat)\n- Snapshot Overhead (Stat)\n- Disk Usage Over Time\n- Usage Breakdown Over Time\n- Disk Usage Percentage Over Time\n- Storage Growth Rate (1h)\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n**Access Settings Panels:**\n- SSH Access Status\n- Samba Access Status\n- WebDAV Access Status\n- ZFS Access Status\n- External Reachability Status\n\n**Configuration Panels:**\n- Storage Box Status\n- Snapshot Plan Status\n- Delete Protection Status\n\n**Details Table:**\n- Storage Box Details (comprehensive table)\n\n\n\n## 🐳 Docker Deployment\n\n### Docker Compose\n\nComplete `docker-compose.yml` example with Prometheus and Grafana:\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand Docker Compose\u003c/summary\u003e\n\n```yaml\nversion: '3.8'\n\nservices:\n  # Storage Box Exporter\n  storagebox-exporter:\n    image: ghcr.io/crstian19/prometheus-storagebox-exporter:latest\n    container_name: storagebox-exporter\n    restart: unless-stopped\n    ports:\n      - \"9509:9509\"\n    environment:\n      - HETZNER_TOKEN=${HETZNER_TOKEN}\n      # Optional cache configuration (uncomment to enable)\n      # - CACHE_TTL=60\n      # - CACHE_MAX_SIZE=1048576\n      # - CACHE_CLEANUP_INTERVAL=30\n    networks:\n      - monitoring\n\n  # Prometheus\n  prometheus:\n    image: prom/prometheus:latest\n    container_name: prometheus\n    restart: unless-stopped\n    ports:\n      - \"9090:9090\"\n    volumes:\n      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro\n      - prometheus-data:/prometheus\n    command:\n      - '--config.file=/etc/prometheus/prometheus.yml'\n      - '--storage.tsdb.path=/prometheus'\n      - '--web.console.libraries=/usr/share/prometheus/console_libraries'\n      - '--web.console.templates=/usr/share/prometheus/consoles'\n      - '--web.enable-lifecycle'\n    networks:\n      - monitoring\n    depends_on:\n      - storagebox-exporter\n\n  # Grafana\n  grafana:\n    image: grafana/grafana:10.2.0\n    container_name: grafana\n    restart: unless-stopped\n    ports:\n      - \"3000:3000\"\n    environment:\n      - GF_SECURITY_ADMIN_USER=admin\n      - GF_SECURITY_ADMIN_PASSWORD=admin\n      - GF_USERS_ALLOW_SIGN_UP=false\n    volumes:\n      - grafana-data:/var/lib/grafana\n      - ./grafana-provisioning:/etc/grafana/provisioning:ro\n    networks:\n      - monitoring\n    depends_on:\n      - prometheus\n\nnetworks:\n  monitoring:\n    driver: bridge\n\nvolumes:\n  prometheus-data:\n  grafana-data:\n```\n\n\u003c/details\u003e\n\n### Prometheus Configuration\n\nAdd to your `prometheus.yml`:\n\n```yaml\nscrape_configs:\n  - job_name: 'hetzner-storagebox'\n    static_configs:\n      - targets: ['storagebox-exporter:9509']\n    scrape_interval: 60s\n    scrape_timeout: 30s\n```\n\n---\n\n## ☸️ Kubernetes Deployment\n\n### Quick Deploy\n\n```bash\n# Apply all manifests\nkubectl apply -f k8s/\n\n# Check status\nkubectl get pods -n monitoring\n```\n\n### Manifests\n\n\u003cdetails\u003e\n\u003csummary\u003eClick to expand Kubernetes YAML\u003c/summary\u003e\n\n```yaml\napiVersion: v1\nkind: Secret\nmetadata:\n  name: storagebox-exporter-secret\n  namespace: monitoring\ntype: Opaque\nstringData:\n  hetzner-token: \"your-api-token-here\"\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: storagebox-exporter\n  namespace: monitoring\n  labels:\n    app: storagebox-exporter\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: storagebox-exporter\n  template:\n    metadata:\n      labels:\n        app: storagebox-exporter\n    spec:\n      containers:\n      - name: storagebox-exporter\n        image: ghcr.io/crstian19/prometheus-storagebox-exporter:latest\n        ports:\n        - containerPort: 9509\n          name: metrics\n        env:\n        - name: HETZNER_TOKEN\n          valueFrom:\n            secretKeyRef:\n              name: storagebox-exporter-secret\n              key: hetzner-token\n        livenessProbe:\n          httpGet:\n            path: /health\n            port: metrics\n          initialDelaySeconds: 10\n          periodSeconds: 30\n        readinessProbe:\n          httpGet:\n            path: /health\n            port: metrics\n          initialDelaySeconds: 5\n          periodSeconds: 10\n        resources:\n          requests:\n            memory: \"32Mi\"\n            cpu: \"50m\"\n          limits:\n            memory: \"64Mi\"\n            cpu: \"100m\"\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: storagebox-exporter\n  namespace: monitoring\n  labels:\n    app: storagebox-exporter\nspec:\n  type: ClusterIP\n  ports:\n  - port: 9509\n    targetPort: metrics\n    name: metrics\n  selector:\n    app: storagebox-exporter\n---\napiVersion: monitoring.coreos.com/v1\nkind: ServiceMonitor\nmetadata:\n  name: storagebox-exporter\n  namespace: monitoring\n  labels:\n    app: storagebox-exporter\nspec:\n  selector:\n    matchLabels:\n      app: storagebox-exporter\n  endpoints:\n  - port: metrics\n    interval: 60s\n    scrapeTimeout: 30s\n```\n\n\u003c/details\u003e\n\n---\n\n## 🏗️ Development\n\n### Building\n\n```bash\n# Build binary\ngo build -o prometheus-storagebox-exporter .\n\n# Build Docker image\ndocker build -t prometheus-storagebox-exporter .\n\n# Run tests\ngo test -v ./...\n\n# Run linter\ngolangci-lint run\n```\n\n### Project Structure\n\n```\n.\n├── main.go                 # Application entry point\n├── internal/\n│   ├── collector/          # Prometheus collector implementation\n│   ├── hetzner/           # Hetzner API client\n│   └── config/            # Configuration handling\n├── grafana-provisioning/  # Grafana dashboard provisioning\n├── k8s/                   # Kubernetes manifests\n├── .github/workflows/     # CI/CD pipelines\n├── Dockerfile             # Multi-stage Docker build\n├── docker-compose.yml     # Docker Compose configuration\n├── docker-compose.dev.yml # Development environment\n└── DESIGN.md             # Architecture documentation\n```\n\n\n## 🐛 Troubleshooting\n\n### Common Issues\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eError: \"HETZNER_TOKEN or HETZNER_TOKEN_FILE environment variable is required\"\u003c/strong\u003e\u003c/summary\u003e\n\nMake sure you've set either the `HETZNER_TOKEN` environment variable or the `HETZNER_TOKEN_FILE` environment variable.\n\n```bash\n# Option 1: Direct token\nexport HETZNER_TOKEN=\"your-token-here\"\n./prometheus-storagebox-exporter\n\n# Option 2: Token from file (recommended for NixOS)\necho \"your-token-here\" \u003e /run/secrets/hetzner-token\nexport HETZNER_TOKEN_FILE=\"/run/secrets/hetzner-token\"\n./prometheus-storagebox-exporter\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eError: \"cannot specify both HETZNER_TOKEN and HETZNER_TOKEN_FILE\"\u003c/strong\u003e\u003c/summary\u003e\n\nYou cannot specify both token methods simultaneously. Choose either `HETZNER_TOKEN` or `HETZNER_TOKEN_FILE`, not both.\n\n```bash\n# Correct: Use only one method\nexport HETZNER_TOKEN=\"your-token-here\"\n# or\nexport HETZNER_TOKEN_FILE=\"/path/to/token/file\"\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eError: \"API request failed with status 401\"\u003c/strong\u003e\u003c/summary\u003e\n\nYour API token is invalid or has expired. Generate a new token from the Hetzner Cloud Console with **Read** permissions.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eError: \"API request failed with status 403\"\u003c/strong\u003e\u003c/summary\u003e\n\nYour API token doesn't have sufficient permissions. Ensure the token has at least **Read** permissions.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eNo metrics appearing in Prometheus\u003c/strong\u003e\u003c/summary\u003e\n\n1. Check exporter health: `curl http://localhost:9509/health`\n2. Check metrics endpoint: `curl http://localhost:9509/metrics`\n3. Verify Prometheus configuration\n4. Check exporter logs: `docker logs storagebox-exporter`\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eGrafana dashboard shows \"No data\"\u003c/strong\u003e\u003c/summary\u003e\n\n1. Verify Prometheus is scraping the exporter\n2. Check the data source URL in Grafana\n3. Ensure the storage box variable has values\n4. Check the time range in Grafana\n\n\u003c/details\u003e\n\n---\n\n## 🤝 Contributing\n\nContributions are welcome! Please:\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n### Adding New Metrics\n\n1. Update the collector in `internal/collector/storagebox.go`\n2. Add metric definitions\n3. Update the Grafana dashboard ([grafana-dashboard.json](grafana-provisioning/dashboards/grafana-dashboard.json)) if needed\n4. Update this README\n\n---\n\n## 📄 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n---\n\n## 🙏 Credits\n\n### Technologies\n- [Hetzner Storage Box](https://www.hetzner.com/storage/storage-box) - Backup storage solution\n- [Hetzner Cloud API](https://docs.hetzner.cloud/) - Modern API infrastructure\n- [Prometheus](https://prometheus.io/) - Monitoring toolkit and time series database\n- [Grafana](https://grafana.com/) - Analytics and monitoring platform\n- [Go](https://golang.org/) - Programming language\n\n### Inspiration\n- [fleaz/prometheus-storagebox-exporter](https://github.com/fleaz/prometheus-storagebox-exporter) - Original implementation\n- [Prometheus exporter best practices](https://github.com/prometheus/client_golang)\n\n---\n\n## 📞 Support\n\n- **Issues**: [Report a bug](https://github.com/crstian19/prometheus-storagebox-exporter/issues)\n- **Features**: [Request a feature](https://github.com/crstian19/prometheus-storagebox-exporter/issues/new?template=feature_request.md)\n- **Security**: [Report a vulnerability](https://github.com/crstian19/prometheus-storagebox-exporter/security)\n- **Documentation**: [DESIGN.md](DESIGN.md) for architecture details\n\n## 💝 Donate\n\nIf you find this project useful and want to support its development, you can donate via PayPal:\n\n[![Donate](https://img.shields.io/badge/Donate-PayPal-blue?style=for-the-badge\u0026logo=paypal\u0026logoColor=white)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=MUW2XFMQB2782)\n\nYour support helps keep this project maintained and improved! 🙏\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\n**⭐ If this project helped you, consider giving it a star!**\n\nMade with ❤️ from 🇪🇸 for the Prometheus and Hetzner communities\n\n\u003c/div\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrstian19%2Fprometheus-storagebox-exporter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcrstian19%2Fprometheus-storagebox-exporter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrstian19%2Fprometheus-storagebox-exporter/lists"}