侧边栏壁纸
博主头像
天马行空 博主等级

凡是过往,皆为序章

  • 累计撰写 632 篇文章
  • 累计创建 11 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

KaraKeep搭建、使用及备份

sortie
2026-03-28 / 0 评论 / 0 点赞 / 82 阅读 / 0 字

在Debian12系统上搭建KaraKeep网络收藏夹,并定期自动异地备份。

为了平衡访问速度和连接性(国内VPS无法访问外网地址),建议用香港VPS,容量大于80GB。

参考:https://blog.laoda.de/archives/docker-compose-install-karakeep

Karakeep简介

Karakeep(前身为 Hoarder)是一款可自托管的「万物皆可存」书签应用,专为数据囤积爱好者打造。

相关地址

官方 GitHub 地址:https://github.com/karakeep-app/karakeep

Demo 地址:https://try.karakeep.app

安装 karakeep

创建安装目录

sudo -i

mkdir -p /root/data/docker_data/karakeep

cd /root/data/docker_data/karakeep

接着我们来编辑下 nano docker-compose.yml

注意:在docker-compose.yml设置MAX_ASSET_SIZE_MB为150,以允许超过默认50M的页面快照(归档)能够顺利保存。

services:
  web:
    image: ghcr.io/karakeep-app/karakeep:release
    restart: unless-stopped
    volumes:
      # By default, the data is stored in a docker volume called "data".
      # If you want to mount a custom directory, change the volume mapping to:
      # - /path/to/your/directory:/data
      - ./data:/data
    ports:
      - 3030:3000
    env_file:
      - .env
    environment:
      MEILI_ADDR: http://meilisearch:7700
      BROWSER_WEB_URL: http://chrome:9222
      MAX_ASSET_SIZE_MB: 150
      # OPENAI_API_KEY: ...

      # You almost never want to change the value of the DATA_DIR variable.
      # If you want to mount a custom directory, change the volume mapping above instead.
      DATA_DIR: /data # DON'T CHANGE THIS
  chrome:
    image: gcr.io/zenika-hub/alpine-chrome:124
    restart: unless-stopped
    command:
      - --no-sandbox
      - --disable-gpu
      - --disable-dev-shm-usage
      - --remote-debugging-address=0.0.0.0
      - --remote-debugging-port=9222
      - --hide-scrollbars
  meilisearch:
    image: getmeili/meilisearch:v1.13.3
    restart: unless-stopped
    env_file:
      - .env
    environment:
      MEILI_NO_ANALYTICS: "true"
    volumes:
      - ./meili_data:/meili_data

#volumes:
#  meilisearch:
#  data:

其中的左边的3030可以改成服务器上没有用过的端口,如果要用到AI功能的话,可以取消OPENAI_API_KEY的注释,填入自己的密钥。

接着我们来编辑下 .env

cd /root/data/docker_data/karakeep
nano .env

粘贴如下内容:

KARAKEEP_VERSION=release
NEXTAUTH_SECRET=C6C6G94pYRt/EwcqmDC+SfxXtJCvqdbfrkJA+WzVwTMEtgm+
MEILI_MASTER_KEY=dyxDFRXX9KXzJ18COhD6I67LwjnC1QC1B3fmmGz7v8ygyv0c
NEXTAUTH_URL=http://localhost:3030

其中的http://localhost:3000这个改成自己之后用域名访问的地址,比如我的https://karakeep.sortiey.com

其中的NEXTAUTH_SECRET和需要我们自己在命令行生成。

openssl rand -base64 36

查看端口是否被占用

apt install lsof  #安装 lsof

查看端口是否被占用(以 3030 为例),输入:

lsof -i:3030  #查看 3030 端口是否被占用,如果被占用,重新自定义一个端口

如果啥也没出现,表示端口未被占用,我们可以继续下面的操作了

启动 karakeep

cd /root/data/docker_data/karakeep
docker compose up -d   # 注意,老版本用户用 docker-compose up -d

耐心等待拉取好镜像,出现 done的字样之后,理论上我们就可以输入 http://ip:3030 访问了。

既然是加密的项目,不能用 http 使用明文传输,我们部署在公网一定要考虑使用反向代理工具NPM配置 SSL!

Nginx Proxy Manager 反向代理

  1. 首先在Cloudflare上绑定域名和ip

  2. 配置NPM

