跳转至

linkwarden

Docker

mkdir -p /data/wwwroot/docker/linkwarden/pgdata && mkdir -p /data/wwwroot/docker/linkwarden/data
nano docker-compose.yml
version: "3.5"

services:
  postgres:
    image: postgres:16-alpine
    container_name: linkwarden-postgres
    restart: always
    env_file: .env
    volumes:
      - /data/wwwroot/docker/linkwarden/pgdata:/var/lib/postgresql/data

  linkwarden:
    image: ghcr.io/linkwarden/linkwarden:latest
    container_name: linkwarden
    restart: unless-stopped
    env_file: .env
    environment:
      - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres
    volumes:
      - /data/wwwroot/docker/linkwarden/data:/data/data
    ports:
      - "23510:3000"
    depends_on:
      - postgres
# Linkwarden 访问地址,按你实际域名/端口改
NEXTAUTH_URL=http://127.0.0.1:23510
# 任意随机字符串,用于加密 Session
NEXTAUTH_SECRET=自己生成的一串随机字符串
# Postgres 超级用户密码
POSTGRES_PASSWORD=postgresql://postgres:你的密码@localhost:5432/linkwarden
# 域名
NEXTAUTH_URL=https://example.com
# 是否注册
NEXT_PUBLIC_DISABLE_REGISTRATION=true

Debian13安装

基础环境

# 安装 Node.js
apt install nodejs npm -y
node -v
npm -v
# 用 npm 安装 Yarn
npm install -g yarn

获取源码与依赖

git clone https://github.com/linkwarden/linkwarden.git
cd linkwarden

yarn    # 安装项目依赖

配置环境变量(.env)

cp .env.sample .env
nano .env

# Linkwarden 访问地址,按你实际域名/端口改
NEXTAUTH_URL=http://127.0.0.1:3000
# 任意随机字符串,用于加密 Session
NEXTAUTH_SECRET=自己生成的一串随机字符串
# Postgres 超级用户密码
POSTGRES_PASSWORD=postgresql://postgres:你的密码@localhost:5432/linkwarden

配置AI

# 一键安装 (推荐)
curl -fsSL https://ollama.com/install.sh | sh
# 查看服务状态
systemctl status ollama
# 查看版本
ollama --version
# 配置监听地址 并且想让 LinkWarden(Docker 容器)或其他机器访问它,必须修改监听地址
# OLLAMA_HOST=0.0.0.0:允许任何 IP 访问(如果在公网,请务必配合防火墙使用)。
# OLLAMA_ORIGINS=*:解决跨域问题(LinkWarden 可能会用到)。
[Service]
Environment="OLLAMA_HOST=0.0.0.0"
Environment="OLLAMA_ORIGINS=*"
# 重启服务生效
systemctl daemon-reload
systemctl restart ollama
# 升级 Ollama 直接再次运行上面的安装脚本 
# 模型选择
# Ollama 默认会自动下载 4-bit 量化 (q4_0) 的模型,这是性能与体积的最佳平衡点。
# 核心公式 (简单估算)
# 对于 4-bit 量化的模型,你可以用这个简单的公式来估算内存需求:
# 显存/内存需求 (GB) ≈ 模型参数量 (B) × 0.7 + 上下文开销
# (例如:7B 的模型,大约需要 7 × 0.7 ≈ 5GB + 少量系统开销)
ollama pull llama3.2
ollama list
# 拉取 1.5B 版本
ollama pull qwen2.5:1.5b
# 修改 LinkWarden 的 .env 文件:
# 必须带上 :1.5b 这个标签,否则默认是 7b
OLLAMA_MODEL=qwen2.5:1.5b
# 拉取 3B 版本
ollama pull qwen2.5:3b
# 别名
ollama cp qwen2.5:3b qwen3b
# 查看实际模型占用
du -sh /usr/share/ollama/.ollama/models

安装Monolith

Monolith 是一个强大的命令行工具,用于将网页及其所有资源(CSS、图片、JS)打包成单一的 HTML 文件。LinkWarden 依赖它来生成“Single HTML”格式的离线快照(比 PDF 更还原网页交互)。

# 下载 Linux x86_64 版本的 monolith
wget https://github.com/Y2Z/monolith/releases/download/v2.8.3/monolith-gnu-linux-x86_64 -O monolith
# 赋予执行权限
chmod +x monolith
# 移动到系统路径
mv monolith /usr/local/bin/
# 验证安装
monolith --version
# 应该输出类似: monolith 2.8.3
# 确保你安装了 Rust/Cargo 环境
# 如果没有:curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
cargo -v

