Spaces:
Running
Running
| set -euo pipefail | |
| PORT="${PORT:-7860}" | |
| MINIO_INTERNAL_PORT="${MINIO_INTERNAL_PORT:-9000}" | |
| MINIO_DATA_DIR="${MINIO_DATA_DIR:-/data/minio}" | |
| MINIO_BUCKET="${MINIO_BUCKET:-mvp-storage}" | |
| MINIO_REGION="${MINIO_REGION:-cn-south-1}" | |
| PUBLIC_BUCKET="${PUBLIC_BUCKET:-0}" | |
| MINIO_BROWSER="${MINIO_BROWSER:-off}" | |
| SPACE_URL="${SPACE_URL:-https://<your-space>.hf.space}" | |
| ADMIN_AUTH_ENABLED="${ADMIN_AUTH_ENABLED:-1}" | |
| if [[ -z "${MINIO_ROOT_USER:-}" || -z "${MINIO_ROOT_PASSWORD:-}" ]]; then | |
| echo "[COS_HF] ERROR: MINIO_ROOT_USER and MINIO_ROOT_PASSWORD are required." >&2 | |
| exit 1 | |
| fi | |
| # Web admin basic auth defaults to the same credentials as MinIO S3 root credentials. | |
| # You can override them with ADMIN_USER and ADMIN_PASSWORD. | |
| ADMIN_USER="${ADMIN_USER:-$MINIO_ROOT_USER}" | |
| ADMIN_PASSWORD="${ADMIN_PASSWORD:-$MINIO_ROOT_PASSWORD}" | |
| mkdir -p "$MINIO_DATA_DIR" /run/nginx /app/public | |
| export MINIO_BROWSER | |
| export MINIO_REGION_NAME="$MINIO_REGION" | |
| ADMIN_AUTH_DIRECTIVES="" | |
| if [[ "$ADMIN_AUTH_ENABLED" == "1" || "$ADMIN_AUTH_ENABLED" == "true" ]]; then | |
| htpasswd -bc /etc/nginx/.admin_htpasswd "$ADMIN_USER" "$ADMIN_PASSWORD" >/dev/null | |
| ADMIN_AUTH_DIRECTIVES='auth_basic "COS_HF Admin"; | |
| auth_basic_user_file /etc/nginx/.admin_htpasswd;' | |
| echo "[COS_HF] Admin page basic auth enabled. User: $ADMIN_USER" | |
| else | |
| echo "[COS_HF] WARNING: Admin page basic auth is disabled. Set ADMIN_AUTH_ENABLED=1 for protection." | |
| fi | |
| cat >/etc/nginx/nginx.conf <<EOF | |
| worker_processes 1; | |
| daemon off; | |
| events { worker_connections 1024; } | |
| http { | |
| include /etc/nginx/mime.types; | |
| default_type application/octet-stream; | |
| sendfile on; | |
| client_max_body_size 0; | |
| # Browser basic auth used for /admin must not be forwarded to MinIO. | |
| # S3 SDK / mc signed requests use AWS4-HMAC-SHA256 and must be preserved. | |
| map \$http_authorization \$s3_authorization { | |
| default \$http_authorization; | |
| ~*^Basic ""; | |
| } | |
| server { | |
| listen ${PORT}; | |
| server_name _; | |
| location = /admin { | |
| ${ADMIN_AUTH_DIRECTIVES} | |
| root /app/public; | |
| try_files /index.html =404; | |
| } | |
| location = /admin/ { | |
| ${ADMIN_AUTH_DIRECTIVES} | |
| root /app/public; | |
| try_files /index.html =404; | |
| } | |
| location /assets/ { | |
| ${ADMIN_AUTH_DIRECTIVES} | |
| root /app/public; | |
| try_files \$uri =404; | |
| } | |
| location = /minio/health/live { | |
| proxy_set_header Host \$host; | |
| proxy_set_header Authorization ""; | |
| proxy_pass http://127.0.0.1:${MINIO_INTERNAL_PORT}/minio/health/live; | |
| } | |
| location = /minio/health/ready { | |
| proxy_set_header Host \$host; | |
| proxy_set_header Authorization ""; | |
| proxy_pass http://127.0.0.1:${MINIO_INTERNAL_PORT}/minio/health/ready; | |
| } | |
| location /minio/ { | |
| proxy_set_header Host \$host; | |
| proxy_set_header Authorization \$s3_authorization; | |
| 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_pass http://127.0.0.1:${MINIO_INTERNAL_PORT}; | |
| } | |
| location / { | |
| proxy_set_header Host \$host; | |
| proxy_set_header Authorization \$s3_authorization; | |
| 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_pass http://127.0.0.1:${MINIO_INTERNAL_PORT}; | |
| } | |
| } | |
| } | |
| EOF | |
| echo "[COS_HF] Starting MinIO internal S3 API on :$MINIO_INTERNAL_PORT" | |
| echo "[COS_HF] Starting public nginx gateway on :$PORT" | |
| echo "[COS_HF] Data dir: $MINIO_DATA_DIR" | |
| echo "[COS_HF] Default bucket: $MINIO_BUCKET" | |
| minio server "$MINIO_DATA_DIR" --address ":${MINIO_INTERNAL_PORT}" & | |
| MINIO_PID=$! | |
| cleanup() { | |
| echo "[COS_HF] Stopping services..." | |
| kill "$MINIO_PID" 2>/dev/null || true | |
| kill "$NGINX_PID" 2>/dev/null || true | |
| wait "$MINIO_PID" 2>/dev/null || true | |
| wait "$NGINX_PID" 2>/dev/null || true | |
| } | |
| trap cleanup SIGTERM SIGINT | |
| for i in $(seq 1 60); do | |
| if curl -fsS "http://127.0.0.1:${MINIO_INTERNAL_PORT}/minio/health/ready" >/dev/null 2>&1; then | |
| break | |
| fi | |
| echo "[COS_HF] Waiting for MinIO readiness... ($i/60)" | |
| sleep 2 | |
| if ! kill -0 "$MINIO_PID" 2>/dev/null; then | |
| echo "[COS_HF] MinIO exited before readiness." >&2 | |
| wait "$MINIO_PID" | |
| exit 1 | |
| fi | |
| done | |
| mc alias set local "http://127.0.0.1:${MINIO_INTERNAL_PORT}" "$MINIO_ROOT_USER" "$MINIO_ROOT_PASSWORD" >/dev/null | |
| if ! mc ls "local/${MINIO_BUCKET}" >/dev/null 2>&1; then | |
| echo "[COS_HF] Creating bucket: ${MINIO_BUCKET}" | |
| mc mb "local/${MINIO_BUCKET}" >/dev/null | |
| else | |
| echo "[COS_HF] Bucket exists: ${MINIO_BUCKET}" | |
| fi | |
| if [[ "$PUBLIC_BUCKET" == "1" || "$PUBLIC_BUCKET" == "true" ]]; then | |
| echo "[COS_HF] Setting bucket anonymous download policy: ${MINIO_BUCKET}" | |
| mc anonymous set download "local/${MINIO_BUCKET}" >/dev/null || true | |
| else | |
| echo "[COS_HF] Bucket remains private: ${MINIO_BUCKET}" | |
| fi | |
| nginx & | |
| NGINX_PID=$! | |
| cat <<EOF | |
| [COS_HF] Ready. | |
| Admin page: /admin auth=${ADMIN_AUTH_ENABLED} user=${ADMIN_USER} | |
| Health live: /minio/health/live | |
| Health ready: /minio/health/ready | |
| Bucket: ${MINIO_BUCKET} | |
| S3 Endpoint: ${SPACE_URL} | |
| Path URL: ${SPACE_URL}/${MINIO_BUCKET}/path/to/file | |
| EOF | |
| wait -n "$MINIO_PID" "$NGINX_PID" |