如果 Nginx Proxy Manager 和 karakeep 在同一台服务器上,可以在终端输入:

ip addr show docker0

查看对应的 Docker 容器内部 IP。

否则直接填 karakeep 所在的服务器 IP 就行。然后访问域名就可以访问了!

KaraKeep使用

用户注册

注意:使用ip访问时,如果.env配置的不是http://localhost:3030,而是https+域名,那么是无法注册成功。

Karakeep浏览器插件

官方Chrome插件

SingleFile插件

http://43.99.8.8:3030/api/v1/bookmarks/singlefile?ifexists=overwrite

令牌在karakeep的用户页面创建

参考配置:singlefile-settings-2026-03-27T17_33_09.662Z.json

配置NPM允许SF上传150M归档

已经在 Karakeep 容器中将上限设为了 150MB,我们需要在 NPM 中也将客户端允许的最大请求体(client max body size)同步提高,建议设为 150M 或稍微留点余量(比如 200M)。同时,针对大文件上传,适当延长超时时间也能有效防止连接被意外切断。

1. 进入 Proxy Host 设置

2. 添加高级自定义配置 (Advanced)

  1. 在弹出的编辑窗口中,点击顶部的 Advanced (高级) 标签页。

  2. 在提供的文本框(Custom Nginx Configuration)中,粘贴以下配置代码:

# 提高允许的最大上传体积 (这里设为 200M 留点余量)
client_max_body_size 200M;

# 延长超时时间,防止大型单页面文件处理或传输过慢导致 abort
proxy_connect_timeout 120s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;

更新 karakeep

cd /root/data/docker_data/karakeep

docker compose pull

docker compose up -d    # 请不要使用 docker compose stop 来停止容器,因为这么做需要额外的时间等待容器停止;docker compose up -d 直接升级容器时会自动停止并立刻重建新的容器,完全没有必要浪费那些时间。

docker image prune  # prune 命令用来删除不再使用的 docker 对象。删除所有未被 tag 标记和未被容器使用的镜像

提示,输入y

WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N]

卸载 karakeep

cd /root/data/docker_data/karakeep

docker compose down

cd ..

rm -rf /root/data/docker_data/karakeep  # 完全删除

最后记得删除image,卸载干净

docker images
docker rmi image_karakeep_id

备份 karakeep

在karakeep主机上的 /root/data/docker_data/目录下创建migrate_karakeep.sh,指定远程备份机ip及登录信息。

date #显示当前系统时间
sudo timedatectl set-timezone Asia/Shanghai #设置时区为北京时间

cd /root/data/docker_data
nano migrate_karakeep.sh
#!/bin/bash

export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# --- 配置信息 ---
PROJECT_NAME="karakeep"
BASE_DIR="/root/data/docker_data"
REMOTE_IP="3.7.1.9"
REMOTE_PORT="22"
REMOTE_USER="root"
REMOTE_PASS="Ca12!"
REMOTE_DIR="/root/data/docker_data"
BACKUP_FILE="karakeep_migration_$(date +%Y%m%d_%H%M).tar.gz"

cd $BASE_DIR

echo "1. [本地] 正在停止 Docker 服务: $PROJECT_NAME..."
cd $PROJECT_NAME && docker compose stop && cd ..

echo "2. [本地] 正在打包压缩文件夹..."
tar -czvf $BACKUP_FILE $PROJECT_NAME/

echo "3. [远程] 正在清理新 VPS 上2天之前的旧备份(保留最近两天)并创建目录..."
#sshpass -p "$REMOTE_PASS" ssh -p $REMOTE_PORT -o StrictHostKeyChecking=no $REMOTE_USER@$REMOTE_IP "mkdir -p $REMOTE_DIR && rm -f $REMOTE_DIR/*.tar.gz"
sshpass -p "$REMOTE_PASS" ssh -p $REMOTE_PORT -o StrictHostKeyChecking=no $REMOTE_USER@$REMOTE_IP "mkdir -p $REMOTE_DIR && find $REMOTE_DIR -name '*.tar.gz' -mtime +1 -delete"