# 强制从 Linkwarden 的仓库安装特定的分支
cargo install --git https://github.com/linkwarden/monolith --force
# 找到编译好的文件(通常在 ~/.cargo/bin/monolith)
sudo cp ~/.cargo/bin/monolith /usr/local/bin/
# 赋予执行权限
sudo chmod +x /usr/local/bin/monolith
# 重启 Linkwarden 服务
sudo systemctl restart Linkwarden # 替换为你的实际服务名

初始化数据库与构建

# 生成 Prisma 客户端
yarn prisma:generate
# 构建前端
NODE_OPTIONS="--max-old-space-size=4096" yarn web:build
# 执行数据库迁移
yarn prisma:deploy       

启动服务

开发/测试阶段可以直接:yarn concurrently:start

用 systemd 守护

which yarn 
systemctl daemon-reload
systemctl restart linkwarden
systemctl status linkwarden

nano /etc/systemd/system/linkwarden.service

[Unit]
Description=Linkwarden
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/data/wwwroot/linkwarden
Environment=NODE_ENV=production
Environment=NODE_OPTIONS=--max-old-space-size=2048
ExecStart=/usr/local/bin/yarn concurrently:start
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

排查错误

journalctl -u linkwarden -n 50 --no-pager
journalctl -u linkwarden -f -n 100
journalctl -u v2ray -f -n 100

数据备份

#!/usr/bin/env bash
set -euo pipefail

SERVICE_NAME="linkwarden"
STOP_TIMEOUT=60   # 最长等待服务停止的秒数

# ==== 自定义配置 ====
DB_NAME="linkwarden"
DB_HOST="localhost"
DB_PORT="5432"

DATA_DIR="/data/wwwroot/linkwarden/data"
BACKUP_DIR="/data/backup/linkwarden"
RETENTION_DAYS=7   # 保留天数

# ==== 不建议改动下面 ====
DATE_STR="$(date +%Y%m%d-%H%M%S)"
DB_BACKUP_FILE="${BACKUP_DIR}/db-${DATE_STR}.sql.gz"
DATA_BACKUP_FILE="${BACKUP_DIR}/data-${DATE_STR}.tar.gz"

mkdir -p "${BACKUP_DIR}"

echo "[$(date)] Stopping ${SERVICE_NAME} service..."
if systemctl is-active --quiet "${SERVICE_NAME}"; then
  systemctl stop "${SERVICE_NAME}"

  # 等待服务完全停止
  SECS_WAITED=0
  while systemctl is-active --quiet "${SERVICE_NAME}"; do
    if [ "${SECS_WAITED}" -ge "${STOP_TIMEOUT}" ]; then
      echo "[$(date)] ERROR: ${SERVICE_NAME} did not stop within ${STOP_TIMEOUT}s, aborting backup."
      exit 1
    fi
    sleep 1
    SECS_WAITED=$((SECS_WAITED + 1))
  done
  echo "[$(date)] ${SERVICE_NAME} stopped."
else
  echo "[$(date)] ${SERVICE_NAME} is not active, skip stopping."
fi

echo "[$(date)] Start Linkwarden backup..."

# 1. 备份 Postgres 数据库
echo "[$(date)] Dumping database ${DB_NAME} ..."
sudo -u postgres pg_dump "${DB_NAME}" \
  | gzip > "${DB_BACKUP_FILE}"

echo "[$(date)] Database backup saved to ${DB_BACKUP_FILE}"

# 2. 备份数据目录
if [ -d "${DATA_DIR}" ]; then
  echo "[$(date)] Archiving data dir ${DATA_DIR} ..."
  tar -czf "${DATA_BACKUP_FILE}" -C "$(dirname "${DATA_DIR}")" "$(basename "${DATA_DIR}")"
  echo "[$(date)] Data backup saved to ${DATA_BACKUP_FILE}"
else
  echo "[$(date)] WARNING: DATA_DIR ${DATA_DIR} not found, skip data backup."
fi

# 3. 清理过期备份
echo "[$(date)] Cleaning backups older than ${RETENTION_DAYS} days..."
find "${BACKUP_DIR}" -type f -mtime +${RETENTION_DAYS} -delete

echo "[$(date)] Starting ${SERVICE_NAME} service..."
systemctl start "${SERVICE_NAME}"

echo "[$(date)] Backup finished."

恢复数据

# 以 postgres 超级用户执行
sudo -u postgres psql -c "DROP DATABASE linkwarden;"
sudo -u postgres psql -d linkwarden -f /path/to/backup.sql
sudo -u postgres psql
-- 创建数据库
CREATE DATABASE linkwarden OWNER linkwarden;