Created
September 8, 2025 09:56
-
-
Save thanosa75/a945e25d9cf49bdc9f48b1549661a259 to your computer and use it in GitHub Desktop.
Creates a mountpoint for a JuiceFS B2(Backblaze) backed mountpoint. Needs REDIS and AWS CLI, environment variables to be configured
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# JuiceFS Setup Script for Debian 13 with BackBlaze B2 and REDIS | |
# This script sets up JuiceFS with BackBlaze B2 as object storage and REDIS as metadata backend | |
set -e # Exit on any error | |
# Colors for output | |
RED='\033[0;31m' | |
GREEN='\033[0;32m' | |
YELLOW='\033[1;33m' | |
BLUE='\033[0;34m' | |
NC='\033[0m' # No Color | |
# Configuration variables - MODIFY THESE | |
JUICEFS_NAME="jfsmountpoint" # Name for your JuiceFS filesystem | |
MOUNT_POINT="/mnt/jfs" # Mount point directory | |
REDIS_URL="redis://localhost:6379/1" # REDIS connection URL (database 1) | |
# BackBlaze B2 Configuration - SET THESE ENVIRONMENT VARIABLES | |
# export B2_APPLICATION_KEY_ID="your_key_id" | |
# export B2_APPLICATION_KEY="your_application_key" | |
# export B2_BUCKET_NAME="your-bucket-name" | |
# export B2_ENDPOINT="https://s3.us-west-004.backblazeb2.com" # Adjust region as needed | |
# export AWS_REGION="us-west-004" # adjust region here as well | |
print_step() { | |
echo -e "${BLUE}[STEP]${NC} $1" | |
} | |
print_success() { | |
echo -e "${GREEN}[SUCCESS]${NC} $1" | |
} | |
print_warning() { | |
echo -e "${YELLOW}[WARNING]${NC} $1" | |
} | |
print_error() { | |
echo -e "${RED}[ERROR]${NC} $1" | |
} | |
# Function to check if command exists | |
command_exists() { | |
command -v "$1" >/dev/null 2>&1 | |
} | |
# Check if running as root for some operations | |
check_root() { | |
if [ "$EUID" -ne 0 ]; then | |
print_error "This script needs to be run as root for mounting operations." | |
echo "Run with: sudo $0" | |
exit 1 | |
fi | |
} | |
# Validate environment variables | |
validate_env() { | |
print_step "Validating environment variables..." | |
if [ -z "$B2_APPLICATION_KEY_ID" ]; then | |
print_error "B2_APPLICATION_KEY_ID environment variable not set" | |
print_error "Set it with: export B2_APPLICATION_KEY_ID='your_key_id'" | |
exit 1 | |
fi | |
if [ -z "$B2_APPLICATION_KEY" ]; then | |
print_error "B2_APPLICATION_KEY environment variable not set" | |
print_error "Set it with: export B2_APPLICATION_KEY='your_application_key'" | |
exit 1 | |
fi | |
if [ -z "$B2_BUCKET_NAME" ]; then | |
print_error "B2_BUCKET_NAME environment variable not set" | |
print_error "Set it with: export B2_BUCKET_NAME='your-bucket-name'" | |
exit 1 | |
fi | |
if [ -z "$B2_ENDPOINT" ]; then | |
print_warning "B2_ENDPOINT not set, using default: https://s3.us-west-004.backblazeb2.com" | |
export B2_ENDPOINT="https://s3.us-west-004.backblazeb2.com" | |
fi | |
if [ -z "$AWS_REGION" ]; then | |
print_warning "AWS_REGION not set, using default: us-west-004" | |
export B2_ENDPOINT="us-west-004" | |
fi | |
print_success "Environment variables validated" | |
} | |
# Install JuiceFS | |
install_juicefs() { | |
print_step "Installing JuiceFS..." | |
if command_exists juicefs; then | |
print_success "JuiceFS is already installed" | |
juicefs version | |
return | |
fi | |
# Update package list | |
apt-get update | |
# Install required dependencies | |
apt-get install -y curl wget fuse3 | |
# Download latest JuiceFS binary | |
JUICEFS_VERSION=$(curl -s https://api.github.com/repos/juicedata/juicefs/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') | |
print_step "Downloading JuiceFS $JUICEFS_VERSION..." | |
wget -O juicefs "https://github.com/juicedata/juicefs/releases/download/${JUICEFS_VERSION}/juicefs-${JUICEFS_VERSION}-linux-amd64" | |
# Make executable and move to system path | |
chmod +x juicefs | |
mv juicefs /usr/local/bin/ | |
print_success "JuiceFS installed successfully" | |
juicefs version | |
} | |
# Check REDIS connection | |
check_redis() { | |
print_step "Checking REDIS connection..." | |
if ! command_exists redis-cli; then | |
print_error "redis-cli not found. Install redis-tools: apt-get install redis-tools" | |
exit 1 | |
fi | |
# Test REDIS connection | |
if redis-cli -u "$REDIS_URL" ping | grep -q "PONG"; then | |
print_success "REDIS connection successful" | |
else | |
print_error "Cannot connect to REDIS at $REDIS_URL" | |
print_error "Make sure REDIS is running: sudo systemctl start redis-server" | |
exit 1 | |
fi | |
} | |
# Format JuiceFS filesystem | |
format_juicefs() { | |
print_step "Formatting JuiceFS filesystem..." | |
# Construct the S3 URL for BackBlaze B2 (just the bucket name, not full URL) | |
S3_BUCKET="$B2_BUCKET_NAME" | |
# Set AWS credentials for S3 compatibility with BackBlaze B2 specifics | |
export AWS_ACCESS_KEY_ID="$B2_APPLICATION_KEY_ID" | |
export AWS_SECRET_ACCESS_KEY="$B2_APPLICATION_KEY" | |
# export AWS_REGION="us-west-004" # BackBlaze B2 region, set on top of file, not here | |
export AWS_ENDPOINT_URL="$B2_ENDPOINT" | |
export AWS_S3_FORCE_PATH_STYLE="true" # Important for BackBlaze B2 | |
export AWS_S3_DISABLE_SSL="false" # Ensure HTTPS is used | |
print_warning "Using endpoint $AWS_ENDPOINT" | |
print_warning "Using region $AWS_REGION - does this match the endpoint region?" | |
# Check if filesystem already exists | |
if juicefs status "$REDIS_URL" >/dev/null 2>&1; then | |
print_warning "JuiceFS filesystem '$JUICEFS_NAME' already exists" | |
return | |
fi | |
# Format the filesystem with BackBlaze B2 specific settings | |
print_step "Creating JuiceFS filesystem '$JUICEFS_NAME'..." | |
print_step "Using endpoint: $B2_ENDPOINT" | |
print_step "Using bucket: $S3_BUCKET" | |
print_step "Force path style: enabled" | |
# Try different format approaches for BackBlaze B2 compatibility | |
if ! juicefs format \ | |
--storage s3 \ | |
--bucket "$S3_BUCKET" \ | |
--access-key "$B2_APPLICATION_KEY_ID" \ | |
--secret-key "$B2_APPLICATION_KEY" \ | |
--force-path-style \ | |
"$REDIS_URL" \ | |
"$JUICEFS_NAME" 2>/dev/null; then | |
print_warning "First attempt failed, trying without --force-path-style flag..." | |
juicefs format \ | |
--storage s3 \ | |
--bucket "$S3_BUCKET" \ | |
--access-key "$B2_APPLICATION_KEY_ID" \ | |
--secret-key "$B2_APPLICATION_KEY" \ | |
"$REDIS_URL" \ | |
"$JUICEFS_NAME" | |
fi | |
print_success "JuiceFS filesystem formatted successfully" | |
} | |
# Create mount point | |
create_mount_point() { | |
print_step "Creating mount point at $MOUNT_POINT..." | |
if [ ! -d "$MOUNT_POINT" ]; then | |
mkdir -p "$MOUNT_POINT" | |
print_success "Mount point created at $MOUNT_POINT" | |
else | |
print_warning "Mount point $MOUNT_POINT already exists" | |
fi | |
} | |
# Mount JuiceFS | |
mount_juicefs() { | |
print_step "Mounting JuiceFS filesystem..." | |
# Check if already mounted | |
if mountpoint -q "$MOUNT_POINT"; then | |
print_warning "$MOUNT_POINT is already mounted" | |
return | |
fi | |
# Set environment variables for mounting | |
export AWS_ACCESS_KEY_ID="$B2_APPLICATION_KEY_ID" | |
export AWS_SECRET_ACCESS_KEY="$B2_APPLICATION_KEY" | |
# export AWS_REGION="us-west-004" | |
export AWS_ENDPOINT_URL="$B2_ENDPOINT" | |
# Create cache directory | |
mkdir -p /var/cache/juicefs | |
# Mount the filesystem | |
juicefs mount \ | |
--background \ | |
--cache-dir /var/cache/juicefs \ | |
--cache-size 10240 \ | |
"$REDIS_URL" \ | |
"$MOUNT_POINT" | |
print_success "JuiceFS mounted at $MOUNT_POINT" | |
} | |
# Display filesystem info | |
show_info() { | |
print_step "JuiceFS filesystem information:" | |
echo "" | |
juicefs status "$REDIS_URL" | |
echo "" | |
echo "Mount information:" | |
df -h "$MOUNT_POINT" | |
echo "" | |
echo "Test the mount:" | |
echo " cd $MOUNT_POINT" | |
echo " touch test_file.txt" | |
echo " ls -la" | |
} | |
# Create systemd service for auto-mounting | |
create_systemd_service() { | |
print_step "Creating systemd service for auto-mounting..." | |
# Create environment file for systemd service | |
cat > /etc/juicefs/juicefs.env << EOF | |
AWS_ACCESS_KEY_ID=${B2_APPLICATION_KEY_ID} | |
AWS_SECRET_ACCESS_KEY=${B2_APPLICATION_KEY} | |
AWS_REGION=${AWS_REGION} | |
AWS_ENDPOINT_URL=${B2_ENDPOINT} | |
EOF | |
# Secure the environment file | |
chmod 600 /etc/juicefs/juicefs.env | |
# Create systemd service file | |
cat > /etc/systemd/system/juicefs-${JUICEFS_NAME}.service << EOF | |
[Unit] | |
Description=JuiceFS Mount for ${JUICEFS_NAME} | |
After=network-online.target redis.service | |
Wants=network-online.target | |
RequiresMountsFor=/var/cache/juicefs | |
[Service] | |
Type=forking | |
User=root | |
Group=root | |
EnvironmentFile=/etc/juicefs/juicefs.env | |
ExecStartPre=/bin/mkdir -p /var/cache/juicefs | |
ExecStartPre=/bin/mkdir -p ${MOUNT_POINT} | |
ExecStart=/usr/local/bin/juicefs mount --background --cache-dir /var/cache/juicefs --cache-size 10240 ${REDIS_URL} ${MOUNT_POINT} | |
ExecStop=/usr/local/bin/juicefs umount ${MOUNT_POINT} | |
Restart=on-failure | |
RestartSec=5 | |
KillMode=process | |
[Install] | |
WantedBy=multi-user.target | |
EOF | |
systemctl daemon-reload | |
systemctl enable juicefs-${JUICEFS_NAME}.service | |
print_success "Systemd service created and enabled" | |
echo "To start: systemctl start juicefs-${JUICEFS_NAME}.service" | |
echo "To check status: systemctl status juicefs-${JUICEFS_NAME}.service" | |
echo "To view logs: journalctl -u juicefs-${JUICEFS_NAME}.service -f" | |
} | |
# Test the mount | |
test_mount() { | |
print_step "Testing JuiceFS mount..." | |
# Create test file | |
TEST_FILE="$MOUNT_POINT/juicefs_test_$(date +%s).txt" | |
echo "JuiceFS is working! $(date)" > "$TEST_FILE" | |
if [ -f "$TEST_FILE" ]; then | |
print_success "Test file created successfully" | |
echo "Content: $(cat $TEST_FILE)" | |
rm "$TEST_FILE" | |
print_success "Test file removed successfully" | |
else | |
print_error "Failed to create test file" | |
exit 1 | |
fi | |
} | |
# Cleanup function for unmounting | |
cleanup() { | |
print_step "Unmounting JuiceFS..." | |
if mountpoint -q "$MOUNT_POINT"; then | |
juicefs umount "$MOUNT_POINT" | |
print_success "JuiceFS unmounted" | |
fi | |
} | |
# Show usage information | |
show_usage() { | |
echo "Usage: $0 [OPTIONS]" | |
echo "" | |
echo "Required environment variables:" | |
echo " B2_APPLICATION_KEY_ID - BackBlaze B2 application key ID" | |
echo " B2_APPLICATION_KEY - BackBlaze B2 application key" | |
echo " B2_BUCKET_NAME - BackBlaze B2 bucket name" | |
echo " B2_ENDPOINT - BackBlaze B2 S3 endpoint (optional)" | |
echo "" | |
echo "Example:" | |
echo " export B2_APPLICATION_KEY_ID='your_key_id'" | |
echo " export B2_APPLICATION_KEY='your_application_key'" | |
echo " export B2_BUCKET_NAME='your-bucket-name'" | |
echo " export AWS_REGION='us-west-004' # this must match the endpoint region" | |
echo " export B2_ENDPOINT='https://s3.us-west-004.backblazeb2.com'" | |
echo " sudo -E $0" | |
echo "" | |
echo "Options:" | |
echo " --cleanup Unmount JuiceFS only" | |
echo " --help Show this help message" | |
echo " --test Test existing mount" | |
} | |
# Backup function | |
backup_metadata() { | |
print_step "Creating metadata backup..." | |
BACKUP_DIR="/var/backups/juicefs" | |
mkdir -p "$BACKUP_DIR" | |
BACKUP_FILE="$BACKUP_DIR/juicefs-${JUICEFS_NAME}-$(date +%Y%m%d_%H%M%S).dump" | |
if redis-cli -u "$REDIS_URL" --rdb "$BACKUP_FILE"; then | |
print_success "Metadata backup created: $BACKUP_FILE" | |
else | |
print_warning "Failed to create metadata backup" | |
fi | |
} | |
# Main execution | |
main() { | |
echo "================================================================" | |
echo "JuiceFS Setup Script for Debian 13 with BackBlaze B2 and REDIS" | |
echo "================================================================" | |
echo "" | |
# Parse command line arguments | |
case "${1:-}" in | |
--cleanup) | |
check_root | |
cleanup | |
exit 0 | |
;; | |
--help) | |
show_usage | |
exit 0 | |
;; | |
--test) | |
check_root | |
if mountpoint -q "$MOUNT_POINT"; then | |
test_mount | |
else | |
print_error "$MOUNT_POINT is not mounted" | |
exit 1 | |
fi | |
exit 0 | |
;; | |
"") | |
# Normal execution | |
;; | |
*) | |
print_error "Unknown option: $1" | |
show_usage | |
exit 1 | |
;; | |
esac | |
# Check if running as root | |
check_root | |
# Validate environment | |
validate_env | |
# Create juicefs config directory | |
mkdir -p /etc/juicefs | |
# Install and setup | |
install_juicefs | |
check_redis | |
format_juicefs | |
create_mount_point | |
mount_juicefs | |
# Test the mount | |
test_mount | |
# Create backup of metadata | |
backup_metadata | |
# Optional: Create systemd service | |
echo "" | |
read -p "Create systemd service for auto-mounting? (y/N): " -n 1 -r | |
echo | |
if [[ $REPLY =~ ^[Yy]$ ]]; then | |
create_systemd_service | |
fi | |
# Show final information | |
show_info | |
echo "" | |
print_success "JuiceFS setup completed successfully!" | |
echo "" | |
echo "Useful commands:" | |
echo " juicefs info $REDIS_URL # Show filesystem info" | |
echo " juicefs status $REDIS_URL # Show status" | |
echo " juicefs umount $MOUNT_POINT # Unmount" | |
echo " juicefs gc $REDIS_URL # Garbage collection" | |
echo " juicefs fsck $REDIS_URL # File system check" | |
echo " $0 --test # Test the mount" | |
echo " $0 --cleanup # Unmount filesystem" | |
echo "" | |
echo "Log files:" | |
echo " /var/log/juicefs.log # JuiceFS logs" | |
echo " journalctl -u juicefs-$JUICEFS_NAME # Service logs" | |
echo "" | |
echo "Configuration:" | |
echo " Filesystem name: $JUICEFS_NAME" | |
echo " Mount point: $MOUNT_POINT" | |
echo " REDIS URL: $REDIS_URL" | |
echo " B2 Bucket: $B2_BUCKET_NAME" | |
echo " B2 Endpoint: $B2_ENDPOINT" | |
echo "" | |
} | |
# Set trap for cleanup on script exit (only for normal execution) | |
if [ "${1:-}" != "--cleanup" ]; then | |
trap cleanup EXIT | |
fi | |
# Run main function with all arguments | |
main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment