Files
fitness/CONFIGURATION.md
T
2026-10-04 00:19:45 +03:00

11 KiB

/**

  • Environment Configuration
  • Development | Staging | Production */

// ============================================================================ // BACKEND CONFIGURATION (PHP) // ============================================================================

// File: backend/config.php

<?php define('ENVIRONMENT', getenv('APP_ENV') ?: 'development'); // Database Configuration if (ENVIRONMENT === 'production') { define('DB_HOST', getenv('DB_HOST') ?: 'prod-db.example.com'); define('DB_USER', getenv('DB_USER') ?: 'fitness_app'); define('DB_PASS', getenv('DB_PASS')); define('DB_NAME', 'fitness_app'); define('DB_PORT', getenv('DB_PORT') ?: 3306); define('DB_CHARSET', 'utf8mb4'); // Security Headers define('FORCE_HTTPS', true); define('SECURE_COOKIES', true); define('HSTS_MAX_AGE', 31536000); // 1 year } elseif (ENVIRONMENT === 'staging') { define('DB_HOST', 'staging-db.example.com'); define('DB_USER', 'fitness_staging'); define('DB_PASS', getenv('DB_PASS')); define('DB_NAME', 'fitness_staging'); define('DB_PORT', 3306); define('FORCE_HTTPS', true); } else { // Development define('DB_HOST', 'localhost'); define('DB_USER', 'root'); define('DB_PASS', 'password'); define('DB_NAME', 'fitness_app_dev'); define('DB_PORT', 3306); define('FORCE_HTTPS', false); } // API Configuration define('API_VERSION', 'v1'); define('API_BASE_PATH', '/api/' . API_VERSION); define('REQUEST_TIMEOUT', 30); // seconds define('MAX_PAYLOAD_SIZE', 10485760); // 10MB // Rate Limiting define('RATE_LIMIT_ENABLED', true); define('RATE_LIMIT_REQUESTS', 100); // per minute define('RATE_LIMIT_WINDOW', 60); // seconds // Logging define('LOG_LEVEL', ENVIRONMENT === 'production' ? 'error' : 'debug'); define('LOG_FILE', '/var/log/fitness_api.log'); define('LOG_DATABASE', true); // Log to DB as well // CORS Configuration define('ALLOWED_ORIGINS', [ 'https://fitness-app.com', 'https://app.fitness-app.com', ENVIRONMENT === 'development' ? 'http://localhost:3000' : null ]); // Email Configuration (for notifications) define('MAIL_HOST', getenv('MAIL_HOST') ?: 'smtp.gmail.com'); define('MAIL_PORT', getenv('MAIL_PORT') ?: 587); define('MAIL_USER', getenv('MAIL_USER')); define('MAIL_PASS', getenv('MAIL_PASS')); define('MAIL_FROM', 'noreply@fitness-app.com'); // Cache Configuration define('CACHE_ENABLED', ENVIRONMENT !== 'development'); define('CACHE_DRIVER', 'redis'); // 'redis' or 'file' define('CACHE_TTL', 3600); // seconds // Security define('HMAC_ALGORITHM', 'sha256'); define('TIMESTAMP_TOLERANCE', 300); // 5 minutes define('BCRYPT_COST', 12); // API Keys (for external services) define('MAPBOX_API_KEY', getenv('MAPBOX_API_KEY')); define('WEATHER_API_KEY', getenv('WEATHER_API_KEY')); // Enable debug mode (NEVER true in production) define('DEBUG_MODE', ENVIRONMENT === 'development'); // Timezone date_default_timezone_set('UTC'); ?>

// ============================================================================ // MOBILE CONFIGURATION (Dart/Flutter) // ============================================================================

// File: mobile/lib/config/environment.dart

const String kEnvironment = String.fromEnvironment('ENVIRONMENT', defaultValue: 'development');

class EnvironmentConfig { static const String apiHost = String.fromEnvironment( 'API_HOST', defaultValue: 'https://api.fitness-app.local', );

static const String mapTileServer = 'https://map-saas.intaleqapp.com/styles/basic-preview/style.json';

static const int locationUpdateInterval = 5; // seconds static const int mapRefreshInterval = 2; // seconds

// API Configuration static const Duration requestTimeout = Duration(seconds: 30); static const int maxRetries = 3;

// Location Configuration static const double minAccuracy = 10.0; // meters static const double minDistance = 10.0; // meters between coordinates static const int foregroundServicePriority = 1; // HIGH

// Database Configuration static const String databaseName = 'fitness_app.db'; static const int databaseVersion = 1;

// Feature Flags static const bool enableBackgroundTracking = true; static const bool enableOfflineSync = true; static const bool enableAnalytics = !kDebugMode;

// Get API endpoint based on environment static String get apiEndpoint { return '$apiHost/api/v1'; }

// Get workout submission endpoint static String get workoutSubmissionEndpoint { return '$apiEndpoint/workouts'; } }

class DevEnvironment { static const String apiHost = 'http://localhost:8080'; static const bool debugLogging = true; }

class StagingEnvironment { static const String apiHost = 'https://staging-api.fitness-app.com'; static const bool debugLogging = true; }

class ProductionEnvironment { static const String apiHost = 'https://api.fitness-app.com'; static const bool debugLogging = false; }

// ============================================================================ // DOCKER COMPOSE CONFIGURATION // ============================================================================

File: docker-compose.yml

version: '3.8'

services: mysql: image: mysql:8.0 container_name: fitness_app_mysql environment: MYSQL_ROOT_PASSWORD: root_password MYSQL_DATABASE: fitness_app MYSQL_USER: fitness_app MYSQL_PASSWORD: ${DB_PASSWORD} ports: - "3306:3306" volumes: - mysql_data:/var/lib/mysql - ./backend/schema.sql:/docker-entrypoint-initdb.d/schema.sql networks: - fitness_network healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] timeout: 20s retries: 10

