metube.sh
· 4.7 KiB · Bash
Bruto
#!/usr/bin/env bash
# MeTube installation script with offline Deno installation
# Place this script and deno-x86_64-unknown-linux-gnu.zip in the same directory
set -e
APP="MeTube"
APP_DIR="/opt/metube"
DENO_INSTALL_DIR="/usr/local"
DENO_ZIP="deno-x86_64-unknown-linux-gnu.zip"
GITHUB_REPO="alexta69/metube"
SERVICE_USER="root"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
info() { echo -e "${GREEN}[INFO]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
step() { echo -e "${BLUE}[STEP]${NC} $1"; }
# Check if running as root
if [[ $EUID -ne 0 ]]; then
error "This script must be run as root"
fi
# Check for local Deno archive
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DENO_ARCHIVE_PATH="${SCRIPT_DIR}/${DENO_ZIP}"
if [[ ! -f "$DENO_ARCHIVE_PATH" ]]; then
error "Deno archive not found at $DENO_ARCHIVE_PATH"
fi
info "Found Deno archive: $DENO_ARCHIVE_PATH"
# Install dependencies
step "Installing system dependencies"
apt-get update
apt-get install -y curl wget unzip git build-essential python3 python3-pip python3-venv
step "Installing NODEJS"
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
apt install -y nodejs
npm install -g pm2
# Install Deno from local archive
step "Installing Deno from local archive"
if [[ -d "${DENO_INSTALL_DIR}/deno" ]]; then
rm -rf "${DENO_INSTALL_DIR}/deno"
fi
unzip -o "$DENO_ARCHIVE_PATH" -d /tmp/deno_extract
chmod +x /tmp/deno_extract/deno
mv /tmp/deno_extract/deno "${DENO_INSTALL_DIR}/bin/deno"
rm -rf /tmp/deno_extract
if command -v deno >/dev/null 2>&1; then
info "Deno installed successfully: $(deno --version)"
else
error "Deno installation failed"
fi
# Install pnpm
step "Installing pnpm"
curl -fsSL https://get.pnpm.io/install.sh | sh -
# Download and setup MeTube
step "Downloading MeTube from GitHub"
LATEST_URL=$(curl -s "https://api.github.com/repos/${GITHUB_REPO}/releases/latest" | grep "tarball_url" | cut -d '"' -f 4)
if [[ -z "$LATEST_URL" ]]; then
error "Failed to get latest release URL"
fi
if [[ -d "$APP_DIR" ]]; then
warn "Existing installation found, backing up..."
mv "$APP_DIR" "${APP_DIR}_bak_$(date +%Y%m%d_%H%M%S)"
fi
mkdir -p "$APP_DIR"
cd "$APP_DIR"
curl -L "$LATEST_URL" -o metube.tar.gz
tar -xzf metube.tar.gz --strip-components=1
rm metube.tar.gz
# Build frontend
step "Building frontend"
if [[ -d "$APP_DIR/ui" ]]; then
cd "$APP_DIR/ui"
/root/.local/share/pnpm/pnpm install --frozen-lockfile
/root/.local/share/pnpm/ run build
else
error "UI directory not found"
fi
# Setup Python backend
step "Setting up Python backend"
cd "$APP_DIR"
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install yt-dlp aiohttp python-dotenv
# Check for requirements.txt
if [[ -f "$APP_DIR/requirements.txt" ]]; then
pip install -r requirements.txt
fi
# Create .env file
step "Creating configuration"
if [[ ! -f "$APP_DIR/.env" ]]; then
cat > "$APP_DIR/.env" <<EOF
# MeTube Configuration
DOWNLOAD_DIR=/downloads
STATE_DIR=/opt/metube/state
URL_PREFIX=
HTTP_USERNAME=
HTTP_PASSWORD=
YTDL_OPTIONS=
EOF
fi
# Create download and state directories
mkdir -p /downloads
mkdir -p "$APP_DIR/state"
# Create systemd service
step "Creating systemd service"
cat > /etc/systemd/system/metube.service <<EOF
[Unit]
Description=MeTube - YouTube Downloader
After=network.target
[Service]
Type=simple
WorkingDirectory=${APP_DIR}
EnvironmentFile=${APP_DIR}/.env
ExecStart=${APP_DIR}/.venv/bin/python3 ${APP_DIR}/app/main.py
Restart=always
User=root
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
# Reload systemd and start service
step "Starting MeTube service"
systemctl daemon-reload
systemctl enable metube
systemctl start metube
# Check if service is running
sleep 3
if systemctl is-active --quiet metube; then
info "MeTube service started successfully"
else
error "MeTube service failed to start. Check logs with: journalctl -u metube"
fi
# Get IP address
IP_ADDRESS=$(hostname -I | awk '{print $1}')
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}MeTube installation completed!${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e "Access MeTube at: ${YELLOW}http://${IP_ADDRESS}:8081${NC}"
echo ""
echo -e "Commands:"
echo -e " Start: ${BLUE}systemctl start metube${NC}"
echo -e " Stop: ${BLUE}systemctl stop metube${NC}"
echo -e " Status: ${BLUE}systemctl status metube${NC}"
echo -e " Logs: ${BLUE}journalctl -u metube -f${NC}"
echo ""
echo -e "Download directory: ${YELLOW}/downloads${NC}"
echo -e "Config file: ${YELLOW}${APP_DIR}/.env${NC}"
| 1 | #!/usr/bin/env bash |
| 2 | |
| 3 | # MeTube installation script with offline Deno installation |
| 4 | # Place this script and deno-x86_64-unknown-linux-gnu.zip in the same directory |
| 5 | |
| 6 | set -e |
| 7 | |
| 8 | APP="MeTube" |
| 9 | APP_DIR="/opt/metube" |
| 10 | DENO_INSTALL_DIR="/usr/local" |
| 11 | DENO_ZIP="deno-x86_64-unknown-linux-gnu.zip" |
| 12 | GITHUB_REPO="alexta69/metube" |
| 13 | SERVICE_USER="root" |
| 14 | |
| 15 | # Colors for output |
| 16 | RED='\033[0;31m' |
| 17 | GREEN='\033[0;32m' |
| 18 | YELLOW='\033[1;33m' |
| 19 | BLUE='\033[0;34m' |
| 20 | NC='\033[0m' |
| 21 | |
| 22 | info() { echo -e "${GREEN}[INFO]${NC} $1"; } |
| 23 | warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } |
| 24 | error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; } |
| 25 | step() { echo -e "${BLUE}[STEP]${NC} $1"; } |
| 26 | |
| 27 | # Check if running as root |
| 28 | if [[ $EUID -ne 0 ]]; then |
| 29 | error "This script must be run as root" |
| 30 | fi |
| 31 | |
| 32 | # Check for local Deno archive |
| 33 | SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| 34 | DENO_ARCHIVE_PATH="${SCRIPT_DIR}/${DENO_ZIP}" |
| 35 | |
| 36 | if [[ ! -f "$DENO_ARCHIVE_PATH" ]]; then |
| 37 | error "Deno archive not found at $DENO_ARCHIVE_PATH" |
| 38 | fi |
| 39 | |
| 40 | info "Found Deno archive: $DENO_ARCHIVE_PATH" |
| 41 | |
| 42 | # Install dependencies |
| 43 | step "Installing system dependencies" |
| 44 | apt-get update |
| 45 | apt-get install -y curl wget unzip git build-essential python3 python3-pip python3-venv |
| 46 | |
| 47 | step "Installing NODEJS" |
| 48 | curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - |
| 49 | apt install -y nodejs |
| 50 | npm install -g pm2 |
| 51 | |
| 52 | # Install Deno from local archive |
| 53 | step "Installing Deno from local archive" |
| 54 | if [[ -d "${DENO_INSTALL_DIR}/deno" ]]; then |
| 55 | rm -rf "${DENO_INSTALL_DIR}/deno" |
| 56 | fi |
| 57 | |
| 58 | unzip -o "$DENO_ARCHIVE_PATH" -d /tmp/deno_extract |
| 59 | chmod +x /tmp/deno_extract/deno |
| 60 | mv /tmp/deno_extract/deno "${DENO_INSTALL_DIR}/bin/deno" |
| 61 | rm -rf /tmp/deno_extract |
| 62 | |
| 63 | if command -v deno >/dev/null 2>&1; then |
| 64 | info "Deno installed successfully: $(deno --version)" |
| 65 | else |
| 66 | error "Deno installation failed" |
| 67 | fi |
| 68 | |
| 69 | # Install pnpm |
| 70 | step "Installing pnpm" |
| 71 | curl -fsSL https://get.pnpm.io/install.sh | sh - |
| 72 | |
| 73 | # Download and setup MeTube |
| 74 | step "Downloading MeTube from GitHub" |
| 75 | LATEST_URL=$(curl -s "https://api.github.com/repos/${GITHUB_REPO}/releases/latest" | grep "tarball_url" | cut -d '"' -f 4) |
| 76 | |
| 77 | if [[ -z "$LATEST_URL" ]]; then |
| 78 | error "Failed to get latest release URL" |
| 79 | fi |
| 80 | |
| 81 | if [[ -d "$APP_DIR" ]]; then |
| 82 | warn "Existing installation found, backing up..." |
| 83 | mv "$APP_DIR" "${APP_DIR}_bak_$(date +%Y%m%d_%H%M%S)" |
| 84 | fi |
| 85 | |
| 86 | mkdir -p "$APP_DIR" |
| 87 | cd "$APP_DIR" |
| 88 | |
| 89 | curl -L "$LATEST_URL" -o metube.tar.gz |
| 90 | tar -xzf metube.tar.gz --strip-components=1 |
| 91 | rm metube.tar.gz |
| 92 | |
| 93 | # Build frontend |
| 94 | step "Building frontend" |
| 95 | if [[ -d "$APP_DIR/ui" ]]; then |
| 96 | cd "$APP_DIR/ui" |
| 97 | /root/.local/share/pnpm/pnpm install --frozen-lockfile |
| 98 | /root/.local/share/pnpm/ run build |
| 99 | else |
| 100 | error "UI directory not found" |
| 101 | fi |
| 102 | |
| 103 | # Setup Python backend |
| 104 | step "Setting up Python backend" |
| 105 | cd "$APP_DIR" |
| 106 | python3 -m venv .venv |
| 107 | source .venv/bin/activate |
| 108 | pip install --upgrade pip |
| 109 | pip install yt-dlp aiohttp python-dotenv |
| 110 | |
| 111 | # Check for requirements.txt |
| 112 | if [[ -f "$APP_DIR/requirements.txt" ]]; then |
| 113 | pip install -r requirements.txt |
| 114 | fi |
| 115 | |
| 116 | # Create .env file |
| 117 | step "Creating configuration" |
| 118 | if [[ ! -f "$APP_DIR/.env" ]]; then |
| 119 | cat > "$APP_DIR/.env" <<EOF |
| 120 | # MeTube Configuration |
| 121 | DOWNLOAD_DIR=/downloads |
| 122 | STATE_DIR=/opt/metube/state |
| 123 | URL_PREFIX= |
| 124 | HTTP_USERNAME= |
| 125 | HTTP_PASSWORD= |
| 126 | YTDL_OPTIONS= |
| 127 | EOF |
| 128 | fi |
| 129 | |
| 130 | # Create download and state directories |
| 131 | mkdir -p /downloads |
| 132 | mkdir -p "$APP_DIR/state" |
| 133 | |
| 134 | # Create systemd service |
| 135 | step "Creating systemd service" |
| 136 | cat > /etc/systemd/system/metube.service <<EOF |
| 137 | [Unit] |
| 138 | Description=MeTube - YouTube Downloader |
| 139 | After=network.target |
| 140 | |
| 141 | [Service] |
| 142 | Type=simple |
| 143 | WorkingDirectory=${APP_DIR} |
| 144 | EnvironmentFile=${APP_DIR}/.env |
| 145 | ExecStart=${APP_DIR}/.venv/bin/python3 ${APP_DIR}/app/main.py |
| 146 | Restart=always |
| 147 | User=root |
| 148 | StandardOutput=journal |
| 149 | StandardError=journal |
| 150 | |
| 151 | [Install] |
| 152 | WantedBy=multi-user.target |
| 153 | EOF |
| 154 | |
| 155 | # Reload systemd and start service |
| 156 | step "Starting MeTube service" |
| 157 | systemctl daemon-reload |
| 158 | systemctl enable metube |
| 159 | systemctl start metube |
| 160 | |
| 161 | # Check if service is running |
| 162 | sleep 3 |
| 163 | if systemctl is-active --quiet metube; then |
| 164 | info "MeTube service started successfully" |
| 165 | else |
| 166 | error "MeTube service failed to start. Check logs with: journalctl -u metube" |
| 167 | fi |
| 168 | |
| 169 | # Get IP address |
| 170 | IP_ADDRESS=$(hostname -I | awk '{print $1}') |
| 171 | |
| 172 | echo "" |
| 173 | echo -e "${GREEN}========================================${NC}" |
| 174 | echo -e "${GREEN}MeTube installation completed!${NC}" |
| 175 | echo -e "${GREEN}========================================${NC}" |
| 176 | echo -e "Access MeTube at: ${YELLOW}http://${IP_ADDRESS}:8081${NC}" |
| 177 | echo "" |
| 178 | echo -e "Commands:" |
| 179 | echo -e " Start: ${BLUE}systemctl start metube${NC}" |
| 180 | echo -e " Stop: ${BLUE}systemctl stop metube${NC}" |
| 181 | echo -e " Status: ${BLUE}systemctl status metube${NC}" |
| 182 | echo -e " Logs: ${BLUE}journalctl -u metube -f${NC}" |
| 183 | echo "" |
| 184 | echo -e "Download directory: ${YELLOW}/downloads${NC}" |
| 185 | echo -e "Config file: ${YELLOW}${APP_DIR}/.env${NC}" |