diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 0000000..471bbe1 --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,83 @@ +name: Build and push images + +on: + push: + branches: [main] + workflow_dispatch: # allow manual trigger from Gitea UI + +env: + REGISTRY: ${{ vars.GITEA_URL }} # e.g. gitea.yourdomain.com — set in repo Settings → Variables + OWNER: ${{ gitea.repository_owner }} + +jobs: + build-backend: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Log in to Gitea registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ gitea.actor }} + password: ${{ secrets.PACKAGE_TOKEN }} + + - name: Build and push backend + uses: docker/build-push-action@v5 + with: + context: ./backend + file: ./backend/Dockerfile + push: true + tags: | + ${{ env.REGISTRY }}/${{ env.OWNER }}/milevault-backend:latest + ${{ env.REGISTRY }}/${{ env.OWNER }}/milevault-backend:${{ gitea.sha }} + + build-worker: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Log in to Gitea registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ gitea.actor }} + password: ${{ secrets.PACKAGE_TOKEN }} + + - name: Build and push worker + uses: docker/build-push-action@v5 + with: + context: ./backend + file: ./backend/Dockerfile.worker + push: true + tags: | + ${{ env.REGISTRY }}/${{ env.OWNER }}/milevault-worker:latest + ${{ env.REGISTRY }}/${{ env.OWNER }}/milevault-worker:${{ gitea.sha }} + + build-frontend: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Log in to Gitea registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ gitea.actor }} + password: ${{ secrets.PACKAGE_TOKEN }} + + - name: Build and push frontend + uses: docker/build-push-action@v5 + with: + context: ./frontend + file: ./frontend/Dockerfile + push: true + tags: | + ${{ env.REGISTRY }}/${{ env.OWNER }}/milevault-frontend:latest + ${{ env.REGISTRY }}/${{ env.OWNER }}/milevault-frontend:${{ gitea.sha }} + build-args: | + VITE_API_URL=/api + VITE_MAPBOX_TOKEN= diff --git a/README.md b/README.md index 36f55fb..571a011 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# FitTracker +# MileVault Self-hosted fitness tracking — Garmin & Strava import, maps, health trends, personal records. @@ -6,14 +6,14 @@ Self-hosted fitness tracking — Garmin & Strava import, maps, health trends, pe ## For users — deploy with two files -Once this repo is pushed to Gitea and the Actions workflow has run once, anyone on your network only needs **two files** to run FitTracker. No source code, no cloning. +Once this repo is pushed to Gitea and the Actions workflow has run once, anyone on your network only needs **two files** to run MileVault. No source code, no cloning. ```bash -mkdir fittracker && cd fittracker +mkdir milevault && cd milevault # Download the two deployment files -curl -O https://gitea.yourdomain.com/yourusername/fittracker/raw/branch/main/docker-compose.deploy.yml -curl -O https://gitea.yourdomain.com/yourusername/fittracker/raw/branch/main/nginx.conf +curl -O https://gitea.yourdomain.com/yourusername/milevault/raw/branch/main/docker-compose.deploy.yml +curl -O https://gitea.yourdomain.com/yourusername/milevault/raw/branch/main/nginx.conf # Start (images pulled automatically from your Gitea registry) docker compose -f docker-compose.deploy.yml up -d @@ -82,7 +82,7 @@ In your repo: **Settings → Variables → Actions → Add Variable** ### 5. Push the repo ```bash -git remote add origin https://gitea.yourdomain.com/yourusername/fittracker.git +git remote add origin https://gitea.yourdomain.com/yourusername/milevault.git git push -u origin main ``` diff --git a/backend/app/main.py b/backend/app/main.py index 511f1d7..a1aa293 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -45,7 +45,7 @@ async def lifespan(app: FastAPI): app = FastAPI( - title="FitTracker", + title="MileVault", version="1.0.0", lifespan=lifespan, ) diff --git a/backend/app/workers/tasks.py b/backend/app/workers/tasks.py index b34b9b9..f8f463a 100644 --- a/backend/app/workers/tasks.py +++ b/backend/app/workers/tasks.py @@ -6,7 +6,7 @@ from celery import Celery from app.core.config import settings celery_app = Celery( - "fittracker", + "milevault", broker=settings.redis_url, backend=settings.redis_url, ) diff --git a/docker-compose.deploy.yml b/docker-compose.deploy.yml index 71734ae..3ee1378 100644 --- a/docker-compose.deploy.yml +++ b/docker-compose.deploy.yml @@ -1,6 +1,6 @@ version: "3.9" -# FitTracker — standalone deployment +# MileVault — standalone deployment # # 1. Copy this file somewhere on your server (no other files needed) # 2. Run: docker compose up -d @@ -16,16 +16,16 @@ x-registry: ®istry gitea.yourdomain.com/yourusername services: db: image: timescale/timescaledb:latest-pg16 - container_name: fittracker_db + container_name: milevault_db restart: unless-stopped environment: - POSTGRES_DB: fittracker - POSTGRES_USER: ${DB_USER:-fittracker} - POSTGRES_PASSWORD: ${DB_PASSWORD:-fittracker} + POSTGRES_DB: milevault + POSTGRES_USER: ${DB_USER:-milevault} + POSTGRES_PASSWORD: ${DB_PASSWORD:-milevault} volumes: - db_data:/var/lib/postgresql/data healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-fittracker} -d fittracker"] + test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-milevault} -d milevault"] interval: 10s timeout: 5s retries: 10 @@ -33,25 +33,25 @@ services: redis: image: redis:7-alpine - container_name: fittracker_redis + container_name: milevault_redis restart: unless-stopped - command: redis-server --requirepass ${REDIS_PASSWORD:-fittracker} + command: redis-server --requirepass ${REDIS_PASSWORD:-milevault} volumes: - redis_data:/data healthcheck: - test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-fittracker}", "ping"] + test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-milevault}", "ping"] interval: 10s timeout: 5s retries: 5 start_period: 10s backend: - image: gitea.yourdomain.com/yourusername/fittracker-backend:latest - container_name: fittracker_backend + image: gitea.yourdomain.com/yourusername/milevault-backend:latest + container_name: milevault_backend restart: unless-stopped environment: - DATABASE_URL: postgresql+asyncpg://${DB_USER:-fittracker}:${DB_PASSWORD:-fittracker}@db:5432/fittracker - REDIS_URL: redis://:${REDIS_PASSWORD:-fittracker}@redis:6379/0 + DATABASE_URL: postgresql+asyncpg://${DB_USER:-milevault}:${DB_PASSWORD:-milevault}@db:5432/milevault + REDIS_URL: redis://:${REDIS_PASSWORD:-milevault}@redis:6379/0 SECRET_KEY: ${SECRET_KEY:-changeme_run_openssl_rand_hex_32} ADMIN_USERNAME: ${ADMIN_USERNAME:-admin} ADMIN_PASSWORD: ${ADMIN_PASSWORD:-admin} @@ -75,12 +75,12 @@ services: start_period: 30s worker: - image: gitea.yourdomain.com/yourusername/fittracker-worker:latest - container_name: fittracker_worker + image: gitea.yourdomain.com/yourusername/milevault-worker:latest + container_name: milevault_worker restart: unless-stopped environment: - DATABASE_URL: postgresql+asyncpg://${DB_USER:-fittracker}:${DB_PASSWORD:-fittracker}@db:5432/fittracker - REDIS_URL: redis://:${REDIS_PASSWORD:-fittracker}@redis:6379/0 + DATABASE_URL: postgresql+asyncpg://${DB_USER:-milevault}:${DB_PASSWORD:-milevault}@db:5432/milevault + REDIS_URL: redis://:${REDIS_PASSWORD:-milevault}@redis:6379/0 SECRET_KEY: ${SECRET_KEY:-changeme_run_openssl_rand_hex_32} FILE_STORE_PATH: /data/files volumes: @@ -92,13 +92,13 @@ services: condition: service_healthy frontend: - image: gitea.yourdomain.com/yourusername/fittracker-frontend:latest - container_name: fittracker_frontend + image: gitea.yourdomain.com/yourusername/milevault-frontend:latest + container_name: milevault_frontend restart: unless-stopped nginx: image: nginx:alpine - container_name: fittracker_nginx + container_name: milevault_nginx restart: unless-stopped ports: - "${HTTP_PORT:-80}:80" diff --git a/docker-compose.yml b/docker-compose.yml index 801c17d..96cfa88 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,17 +3,17 @@ version: "3.9" services: db: image: timescale/timescaledb:latest-pg16 - container_name: fittracker_db + container_name: milevault_db restart: unless-stopped environment: - POSTGRES_DB: fittracker - POSTGRES_USER: ${DB_USER:-fittracker} - POSTGRES_PASSWORD: ${DB_PASSWORD:-fittracker} + POSTGRES_DB: milevault + POSTGRES_USER: ${DB_USER:-milevault} + POSTGRES_PASSWORD: ${DB_PASSWORD:-milevault} volumes: - db_data:/var/lib/postgresql/data - ./docker/init.sql:/docker-entrypoint-initdb.d/init.sql:ro healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-fittracker} -d fittracker"] + test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-milevault} -d milevault"] interval: 10s timeout: 5s retries: 10 @@ -21,13 +21,13 @@ services: redis: image: redis:7-alpine - container_name: fittracker_redis + container_name: milevault_redis restart: unless-stopped - command: redis-server --requirepass ${REDIS_PASSWORD:-fittracker} + command: redis-server --requirepass ${REDIS_PASSWORD:-milevault} volumes: - redis_data:/data healthcheck: - test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-fittracker}", "ping"] + test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-milevault}", "ping"] interval: 10s timeout: 5s retries: 5 @@ -37,11 +37,11 @@ services: build: context: ./backend dockerfile: Dockerfile - container_name: fittracker_backend + container_name: milevault_backend restart: unless-stopped environment: - DATABASE_URL: postgresql+asyncpg://${DB_USER:-fittracker}:${DB_PASSWORD:-fittracker}@db:5432/fittracker - REDIS_URL: redis://:${REDIS_PASSWORD:-fittracker}@redis:6379/0 + DATABASE_URL: postgresql+asyncpg://${DB_USER:-milevault}:${DB_PASSWORD:-milevault}@db:5432/milevault + REDIS_URL: redis://:${REDIS_PASSWORD:-milevault}@redis:6379/0 SECRET_KEY: ${SECRET_KEY:-changeme_please_set_in_env_file_32chars} ADMIN_USERNAME: ${ADMIN_USERNAME:-admin} ADMIN_PASSWORD: ${ADMIN_PASSWORD:-admin} @@ -68,11 +68,11 @@ services: build: context: ./backend dockerfile: Dockerfile.worker - container_name: fittracker_worker + container_name: milevault_worker restart: unless-stopped environment: - DATABASE_URL: postgresql+asyncpg://${DB_USER:-fittracker}:${DB_PASSWORD:-fittracker}@db:5432/fittracker - REDIS_URL: redis://:${REDIS_PASSWORD:-fittracker}@redis:6379/0 + DATABASE_URL: postgresql+asyncpg://${DB_USER:-milevault}:${DB_PASSWORD:-milevault}@db:5432/milevault + REDIS_URL: redis://:${REDIS_PASSWORD:-milevault}@redis:6379/0 SECRET_KEY: ${SECRET_KEY:-changeme_please_set_in_env_file_32chars} FILE_STORE_PATH: /data/files volumes: @@ -90,12 +90,12 @@ services: args: VITE_API_URL: ${VITE_API_URL:-/api} VITE_MAPBOX_TOKEN: ${VITE_MAPBOX_TOKEN:-} - container_name: fittracker_frontend + container_name: milevault_frontend restart: unless-stopped nginx: image: nginx:alpine - container_name: fittracker_nginx + container_name: milevault_nginx restart: unless-stopped ports: - "${HTTP_PORT:-80}:80" diff --git a/frontend/index.html b/frontend/index.html index e1b2ecf..1a47e01 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -3,7 +3,7 @@ - FitTracker + MileVault diff --git a/frontend/package.json b/frontend/package.json index dc5098d..60487d3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,5 +1,5 @@ { - "name": "fittracker-frontend", + "name": "milevault-frontend", "version": "1.0.0", "private": true, "type": "module", diff --git a/frontend/src/components/ui/Layout.jsx b/frontend/src/components/ui/Layout.jsx index 853dec7..71b9603 100644 --- a/frontend/src/components/ui/Layout.jsx +++ b/frontend/src/components/ui/Layout.jsx @@ -26,7 +26,7 @@ export default function Layout() { {/* Logo */}

