Last active
May 6, 2026 15:30
-
-
Save jenishngl/675e309f590349917d0a2e606fdac90d to your computer and use it in GitHub Desktop.
Booklore to Grimmory Proxmox LXC Update script
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
| #!/usr/bin/env bash | |
| source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) | |
| # Author: Jenish (jenishngl) | |
| APP="Grimmory" | |
| var_tags="${var_tags:-books;library}" | |
| var_cpu="${var_cpu:-3}" | |
| var_ram="${var_ram:-3072}" | |
| var_disk="${var_disk:-7}" | |
| var_os="${var_os:-debian}" | |
| var_version="${var_version:-13}" | |
| var_unprivileged="${var_unprivileged:-1}" | |
| header_info "$APP" | |
| variables | |
| color | |
| catch_errors | |
| function setup_kepubify() { | |
| local OLD_PATH="/opt/booklore_storage/data/tools/kepubify" | |
| local NEW_PATH="/usr/local/bin/kepubify" | |
| local ARCH | |
| local URL | |
| ARCH="$(dpkg --print-architecture)" | |
| case "$ARCH" in | |
| amd64) URL="https://github.com/pgaskin/kepubify/releases/latest/download/kepubify-linux-64bit" ;; | |
| arm64) URL="https://github.com/pgaskin/kepubify/releases/latest/download/kepubify-linux-arm64" ;; | |
| *) | |
| msg_error "Unsupported architecture: $ARCH" | |
| return 1 | |
| ;; | |
| esac | |
| mkdir -p /usr/local/bin | |
| # Fail clearly if a previous bad install created a directory here | |
| if [[ -d "$NEW_PATH" ]]; then | |
| msg_error "Invalid kepubify install detected at $NEW_PATH. It is a directory, not a binary." | |
| return 1 | |
| fi | |
| # Migrate from old location if present and valid | |
| if [[ -f "$OLD_PATH" && -x "$OLD_PATH" && ! -f "$NEW_PATH" ]]; then | |
| if "$OLD_PATH" --help >/dev/null 2>&1; then | |
| msg_info "Migrating kepubify to /usr/local/bin" | |
| mv "$OLD_PATH" "$NEW_PATH" | |
| chmod 0755 "$NEW_PATH" | |
| else | |
| msg_warn "Skipping migration: invalid kepubify binary at $OLD_PATH" | |
| fi | |
| fi | |
| # If not installed → ask user | |
| if [[ -f "$NEW_PATH" ]]; then | |
| msg_info "Updating Kepubify" | |
| else | |
| if command -v whiptail >/dev/null 2>&1; then | |
| if ! whiptail \ | |
| --backtitle "Proxmox VE Helper Scripts" \ | |
| --title "KEPUBIFY" \ | |
| --yesno "Kepubify not found.\n\nInstall it for Kobo Sync support?" 10 60; then | |
| msg_info "Skipping Kepubify" | |
| return 0 | |
| fi | |
| else | |
| read -r -p "Kepubify not found. Install it? [y/N]: " reply | |
| [[ "$reply" =~ ^[Yy]$ ]] || return 0 | |
| fi | |
| msg_info "Installing Kepubify" | |
| fi | |
| # Download latest | |
| if ! wget -q "$URL" -O /tmp/kepubify; then | |
| msg_error "Failed to download Kepubify" | |
| return 1 | |
| fi | |
| # Install | |
| if ! install -m 0755 -T /tmp/kepubify "$NEW_PATH"; then | |
| rm -f /tmp/kepubify | |
| msg_error "Failed to install Kepubify" | |
| return 1 | |
| fi | |
| rm -f /tmp/kepubify | |
| if [[ ! -f "$NEW_PATH" || ! -x "$NEW_PATH" ]]; then | |
| msg_error "Kepubify install verification failed: binary missing or not executable" | |
| return 1 | |
| fi | |
| if ! command -v kepubify >/dev/null 2>&1; then | |
| msg_error "Kepubify install verification failed: not found in PATH" | |
| return 1 | |
| fi | |
| msg_ok "Kepubify ready" | |
| } | |
| function update_script() { | |
| header_info | |
| check_container_storage | |
| check_container_resources | |
| # Installation check: | |
| if [[ ! -d /opt/booklore && ! -d /opt/grimmory ]]; then | |
| msg_error "No BookLore or ${APP} Installation Found!" | |
| exit | |
| fi | |
| if check_for_gh_release "grimmory" "grimmory-tools/grimmory"; then | |
| JAVA_VERSION="25" | |
| setup_java | |
| setup_mariadb | |
| ensure_dependencies ffmpeg libarchive13 curl jq | |
| setup_kepubify | |
| # Confirm libarchive symlink | |
| if [[ ! -L /usr/lib/libarchive.so ]]; then | |
| ln -s /lib/x86_64-linux-gnu/libarchive.so /usr/lib/ | |
| fi | |
| # Service stop: | |
| msg_info "Stopping Service" | |
| if [[ -d /opt/grimmory ]]; then | |
| systemctl stop grimmory || true | |
| else | |
| systemctl stop booklore || true | |
| fi | |
| msg_ok "Stopped Service" | |
| # Env var migration: | |
| if grep -qE "^BOOKLORE_(DATA_PATH|BOOKDROP_PATH|BOOKS_PATH|PORT)=" /opt/booklore_storage/.env 2>/dev/null; then | |
| msg_info "Migrating old environment variables" | |
| sed -i 's/^BOOKLORE_DATA_PATH=/APP_PATH_CONFIG=/g' /opt/booklore_storage/.env | |
| sed -i 's/^BOOKLORE_BOOKDROP_PATH=/APP_BOOKDROP_FOLDER=/g' /opt/booklore_storage/.env | |
| sed -i '/^BOOKLORE_BOOKS_PATH=/d' /opt/booklore_storage/.env | |
| sed -i '/^BOOKLORE_PORT=/d' /opt/booklore_storage/.env | |
| msg_ok "Migrated old environment variables" | |
| fi | |
| # Backup: | |
| msg_info "Backing up old installation" | |
| rm -rf /opt/grimmory_bak /opt/booklore_bak | |
| if [[ -d /opt/booklore ]]; then | |
| mv /opt/booklore /opt/booklore_bak | |
| elif [[ -d /opt/grimmory ]]; then | |
| cp -a /opt/grimmory /opt/grimmory_bak | |
| fi | |
| msg_ok "Backed up old installation" | |
| # Wipe existing grimmory dir before fresh deploy | |
| rm -rf /opt/grimmory | |
| mkdir -p /opt/grimmory/dist | |
| # Download Pre-built Jar | |
| msg_info "Downloading Pre-built Grimmory JAR" | |
| APP_VERSION=$(get_latest_github_release "grimmory-tools/grimmory") | |
| JAR_URL=$(curl -s "https://api.github.com/repos/grimmory-tools/grimmory/releases/latest" | grep "browser_download_url" | grep "\.jar" | head -n 1 | cut -d '"' -f 4) | |
| if [[ -z "$JAR_URL" ]]; then | |
| msg_error "Failed to locate pre-built JAR for version ${APP_VERSION}" | |
| exit 1 | |
| fi | |
| $STD wget -q "$JAR_URL" -O /opt/grimmory/dist/app.jar | |
| msg_ok "Downloaded Pre-built JAR (${APP_VERSION})" | |
| # Update local version tracker for Proxmox script compatibility | |
| echo "${APP_VERSION}" > /opt/${APP}_version.txt | |
| # Nginx removal: | |
| if systemctl is-active --quiet nginx 2>/dev/null; then | |
| msg_info "Removing Nginx (no longer needed)" | |
| systemctl disable --now nginx >/dev/null 2>&1 || true | |
| $STD apt-get purge -y nginx nginx-common | |
| msg_ok "Removed Nginx" | |
| fi | |
| # SERVER_PORT injection: | |
| if ! grep -q "^SERVER_PORT=" /opt/booklore_storage/.env 2>/dev/null; then | |
| echo "SERVER_PORT=6060" >> /opt/booklore_storage/.env | |
| fi | |
| if [[ -f /etc/systemd/system/booklore.service && ! -f /etc/systemd/system/grimmory.service ]]; then | |
| mv /etc/systemd/system/booklore.service /etc/systemd/system/grimmory.service | |
| fi | |
| # Service file migration: | |
| if [[ ! -f /etc/systemd/system/grimmory.service ]]; then | |
| msg_error "grimmory.service not found" | |
| exit | |
| fi | |
| sed -i 's|WorkingDirectory=.*|WorkingDirectory=/opt/grimmory/dist|' /etc/systemd/system/grimmory.service | |
| sed -i 's|ExecStart=.*|ExecStart=/usr/bin/java --enable-preview -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+UseCompactObjectHeaders -XX:MaxRAMPercentage=75.0 -XX:+ExitOnOutOfMemoryError -jar /opt/grimmory/dist/app.jar|' /etc/systemd/system/grimmory.service | |
| systemctl daemon-reload | |
| systemctl disable --now booklore.service >/dev/null 2>&1 || true | |
| # Start + cleanup: | |
| msg_info "Starting Service" | |
| systemctl enable --now grimmory.service | |
| sleep 2 | |
| if ! systemctl is-active --quiet grimmory.service; then | |
| msg_error "Grimmory service failed to start. Backups were retained." | |
| exit 1 | |
| fi | |
| rm -rf /opt/grimmory_bak /opt/booklore_bak | |
| msg_ok "Started Service" | |
| msg_ok "Updated successfully!" | |
| fi | |
| exit | |
| } | |
| start | |
| build_container | |
| description | |
| update_script "$@" | |
| msg_ok "Completed successfully!\n" | |
| echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" | |
| echo -e "${INFO}${YW} Access it using the following URL:${CL}" | |
| echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:6060${CL}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment