Spaces:
Sleeping
Sleeping
| set -e | |
| # Environment variables | |
| export UVICORN_PORT=8000 | |
| export NEXT_PORT=3000 | |
| export HF_SPACES_PORT=7860 | |
| export POSTGRES_USER=postgres | |
| export POSTGRES_PASSWORD=postgres | |
| export POSTGRES_DB=surfsense | |
| export REDIS_PORT=6379 | |
| echo "π Starting SurfSense all-in-one container..." | |
| # Function to wait for a service to be ready | |
| wait_for_service() { | |
| local host=$1 | |
| local port=$2 | |
| local service=$3 | |
| echo "β³ Waiting for $service to be ready on $host:$port..." | |
| while ! nc -z -w 1 $host $port 2>/dev/null; do | |
| sleep 1 | |
| done | |
| echo "β $service is ready!" | |
| } | |
| # Check if using external database | |
| if [ -n "$EXTERNAL_DATABASE_URL" ]; then | |
| echo "π Using external database, skipping local PostgreSQL setup..." | |
| else | |
| # Initialize PostgreSQL data directory if it doesn't exist | |
| if [ ! -d "/var/lib/postgresql/14/main" ]; then | |
| echo "πΎ Initializing PostgreSQL database..." | |
| mkdir -p /var/lib/postgresql/14/main | |
| chown -R postgres:postgres /var/lib/postgresql/14/main | |
| chmod 0700 /var/lib/postgresql/14/main | |
| # Initialize database cluster | |
| sudo -u postgres /usr/lib/postgresql/14/bin/initdb -D /var/lib/postgresql/14/main | |
| # Configure PostgreSQL to accept connections | |
| echo "listen_addresses = '*'" >> /var/lib/postgresql/14/main/postgresql.conf | |
| echo "host all all 0.0.0.0/0 trust" >> /var/lib/postgresql/14/main/pg_hba.conf | |
| fi | |
| # Start PostgreSQL in background | |
| echo "π Starting PostgreSQL server..." | |
| sudo -u postgres /usr/lib/postgresql/14/bin/postgres -D /var/lib/postgresql/14/main & | |
| POSTGRES_PID=$! | |
| export POSTGRES_PID | |
| # Wait for PostgreSQL to be ready | |
| wait_for_service localhost 5432 "PostgreSQL" | |
| # Create database and enable pgvector extension if needed | |
| echo "π§ Setting up database..." | |
| sudo -u postgres psql -c "SELECT 1 FROM pg_database WHERE datname = '$POSTGRES_DB'" | grep -q 1 || \ | |
| sudo -u postgres psql -c "CREATE DATABASE $POSTGRES_DB" | |
| sudo -u postgres psql -d $POSTGRES_DB -c "CREATE EXTENSION IF NOT EXISTS vector;" | |
| fi | |
| # Start Redis in background | |
| echo "π Starting Redis server..." | |
| redis-server --port $REDIS_PORT --bind 0.0.0.0 --protected-mode no --dir /var/lib/redis & | |
| REDIS_PID=$! | |
| export REDIS_PID | |
| # Wait for Redis to be ready | |
| wait_for_service localhost $REDIS_PORT "Redis" | |
| # Set up backend environment variables | |
| echo "βοΈ Configuring backend environment..." | |
| cd /app/surfsense_backend | |
| # Determine DATABASE_URL | |
| if [ -n "$EXTERNAL_DATABASE_URL" ]; then | |
| echo "π Using external database URL..." | |
| DATABASE_URL="$EXTERNAL_DATABASE_URL" | |
| else | |
| echo "π Using local PostgreSQL URL..." | |
| DATABASE_URL="postgresql+asyncpg://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}" | |
| fi | |
| # Create .env file with all required variables | |
| cat > .env << EOF | |
| DATABASE_URL=${DATABASE_URL} | |
| SECRET_KEY=$(openssl rand -hex 32) | |
| NEXT_FRONTEND_URL=https://charan5775-scense.hf.space | |
| AUTH_TYPE=LOCAL | |
| EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2 | |
| RERANKERS_MODEL_NAME=ms-marco-MiniLM-L-12-v2 | |
| RERANKERS_MODEL_TYPE=flashrank | |
| TTS_SERVICE=local/kokoro | |
| STT_SERVICE=local/base | |
| ETL_SERVICE=DOCLING | |
| CELERY_BROKER_URL=redis://localhost:${REDIS_PORT}/0 | |
| CELERY_RESULT_BACKEND=redis://localhost:${REDIS_PORT}/0 | |
| REGISTRATION_ENABLED=TRUE | |
| UVICORN_HOST=0.0.0.0 | |
| UVICORN_PORT=${UVICORN_PORT} | |
| EOF | |
| # Set up frontend environment variables | |
| echo "βοΈ Configuring frontend environment..." | |
| cd /app/surfsense_web | |
| cat > .env << EOF | |
| NEXT_PUBLIC_FASTAPI_BACKEND_URL=https://charan5775-scense.hf.space/pi | |
| NEXT_PUBLIC_FASTAPI_BACKEND_AUTH_TYPE=LOCAL | |
| NEXT_PUBLIC_ETL_SERVICE=DOCLING | |
| EOF | |
| # Start backend in background | |
| echo "π Starting backend server..." | |
| cd /app/surfsense_backend | |
| . .venv/bin/activate | |
| #uvicorn main:app --host 0.0.0.0 --port $UVICORN_PORT & | |
| uv run main.py & | |
| BACKEND_PID=$! | |
| export BACKEND_PID | |
| # Wait for backend to be ready | |
| wait_for_service localhost $UVICORN_PORT "Backend API" | |
| # Start Celery worker in background | |
| echo "π Starting Celery worker..." | |
| celery -A celery_worker.celery_app worker --loglevel=info --concurrency=1 --pool=solo & | |
| CELERY_WORKER_PID=$! | |
| export CELERY_WORKER_PID | |
| # Start Celery beat in background | |
| echo "π Starting Celery beat..." | |
| celery -A celery_worker.celery_app beat --loglevel=info & | |
| CELERY_BEAT_PID=$! | |
| export CELERY_BEAT_PID | |
| # Start frontend in background | |
| echo "π Starting frontend server..." | |
| cd /app/surfsense_web | |
| pnpm run build && pnpm run start & | |
| #pnpm run dev & | |
| FRONTEND_PID=$! | |
| export FRONTEND_PID | |
| # Wait for frontend to be ready | |
| wait_for_service localhost $NEXT_PORT "Frontend" | |
| # Configure Nginx dynamically | |
| echo "βοΈ Configuring Nginx reverse proxy..." | |
| cat > /etc/nginx/sites-available/surfsense << EOF | |
| server { | |
| listen ${HF_SPACES_PORT}; | |
| server_name localhost; | |
| # Backend API routes | |
| location /pi/ { | |
| proxy_pass http://localhost:${UVICORN_PORT}/; | |
| proxy_set_header Host \$host; | |
| proxy_set_header X-Real-IP \$remote_addr; | |
| proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; | |
| proxy_set_header X-Forwarded-Proto \$scheme; | |
| proxy_http_version 1.1; | |
| proxy_set_header Upgrade \$http_upgrade; | |
| proxy_set_header Connection "upgrade"; | |
| proxy_read_timeout 86400s; | |
| proxy_send_timeout 86400s; | |
| } | |
| # Frontend routes | |
| location / { | |
| proxy_pass http://localhost:${NEXT_PORT}/; | |
| proxy_set_header Host \$host; | |
| proxy_set_header X-Real-IP \$remote_addr; | |
| proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; | |
| proxy_set_header X-Forwarded-Proto \$scheme; | |
| proxy_http_version 1.1; | |
| proxy_set_header Upgrade \$http_upgrade; | |
| proxy_set_header Connection "upgrade"; | |
| proxy_read_timeout 86400s; | |
| proxy_send_timeout 86400s; | |
| } | |
| # Health check endpoint for Hugging Face | |
| location /health { | |
| return 200 'OK'; | |
| add_header Content-Type text/plain; | |
| } | |
| } | |
| EOF | |
| # Enable the Nginx configuration | |
| rm -f /etc/nginx/sites-enabled/default | |
| ln -sf /etc/nginx/sites-available/surfsense /etc/nginx/sites-enabled/ | |
| # Test Nginx configuration | |
| echo "π Testing Nginx configuration..." | |
| nginx -t | |
| # Start Nginx in foreground (this will keep the container running) | |
| echo "π Starting Nginx reverse proxy on port ${HF_SPACES_PORT}..." | |
| echo "π SurfSense is ready! Access it at http://localhost:${HF_SPACES_PORT}" | |
| # Set up cleanup function for graceful shutdown | |
| cleanup() { | |
| echo "π Shutting down services..." | |
| # Stop services in reverse order of startup | |
| if [ ! -z "$NGINX_PID" ]; then | |
| echo "Stopping Nginx..." | |
| kill -TERM $NGINX_PID 2>/dev/null || true | |
| fi | |
| if [ ! -z "$FRONTEND_PID" ]; then | |
| echo "Stopping frontend..." | |
| kill -TERM $FRONTEND_PID 2>/dev/null || true | |
| fi | |
| if [ ! -z "$CELERY_BEAT_PID" ]; then | |
| echo "Stopping Celery beat..." | |
| kill -TERM $CELERY_BEAT_PID 2>/dev/null || true | |
| fi | |
| if [ ! -z "$CELERY_WORKER_PID" ]; then | |
| echo "Stopping Celery worker..." | |
| kill -TERM $CELERY_WORKER_PID 2>/dev/null || true | |
| fi | |
| if [ ! -z "$BACKEND_PID" ]; then | |
| echo "Stopping backend..." | |
| kill -TERM $BACKEND_PID 2>/dev/null || true | |
| fi | |
| if [ ! -z "$REDIS_PID" ]; then | |
| echo "Stopping Redis..." | |
| kill -TERM $REDIS_PID 2>/dev/null || true | |
| fi | |
| if [ ! -z "$POSTGRES_PID" ]; then | |
| echo "Stopping PostgreSQL..." | |
| sudo -u postgres /usr/lib/postgresql/14/bin/pg_ctl -D /var/lib/postgresql/14/main stop -m fast | |
| fi | |
| echo "β All services stopped" | |
| exit 0 | |
| } | |
| # Trap termination signals | |
| trap cleanup TERM INT | |
| # Start Nginx in the foreground (this keeps the container running) | |
| nginx -g "daemon off;" | |
| # This line should never be reached, but just in case | |
| wait |