- FitTracker + MileVault

{user && (

@{user.username}

diff --git a/frontend/src/pages/LoginPage.jsx b/frontend/src/pages/LoginPage.jsx index da70919..b566e7c 100644 --- a/frontend/src/pages/LoginPage.jsx +++ b/frontend/src/pages/LoginPage.jsx @@ -37,7 +37,7 @@ export default function LoginPage() {

- FitTracker + MileVault

Your personal fitness dashboard

diff --git a/install.sh b/install.sh index 0b06ceb..335bf68 100755 --- a/install.sh +++ b/install.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# FitTracker installer -# Usage: curl -fsSL https://raw.githubusercontent.com/you/fittracker/main/install.sh | bash +# MileVault installer +# Usage: curl -fsSL https://raw.githubusercontent.com/you/milevault/main/install.sh | bash # Or: bash install.sh set -euo pipefail @@ -48,7 +48,7 @@ info "Docker daemon is running" step "Setting up install directory" -INSTALL_DIR="${FITTRACKER_DIR:-$HOME/fittracker}" +INSTALL_DIR="${FITTRACKER_DIR:-$HOME/milevault}" if [ -d "$INSTALL_DIR" ] && [ "$(ls -A "$INSTALL_DIR" 2>/dev/null)" ]; then warn "Directory $INSTALL_DIR already exists." @@ -62,7 +62,7 @@ info "Install directory: $INSTALL_DIR" # ── Download project files ──────────────────────────────────────────────────── -step "Downloading FitTracker" +step "Downloading MileVault" # If we're already inside the repo (files exist), skip download if [ -f "docker-compose.yml" ]; then @@ -70,7 +70,7 @@ if [ -f "docker-compose.yml" ]; then else # Try git first, fall back to curl if command -v git >/dev/null 2>&1; then - git clone --depth 1 https://github.com/yourusername/fittracker.git . 2>/dev/null || { + git clone --depth 1 https://github.com/yourusername/milevault.git . 2>/dev/null || { warn "Git clone failed — copying bundled files instead" } fi @@ -111,7 +111,7 @@ else PORT="${FITTRACKER_PORT:-80}" cat > .env << ENV -# FitTracker configuration — generated $(date) +# MileVault configuration — generated $(date) # Edit this file to change settings, then run: docker compose up -d # Admin login @@ -121,7 +121,7 @@ ADMIN_PASSWORD=${ADMIN_PASSWORD} # Secrets (auto-generated — do not share) SECRET_KEY=${SECRET_KEY} DB_PASSWORD=${DB_PASSWORD} -DB_USER=fittracker +DB_USER=milevault REDIS_PASSWORD=${REDIS_PASSWORD} # Server @@ -133,7 +133,7 @@ VITE_MAPBOX_TOKEN= # Optional: PocketID passkey authentication # POCKETID_ISSUER=https://your-pocketid.example.com -# POCKETID_CLIENT_ID=fittracker +# POCKETID_CLIENT_ID=milevault # POCKETID_CLIENT_SECRET= ENV @@ -160,7 +160,7 @@ step "Waiting for services to be ready" TIMEOUT=120 ELAPSED=0 printf " Waiting" -while ! docker inspect fittracker_backend 2>/dev/null | grep -q '"healthy"' ; do +while ! docker inspect milevault_backend 2>/dev/null | grep -q '"healthy"' ; do if [ $ELAPSED -ge $TIMEOUT ]; then echo "" warn "Backend taking longer than expected. Check logs: docker compose logs backend" @@ -181,7 +181,7 @@ URL="http://localhost${PORT:+:${PORT}}" echo "" echo -e "${GREEN}${BOLD}╔══════════════════════════════════════════╗${NC}" -echo -e "${GREEN}${BOLD}║ FitTracker is ready! ║${NC}" +echo -e "${GREEN}${BOLD}║ MileVault is ready! ║${NC}" echo -e "${GREEN}${BOLD}╚══════════════════════════════════════════╝${NC}" echo "" echo -e " 🌐 Open: ${CYAN}${URL}${NC}" diff --git a/scripts/manage.sh b/scripts/manage.sh index 9f1f444..46b4c52 100755 --- a/scripts/manage.sh +++ b/scripts/manage.sh @@ -6,9 +6,9 @@ cd "$SCRIPT_DIR/.." RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' -info() { echo -e "${GREEN}[fittracker]${NC} $*"; } -warn() { echo -e "${YELLOW}[fittracker]${NC} $*"; } -error() { echo -e "${RED}[fittracker]${NC} $*"; exit 1; } +info() { echo -e "${GREEN}[milevault]${NC} $*"; } +warn() { echo -e "${YELLOW}[milevault]${NC} $*"; } +error() { echo -e "${RED}[milevault]${NC} $*"; exit 1; } check_env() { if [ ! -f .env ]; then @@ -49,13 +49,13 @@ generate_secrets() { cmd_start() { check_env - info "Starting FitTracker..." + info "Starting MileVault..." docker compose up -d --build info "Started! Visit http://localhost:${HTTP_PORT:-80}" } cmd_stop() { - info "Stopping FitTracker..." + info "Stopping MileVault..." docker compose down } @@ -71,10 +71,10 @@ cmd_setup() { cmd_backup() { source .env - BACKUP_FILE="fittracker_backup_$(date +%Y%m%d_%H%M%S).sql" + BACKUP_FILE="milevault_backup_$(date +%Y%m%d_%H%M%S).sql" info "Backing up database to $BACKUP_FILE..." docker compose exec -T db pg_dump \ - -U "${DB_USER:-fittracker}" fittracker > "$BACKUP_FILE" + -U "${DB_USER:-milevault}" milevault > "$BACKUP_FILE" info "Backup saved: $BACKUP_FILE" } @@ -83,7 +83,7 @@ cmd_restore() { source .env info "Restoring from $1..." docker compose exec -T db psql \ - -U "${DB_USER:-fittracker}" fittracker < "$1" + -U "${DB_USER:-milevault}" milevault < "$1" info "Restore complete" } @@ -105,7 +105,7 @@ case "${1:-help}" in restore) cmd_restore "${2:-}" ;; update) cmd_update ;; *) - echo "FitTracker management script" + echo "MileVault management script" echo "" echo "Usage: $0 " echo ""