# Release Notes - v1.3.75

**Release Date:** 2. januar 2026

## ✨ New Features

### SFTP Offsite Backup
- **Implemented SFTP offsite backup** - Backups can now be uploaded to remote SFTP server
- **Auto-upload support** - Backups can be automatically uploaded after creation
- **Manual upload** - Backups can be manually uploaded via web UI
- **Upload verification** - File size verification ensures successful upload
- **Retry mechanism** - Failed uploads can be retried with error tracking

### Database Schema Updates
- Added `offsite_status` column (pending, uploading, uploaded, failed)
- Added `offsite_location` column for remote file path
- Added `offsite_attempts` counter for retry tracking
- Added `offsite_last_error` for error logging

## 🔧 Technical Improvements

### SFTP Implementation
- Uses `paramiko` library for SFTP connections
- Supports password authentication
- Automatic directory creation on remote server
- Progress tracking during upload
- Connection timeout protection (30s banner timeout)

### Configuration
- `OFFSITE_ENABLED` - Enable/disable offsite uploads
- `SFTP_HOST` - Remote SFTP server hostname
- `SFTP_PORT` - SFTP port (default: 22)
- `SFTP_USER` - SFTP username
- `SFTP_PASSWORD` - SFTP password
- `SFTP_REMOTE_PATH` - Remote directory path

### Bug Fixes
- Fixed infinite loop in `_ensure_remote_directory()` for relative paths
- Fixed duplicate `upload_to_offsite()` method - removed redundant code
- Fixed router method name mismatch (`upload_offsite` vs `upload_to_offsite`)
- Added protection against empty/root path directory creation

## 📝 Files Changed

- `app/backups/backend/service.py` - SFTP upload implementation
- `app/backups/backend/router.py` - Offsite upload endpoint
- `app/backups/templates/index.html` - Frontend offsite upload button
- `app/core/config.py` - SFTP configuration settings
- `migrations/052_backup_offsite_columns.sql` - Database schema migration
- `.env` - SFTP configuration

## 🚀 Deployment Instructions

### Prerequisites
- Ensure `.env` file contains SFTP credentials
- Database migration must be applied

### Production Server Update

1. **SSH til serveren:**
   ```bash
   ssh bmcadmin@172.16.31.183
   ```

2. **Naviger til projekt directory:**
   ```bash
   cd /opt/bmc_hub  # Eller korrekt sti
   ```

3. **Pull ny version:**
   ```bash
   git fetch --tags
   git checkout v1.3.75
   ```

4. **Opdater .env fil med SFTP credentials:**
   ```bash
   nano .env
   # Tilføj:
   # OFFSITE_ENABLED=true
   # SFTP_HOST=sftp.acdu.dk
   # SFTP_PORT=9022
   # SFTP_USER=sftp_bmccrm
   # SFTP_PASSWORD=<password>
   # SFTP_REMOTE_PATH=SFTP_BMCCRM
   ```

5. **Kør database migration:**
   ```bash
   docker-compose exec postgres psql -U bmcnetworks -d bmc_hub -f /migrations/052_backup_offsite_columns.sql
   # ELLER manuel ALTER TABLE:
   docker-compose exec postgres psql -U bmcnetworks -d bmc_hub -c "
   ALTER TABLE backup_jobs ADD COLUMN IF NOT EXISTS offsite_status VARCHAR(20) CHECK(offsite_status IN ('pending','uploading','uploaded','failed'));
   ALTER TABLE backup_jobs ADD COLUMN IF NOT EXISTS offsite_location VARCHAR(500);
   ALTER TABLE backup_jobs ADD COLUMN IF NOT EXISTS offsite_attempts INTEGER DEFAULT 0;
   ALTER TABLE backup_jobs ADD COLUMN IF NOT EXISTS offsite_last_error TEXT;
   "
   ```

6. **Genstart containers:**
   ```bash
   docker-compose down
   docker-compose up -d --build
   ```

7. **Verificer:**
   ```bash
   docker-compose logs -f api | grep -i offsite
   curl http://localhost:8001/health
   # Test offsite upload:
   curl -X POST http://localhost:8001/api/v1/backups/offsite/{job_id}
   ```

## 🧪 Testing

### Verify SFTP Connection
```bash
# From inside API container:
docker-compose exec api bash
apt-get update && apt-get install -y lftp
lftp -u sftp_bmccrm,'<password>' sftp://sftp.acdu.dk:9022 -e 'ls SFTP_BMCCRM; quit'
```

### Test Upload
1. Create a backup via web UI: http://localhost:8001/backups
2. Click "Upload to Offsite" button for the backup
3. Check logs for "✅ Upload completed"
4. Verify `offsite_uploaded_at` is set in database

## ⚠️ Breaking Changes

None - this is a feature addition

## 📊 Database Migration

**Migration File:** `migrations/052_backup_offsite_columns.sql`

**Impact:** Adds 4 new columns to `backup_jobs` table
- Safe to run on existing data (uses ADD COLUMN IF NOT EXISTS)
- No data loss risk
- Existing backups will have NULL values for new columns

## 🔐 Security Notes

- SFTP password stored in `.env` file (not in repository)
- Uses paramiko's `AutoAddPolicy` for host keys
- File size verification prevents corrupt uploads
- Connection timeout prevents indefinite hangs

## 📞 Support

Ved problemer, kontakt Christian Thomas eller check logs:
```bash
docker-compose logs -f api | grep -E "(offsite|SFTP|Upload)"
```

---

**Git Tag:** v1.3.75  
**Previous Version:** v1.3.74  
**Tested on:** Local development environment (macOS Docker)
