diff --git a/.github/packaging/linux/AppDir/AppRun b/.github/packaging/linux/AppDir/AppRun new file mode 100644 index 00000000..b047e32a --- /dev/null +++ b/.github/packaging/linux/AppDir/AppRun @@ -0,0 +1,81 @@ +#!/bin/sh +LAUNCH_DIR="$PWD" + +# Define persistent storage for extracted LNbits +PERSISTENT_DIR="$HOME/.local/share/lnbits" + +# Remove existing LNbits directory before extraction +if [ -d "$PERSISTENT_DIR" ]; then + echo "Removing existing LNbits directory..." + rm -rf "$PERSISTENT_DIR" +fi + +# Ensure the persistent directory exists +mkdir -p "$PERSISTENT_DIR" + +# Extract LNbits from the AppImage if not already extracted +echo "Extracting LNbits to disk for better performance..." +cp -r "$APPDIR/usr/lnbits"/* "$PERSISTENT_DIR/" +chmod +x "$PERSISTENT_DIR/dist/lnbits" + +# Check if the directory exists, and create it if it doesn't +if [ ! -d "$LAUNCH_DIR/lnbits/database" ]; then + mkdir -p "$LAUNCH_DIR/lnbits/database" + echo "Created database directory at $LAUNCH_DIR/lnbits/database" +fi + +if [ ! -d "$LAUNCH_DIR/lnbits/extensions" ]; then + mkdir -p "$LAUNCH_DIR/lnbits/extensions" + echo "Created extensions directory at $LAUNCH_DIR/lnbits/extensions" +fi + +cd "$PERSISTENT_DIR" + +# Export the directory as an environment variable for the app +LNBITS_DATA_FOLDER="${LNBITS_DATA_FOLDER:-$LAUNCH_DIR/lnbits/database}" +LNBITS_EXTENSIONS_PATH="${LNBITS_EXTENSIONS_PATH:-$LAUNCH_DIR/lnbits/extensions}" +export LNBITS_DATA_FOLDER +export LNBITS_EXTENSIONS_PATH +export LNBITS_ADMIN_UI=true + +# Define the LNbits URL +URL="http://0.0.0.0:5000" + +"./dist/lnbits" "$@" & +LNBITS_PID=$! + +# Wait for LNbits to be ready before showing the popup +sleep 3 +CLOSED=false + +# Function to stop LNbits gracefully +kill_lnbits() { + LN_PIDS=$(lsof -t -i:5000 2>/dev/null) # Capture all PIDs + if [ -n "$LN_PIDS" ]; then + echo "Stopping LNbits (PIDs: $LN_PIDS)..." + kill -2 $LN_PIDS # Send SIGINT to all processes on port 5000 + CLOSED=true + fi +} + +# Show a GUI with a clickable link to open the browser +if command -v zenity >/dev/null 2>&1; then + while [ "$CLOSED" = false ]; do + zenity --info --title="LNbits" --width=400 --text="LNbits is running.\n\n$URL\n\nClick 'Close Server' to stop LNbits." --ok-label="Close Server" + kill_lnbits + sleep 1 + done +elif command -v yad >/dev/null 2>&1; then + while [ "$CLOSED" = false ]; do + yad --title="LNbits" --width=400 --text="LNbits is running.\n\n$URL\n\nClick 'Close Server' to stop LNbits." --button="Close Server":0 + kill_lnbits + sleep 1 + done +else + echo "No GUI tool found. LNbits is running at $URL" +fi + +# Ensure the script doesn't hang after closing +if ps -p $LNBITS_PID >/dev/null 2>&1; then + wait $LNBITS_PID 2>/dev/null || true +fi diff --git a/.github/packaging/linux/AppDir/lnbits.desktop b/.github/packaging/linux/AppDir/lnbits.desktop new file mode 100644 index 00000000..2946c212 --- /dev/null +++ b/.github/packaging/linux/AppDir/lnbits.desktop @@ -0,0 +1,6 @@ +[Desktop Entry] +Name=LNbits +Exec=lnbits +Icon=lnbits +Type=Application +Categories=X-Bitcoin;X-LightningNetwork;X-Finance;Network; diff --git a/.github/packaging/linux/AppDir/lnbits.png b/.github/packaging/linux/AppDir/lnbits.png new file mode 100644 index 00000000..5437551b Binary files /dev/null and b/.github/packaging/linux/AppDir/lnbits.png differ diff --git a/.github/packaging/linux/AppDir/usr/share/icons/128x128/apps/lnbits.png b/.github/packaging/linux/AppDir/usr/share/icons/128x128/apps/lnbits.png new file mode 100644 index 00000000..2dc26564 Binary files /dev/null and b/.github/packaging/linux/AppDir/usr/share/icons/128x128/apps/lnbits.png differ diff --git a/.github/packaging/linux/AppDir/usr/share/icons/256x256/apps/lnbits.png b/.github/packaging/linux/AppDir/usr/share/icons/256x256/apps/lnbits.png new file mode 100644 index 00000000..2eb6d2d7 Binary files /dev/null and b/.github/packaging/linux/AppDir/usr/share/icons/256x256/apps/lnbits.png differ diff --git a/.github/packaging/linux/AppDir/usr/share/icons/512x512/apps/lnbits.png b/.github/packaging/linux/AppDir/usr/share/icons/512x512/apps/lnbits.png new file mode 100644 index 00000000..38a15238 Binary files /dev/null and b/.github/packaging/linux/AppDir/usr/share/icons/512x512/apps/lnbits.png differ diff --git a/.github/workflows/packaging.yml b/.github/workflows/packaging.yml new file mode 100644 index 00000000..0fa8dee9 --- /dev/null +++ b/.github/workflows/packaging.yml @@ -0,0 +1,73 @@ +name: Build LNbits AppImage DMG + +on: + release: + types: [published] + +jobs: + + build-linux-package: + runs-on: ubuntu-latest + steps: + # Step 1: Checkout the repository + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + # Step 2: Install Dependencies + - name: Install Dependencies + run: | + curl -sSL https://install.python-poetry.org | python3 - + echo "$HOME/.local/bin" >> $GITHUB_PATH + sudo apt-get update + sudo apt-get install -y libfuse2 + shell: bash + + # Step 3: Clone LNbits Repository + - name: Clone LNbits + run: | + mv .github/packaging packaging + mkdir -p packaging/linux/AppDir/usr + git clone https://github.com/lnbits/lnbits.git packaging/linux/AppDir/usr/lnbits + shell: bash + + # Step 4: Make the AppImage Asset + - name: Make Asset + run: | + cd packaging/linux/AppDir/usr/lnbits + git checkout main + poetry install --main + poetry run pip install pyinstaller + + # Build the LNbits binary + poetry run pyinstaller --onefile --name lnbits --collect-all lnbits --collect-all sqlalchemy --collect-all aiosqlite --hidden-import=passlib.handlers.bcrypt $(poetry run which lnbits) + cd ../../../../.. + chmod +x packaging/linux/AppDir/AppRun + chmod +x packaging/linux/AppDir/lnbits.desktop + chmod +x packaging/linux/AppDir/usr/lnbits/dist/lnbits + + find packaging/linux/AppDir/usr/lnbits -mindepth 1 -maxdepth 1 \ + ! -name 'dist' \ + ! -name 'lnbits' \ + -exec rm -rf {} + + + wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage + chmod +x appimagetool-x86_64.AppImage + TAG_NAME=${{ github.event.release.tag_name }} + APPIMAGE_NAME="LNbits-${TAG_NAME}.AppImage" + ./appimagetool-x86_64.AppImage --updateinformation "gh-releases-zsync|lnbits|lnbits|latest|*.AppImage.zsync" packaging/linux/AppDir "$APPIMAGE_NAME" + chmod +x "$APPIMAGE_NAME" + echo "APPIMAGE_NAME=$APPIMAGE_NAME" >> $GITHUB_ENV + shell: bash + + # Step 5: Upload Linux Release Asset + - name: Upload Linux Release Asset + uses: actions/upload-release-asset@v1 + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ${{ env.APPIMAGE_NAME }} + asset_name: ${{ env.APPIMAGE_NAME }} + asset_content_type: application/octet-stream + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/docs/guide/installation.md b/docs/guide/installation.md index db763bd6..d1f0f874 100644 --- a/docs/guide/installation.md +++ b/docs/guide/installation.md @@ -6,11 +6,23 @@ nav_order: 2 # Basic installation -The following sections explain how to install LNbits using varions package managers: `poetry`, `nix`, `Docker` and `Fly.io`. - Note that by default LNbits uses SQLite as its database, which is simple and effective but you can configure it to use PostgreSQL instead which is also described in a section below. -## Option 1 (recommended): Poetry +## Option 1: AppImage (LInux) + +### AppImage (Linux) + +Go to [releases](https://github.com/lnbits/lnbits/releases) and pull latest AppImage, or: + +```sh +wget $(curl -s https://api.github.com/repos/lnbits/lnbits/releases/latest | jq -r '.assets[] | select(.name | endswith(".AppImage")) | .browser_download_url') -O LNbits-latest.AppImage +chmod +x LNbits-latest.AppImage +./LNbits-latest.AppImage --host 0.0.0.0 +``` + +LNbits will create a folder for db and extension files in the folder the AppImage runs from. + +## Option 2: Poetry (recommended for developers) It is recommended to use the latest version of Poetry. Make sure you have Python version `3.12` installed. @@ -71,18 +83,6 @@ poetry install --only main # Start LNbits with `poetry run lnbits` ``` -## Option 2: Install script (on Debian/Ubuntu) - -```sh -wget https://raw.githubusercontent.com/lnbits/lnbits/main/lnbits.sh && -chmod +x lnbits.sh && -./lnbits.sh -``` - -Now visit `0.0.0.0:5000` to make a super-user account. - -`export PATH="/home/$USER/.local/bin:$PATH"` then `./lnbits.sh` can be used to run, but for more control `cd lnbits` and use `poetry run lnbits` (see previous option). - ## Option 3: Nix ```sh diff --git a/lnbits.sh b/lnbits.sh deleted file mode 100644 index 38518fba..00000000 --- a/lnbits.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash - -# Check install has not already run -if [ ! -d lnbits/data ]; then - - # Update package list and install prerequisites non-interactively - sudo apt update -y - sudo apt install -y software-properties-common - - # Add the deadsnakes PPA repository non-interactively - sudo add-apt-repository -y ppa:deadsnakes/ppa - - # Install Python 3.9 and distutils non-interactively - sudo apt install -y python3.9 python3.9-distutils - - # Install Poetry - curl -sSL https://install.python-poetry.org | python3.9 - - - # Add Poetry to PATH for the current session - export PATH="/home/$USER/.local/bin:$PATH" - - if [ ! -d lnbits/wallets ]; then - # Clone the LNbits repository - git clone https://github.com/lnbits/lnbits.git - if [ $? -ne 0 ]; then - echo "Failed to clone the repository ... FAIL" - exit 1 - fi - # Ensure we are in the lnbits directory - cd lnbits || { echo "Failed to cd into lnbits ... FAIL"; exit 1; } - fi - - git checkout main - # Make data folder - mkdir data - - # Copy the .env.example to .env - cp .env.example .env - -elif [ ! -d lnbits/wallets ]; then - # cd into lnbits - cd lnbits || { echo "Failed to cd into lnbits ... FAIL"; exit 1; } -fi - -# Set path for running after install -export PATH="/home/$USER/.local/bin:$PATH" - -# Install the dependencies using Poetry -poetry env use python3.9 -poetry install --only main - -# Set environment variables for LNbits -export LNBITS_ADMIN_UI=true -export HOST=0.0.0.0 - -# Run LNbits -poetry run lnbits \ No newline at end of file