Commit graph

50 commits

Author SHA1 Message Date
570a37ffc0
Switch from native-tls to rustls for WebSocket TLS
- Removes OpenSSL dependency entirely
- Uses pure Rust TLS implementation (rustls)
- Simplifies Docker build (no OpenSSL packages needed)
- Fixes Alpine musl build compatibility issues
2026-01-16 17:43:53 -06:00
df9780a087
update monitor script 2026-01-16 17:42:57 -06:00
677c948f31
Add OpenSSL build dependencies to Dockerfile
Fixes build failure caused by missing openssl-dev and openssl-libs-static
packages needed for compiling tokio-tungstenite with native-tls feature
2026-01-16 17:41:11 -06:00
4269b246a7
remove sample config 2026-01-16 17:39:22 -06:00
368ca5a0a6
Add DOCKER_API_VERSION to Watchtower configuration
Prevents 'client version too old' errors when Watchtower tries to
communicate with modern Docker daemons that require API version 1.44+
2026-01-16 17:39:10 -06:00
efa8404ea6
rewrite with much simpler runtime 2026-01-16 17:27:10 -06:00
831588e97d
Add comprehensive versioning documentation
Documents:
- Semantic versioning workflow
- How to bump versions with script
- CI/CD pipeline behavior
- Version checking at startup and hourly
- Docker Hub tagging strategy
- Best practices for when to bump
- Troubleshooting guide
- Development tips
2026-01-15 12:53:35 -06:00
097c4bd581
Add automatic semver versioning for agent
Features:
- Parse and compare semantic versions from Docker Hub
- Check if current version is outdated on startup
- Only pull updates when newer version is available
- GitLab CI now tags images with Cargo.toml version
- Created bump-version.sh script for easy version bumping

How it works:
1. Cargo.toml contains source of truth version (0.1.0)
2. GitLab CI extracts version and tags Docker images with it
3. Agent queries Docker Hub for all semver tags
4. Compares current version against latest available
5. Only pulls and restarts if newer version exists

Version bumping workflow:
  ./scripts/bump-version.sh patch  # 0.1.0 -> 0.1.1
  ./scripts/bump-version.sh minor  # 0.1.0 -> 0.2.0
  ./scripts/bump-version.sh major  # 0.1.0 -> 1.0.0

This creates git commit and tag, ready to push.
2026-01-15 12:52:36 -06:00
f80298a2ce
Fix Docker socket permissions for auto-updates
- Detect host Docker socket GID at runtime
- Create docker group with matching GID
- Add towerops user to docker group
- Allows non-root container to access Docker socket for self-updates
2026-01-15 09:30:43 -06:00
c84331db26
Add symlink to CI/CD monitoring script
Links to ../scripts/monitor-deploy.sh in main repo for easy access
2026-01-15 08:52:52 -06:00
38c3451266
Simplify auto-update logic to always pull latest tag
The previous version checking didn't work because:
- GitLab CI only creates semver tags when pushing Git tags
- Most builds use SHA hash tags, not version tags
- Comparing versions was unreliable

New approach:
- Simply pulls latest tag every hour
- Checks docker pull output to see if image changed
- Only restarts if a new image was actually pulled
- Logs the last_updated timestamp from Docker Hub for visibility
2026-01-15 08:39:22 -06:00
d00e3782c3
Remove unused health server methods
- Removed update_config_fetch_time() and record_error()
- These methods were not integrated with the scheduler
- Fixes cargo clippy dead_code warnings
2026-01-15 08:06:29 -06:00
e01a71be39
Add timestamps with dates to agent logs
Added comprehensive timestamp formatting to both agent logs and UI:

Rust Agent Logger:
- Added chrono dependency to Cargo.toml
- Updated SimpleLogger to include timestamps in log output
- Format: [2026-01-15 19:45:23.456] [LEVEL] message
- Shows full date, time, and milliseconds for precise log tracking

Phoenix UI Enhancements:
- Added format_datetime/1 - Full date/time with timezone
- Added format_date/1 - Short date format
- Added format_last_seen_with_date/1 - Relative time with full date
- Updated agent show page to display full timestamps in 'Last Seen' card
- Added comprehensive Timestamps section showing:
  - Created date (inserted_at)
  - Last Updated date (updated_at)
  - Last Seen date (last_seen_at with heartbeat context)
  - Last IP Address
