mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-02-13 23:59:00 -06:00
Store user avatars in persistent /data volume instead of application directory to ensure profile pictures survive container rebuilds and version updates. Changes: - Update avatar upload folder from app/static/uploads/avatars to /data/uploads/avatars using existing app_data volume mount - Modify get_avatar_upload_folder() in auth routes to use persistent location with UPLOAD_FOLDER config - Update User.get_avatar_path() to reference new storage location - Add migration script to safely move existing avatars to new location - Preserve backward compatibility - no database changes required Benefits: - Profile pictures now persist between Docker image updates - Consistent with company logo storage pattern (/data/uploads) - Better user experience - avatars not lost during upgrades - Production-ready data/code separation - All persistent uploads consolidated in app_data volume Migration: For existing installations with user avatars, run: docker-compose run --rm app python /app/docker/migrate-avatar-storage.py New installations work automatically with no action required. Documentation: - docs/AVATAR_STORAGE_MIGRATION.md - Full migration guide - docs/AVATAR_PERSISTENCE_SUMMARY.md - Quick reference - docs/TEST_AVATAR_PERSISTENCE.md - Testing guide - AVATAR_PERSISTENCE_CHANGELOG.md - Detailed changelog Files modified: - app/routes/auth.py - app/models/user.py Files added: - docker/migrate-avatar-storage.py - docs/AVATAR_STORAGE_MIGRATION.md - docs/AVATAR_PERSISTENCE_SUMMARY.md - docs/TEST_AVATAR_PERSISTENCE.md - AVATAR_PERSISTENCE_CHANGELOG.md Tested: ✓ No linter errors, backward compatible, volume mount verified
190 lines
5.5 KiB
Markdown
190 lines
5.5 KiB
Markdown
# User Avatar Storage Migration Guide
|
|
|
|
## Overview
|
|
|
|
As of this update, user profile pictures (avatars) are now stored in the persistent `/data` volume instead of the application directory. This ensures that **profile pictures persist between Docker container updates and rebuilds**.
|
|
|
|
## What Changed?
|
|
|
|
### Previous Behavior
|
|
- **Location:** `app/static/uploads/avatars/`
|
|
- **Problem:** This directory is inside the application container, so avatars were lost when updating or rebuilding the Docker image
|
|
- **Impact:** Users had to re-upload their profile pictures after each update
|
|
|
|
### New Behavior
|
|
- **Location:** `/data/uploads/avatars/`
|
|
- **Solution:** This directory is on the persistent `app_data` Docker volume
|
|
- **Benefit:** Profile pictures are preserved across all updates and rebuilds
|
|
|
|
## Migration Required?
|
|
|
|
**If you have existing user avatars**, you need to run the migration script to move them to the new location.
|
|
|
|
**If you're setting up a fresh installation**, no migration is needed - the new location will be used automatically.
|
|
|
|
## How to Migrate Existing Avatars
|
|
|
|
### Docker Environment
|
|
|
|
1. **Stop your TimeTracker containers:**
|
|
```bash
|
|
docker-compose down
|
|
```
|
|
|
|
2. **Run the migration script:**
|
|
```bash
|
|
docker-compose run --rm app python /app/docker/migrate-avatar-storage.py
|
|
```
|
|
|
|
3. **Start your containers:**
|
|
```bash
|
|
docker-compose up -d
|
|
```
|
|
|
|
4. **Verify avatars are working:**
|
|
- Log in to TimeTracker
|
|
- Check that user profile pictures are displayed correctly
|
|
- Try uploading a new avatar to confirm uploads work
|
|
|
|
5. **Optional - Cleanup old files:**
|
|
After confirming everything works, you can remove the old avatar directory:
|
|
```bash
|
|
docker-compose exec app rm -rf /app/static/uploads/avatars
|
|
```
|
|
|
|
### Bare Metal / Development Environment
|
|
|
|
1. **Navigate to your TimeTracker directory:**
|
|
```bash
|
|
cd /path/to/TimeTracker
|
|
```
|
|
|
|
2. **Ensure the new directory exists:**
|
|
```bash
|
|
mkdir -p /data/uploads/avatars
|
|
```
|
|
|
|
3. **Run the migration script:**
|
|
```bash
|
|
python docker/migrate-avatar-storage.py
|
|
```
|
|
|
|
4. **Restart your application:**
|
|
```bash
|
|
# Your normal restart command
|
|
systemctl restart timetracker
|
|
# or
|
|
./restart.sh
|
|
```
|
|
|
|
5. **Verify and cleanup:**
|
|
Follow steps 4-5 from the Docker instructions above.
|
|
|
|
## Technical Details
|
|
|
|
### Files Modified
|
|
|
|
1. **`app/routes/auth.py`**
|
|
- Updated `get_avatar_upload_folder()` to use `/data/uploads/avatars`
|
|
- Comment added explaining the persistence benefit
|
|
|
|
2. **`app/models/user.py`**
|
|
- Updated `get_avatar_path()` to use `/data/uploads/avatars`
|
|
- Added fallback for development environments
|
|
|
|
3. **`docker-compose.yml`**
|
|
- Already had `app_data:/data` volume mount (no changes needed)
|
|
|
|
### Configuration
|
|
|
|
The avatar location now respects the `UPLOAD_FOLDER` configuration:
|
|
- **Default:** `/data/uploads` (avatars go to `/data/uploads/avatars`)
|
|
- **Configurable:** Set `UPLOAD_FOLDER` in your environment to change the base path
|
|
|
|
### URL Structure
|
|
|
|
The public URL structure **remains unchanged**:
|
|
- **URL:** `/uploads/avatars/{filename}`
|
|
- **Route:** Handled by `auth.serve_uploaded_avatar()`
|
|
|
|
This means existing avatar URLs in the database continue to work without modification.
|
|
|
|
## Troubleshooting
|
|
|
|
### Avatars not displaying after migration
|
|
|
|
1. **Check file permissions:**
|
|
```bash
|
|
docker-compose exec app ls -la /data/uploads/avatars/
|
|
```
|
|
Files should be readable by the app user.
|
|
|
|
2. **Verify volume mount:**
|
|
```bash
|
|
docker inspect timetracker-app | grep -A 5 Mounts
|
|
```
|
|
Should show `/data` mounted from the `app_data` volume.
|
|
|
|
3. **Check migration log:**
|
|
Re-run the migration script to see if files were actually copied.
|
|
|
|
### New avatar uploads failing
|
|
|
|
1. **Check directory permissions:**
|
|
```bash
|
|
docker-compose exec app touch /data/uploads/avatars/.test
|
|
```
|
|
If this fails, fix permissions:
|
|
```bash
|
|
docker-compose exec app chown -R app:app /data/uploads/avatars
|
|
docker-compose exec app chmod -R 755 /data/uploads/avatars
|
|
```
|
|
|
|
2. **Check disk space:**
|
|
```bash
|
|
docker-compose exec app df -h /data
|
|
```
|
|
|
|
### Migration script can't find old directory
|
|
|
|
This is normal if:
|
|
- You're setting up a fresh installation (no avatars to migrate)
|
|
- Avatars were already migrated previously
|
|
- No users have uploaded avatars yet
|
|
|
|
The script will create the new directory structure automatically.
|
|
|
|
## Benefits of This Change
|
|
|
|
✅ **Persistent Storage:** Profile pictures survive Docker updates and rebuilds
|
|
✅ **Consistent with Logos:** Company logos already use `/data/uploads` (consistency)
|
|
✅ **Better UX:** Users don't lose their profile pictures during updates
|
|
✅ **Production Ready:** Proper separation of persistent data from application code
|
|
✅ **Backup Friendly:** All persistent uploads are in one volume (`app_data`)
|
|
|
|
## Backup Recommendations
|
|
|
|
Since avatars are now on the `app_data` volume, include this volume in your backup strategy:
|
|
|
|
```bash
|
|
# Backup the entire data volume
|
|
docker run --rm -v timetracker_app_data:/data -v $(pwd):/backup ubuntu tar czf /backup/app_data_backup.tar.gz -C /data .
|
|
|
|
# Restore the data volume
|
|
docker run --rm -v timetracker_app_data:/data -v $(pwd):/backup ubuntu tar xzf /backup/app_data_backup.tar.gz -C /data
|
|
```
|
|
|
|
## Questions?
|
|
|
|
If you encounter any issues with the avatar migration:
|
|
|
|
1. Check the [Troubleshooting](#troubleshooting) section above
|
|
2. Review the Docker logs: `docker-compose logs app`
|
|
3. Open an issue on GitHub with migration script output
|
|
|
|
---
|
|
|
|
**Last Updated:** October 2025
|
|
**Applies to:** TimeTracker v2.x and later
|
|
|