php_api: image: php:8.2-fpm container_name: fitness_app_php environment: APP_ENV: ${APP_ENV:-development} DB_HOST: mysql DB_USER: fitness_app DB_PASS: ${DB_PASSWORD} DB_NAME: fitness_app volumes: - ./backend:/app depends_on: mysql: condition: service_healthy networks: - fitness_network

nginx: image: nginx:alpine container_name: fitness_app_nginx ports: - "80:80" - "443:443" volumes: - ./backend:/app - ./nginx.conf:/etc/nginx/nginx.conf - ./ssl:/etc/nginx/ssl depends_on: - php_api networks: - fitness_network

redis: image: redis:7-alpine container_name: fitness_app_redis ports: - "6379:6379" networks: - fitness_network healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5

volumes: mysql_data:

networks: fitness_network: driver: bridge

============================================================================

// ENVIRONMENT VARIABLES (.env file) // ============================================================================

File: .env.example (copy to .env for development)

Application

APP_ENV=development APP_DEBUG=true TIMEZONE=UTC

Database

DB_HOST=localhost DB_PORT=3306 DB_USER=fitness_app DB_PASS=your_secure_password_here DB_NAME=fitness_app

API Configuration

API_HOST=http://localhost:8080 API_VERSION=v1 API_RATE_LIMIT=100

Map Tile Server

TILE_SERVER_URL=https://map-saas.intaleqapp.com/styles/basic-preview/style.json

Email (for notifications)

MAIL_HOST=smtp.gmail.com MAIL_PORT=587 MAIL_USER=your_email@gmail.com MAIL_PASS=your_app_password

External Services

MAPBOX_API_KEY= WEATHER_API_KEY=

Security

HMAC_ALGORITHM=sha256 BCRYPT_COST=12

Logging

LOG_LEVEL=debug LOG_FILE=/var/log/fitness_api.log

Cache

CACHE_DRIVER=redis CACHE_TTL=3600

============================================================================

// NGINX CONFIGURATION // ============================================================================

File: nginx.conf

user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid;

events { worker_connections 1024; }

http { include /etc/nginx/mime.types; default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" '
                '"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;

# Gzip compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript
           application/json application/javascript application/xml+rss;

# Rate limiting
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_zone $http_x_api_key zone=api:10m rate=100r/m;

upstream php_backend {
    server php_api:9000;
}

# Redirect HTTP to HTTPS
server {
    listen 80;
    server_name _;
    return 301 https://$host$request_uri;
}

# HTTPS Server
server {
    listen 443 ssl http2;
    server_name api.fitness-app.com;

    ssl_certificate /etc/nginx/ssl/cert.crt;
    ssl_certificate_key /etc/nginx/ssl/key.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # Security headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;

    root /app;

    # Rate limiting
    limit_req zone=api burst=20 nodelay;

    location / {
        try_files $uri $uri/ @rewrite;
    }

    location @rewrite {
        rewrite ^/(.*)$ /api_workouts.php?url=$1 last;
    }

    location ~ \.php$ {
        fastcgi_pass php_backend;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;

        fastcgi_connect_timeout 60s;
        fastcgi_send_timeout 60s;
        fastcgi_read_timeout 60s;
    }

    # Deny access to sensitive files
    location ~ /\. {
        deny all;
    }

    location ~ ~$ {
        deny all;
    }
}

}

// ============================================================================ // BUILD CONFIGURATION (Android) // ============================================================================

File: android/app/build.gradle

android { compileSdkVersion 34 ndkVersion "25.1.8937393"

defaultConfig {
    applicationId "com.fitness.tracker"
    minSdkVersion 21
    targetSdkVersion 34
    versionCode flutterVersionCode.toInteger()
    versionName flutterVersionName
}

buildTypes {
    debug {
        debuggable true
        signingConfig signingConfigs.debug
        buildConfigField "String", "API_HOST", '"http://192.168.1.100:8080"'
    }

    staging {
        debuggable false
        signingConfig signingConfigs.release
        buildConfigField "String", "API_HOST", '"https://staging-api.fitness-app.com"'
    }

    release {
        signingConfig signingConfigs.release
        buildConfigField "String", "API_HOST", '"https://api.fitness-app.com"'
    }
}

}

// ============================================================================ // GIT IGNORE (.gitignore) // ============================================================================

File: .gitignore

Environment

.env .env.local .env.*.local

API Credentials

api_key.txt api_secret.txt

Database

_.db _.sqlite *.sqlite3

Logs

*.log logs/

IDE

.vscode/ .idea/ _.swp _.swo

Flutter

.dart_tool/ .flutter-plugins .packages build/

Backend

vendor/ node_modules/

OS

.DS_Store Thumbs.db

Secrets

secrets.json credentials.json