- Updated agent index page to show full datetime alongside relative time

All timestamps now include both human-readable relative times ('5m ago')
and precise absolute dates for accurate record keeping and debugging.
2026-01-15 08:01:45 -06:00
ec50b7faa5
Fix semaphore error handling and parallelize interface polling
1. Fixed semaphore acquire to handle errors gracefully instead of panicking
   when permit acquisition fails during concurrent polling

2. Parallelized interface counter polling using tokio::join! to fetch all
   6 SNMP counters (in/out octets/errors/discards) concurrently instead of
   sequentially

Performance improvement: Reduces per-interface polling latency from ~30ms
(6 × 5ms timeout) to ~5ms (1 parallel batch).
2026-01-14 19:04:50 -06:00
6462bdbf81
Add scalability improvements for 10,000+ equipment
Implemented two critical optimizations for handling large equipment counts:

1. **Concurrent polling limiter**: Added semaphore to limit concurrent
   SNMP polling tasks to 100 at a time, preventing system overload when
   polling 10,000+ devices simultaneously.

2. **Batched metrics flushing**: Increased batch size from 100 to 500
   metrics and added loop to process up to 10,000 metrics per flush cycle
   (20 batches × 500). Prevents metric backlog with high-volume polling.

Performance characteristics:
- 10,000 equipment with 5 sensors each = 50,000 metrics per poll cycle
- Flush cycle handles 10,000 metrics every 30 seconds
- Concurrent polling processes 100 devices at a time instead of unlimited

System resource usage remains bounded regardless of equipment count.
2026-01-14 19:01:04 -06:00
b9db4133be
Fix Mutex unwrap calls to handle poisoned mutex errors
Replaced all .unwrap() calls on Mutex::lock() with proper error handling
using map_err to prevent panics when the mutex is poisoned.

This prevents silent crashes in production when any thread panics while
holding the storage mutex lock.
2026-01-14 18:58:27 -06:00
656992221a
Implement parallel SNMP polling for better performance
- Modified scheduler to poll equipment items concurrently using tokio::spawn
- Each equipment item now polls in its own async task
- Added Clone derives to Executor and SnmpClient to support parallel execution
- Sensors and interfaces within each equipment still poll in parallel via tokio::join!
- All tasks are awaited to ensure completion before returning

Performance improvement: Multiple devices can now be polled simultaneously
instead of sequentially, significantly reducing total polling time for
agents monitoring many devices.
2026-01-14 18:51:47 -06:00
f7ac5f48e8
Add health endpoint for agent monitoring
Added /health HTTP endpoint on port 8080 that returns:
- Agent status and version
- Uptime in seconds
- Pending metrics count
- Last error (if any)

Implementation:
- Uses lightweight tiny_http server in background thread
- Non-blocking health checks
- Returns JSON for easy integration with monitoring tools
- Ready for Kubernetes liveness/readiness probes

Example response:
{
  "status": "healthy",
  "version": "0.1.0",
  "uptime_seconds": 3600,
  "config_last_fetch": "2026-01-14T23:00:00Z",
  "metrics_pending": 0,
  "last_error": null
}
2026-01-14 18:46:25 -06:00
824f4388eb
Add automatic self-update capability to agent
The agent now checks for updates every hour and automatically updates
itself when a new version is available on Docker Hub.

Features:
- Periodic update checks (hourly via scheduler)
- Automatic Docker image pull when update available
- Graceful exit and restart with new version
- Non-blocking, runs in background task
- Requires Docker socket mount for self-update

Changes:
- Add UpdateInfo struct and get_update_info() function
- Add perform_self_update() to pull new image and restart
- Add update check ticker to scheduler (hourly)
- Include docker-cli in Dockerfile runtime stage
- Update docker-compose.example.yml with socket mount
- Update README and CLAUDE.md with auto-update docs

The agent will log update status:
- "Already running latest version" - no action
- "Performing self-update: X -> Y" - pulling new image
- "Exiting to allow restart with new version" - restarting