echo "4. [传输] 正在采用断点续传模式发送压缩包..."
# 使用 rsync 的 --append-verify 实现断点续传,-e 指定 sshpass
sshpass -p "$REMOTE_PASS" rsync -avP --append-verify -e "ssh -p $REMOTE_PORT -o StrictHostKeyChecking=no" $BACKUP_FILE $REMOTE_USER@$REMOTE_IP:$REMOTE_DIR/

echo "5. [本地] 正在删除本地临时压缩包..."
rm -f $BACKUP_FILE

echo "6. [本地] 正在恢复原 VPS 服务..."
cd $PROJECT_NAME && docker compose up -d && cd ..

echo "------------------------------------------------"
echo "迁移任务完成!"
echo "压缩包已传输至新 VPS: $REMOTE_DIR/$BACKUP_FILE"

需要使用 sshpass 来自动化处理密码输入,并使用 rsync 来实现断点续传

在原 VPS 上,需要安装 sshpass 和 rsync(如果尚未安装):

apt-get update && apt-get install -y sshpass rsync

在目标VPS上,安装 rsync

apt-get update && apt-get install -y rsync

如何使用:

  1. 赋予权限:chmod +x migrate_karakeep.sh

  2. 执行脚本:./migrate_karakeep.sh

添加定时任务

1. 确保脚本具有执行权限

chmod +x /root/data/docker_data/migrate_karakeep.sh

2. 打开 Crontab 编辑器

crontab -e

如果是第一次运行,它可能会让你选择编辑器,通常建议选 1 (nano)

3. 添加定时任务

在文件的最后一行,添加以下内容:

0 3 * * * /bin/bash /root/data/docker_data/migrate_karakeep.sh >> /root/data/docker_data/migrate.log 2>&1

这行命令的含义:

0 3 * * *: 表示每天凌晨3点执行一次。

/bin/bash: 指定使用 bash 运行脚本,确保环境兼容。

/root/data/docker_data/migrate_karakeep.sh: 脚本的绝对路径(Crontab 中必须使用绝对路径)。

>> /root/data/docker_data/migrate.log 2>&1: 这是日志记录。它会将脚本运行的所有输出(包括报错)保存到 migrate.log 文件中。这样如果哪次迁移失败了,你可以通过查看日志找到原因。

5. 验证定时任务是否生效

crontab -l

只要能看到刚才添加的那行代码,任务就已经在后台排队了。

6. 日志检查

cat /root/data/docker_data/migrate.log

确认有没有出现 command not found 之类的错误。

检查karakeep备份(远程VPS)

在远程VPS 上创建一个新文件(命名为 check_backup.sh)

date #显示当前系统时间
sudo timedatectl set-timezone Asia/Shanghai #设置时区为北京时间

cd /root/data/docker_data
nano check_backup.sh
chmod +x /root/data/docker_data/check_backup.sh
#!/bin/bash

# 1. 设置检查目录
DIR="/root/data/docker_data"

# 2. 获取系统当前日期,格式为 YYYYMMDD (例如:20260315)
CURRENT_DATE=$(date +%Y%m%d)

# 3. 拼接目标文件名和完整路径
FILE_NAME="karakeep_migration_${CURRENT_DATE}.tar.gz"
FILE_PATH="${DIR}/${FILE_NAME}"

# 4. 设置 Bark 通知 URL (包含中文)
BARK_URL="https://bark.soey.com/3vdWZjh9QrvbCN93h83X3J/karakeep/备份失败"

# 5. 检查文件是否存在
if ls "${DIR}/karakeep_migration_${CURRENT_DATE}"*.tar.gz 1> /dev/null 2>&1; then

    echo "[$(date '+%Y-%m-%d %H:%M:%S')] 检查成功:找到备份文件 $FILE_PATH"
else
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] 检查失败:未找到备份文件 $FILE_PATH"
    echo "正在发送 Bark 通知..."

    # 使用 curl 发送请求,-s 参数表示静默模式,不输出下载进度条
    curl -s "$BARK_URL" > /dev/null

    echo -e "\n通知已触发。"

fi

运行脚本

./check_backup.sh

加入定时器

crontab -e
30 5 * * * /root/data/docker_data/check_backup.sh > /dev/null 2>&1

每天5点30检查当天备份的文件是否存在,如果不存在,使用bark发送消息通知,并且不需要保留日志。

> /dev/null:将正常的输出信息(标准输出)丢弃。

