Reverse Tunnel Feature Finalization
Summary
Successfully finalized the reverse tunnel feature with comprehensive lifecycle management, auto-expiration, cascade cleanup, and device reconnection capabilities.Features Implemented
1. ✅ Tunnel Expiration Tracking
Backend:expires_atfield already exists inreverse_tunnelstable- Automatically set to 12 hours when creating AWS IoT Secure Tunnel
- Location:
backend/app/services/reverse_tunnel_service.py:724
- Added
expires_atfield to TypeScript interface - Added
tunnel_statusfield for status tracking - Location:
frontend/src/pages/ReverseTunnels.tsx
2. ✅ Background Expiration Checker
Implementation:- Created
backend/app/services/reverse_tunnel_expiration.py - Runs every 5 minutes checking for expired tunnels
- Queries tunnels where
expires_at < nowandtunnel_status = 'active' - Calls
stop_reverse_tunnel()withreason="expired"
- Integrated into FastAPI startup via lifespan manager
- Location:
backend/app/main.py:95-128 - Automatically starts when backend launches
- Gracefully cancels on shutdown
3. ✅ Cascade Cleanup on Expiration
Flow: When a tunnel expires, the system automatically:- Deregisters ECS task IP from ALB target group
- Deletes ALB listener rule
- Stops ECS Fargate task
- Closes AWS IoT Secure Tunnel
- Sends MQTT control message to device:
- Topic:
roboticks/fleet/{device_id}/reverse-tunnel/control - Payload:
action: "reverse_tunnel_stopped",reason: "expired"
- Topic:
- Marks tunnel as disabled and stopped in database
- Existing
stop_reverse_tunnel()handles full cleanup - Location:
backend/app/services/reverse_tunnel_service.py:177-249
4. ✅ Device Reconnection on Heartbeat
Lambda Function:- Updated
infrastructure/lambda/device-heartbeat-handler/index.py - Detects offline → online transitions
- Queries for active reverse tunnels
- Sends MQTT reconnection messages
- Device sends heartbeat after being offline
- Lambda checks previous status:
was_offline = (previous_status != 'ONLINE') - If offline → online transition detected:
- Query:
SELECT * FROM reverse_tunnels WHERE device_id = ? AND is_enabled = true AND tunnel_status = 'active' - For each active tunnel, publish MQTT message with
reconnect: trueflag - Device reconnects to existing ECS proxy task and IoT tunnel
- Query:
- ECS tasks and IoT tunnels remain running during device offline periods
5. ✅ UI Enhancements
Expiration Display:- Shows time remaining in status column
- Color coding:
- Red: < 1 hour remaining or expired
- Orange: < 2 hours remaining
- Gray: > 2 hours remaining
- Format: “Xh Ym left” or “Expired”
- Location:
frontend/src/pages/ReverseTunnels.tsx:247-267
- Shows tunnel status chip:
pending,starting,active,stopping,stopped,error - Color coding:
- Green:
active - Orange:
starting,stopping - Red:
error - Gray:
stopped,pending
- Green:
- Alert box at top of create dialog
- Warning icon
- Clear message about 12-hour expiration
- Location:
frontend/src/pages/ReverseTunnels.tsx:552-560
6. ✅ API Documentation
Endpoint Documentation:- Updated
POST /devices/{dsn}/reverse-tunnelsdocstring - Added prominent warning about 12-hour expiration
- Location:
backend/app/api/v1/reverse_tunnels.py:112-114
- Added
tunnel_statusfield toReverseTunnelResponse - Added comment on
expires_at: “Auto-expiration time (12 hours from creation)” - Location:
backend/app/schemas/reverse_tunnel.py:72,81
Architecture Diagrams
Expiration Flow
Device Reconnection Flow
Testing Checklist
Backend
- Verify background task starts on backend launch
- Verify tunnels expire after 12 hours
- Verify cascade cleanup runs (check CloudWatch logs)
- Verify MQTT stop message sent on expiration
- Verify device reconnection MQTT sent on heartbeat after offline
Frontend
- Verify expiration time displays correctly
- Verify color changes as expiration approaches
- Verify “Expired” shows for expired tunnels
- Verify tunnel status chip shows correct status
- Verify warning alert shows in create dialog
End-to-End
- Create tunnel → verify expires_at is set
- Wait 12+ hours → verify tunnel auto-expires
- Verify ECS task stopped
- Verify ALB rule deleted
- Verify IoT tunnel closed
- Device offline → online → verify reconnection MQTT sent
- Verify device reconnects and tunnel works
Configuration
Environment Variables
No new environment variables needed. Uses existing:AWS_REGION- For AWS API calls- Database connection settings
- IoT endpoint settings
Background Task Interval
Default: 300 seconds (5 minutes) To change, editbackend/app/main.py:111:
Tunnel Expiration Time
Default: 720 minutes (12 hours) To change, editbackend/app/services/reverse_tunnel_service.py:114:
Deployment Notes
Backend Deployment
- Deploy backend with updated code
- Background task automatically starts
- Existing tunnels will be checked for expiration
- No database migration needed (
expires_atalready exists)
Lambda Deployment
- Update device-heartbeat-handler Lambda
- Add IAM permissions for IoT Data publish (should already exist)
- No environment variables needed
Frontend Deployment
- Build frontend with updated code
- Users will immediately see expiration times
- Create dialog will show warning
Monitoring
CloudWatch Logs
Backend logs to watch:Metrics to Track
- Number of tunnels expired per day
- Average tunnel lifetime
- Device reconnection success rate
- ECS task cleanup success rate
Future Enhancements
-
Configurable Expiration Time
- Allow users to set expiration time (1-24 hours)
- Enforce organization tier limits
-
Expiration Notifications
- Email warning 1 hour before expiration
- Dashboard notification for expiring tunnels
-
Auto-Renewal
- Optional auto-renewal for active tunnels
- Configurable maximum renewal count
-
Usage Tracking
- Track bandwidth usage per tunnel
- Generate usage reports
-
Connection Health
- Monitor ECS task health
- Auto-restart failed tunnels
- Alert on connection issues
Files Modified
Backend
backend/app/main.py- Added lifespan managerbackend/app/services/reverse_tunnel_expiration.py- New filebackend/app/schemas/reverse_tunnel.py- Added tunnel_statusbackend/app/api/v1/reverse_tunnels.py- Updated docs
Lambda
infrastructure/lambda/device-heartbeat-handler/index.py- Added reconnection logic
Frontend
frontend/src/pages/ReverseTunnels.tsx- Added expiration display and warning
Device SDK
roboticks-sdk/docker/roboticks/Dockerfile- Fixed nginx gzip issue
Rollback Plan
If issues occur:-
Disable Background Task:
- Comment out lines 111-113 in
backend/app/main.py - Restart backend
- Comment out lines 111-113 in
-
Disable Reconnection:
- Comment out lines 311-325 in Lambda heartbeat handler
- Redeploy Lambda
-
Revert Frontend:
- Deploy previous frontend version
- Users won’t see expiration times but functionality continues
Support
For issues or questions:- Check CloudWatch logs for backend/Lambda errors
- Verify ECS tasks are running
- Check AWS IoT tunnel status in console
- Review device logs for reconnection attempts