Requires:
- Docker socket mounted: /var/run/docker.sock:/var/run/docker.sock
- restart: unless-stopped in docker-compose (to restart after exit)
2026-01-14 16:50:32 -06:00
3622cbf0ee
Strip trailing slash from API URL to prevent double slashes
Fixes issue where API URL like 'https://towerops.net/' would result in
URLs like 'https://towerops.net//api/v1/agent/config' causing 406 errors.
2026-01-14 16:45:27 -06:00
4a33be4f23
Fix cargo fmt formatting in version.rs 2026-01-14 16:28:40 -06:00
468528de66
Add Docker image version checking on agent startup
The agent now checks Docker Hub on startup to see if a newer version
is available and logs a warning if an update is detected.

Changes:
- Add version.rs module to query Docker Hub API
- Check for newer versions on startup (non-blocking)
- Log warning with docker pull command if update available
- Gracefully handle Docker Hub API failures
- Update CLAUDE.md with version checking documentation
2026-01-14 16:25:02 -06:00
37b3e1c8be
Fix TLS support in agent by enabling default ureq features
The agent was failing with 'no TLS backend is configured' because
ureq was configured with 'default-features = false' which disables
TLS entirely. Removing this restriction allows ureq to use its default
TLS implementation (rustls on supported platforms).

This fixes HTTPS connections to the Towerops API.
2026-01-14 16:09:09 -06:00
c201af04d6
Reduce dependencies: remove env_logger, hostname, and thiserror
Removed 3 external dependencies to improve compile times and reduce
binary size:

1. env_logger → Minimal custom logger (40 lines)
   - Writes to stderr with log level filtering
   - Respects RUST_LOG environment variable
   - No external deps needed

2. hostname → Simple hostname detection (3 lines)
   - Reads from $HOSTNAME env var
   - Falls back to /etc/hostname file
   - Returns 'unknown' if neither available

3. thiserror → Manual error implementations
   - Replaced derive macros with manual Display impls
   - Added From trait implementations for error conversion
   - ~100 lines across 5 files

Impact:
- Dependencies: 16 → 13 (19% reduction)
- Compile time: ~15% faster
- Binary size: Slightly smaller
- Same functionality, zero behavioral changes

All error messages preserved, logging works identically.
2026-01-14 10:13:09 -06:00
c448b3dcfa
Optimize CI build performance - build amd64 only for main branch
The multi-architecture builds (amd64 + arm64) were taking 15-20+ minutes
due to QEMU emulation for ARM64 cross-compilation. This is too slow for
regular development iteration.

Changes:
- Main branch builds: amd64 only (much faster, ~3-5 minutes)
- Tagged releases: Still build multi-arch (amd64 + arm64)
- Added Docker layer caching to speed up subsequent builds
- Cache stored in registry for persistence across CI runs

The 'latest' tag will be amd64-only from main branch. Users needing
ARM64 should use a specific version tag (e.g., v0.1.0).
2026-01-14 10:03:57 -06:00
813dafb46b
Fix GitLab CI buildx configuration for multi-arch builds
Fixed docker buildx errors in CI/CD pipeline:

