Spaces:
Running
Running
| # Define paths | |
| CONFIG_PATH="/tmp/rclone.conf" | |
| DB_PATH="/tmp/filebrowser.db" | |
| DATA_DIR="/data" | |
| # Check if RCLONE_CONFIG_DATA secret is set | |
| if [ -z "$RCLONE_CONFIG_DATA" ]; then | |
| echo "RCLONE_CONFIG_DATA is missing. Starting setup guide server on port 7860..." | |
| # Start a simple python server to show the configuration guide | |
| python3 -m http.server 7860 --directory /home/user/setup_guide | |
| exit 0 | |
| fi | |
| # Write the rclone config file | |
| echo "$RCLONE_CONFIG_DATA" > "$CONFIG_PATH" | |
| chmod 600 "$CONFIG_PATH" | |
| # Extract the remote name dynamically using Python (robust against newlines and spaces) | |
| REMOTE_NAME=$(python3 -c " | |
| import configparser | |
| config = configparser.ConfigParser() | |
| try: | |
| config.read('$CONFIG_PATH') | |
| sections = config.sections() | |
| if sections: | |
| print(sections[0].strip()) | |
| else: | |
| print('') | |
| except Exception: | |
| print('') | |
| ") | |
| if [ -z "$REMOTE_NAME" ]; then | |
| echo "Failed to parse remote name from rclone config. Using fallback 'gdrive'." | |
| REMOTE_NAME="gdrive" | |
| fi | |
| # Determine the remote path (root or subfolder) to prevent exceeding Hugging Face's 50GB limit | |
| if [ -n "$RCLONE_REMOTE_PATH" ]; then | |
| # Trim leading/trailing slashes | |
| CLEAN_PATH=$(echo "$RCLONE_REMOTE_PATH" | sed -e 's/^\///' -e 's/\/$//') | |
| REMOTE_PATH="$REMOTE_NAME:$CLEAN_PATH" | |
| echo "Using subfolder path: $REMOTE_PATH" | |
| else | |
| REMOTE_PATH="$REMOTE_NAME:" | |
| echo "Using root path: $REMOTE_PATH" | |
| fi | |
| # Set shared-with-me flag if requested | |
| SHARED_FLAG="" | |
| if [ "$RCLONE_SHARED_WITH_ME" = "true" ]; then | |
| SHARED_FLAG="--drive-shared-with-me" | |
| echo "Rclone will access 'Shared with me' files/folders." | |
| fi | |
| # Ensure SQLite database file exists so inotifywait can monitor it | |
| touch "$DB_PATH" | |
| # 1. Download database from Google Drive if it exists | |
| echo "Checking for persistent database on Google Drive..." | |
| rclone copyto "$REMOTE_PATH/.filebrowser.db" "$DB_PATH" --config "$CONFIG_PATH" --drive-skip-shortcuts --drive-acknowledge-abuse $SHARED_FLAG || true | |
| # Initialize config if export fails (e.g. database doesn't exist or is empty) | |
| if ! filebrowser config export -d "$DB_PATH" >/dev/null 2>&1; then | |
| echo "Initializing database..." | |
| filebrowser config init -d "$DB_PATH" | |
| filebrowser config set --root "$DATA_DIR" -d "$DB_PATH" | |
| fi | |
| # Enable Command Runner (shell execution) globally | |
| echo "Enabling Command Runner globally..." | |
| filebrowser config set --disable-exec=false --commands "zip,unzip,wget,curl,ls" -d "$DB_PATH" | |
| # Configure admin password and execution permissions via FILEBROWSER_PASSWORD secret if set | |
| if [ -n "$FILEBROWSER_PASSWORD" ]; then | |
| echo "FILEBROWSER_PASSWORD secret is set. Configuring admin password..." | |
| # Set or update the admin user password and execution permissions | |
| echo "Setting admin user password..." | |
| if filebrowser users update admin --password "$FILEBROWSER_PASSWORD" --commands "zip,unzip,wget,curl,ls" --perm.execute=true -d "$DB_PATH" >/dev/null 2>&1; then | |
| echo "Admin password and permissions updated successfully." | |
| else | |
| echo "Admin user not found. Creating admin user with custom password..." | |
| filebrowser users add admin "$FILEBROWSER_PASSWORD" --perm.admin --perm.execute=true --commands "zip,unzip,wget,curl,ls" -d "$DB_PATH" | |
| fi | |
| else | |
| # Even if password secret is not set, ensure default admin has execute permissions | |
| echo "Updating default admin user commands and permissions..." | |
| filebrowser users update admin --commands "zip,unzip,wget,curl,ls" --perm.execute=true -d "$DB_PATH" || true | |
| fi | |
| # 2. Download files from Google Drive to local /data directory | |
| echo "Syncing files from Google Drive..." | |
| rclone copy "$REMOTE_PATH" "$DATA_DIR" --config "$CONFIG_PATH" --drive-skip-shortcuts --drive-acknowledge-abuse $SHARED_FLAG || true | |
| # 3. Start background sync loops | |
| # Loop A: Sync files in /data to Google Drive when modified (Debounced & Robust) | |
| ( | |
| echo "Starting file sync daemon..." | |
| LAST_EVENT_FILE="/tmp/last_event_time" | |
| PENDING_FILE="/tmp/sync_pending" | |
| DEBOUNCE_SECS=10 | |
| # Clear any old state | |
| rm -f "$LAST_EVENT_FILE" "$PENDING_FILE" | |
| # Start inotifywait in monitor mode to ensure we don't miss any events while syncing | |
| inotifywait -r -m -e close_write,delete,move "$DATA_DIR" 2>/dev/null | while read -r _; do | |
| date +%s > "$LAST_EVENT_FILE" | |
| if [ ! -f "$PENDING_FILE" ]; then | |
| touch "$PENDING_FILE" | |
| fi | |
| done & | |
| # Background runner that waits for a quiet period before syncing | |
| while true; do | |
| if [ -f "$PENDING_FILE" ]; then | |
| last_time=$(cat "$LAST_EVENT_FILE" 2>/dev/null || echo 0) | |
| now=$(date +%s) | |
| elapsed=$((now - last_time)) | |
| if [ "$elapsed" -ge "$DEBOUNCE_SECS" ]; then | |
| rm -f "$PENDING_FILE" | |
| echo "Changes detected in $DATA_DIR, syncing to Google Drive ($REMOTE_PATH)..." | |
| if rclone copy "$DATA_DIR" "$REMOTE_PATH" --config "$CONFIG_PATH" --drive-skip-shortcuts --drive-acknowledge-abuse $SHARED_FLAG; then | |
| echo "File sync successful." | |
| else | |
| echo "File sync failed or partially completed (e.g. active uploads). Will retry..." | |
| # Set last event to now to debounce the next retry | |
| date +%s > "$LAST_EVENT_FILE" | |
| touch "$PENDING_FILE" | |
| fi | |
| fi | |
| fi | |
| sleep 2 | |
| done | |
| ) & | |
| # Loop B: Sync database /tmp/filebrowser.db to Google Drive when modified (Debounced & Robust) | |
| ( | |
| echo "Starting database sync daemon..." | |
| DB_LAST_EVENT="/tmp/db_last_event" | |
| DB_PENDING="/tmp/db_sync_pending" | |
| DEBOUNCE_SECS=3 | |
| # Clear any old state | |
| rm -f "$DB_LAST_EVENT" "$DB_PENDING" | |
| # Start inotifywait in monitor mode | |
| inotifywait -m -e modify "$DB_PATH" 2>/dev/null | while read -r _; do | |
| date +%s > "$DB_LAST_EVENT" | |
| if [ ! -f "$DB_PENDING" ]; then | |
| touch "$DB_PENDING" | |
| fi | |
| done & | |
| # Background runner for database sync | |
| while true; do | |
| if [ -f "$DB_PENDING" ]; then | |
| last_time=$(cat "$DB_LAST_EVENT" 2>/dev/null || echo 0) | |
| now=$(date +%s) | |
| elapsed=$((now - last_time)) | |
| if [ "$elapsed" -ge "$DEBOUNCE_SECS" ]; then | |
| rm -f "$DB_PENDING" | |
| echo "Database modified, uploading to Google Drive ($REMOTE_PATH)..." | |
| if rclone copyto "$DB_PATH" "$REMOTE_PATH/.filebrowser.db" --config "$CONFIG_PATH" $SHARED_FLAG; then | |
| echo "Database sync successful." | |
| else | |
| echo "Database sync failed. Will retry..." | |
| date +%s > "$DB_LAST_EVENT" | |
| touch "$DB_PENDING" | |
| fi | |
| fi | |
| fi | |
| sleep 1 | |
| done | |
| ) & | |
| # 4. Start File Browser | |
| echo "Starting File Browser on port 7860..." | |
| filebrowser --port 7860 --address 0.0.0.0 --database "$DB_PATH" --root "$DATA_DIR" | |