2>&1:将错误信息(标准错误)也重定向到标准输出,最终一起被丢弃。

系统时间相关

通常 Debian 12 默认开启了网络时间同步(NTP),以保证时间的准确性。您可以通过以下命令确认它的状态:

timedatectl status

在输出的信息中,确保 NTP service: active 或 System clock synchronized: yes

如果:系统时间并没有开启自动同步(System clock synchronized: no,且 NTP service: n/a)。

这在很多精简版的 Debian VPS 系统中非常常见,通常是因为系统镜像移除了默认的时间同步组件。为了确保您的备份检查脚本(依赖 CURRENT_DATE)能长期在准确的时间运行,我们需要把 NTP 服务跑起来。

请在终端中依次执行以下命令来安装并启用系统默认的轻量级时间同步服务 (systemd-timesyncd):

1. 安装时间同步服务

apt update
apt install systemd-timesyncd -y

2. 启用并启动 NTP 同步

timedatectl set-ntp true

3. 再次验证状态

timedatectl status

这时候,应该能看到输出中显示 System clock synchronized: yes 以及 NTP service: active,这代表 VPS 时间已经和全球标准时间精准同步了。

如果出现:Failed to set ntp: NTP not supported 的报错,在 VPS 环境中非常常见。

出现这个提示通常是因为您的 VPS 可能是基于 LXCOpenVZ 等容器虚拟化技术。在这种架构下,VPS 的底层硬件时钟是由宿主机(母机)统一管理和同步的,系统会禁止虚拟机内部自行运行或修改底层 NTP 服务。如果date输出的时间(CST)与当前的北京时间一致,那您完全不需要理会这个报错,也不需要再配置 NTP。

在远程VPS上镜像同步karakeep服务

cd /root/data/docker_data/
nano update_karakeep.sh
#!/bin/bash

# --- 配置信息 ---
BASE_DIR="/root/data/docker_data"
PROJECT_DIR="$BASE_DIR/karakeep"

cd $BASE_DIR

# 1. 自动寻找最新的备份压缩包
LATEST_BACKUP=$(ls -t karakeep_migration_*.tar.gz 2>/dev/null | head -n 1)

if [ -z "$LATEST_BACKUP" ]; then
    echo "错误: 未找到 karakeep_migration_*.tar.gz 压缩包!"
    exit 1
fi

echo "检测到最新备份文件: $LATEST_BACKUP"

# 2. 进入项目目录并停止当前服务
echo "1. 正在停止当前运行的 KaraKeep 服务..."
if [ -d "$PROJECT_DIR" ]; then
    cd $PROJECT_DIR && docker compose down
else
    echo "错误: 未找到项目目录 $PROJECT_DIR"
    exit 1
fi

# 3. 备份旧数据(以防万一)
echo "2. 正在备份当前旧数据至 karakeep_old_backup..."
cd $BASE_DIR
rm -rf karakeep_old_backup
mv $PROJECT_DIR karakeep_old_backup

# 4. 解压新数据
echo "3. 正在解压新备份数据..."
tar -xzvf $LATEST_BACKUP

# 5. 启动服务
echo "4. 正在启动更新后的服务..."
cd $PROJECT_DIR
docker compose up -d

# 6. 清理
echo "5. 更新完成,正在清理..."
# 如果你希望保留压缩包,可以注释掉下面这行
# rm -f $BASE_DIR/$LATEST_BACKUP

echo "------------------------------------------------"
echo "KaraKeep 数据更新成功!"
echo "如果发现数据异常,旧数据存放在: $BASE_DIR/karakeep_old_backup"

1. 赋予权限:chmod +x update_karakeep.sh

2. 执行更新:./update_karakeep.sh

脚本逻辑说明:

安全第一:脚本使用 docker compose down 而不是 stop,确保容器和网络被彻底清理后再替换文件,避免文件占用导致解压失败。

双重保险(karakeep_old_backup):在解压新包之前,它会将你当前正在运行的文件夹重命名为 karakeep_old_backup。如果更新后发现新数据不对,你可以随时通过 mv 命令换回来。

自动识别:因为它使用了 ls -t | head -n 1,即使你目录下有好几个带不同时间戳的备份包,它也只会使用最新生成的那一个。

博主关闭了所有页面的评论