在 RockyLinux 8/9 服务器上部署 LinkStash,使用 Caddy 反向代理 + HTTPS。
# 一键安装:创建用户/目录、下载二进制+Web资源、配置systemd、安装Chromium
curl -fsSL https://raw.githubusercontent.com/lupguo/linkstash/main/INSTALL.sh | sudo bash
# 填入 LLM API Key
sudo vim /opt/linkstash/.env
# 启动服务
sudo systemctl start linkstash
# 验证
curl -s http://127.0.0.1:8085/health安装完成后只需配置 Caddy 反向代理(见下方第三节)即可对外提供 HTTPS 服务。
以下为手动安装步骤(了解细节或排查问题时参考)。
| 项目 | 要求 |
|---|---|
| 操作系统 | RockyLinux 8+ / AlmaLinux 8+ / CentOS Stream 8+ |
| 域名 | linkstash.sapaude.tech 已解析到服务器公网 IP |
| 端口 | 80(HTTP)、443(HTTPS) |
| 内存 | ≥ 1GB(Chromium headless 需要额外内存) |
| 依赖 | Chromium(URL 自动分析用) |
# 创建专用用户
sudo useradd -r -s /sbin/nologin linkstash
# 创建安装目录
sudo mkdir -p /opt/linkstash/{bin,conf,data,logs,web}
sudo chown -R linkstash:linkstash /opt/linkstash方式 A:从 Release 下载
VERSION="v0.1.0" # 替换为最新版本
REPO="lupguo/linkstash"
# 下载 server 和 CLI
curl -fsSL "https://github.com/${REPO}/releases/download/${VERSION}/linkstash-server-linux-amd64" \
-o /opt/linkstash/bin/linkstash-server
curl -fsSL "https://github.com/${REPO}/releases/download/${VERSION}/linkstash-linux-amd64" \
-o /opt/linkstash/bin/linkstash
chmod +x /opt/linkstash/bin/linkstash-server /opt/linkstash/bin/linkstash方式 B:从源码编译
# 需要 Go 1.25+、make、esbuild、tailwindcss
git clone https://github.com/lupguo/linkstash.git /tmp/linkstash-build
cd /tmp/linkstash-build
make release
# 复制二进制
sudo cp bin/release/linkstash-server-linux-amd64 /opt/linkstash/bin/linkstash-server
sudo cp bin/release/linkstash-linux-amd64 /opt/linkstash/bin/linkstash
# 复制 web 资源(模板 + 静态文件)
sudo cp -r web/templates web/components web/static /opt/linkstash/web/
# 复制配置模板
sudo cp conf/app_prod.yaml /opt/linkstash/conf/app_prod.yamlLinkStash 使用 rod 驱动 headless Chromium 抓取网页内容,供 LLM 分析。
# RockyLinux 8/9
sudo dnf install -y chromium
# 验证
chromium-browser --version如果 chromium 包不可用:
# 使用 EPEL
sudo dnf install -y epel-release
sudo dnf install -y chromium在
app_prod.yaml中配置browser.bin_path指向实际路径:browser: enabled: true bin_path: "/usr/bin/chromium-browser" # 留空则自动下载 headless: true timeout_sec: 30
/opt/linkstash/
├── bin/
│ ├── linkstash-server # 主服务
│ └── linkstash # CLI 工具
├── conf/
│ └── app_prod.yaml # 生产配置
├── data/
│ ├── linkstash.db # SQLite 数据库(自动生成)
│ └── linkstash.bleve/ # Bleve 全文搜索索引(自动生成)
├── logs/
│ └── app.log # 应用日志
└── web/
├── templates/ # Go HTML 模板
├── components/ # 共享模板组件
└── static/ # CSS/JS/图片
sudo -u linkstash vim /opt/linkstash/conf/app_prod.yamlserver:
host: 127.0.0.1 # 仅本地监听,通过 Caddy 反向代理
port: 8085
auth:
secret_key: "替换为强随机字符串" # 登录密钥
jwt_secret: "替换为另一个强随机字符串" # JWT 签名密钥
jwt_expire_hours: 72
database:
path: "./data/linkstash.db"
log:
level: "info"
file: "./logs/app.log"
format: "text"
short:
ttl_options:
- label: "永久"
value: ""
- label: "7 天"
value: "7d"
- label: "30 天"
value: "30d"
- label: "1 年"
value: "365d"
# LLM 配置 — 用于 URL 自动分析(标题/摘要/分类/标签)
# 方式 A:OpenRouter(推荐,支持多模型切换)
llm:
chat:
provider: "openrouter"
endpoint: "https://openrouter.ai/api/v1/chat/completions"
api_key: "${OPENROUTER_API_KEY}"
model: "minimax/minimax-m2.5"
embedding:
provider: "openrouter"
endpoint: "https://openrouter.ai/api/v1/embeddings"
api_key: "${OPENROUTER_API_KEY}"
model: "qwen/qwen3-embedding-8b"
dimensions: 512
prompts:
url_analysis: |
分析以下网页内容,返回JSON格式:
{"title":"标题","keywords":"关键词1,关键词2","description":"50字内摘要","category":"分类","tags":"标签1,标签2"}
category必须从以下选项中选择:技术、设计、产品、商业、科学、生活、工具、资讯、其他
tags基于内容自由生成,用逗号分隔,2-5个标签。
仅返回JSON,不要其他内容。
# 方式 B:OpenAI 直连
# llm:
# chat:
# endpoint: "https://api.openai.com/v1/chat/completions"
# api_key: "${OPENAI_API_KEY}"
# model: "gpt-4o-mini"
# embedding:
# endpoint: "https://api.openai.com/v1/embeddings"
# api_key: "${OPENAI_API_KEY}"
# model: "text-embedding-3-small"
# dimensions: 512
categories:
- "技术"
- "设计"
- "产品"
- "商业"
- "科学"
- "生活"
- "工具"
- "资讯"
- "其他"
browser:
enabled: true
bin_path: "/usr/bin/chromium-browser"
headless: true
timeout_sec: 30
# 可选:代理(服务器无法直接访问外网时)
# proxy:
# http_proxy: "http://127.0.0.1:8118"
⚠️ 安全提示:secret_key和jwt_secret必须替换为强随机字符串。可用openssl rand -hex 32生成。
sudo vim /opt/linkstash/.env# LLM API Key(二选一)
OPENROUTER_API_KEY=sk-or-your-api-key-here
# OPENAI_API_KEY=sk-your-api-key-here
# 可选:代理
# HTTP_PROXY=http://127.0.0.1:8118
# HTTPS_PROXY=http://127.0.0.1:8118# 仅 linkstash 用户可读
sudo chown linkstash:linkstash /opt/linkstash/.env
sudo chmod 600 /opt/linkstash/.envsudo vim /etc/systemd/system/linkstash.service[Unit]
Description=LinkStash - Bookmark Management Service
After=network.target
[Service]
Type=simple
User=linkstash
Group=linkstash
WorkingDirectory=/opt/linkstash
ExecStart=/opt/linkstash/bin/linkstash-server -conf /opt/linkstash/conf/app_prod.yaml
EnvironmentFile=/opt/linkstash/.env
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
# 安全加固
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/linkstash/data /opt/linkstash/logs
[Install]
WantedBy=multi-user.target注意
ReadWritePaths包含logs目录,否则日志写入会被ProtectSystem=strict阻止。
sudo systemctl daemon-reload
sudo systemctl enable --now linkstash
sudo systemctl status linkstash# 健康检查
curl -s http://127.0.0.1:8085/health
# 期望输出: {"status":"ok"}
# 查看日志
journalctl -u linkstash -fsudo dnf install -y 'dnf-command(copr)'
sudo dnf copr enable -y @caddy/caddy
sudo dnf install -y caddy如果 copr 不可用:
sudo curl -fsSL "https://caddyserver.com/api/download?os=linux&arch=amd64" -o /usr/bin/caddy
sudo chmod +x /usr/bin/caddy
sudo groupadd --system caddy 2>/dev/null
sudo useradd --system --gid caddy --create-home --home-dir /var/lib/caddy --shell /usr/sbin/nologin caddy 2>/dev/nullsudo vim /etc/caddy/Caddyfilelinkstash.sapaude.tech {
reverse_proxy 127.0.0.1:8085
encode gzip zstd
log {
output file /var/log/caddy/linkstash.log
format json
}
}Caddy 自动申请 Let's Encrypt 证书,自动处理 HTTP → HTTPS 重定向。
sudo mkdir -p /var/log/caddy
sudo chown caddy:caddy /var/log/caddy
sudo systemctl enable --now caddy
sudo systemctl status caddy# firewalld
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-services同时在腾讯云控制台的安全组中开放入站 80 和 443 端口。
在腾讯云 DNS 控制台添加:
| 类型 | 主机记录 | 记录值 | TTL |
|---|---|---|---|
| A | linkstash | <服务器公网 IP> |
600 |
# 本地
curl -s http://127.0.0.1:8085/health
# 外网
curl -I https://linkstash.sapaude.tech浏览器访问 https://linkstash.sapaude.tech 确认:
- ✅ HTTPS 证书有效(🔒)
- ✅ 登录页正常显示
- ✅ 登录后首页卡片列表渲染
- ✅ 无限滚动加载正常
- ✅ 搜索功能正常
journalctl -u linkstash -f # 实时日志
journalctl -u linkstash -n 100 # 最近 100 条
journalctl -u caddy -f # Caddy 日志
tail -f /opt/linkstash/logs/app.log # 应用日志文件# 手动备份
sudo -u linkstash cp /opt/linkstash/data/linkstash.db \
/opt/linkstash/data/linkstash.db.bak.$(date +%Y%m%d)
# 定时备份(每天凌晨 3 点)
echo '0 3 * * * cp /opt/linkstash/data/linkstash.db /opt/linkstash/data/linkstash.db.bak.$(date +\%Y\%m\%d)' \
| sudo crontab -u linkstash -# 1. 备份
sudo -u linkstash cp /opt/linkstash/data/linkstash.db /opt/linkstash/data/linkstash.db.bak
# 2. 下载新版本
VERSION="v0.2.0"
sudo curl -fsSL "https://github.com/lupguo/linkstash/releases/download/${VERSION}/linkstash-server-linux-amd64" \
-o /opt/linkstash/bin/linkstash-server
sudo chmod +x /opt/linkstash/bin/linkstash-server
sudo chown linkstash:linkstash /opt/linkstash/bin/linkstash-server
# 3. 重启
sudo systemctl restart linkstash
sudo systemctl status linkstash
curl -s http://127.0.0.1:8085/health| 问题 | 排查方法 |
|---|---|
| 服务启动失败 | journalctl -u linkstash -n 50 查看错误 |
| 端口未监听 | ss -tlnp | grep 8085 |
| Caddy 证书失败 | 确认域名解析正确 + 80/443 端口开放 |
| 502 Bad Gateway | 确认 LinkStash 服务正在运行 |
| URL 分析失败 | 检查 Chromium 安装 + LLM API Key 配置 |
| 搜索无结果 | 检查 data/linkstash.bleve/ 索引目录是否存在 |
| 日志写入失败 | 检查 systemd ReadWritePaths 是否包含 logs 目录 |
| 数据库锁定 | 确认只有一个进程访问 SQLite 文件 |