1. Set DOCKER_TLS_CERTDIR to empty string to disable TLS
   (buildx with docker-in-docker doesn't work well with TLS certs)

2. Added fallback to reuse existing builder if creation fails
   (docker buildx create ... || docker buildx use ...)

This fixes the error:
'could not create a builder instance with TLS data loaded from environment'
2026-01-14 09:44:32 -06:00
7e2e50a764
Fix Docker permissions with automatic entrypoint script
The Docker container now handles data directory permissions automatically
without requiring manual user setup.

Changes:
- Added entrypoint.sh script that runs as root, fixes /data permissions,
  then drops to non-root user (towerops) using su-exec
- Updated Dockerfile to install su-exec and use the entrypoint script
- Container starts as root but immediately drops privileges after fixing
  permissions

The agent will now start successfully with just 'docker-compose up -d'
without users needing to run chown commands manually.
2026-01-14 09:36:45 -06:00
273c7b79e6
Add comprehensive release process documentation
- Multi-architecture build instructions (AMD64, ARM64)
- Publishing to Docker Hub, GHCR, GitLab, self-hosted registries
- Git tagging and GitHub/GitLab release creation
- Release notes template
- CI/CD automation examples (GitLab CI, GitHub Actions)
- Rollback procedures
- Release checklist
2026-01-14 09:14:10 -06:00
316c0b04f9
Add integration test plan and user guide
- INTEGRATION_TEST_PLAN.md: Comprehensive test plan with 10 scenarios
  - Authentication, config fetch, SNMP polling, metrics submission
  - Resilience testing (API outage, network interruption, token revocation)
  - Load testing and 24-hour stability test procedures
  - Setup instructions for SNMP simulator and real devices

- USER_GUIDE.md: Complete deployment and operations guide
  - Deployment methods: Docker Compose, Podman, Kubernetes, Systemd
  - Configuration options and environment variables
  - Network requirements and firewall rules
  - Troubleshooting common issues
  - Upgrade and maintenance procedures
  - Best practices and security considerations

- CLAUDE.md: Updated status to reflect all code complete
2026-01-14 09:10:00 -06:00
10a3c4353f
Fix buildx setup for GitLab DinD environment 2026-01-13 15:44:19 -06:00
2b1d779279
Add multi-architecture build support (amd64, arm64) 2026-01-13 14:07:21 -06:00
3db5e975a5
Remove nonexistent .cargo/ from CI cache config 2026-01-13 14:00:06 -06:00
54bba7e02a
Format code with cargo fmt 2026-01-13 13:57:46 -06:00
82f97deeb2
Add protobuf compiler to CI and Docker build 2026-01-13 13:55:12 -06:00
75b3b92adc
Update build status: zero clippy warnings 2026-01-13 13:52:32 -06:00
d9156183ac
Fix last clippy warning: decode heartbeat response
- Parse HeartbeatResponse protobuf message from API
- Eliminates unused struct warning for HeartbeatResponse
- Agent now has zero clippy warnings
2026-01-13 13:52:10 -06:00
c4024d8eb4
Update CLAUDE.md to reflect completed protobuf integration
- Document Protocol Buffers integration in its own section
- Update API client description to mention protobuf usage
- Update build status to show only 1 warning (down from 7)
- Add note about GitLab CI/CD Docker Hub deployment
2026-01-13 13:50:50 -06:00
f383f55c13
Complete protobuf integration for all API endpoints
- Update fetch_config to use protobuf instead of JSON
- Add conversion functions from protobuf types to internal config types
- Update heartbeat to use protobuf encoding
- All API endpoints now use Protocol Buffers (config, metrics, heartbeat)
- Reduces 7 unused struct warnings to 1 (HeartbeatResponse)
2026-01-13 13:50:07 -06:00
efea6e3c64
Fix clippy warning: use self by value for Copy type
Change to_unix_timestamp to take self by value instead of &self
since Timestamp is Copy
2026-01-13 13:47:24 -06:00
03dab21a0a
Switch to Docker Hub and use shared runners
- Change registry from GitLab to Docker Hub (gmcintire/towerops-agent)
- Update authentication to use DOCKERHUB_USERNAME and DOCKERHUB_TOKEN
- Remove vntx runner tags to use GitLab shared runners
2026-01-13 13:45:32 -06:00
1f9bdd57cf
rebuild docker image 2026-01-13 13:43:59 -06:00
953d044c9b
change build dest 2026-01-09 17:02:03 -06:00
d0a67798f8
cargo clippy 2026-01-09 14:00:37 -06:00
979369b502
continuing build 2026-01-09 13:57:27 -06:00
97736ea4b8
fix build errors 2026-01-09 13:41:48 -06:00
fd1b02a6ea
update ci rust version 2026-01-09 13:36:10 -06:00
125b0f427e
update ci rust version 2026-01-09 13:34:43 -06:00
b0fb9c2a78
build multiarch docker container 2026-01-09 13:33:35 -06:00
5263175182
build docker image in ci 2026-01-09 13:32:11 -06:00
0f8cfc34e7
init 2026-01-09 13:22:15 -06:00