aboutsummaryrefslogtreecommitdiffstats
path: root/karakeep-linux.sh
diff options
context:
space:
mode:
Diffstat (limited to 'karakeep-linux.sh')
-rw-r--r--karakeep-linux.sh355
1 files changed, 355 insertions, 0 deletions
diff --git a/karakeep-linux.sh b/karakeep-linux.sh
new file mode 100644
index 00000000..4e7123df
--- /dev/null
+++ b/karakeep-linux.sh
@@ -0,0 +1,355 @@
+#!/usr/bin/env bash
+
+set -Eeuo pipefail
+
+# v2.1
+# Copyright 2024-2025
+# Author: vhsdream
+# Adapted from: The Karakeep installation script from https://github.com/community-scripts/ProxmoxVE
+# License: MIT
+
+# Basic error handling
+trap 'catch $? $LINENO' ERR
+
+catch() {
+ if [ "$1" == 0 ]; then
+ return
+ fi
+ echo "Caught error $1 on line $2"
+}
+
+OS="$(awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release)"
+INSTALL_DIR=/opt/karakeep
+export DATA_DIR=/var/lib/karakeep
+CONFIG_DIR=/etc/karakeep
+LOG_DIR=/var/log/karakeep
+ENV_FILE=${CONFIG_DIR}/karakeep.env
+
+install() {
+ echo "Karakeep installation for Debian 12/Ubuntu 24.04" && sleep 4
+ echo "Installing Dependencies..." && sleep 1
+ apt-get install --no-install-recommends -y \
+ g++ \
+ curl \
+ build-essential \
+ sudo \
+ unzip \
+ gnupg \
+ graphicsmagick \
+ ghostscript \
+ ca-certificates
+ if [[ "$OS" == "noble" ]]; then
+ apt-get install -y software-properties-common
+ add-apt-repository ppa:xtradeb/apps -y
+ apt-get install --no-install-recommends -y ungoogled-chromium yt-dlp
+ ln -s /usr/bin/ungoogled-chromium /usr/bin/chromium
+ else
+ apt-get install --no-install-recommends -y chromium
+ wget -q https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux -O /usr/bin/yt-dlp && chmod +x /usr/bin/yt-dlp
+ fi
+
+ wget -q https://github.com/Y2Z/monolith/releases/latest/download/monolith-gnu-linux-x86_64 -O /usr/bin/monolith && chmod +x /usr/bin/monolith
+ wget -q https://github.com/meilisearch/meilisearch/releases/latest/download/meilisearch.deb &&
+ DEBIAN_FRONTEND=noninteractive dpkg -i meilisearch.deb && rm meilisearch.deb
+ echo "Installed Dependencies" && sleep 1
+
+ echo "Installing Node.js..."
+ mkdir -p /etc/apt/keyrings
+ curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
+ echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" >/etc/apt/sources.list.d/nodesource.list
+ apt-get update
+ apt-get install -y nodejs
+ # https://github.com/karakeep-app/karakeep/issues/967
+ npm install -g corepack@0.31.0
+ echo "Installed Node.js" && sleep 1
+
+ echo "Installing Karakeep..."
+ mkdir -p "$DATA_DIR"
+ mkdir -p "$CONFIG_DIR"
+ mkdir -p "$LOG_DIR"
+ M_DATA_DIR=/var/lib/meilisearch
+ M_CONFIG_FILE=/etc/meilisearch.toml
+ RELEASE=$(curl -s https://api.github.com/repos/karakeep-app/karakeep/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
+ cd /tmp
+ wget -q "https://github.com/karakeep-app/karakeep/archive/refs/tags/v${RELEASE}.zip"
+ unzip -q v"$RELEASE".zip
+ mv karakeep-"$RELEASE" "$INSTALL_DIR" && cd "$INSTALL_DIR"/apps/web
+ corepack enable
+ export NEXT_TELEMETRY_DISABLED=1
+ export PUPPETEER_SKIP_DOWNLOAD="true"
+ export CI="true"
+ pnpm i --frozen-lockfile
+ pnpm exec next build --experimental-build-mode compile
+ cd "$INSTALL_DIR"/apps/workers
+ pnpm i --frozen-lockfile
+ cd "$INSTALL_DIR"/apps/cli
+ pnpm i --frozen-lockfile
+ pnpm build
+ cd "$INSTALL_DIR"/packages/db
+ pnpm migrate
+ echo "Installed Karakeep" && sleep 1
+
+ echo "Creating configuration files..."
+ cd "$INSTALL_DIR"
+ MASTER_KEY="$(openssl rand -base64 12)"
+ cat <<EOF >${M_CONFIG_FILE}
+env = "production"
+master_key = "$MASTER_KEY"
+db_path = "${M_DATA_DIR}/data"
+dump_dir = "${M_DATA_DIR}/dumps"
+snapshot_dir = "${M_DATA_DIR}/snapshots"
+no_analytics = true
+EOF
+ chmod 600 "$M_CONFIG_FILE"
+
+ karakeep_SECRET="$(openssl rand -base64 36 | cut -c1-24)"
+ cat <<EOF >${ENV_FILE}
+NODE_ENV=production
+SERVER_VERSION=${RELEASE}
+NEXTAUTH_SECRET="${karakeep_SECRET}"
+NEXTAUTH_URL="http://localhost:3000"
+DATA_DIR=${DATA_DIR}
+MEILI_ADDR="http://127.0.0.1:7700"
+MEILI_MASTER_KEY="${MASTER_KEY}"
+BROWSER_WEB_URL="http://127.0.0.1:9222"
+# CRAWLER_VIDEO_DOWNLOAD=true
+# CRAWLER_VIDEO_DOWNLOAD_MAX_SIZE=
+# OPENAI_API_KEY=
+# OLLAMA_BASE_URL=
+# INFERENCE_TEXT_MODEL=
+# INFERENCE_IMAGE_MODEL=
+EOF
+ chmod 600 "$ENV_FILE"
+ echo "$RELEASE" >"$INSTALL_DIR"/version.txt
+ echo "Configuration complete" && sleep 1
+
+ echo "Creating users and modifying permissions..."
+ useradd -U -s /usr/sbin/nologin -r -m -d "$M_DATA_DIR" meilisearch
+ useradd -U -s /usr/sbin/nologin -r -M -d "$INSTALL_DIR" karakeep
+ chown meilisearch:meilisearch "$M_CONFIG_FILE"
+ chown -R karakeep:karakeep "$INSTALL_DIR" "$CONFIG_DIR" "$DATA_DIR" "$LOG_DIR"
+ echo "Users created, permissions modified" && sleep 1
+
+ echo "Creating service files..."
+ cat <<EOF >/etc/systemd/system/meilisearch.service
+[Unit]
+Description=MeiliSearch is a RESTful search API
+Documentation=https://docs.meilisearch.com/
+After=network.target
+
+[Service]
+User=meilisearch
+Group=meilisearch
+Restart=on-failure
+WorkingDirectory=${M_DATA_DIR}
+ExecStart=/usr/bin/meilisearch --config-file-path ${M_CONFIG_FILE}
+NoNewPrivileges=true
+ProtectHome=true
+ReadWritePaths=${M_DATA_DIR}
+ProtectSystem=full
+ProtectHostname=true
+ProtectControlGroups=true
+ProtectKernelModules=true
+ProtectKernelTunables=true
+ProtectKernelLogs=true
+ProtectClock=true
+LockPersonality=true
+RestrictRealtime=yes
+RestrictNamespaces=yes
+MemoryDenyWriteExecute=yes
+PrivateDevices=yes
+PrivateTmp=true
+CapabilityBoundingSet=
+RemoveIPC=true
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+ cat <<EOF >/etc/systemd/system/karakeep-browser.service
+[Unit]
+Description=Karakeep headless browser
+After=network.target
+
+[Service]
+User=root
+Restart=on-failure
+ExecStart=/usr/bin/chromium --headless --no-sandbox --disable-gpu --disable-dev-shm-usage --remote-debugging-address=127.0.0.1 --remote-debugging-port=9222 --hide-scrollbars
+TimeoutStopSec=5
+SyslogIdentifier=karakeep-browser
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+ cat <<EOF >/etc/systemd/system/karakeep-workers.service
+[Unit]
+Description=Karakeep workers
+Wants=network.target karakeep-browser.service meilisearch.service
+After=network.target karakeep-browser.service meilisearch.service
+
+[Service]
+User=karakeep
+Group=karakeep
+Restart=always
+EnvironmentFile=${ENV_FILE}
+WorkingDirectory=${INSTALL_DIR}/apps/workers
+ExecStart=/usr/bin/pnpm run start:prod
+StandardOutput=file:${LOG_DIR}/karakeep-workers.log
+StandardError=file:${LOG_DIR}/karakeep-workers.log
+TimeoutStopSec=5
+SyslogIdentifier=karakeep-workers
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+ cat <<EOF >/etc/systemd/system/karakeep-web.service
+[Unit]
+Description=Karakeep web
+Wants=network.target karakeep-workers.service
+After=network.target karakeep-workers.service
+
+[Service]
+User=karakeep
+Group=karakeep
+Restart=on-failure
+EnvironmentFile=${ENV_FILE}
+WorkingDirectory=${INSTALL_DIR}/apps/web
+ExecStart=/usr/bin/pnpm start
+StandardOutput=file:${LOG_DIR}/karakeep-web.log
+StandardError=file:${LOG_DIR}/karakeep-web.log
+TimeoutStopSec=5
+SyslogIdentifier=karakeep-web
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+ cat <<EOF >/etc/systemd/system/karakeep.target
+[Unit]
+Description=Karakeep Services
+After=network-online.target
+Wants=meilisearch.service karakeep-browser.service karakeep-workers.service karakeep-web.service
+
+[Install]
+WantedBy=multi-user.target
+EOF
+ echo "Service files created" && sleep 1
+
+ echo "Enabling and starting services, please wait..." && sleep 3
+ systemctl enable -q --now meilisearch.service karakeep.target
+ echo "Done" && sleep 1
+
+ echo "Cleaning up" && sleep 1
+ rm /tmp/v"$RELEASE".zip
+ apt -y autoremove
+ apt -y autoclean
+ echo "Cleaned" && sleep 1
+
+ echo "OK, Karakeep should be accessible on port 3000 of this device's IP address!" && sleep 4
+ exit 0
+}
+
+update() {
+ echo "Checking for an update..." && sleep 1
+ if [[ ! -d ${INSTALL_DIR} ]]; then
+ echo "Is Karakeep even installed?"
+ exit 1
+ fi
+ RELEASE=$(curl -s https://api.github.com/repos/karakeep-app/karakeep/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
+ PREV_RELEASE=$(cat "$INSTALL_DIR"/version.txt)
+ if [[ "$RELEASE" != "$PREV_RELEASE" ]]; then
+ if [[ "$(systemctl is-active karakeep-web)" == "active" ]]; then
+ echo "Stopping affected services..." && sleep 1
+ systemctl stop karakeep-web karakeep-workers
+ echo "Stopped services" && sleep 1
+ fi
+ echo "Updating Karakeep to v${RELEASE}..." && sleep 1
+ sed -i "s|SERVER_VERSION=${PREV_RELEASE}|SERVER_VERSION=${RELEASE}|" "$ENV_FILE"
+ rm -R "$INSTALL_DIR"
+ cd /tmp
+ wget -q "https://github.com/karakeep-app/karakeep/archive/refs/tags/v${RELEASE}.zip"
+ unzip -q v"$RELEASE".zip
+ mv karakeep-"$RELEASE" "$INSTALL_DIR"
+ # https://github.com/karakeep-app/karakeep/issues/967
+ if [[ $(corepack -v) < "0.31.0" ]]; then
+ npm install -g corepack@0.31.0
+ fi
+ corepack enable
+ export NEXT_TELEMETRY_DISABLED=1
+ export PUPPETEER_SKIP_DOWNLOAD="true"
+ export CI="true"
+ cd "$INSTALL_DIR"/apps/web && pnpm i --frozen-lockfile
+ pnpm exec next build --experimental-build-mode compile
+ cd "$INSTALL_DIR"/apps/workers && pnpm i --frozen-lockfile
+ cd "$INSTALL_DIR"/apps/cli && pnpm i --frozen-lockfile
+ pnpm build
+ cd "$INSTALL_DIR"/packages/db && pnpm migrate
+ echo "$RELEASE" >"$INSTALL_DIR"/version.txt
+ chown -R karakeep:karakeep "$INSTALL_DIR" "$DATA_DIR"
+ echo "Updated Karakeep to v${RELEASE}" && sleep 1
+ echo "Restarting services and cleaning up..." && sleep 1
+ systemctl start karakeep-workers karakeep-web
+ rm /tmp/v"$RELEASE".zip
+ echo "Ready!"
+ else
+ echo "No update required."
+ fi
+ exit 0
+}
+
+migrate() {
+ if [[ ! -d /opt/karakeep ]]; then
+ echo "Migrating your Hoarder installation to Karakeep, then checking for an update..." && sleep 3
+ systemctl stop hoarder-browser hoarder-workers hoarder-web
+ sed -i -e "s|hoarder|karakeep|g" /etc/hoarder/hoarder.env /etc/systemd/system/hoarder-{browser,web,workers}.service /etc/systemd/system/hoarder.target \
+ -e "s|Hoarder|Karakeep|g" /etc/systemd/system/hoarder-{browser,web,workers}.service /etc/systemd/system/hoarder.target
+ for path in /etc/systemd/system/hoarder*.service; do
+ new_path="${path//hoarder/karakeep}"
+ mv "$path" "$new_path"
+ done
+ mv /etc/systemd/system/hoarder.target /etc/systemd/system/karakeep.target
+ mv /opt/hoarder "$INSTALL_DIR"
+ mv /var/lib/hoarder "$DATA_DIR"
+ mv /etc/hoarder "$CONFIG_DIR"
+ mv /var/log/hoarder "$LOG_DIR"
+ mv "$CONFIG_DIR"/hoarder.env "$ENV_FILE"
+ mv "$LOG_DIR"/hoarder-web.log "$LOG_DIR"/karakeep-web.log
+ mv "$LOG_DIR"/hoarder-workers.log "$LOG_DIR"/karakeep-workers.log
+ usermod -l karakeep hoarder -d "$INSTALL_DIR"
+ groupmod -n karakeep hoarder
+ chown -R karakeep:karakeep "$INSTALL_DIR" "$CONFIG_DIR" "$DATA_DIR" "$LOG_DIR"
+ systemctl daemon-reload
+ systemctl -q enable --now karakeep.target
+ echo "Migration complete!" && sleep 2
+ else
+ echo "There is no need for a migration: Karakeep is already installed."
+ exit 1
+ fi
+}
+
+[ "$(id -u)" -ne 0 ] && echo "This script requires root privileges. Please run with sudo or as the root user." && exit 1
+command="${1:-}"
+if [ "$command" = "" ]; then
+ echo -e "\nRun script with:\r
+parameter 'install' to install Karakeep\r
+parameter 'update' to update Karakeep\r
+parameter 'migrate' to migrate your Hoarder install to Karakeep\n
+Note: 'migrate' will also update to the latest version if necessary" && exit 1
+fi
+
+case "$command" in
+install)
+ install
+ ;;
+update)
+ update
+ ;;
+migrate)
+ migrate && update
+ ;;
+*)
+ echo -e "Unknown command. Choose 'install', 'update' or 'migrate'." && exit 1
+ ;;
+esac