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;