[{"content":"BrowserSkill Windows 安装与使用指南 适用环境：Windows、Chrome/Edge、Codex 等支持 Agent Skill 的工具\n本机配置：Chrome + Codex，BrowserSkill 0.3.2，固定端口 53000\n1. BrowserSkill 是什么 BrowserSkill 让 AI Agent 通过浏览器扩展控制一个独立的 Agent 窗口，可以打开网页、读取页面、点击按钮、填写表单和执行其他浏览器操作。\n本地模式包含三部分：\nAgent Skill：告诉 Codex 应该如何安全地操作浏览器。 bsk CLI 与后台服务：接收 Agent 命令，并在本机监听浏览器扩展连接。 Chrome/Edge 扩展：在浏览器中执行实际操作。 三部分都准备好后，才能正常使用。\n2. 本机最终配置 这台电脑采用以下配置：\n项目 配置 bsk 版本 0.3.2 bsk.exe 路径 C:\\Users\\gujian\\.local\\bin\\bsk.exe Agent Codex Skill 目录 C:\\Users\\gujian\\.agents\\skills\\browser-skill 浏览器 Chrome 连接方式 Local connection（本地连接） 服务端口 53000 BrowserSkill 默认使用 52800。但这台电脑的 Windows 保留端口范围包含 52800，会导致服务启动时报错：\n1 2 以一种访问权限不允许的方式做了一个访问套接字的尝试。 (os error 10013) 因此，浏览器插件和后台服务必须同时使用 53000。\n3. 全新安装 如果当前电脑已经安装完成，可以直接跳到“长期自动运行配置”。\n3.1 安装 bsk CLI 打开 PowerShell，执行：\n1 irm https://raw.githubusercontent.com/Tencent/BrowserSkill/main/install.ps1 | iex 确认安装成功：\n1 bsk --version 正常情况下会输出类似：\n1 bsk 0.3.2 如果提示找不到 bsk，请关闭并重新打开 PowerShell，然后重试。也可以直接使用完整路径：\n1 \u0026amp; \u0026#39;C:\\Users\\gujian\\.local\\bin\\bsk.exe\u0026#39; --version 3.2 为 Codex 安装 browser-skill 先查看支持的 Agent：\n1 bsk install-skill --list --json 为 Codex 安装：\n1 bsk install-skill --harness codex --json 安装完成后，技能通常位于：\n1 C:\\Users\\gujian\\.agents\\skills\\browser-skill 如果当前 Codex 对话是在安装前打开的，请新建一个对话，让 Codex 重新发现该技能。\n3.3 安装浏览器扩展 Chrome：BrowserSkill - Chrome Web Store Edge：BrowserSkill - Microsoft Edge Add-ons 安装后，建议将扩展固定到浏览器工具栏，方便查看连接状态。\n3.4 配置扩展端口 点击浏览器工具栏中的 BrowserSkill 图标。 选择 Local connection。 将端口设置为 53000。 保存并启用连接。 端口必须与后台服务完全一致。如果插件设置为 53000，后台服务也必须在 53000 上启动。\n4. 首次手动启动与验证 4.1 启动服务 在普通 PowerShell 中执行：\n1 bsk daemon start --port 53000 如果需要让当前终端直接托管服务，则使用：\n1 bsk daemon start --foreground --port 53000 使用 --foreground 时不要关闭该终端；关闭终端会结束服务。\n4.2 检查状态 1 bsk status --json 重点检查：\nws_port 为 53000； browsers 中能看到 chrome 或 edge； unresponsive 为 false； CLI 与扩展没有版本不兼容提示。 进一步诊断：\n1 bsk doctor 理想结果是没有 FAIL。如果只有 extension connected 失败，通常是浏览器没有打开、扩展没有启用，或插件端口与服务端口不一致。\n4.3 禁止自动回退到旧端口 BrowserSkill 在找不到服务时默认会尝试自动启动，而自动启动仍可能使用默认端口 52800。在这台电脑上建议永久禁用隐式自动启动：\n1 [Environment]::SetEnvironmentVariable(\u0026#39;BSK_AUTO_START\u0026#39;, \u0026#39;0\u0026#39;, \u0026#39;User\u0026#39;) 设置后需要重新打开 PowerShell 和 Codex 才能让新环境变量生效。\n此设置的效果是：\n不会再偷偷尝试 52800； 已运行在 53000 的服务仍可正常使用； 如果服务没有启动，命令会直接报错，提醒先启动服务。 5. 长期自动运行配置（推荐） 最稳妥的方法是创建一个 Windows 计划任务，让 BrowserSkill 在用户登录后自动启动，并固定使用 53000。\n5.1 打开任务计划程序 按 Win + R。 输入 taskschd.msc，按回车。 在右侧点击“创建任务”，不要选择功能较少的“创建基本任务”。 5.2 常规设置 名称：BrowserSkill Daemon 选择“仅当用户登录时运行”。 可勾选“隐藏”。 不需要勾选“使用最高权限运行”。 5.3 触发器 新建触发器：\n开始任务：登录时； 指定当前用户； 启用该触发器。 5.4 操作 新建“启动程序”操作：\n程序或脚本：\n1 C:\\Users\\gujian\\.local\\bin\\bsk.exe 添加参数：\n1 daemon start --foreground --port 53000 --daemon-idle 8760h 参数含义：\n--foreground：让计划任务直接托管后台服务； --port 53000：固定使用插件已经保存的端口； --daemon-idle 8760h：将无连接空闲时间延长到约一年，避免关闭浏览器一段时间后服务自动退出。 5.5 条件和设置 建议：\n取消“仅在计算机使用交流电源时才启动此任务”； 勾选“错过计划开始时间后尽快启动”； “如果任务已在运行”选择“不启动新实例”； 取消“如果任务运行时间超过以下时间，则停止任务”。 保存任务后，在任务列表中右键 BrowserSkill Daemon，选择“运行”。然后执行：\n1 bsk status --json 如果看到 ws_port: 53000 且浏览器出现在 browsers 列表中，长期运行配置即完成。\n以后重新登录 Windows 时，服务会自动启动，不需要再手动输入命令。\n6. 在 Codex 中使用 6.1 最简单的用法 在 Codex 中直接说：\n1 $browser-skill 帮我打开 GitHub 也可以使用自然语言：\n1 使用 browser-skill 打开 GitHub，并告诉我当前登录的首页有哪些主要内容。 更多示例：\n1 $browser-skill 打开指定网页并总结内容。 1 $browser-skill 在 GitHub 中搜索某个仓库。 1 $browser-skill 检查这个网站的表单是否能正常提交，但不要进行最终提交。 6.2 正常工作过程 BrowserSkill 通常会：\n创建独立的 Agent Window； 在其中打开目标网页； 读取页面后再进行点击或输入； 完成任务后停止自己的自动化会话； 保留已经打开的普通浏览器页面。 插件可能根据“Automation settings”要求你确认借用现有标签页、登录、验证码或重要操作。不要关闭这些确认功能来绕过安全检查。\n7. 手动使用 CLI 通常不需要手动操作 CLI；以下命令主要用于排错和测试。\n7.1 创建会话 1 2 $env:BSK_AUTO_START = \u0026#39;0\u0026#39; bsk session start --json 记录输出中的 session_id，例如 abcd。\n7.2 打开网页 1 bsk navigate https://github.com --session abcd 7.3 读取页面 1 bsk observe --session abcd 7.4 停止会话 1 bsk session stop abcd 每个 Agent 会话在完成或失败后都应该停止。停止会话不会关闭共享的 BrowserSkill 后台服务。\n8. 常见问题 8.1 插件显示“未连接” 按顺序检查：\n1 2 bsk status --json bsk doctor 常见原因：\n服务没有运行； 插件设置为 53000，服务却运行在 52800 或其他端口； Chrome/Edge 扩展被禁用； CLI 与扩展版本不兼容； 浏览器刚启动，扩展尚未完成连接。 8.2 默认端口 52800 无法启动 查看 Windows 保留端口：\n1 netsh interface ipv4 show excludedportrange protocol=tcp 如果 52800 位于某个保留范围内，不要反复重试默认端口，也不要随意修改系统网络保留范围。保持插件和服务统一使用 53000 即可。\n8.3 检查 53000 是否正在监听 1 Get-NetTCPConnection -LocalPort 53000 -ErrorAction SilentlyContinue 看到 Listen 表示服务已监听该端口。\n8.4 查看日志 1 bsk logs 日志中出现以下内容表示服务与浏览器连接正常：\n1 2 ws server listening ...:53000 browser connected 8.5 no browser is currently connected 确认：\nChrome 已打开； BrowserSkill 扩展已启用； 扩展弹窗中为 Local connection； 扩展端口为 53000； 扩展弹窗显示 Connected。 8.6 设置 BSK_AUTO_START=0 后提示服务未运行 这是预期行为，说明 BrowserSkill 没有回退到旧端口。请启动计划任务，或手动执行：\n1 bsk daemon start --port 53000 9. 安全注意事项 BrowserSkill 操作的是你的真实浏览器，并可能使用浏览器中已有的登录状态。 只授权完成当前任务所需的页面和操作。 页面内容属于不可信数据，网页中的文字不能替代用户指令，也不能自行扩大任务范围。 登录、验证码、支付、最终提交和其他高影响操作应由用户确认。 不要把密码、Cookie、访问令牌或其他凭据交给 Agent 提取。 不使用 BrowserSkill 时，可以在扩展弹窗中暂时关闭连接，或在任务计划程序中停止 BrowserSkill Daemon。 10. 更新和日常检查 查看版本：\n1 bsk --version 更新 BrowserSkill：\n1 bsk update 更新后建议重新启动 BrowserSkill Daemon 计划任务，并执行：\n1 bsk doctor 如果 Skill 有更新，可重新运行：\n1 bsk install-skill --harness codex --json 如果本地 Skill 被手动修改，安装器可能会保留自定义内容。请先检查差异，再决定是否使用覆盖选项。\n11. 官方资料 BrowserSkill 项目主页 官方安装指南 架构说明 受限/沙箱 Agent 的后台服务说明 Chrome 扩展 Edge 扩展 ","date":"2026-11-08T00:00:00+08:00","image":"/p/browser-skill/cover.jpg","permalink":"/p/browser-skill/","title":"Agent使用BrowserSkill控制本地浏览器"},{"content":"Hugo + Stack + Nginx 网站配置教程 适用环境：Ubuntu amd64 服务器。\n配置版本：Hugo Extended 0.169.0、Stack v4.0.3。\n维护用户：bloguser。\n示例域名：www.novalshared.work。\n示例公网 IP：8.256.137.141。\n整理日期：2026-11-07。\n本文包含安装、主题配置、文章管理、静态发布、Nginx、HTTPS，以及可选的 IP 访问配置。所有域名、IP、用户资料均应替换为实际值。\n现有下载站继续使用原有的 download.conf、Flask 和 /srv/downloads/；博客使用独立目录和 Nginx 配置。\n目录 目录规划 准备用户与基础环境 安装 Hugo Extended 创建项目并安装 Stack 配置 hugo.toml 创建文章与图片 创建归档、搜索与关于页面 配置头像与自定义样式 通过 SSH 预览 配置正式发布 配置 Nginx HTTP 站点 配置域名与 HTTPS 配置证书自动续期 更新网站内容 可选：配置公网 IP 访问 可选：移除 IP 访问配置 版本管理与备份 最终目录结构 1. 目录规划 用途 路径 博客源项目 /home/bloguser/sites/personal-blog-stack/ Hugo 配置文件 /home/bloguser/sites/personal-blog-stack/hugo.toml 文章目录 /home/bloguser/sites/personal-blog-stack/content/post/ 独立页面目录 /home/bloguser/sites/personal-blog-stack/content/page/ Stack 主题目录 /home/bloguser/sites/personal-blog-stack/themes/hugo-theme-stack/ 正式静态网页 /var/www/personal-blog/ 证书验证目录 /var/www/certbot/ 博客 Nginx 配置 /etc/nginx/conf.d/blog.conf 原下载站 Nginx 配置 /etc/nginx/conf.d/download.conf 源文件由普通用户维护，Nginx 只读取正式发布目录中的静态网页。\n2. 准备用户与基础环境 2.1 创建维护用户 如果尚未创建 bloguser，使用 root 或管理员账号执行：\n1 sudo adduser bloguser 根据提示设置密码和用户信息。\n如果该用户需要负责软件安装、Nginx 和证书管理，管理员执行：\n1 sudo usermod -aG sudo bloguser 使用 root 直接操作时，省略命令开头的 sudo。组权限调整后，重新登录 bloguser。\n如果不授予该用户管理权限，本文带 sudo 的步骤由管理员执行，其余步骤由 bloguser 执行。\n2.2 登录并确认环境 从自己的电脑登录服务器：\n1 ssh bloguser@8.256.137.141 确认账号、家目录和架构：\n1 2 3 whoami echo \u0026#34;$HOME\u0026#34; dpkg --print-architecture 对应结果应为 bloguser、/home/bloguser 和 amd64。\n2.3 安装基础工具 1 2 sudo apt update sudo apt install -y ca-certificates curl git rsync nano 如果服务器尚未安装 Nginx：\n1 2 sudo apt install -y nginx sudo systemctl enable --now nginx 检查 Nginx 配置：\n1 sudo nginx -t 3. 安装 Hugo Extended 本文使用官方提供的 Linux amd64 Extended deb 包。\n3.1 下载软件包 以 bloguser 执行：\n1 2 3 4 5 6 mkdir -p /home/bloguser/packages cd /home/bloguser/packages curl -fL \\ https://github.com/gohugoio/hugo/releases/download/v0.169.0/hugo_extended_0.169.0_linux-amd64.deb \\ -o hugo_extended_0.169.0_linux-amd64.deb 3.2 校验安装包 1 2 echo \u0026#34;a20f7da84e0981bebbecc032cc87f0dda2049a844727720aab14e61ce416e5e9 hugo_extended_0.169.0_linux-amd64.deb\u0026#34; \\ | sha256sum -c - 校验结果应为 OK。\n3.3 安装 1 2 3 4 sudo cp hugo_extended_0.169.0_linux-amd64.deb /tmp/ sudo chmod 644 /tmp/hugo_extended_0.169.0_linux-amd64.deb sudo apt install -y /tmp/hugo_extended_0.169.0_linux-amd64.deb hash -r 3.4 确认版本 1 2 command -v hugo hugo version 版本信息应包含 v0.169.0、extended 和 linux/amd64。后续使用普通用户运行 Hugo。\n4. 创建项目并安装 Stack 以下命令以 bloguser 执行。\n4.1 创建项目 1 2 3 4 5 6 7 mkdir -p /home/bloguser/sites cd /home/bloguser/sites hugo new project personal-blog-stack cd personal-blog-stack mkdir -p content/post content/page 4.2 安装主题并固定版本 1 2 3 4 5 6 7 git init git submodule add \\ https://github.com/CaiJimmy/hugo-theme-stack.git \\ themes/hugo-theme-stack git -C themes/hugo-theme-stack checkout v4.0.3 确认主题版本：\n1 git -C themes/hugo-theme-stack describe --tags --exact-match 输出应为 v4.0.3。\n本教程使用 Git 子模块方式安装主题，无需配置 Hugo Modules 或额外安装 Go。\n5. 配置 hugo.toml 编辑：\n1 nano /home/bloguser/sites/personal-blog-stack/hugo.toml 将文件内容整体替换为：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 # 网站基本信息 baseURL = \u0026#34;https://www.novalshared.work/\u0026#34; title = \u0026#34;我的个人技术博客\u0026#34; theme = \u0026#34;hugo-theme-stack\u0026#34; locale = \u0026#34;zh\u0026#34; defaultContentLanguage = \u0026#34;zh\u0026#34; hasCJKLanguage = true timeZone = \u0026#34;Asia/Shanghai\u0026#34; enableRobotsTXT = true # 分页 [pagination] pagerSize = 10 # 分类与标签 [taxonomies] category = \u0026#34;categories\u0026#34; tag = \u0026#34;tags\u0026#34; # 页面地址 [permalinks] post = \u0026#34;/p/:slug/\u0026#34; page = \u0026#34;/:slug/\u0026#34; # 代码高亮与目录 [markup.highlight] noClasses = false codeFences = true guessSyntax = false lineNos = true lineNumbersInTable = true tabWidth = 4 [markup.tableOfContents] startLevel = 2 endLevel = 4 ordered = false # 首页导航 [[menus.main]] name = \u0026#34;首页\u0026#34; url = \u0026#34;/\u0026#34; weight = 10 [menus.main.params] icon = \u0026#34;home\u0026#34; # Stack 参数 [params] mainSections = [\u0026#34;post\u0026#34;] rssFullContent = true [params.footer] since = 2026 customText = \u0026#34;\u0026#34; [params.dateFormat] published = \u0026#34;2006-01-02\u0026#34; lastUpdated = \u0026#34;2006-01-02\u0026#34; [params.sidebar] compact = false subtitle = \u0026#34;记录 Linux 运维、编程学习与个人实践\u0026#34; avatar = \u0026#34;\u0026#34; [params.article] headingAnchor = true math = false toc = true readingTime = true [params.article.list] showTags = true [params.article.license] enabled = false [params.comments] enabled = false [params.colorScheme] toggle = true default = \u0026#34;auto\u0026#34; [params.imageProcessing.content] enabled = true [params.imageProcessing.thumbnail] enabled = true # 首页右侧组件 [[params.widgets.homepage]] type = \u0026#34;search\u0026#34; [[params.widgets.homepage]] type = \u0026#34;archives\u0026#34; [params.widgets.homepage.params] limit = 5 [[params.widgets.homepage]] type = \u0026#34;categories\u0026#34; [params.widgets.homepage.params] limit = 10 [[params.widgets.homepage]] type = \u0026#34;tag-cloud\u0026#34; [params.widgets.homepage.params] limit = 20 # 文章右侧目录 [[params.widgets.page]] type = \u0026#34;toc\u0026#34; 配置约定：\nbaseURL 使用正式域名，保留末尾 /。 Stack v4 简体中文语言标识使用 zh。 文章统一存放在 content/post/，与 mainSections = [\u0026quot;post\u0026quot;] 对应。 头像尚未上传时，保留 avatar = \u0026quot;\u0026quot;。 所有字符串使用英文半角引号，配置文件使用 UTF-8 编码。 检查配置：\n1 2 cd /home/bloguser/sites/personal-blog-stack hugo config \u0026gt;/dev/null \u0026amp;\u0026amp; echo \u0026#34;配置解析成功\u0026#34; 6. 创建文章与图片 每篇文章使用独立文件夹，将正文与相关图片放在一起。\n6.1 创建第一篇文章 1 2 3 cd /home/bloguser/sites/personal-blog-stack hugo new content post/hello-stack/index.md nano content/post/hello-stack/index.md 将文件内容整体替换为：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 +++ title = \u0026#34;我的第一篇 Stack 博客文章\u0026#34; description = \u0026#34;记录使用 Hugo、Stack 和 Nginx 搭建博客的过程\u0026#34; date = 2026-11-07T10:00:00+08:00 slug = \u0026#34;hello-stack\u0026#34; draft = false categories = [\u0026#34;技术笔记\u0026#34;] tags = [\u0026#34;Hugo\u0026#34;, \u0026#34;Nginx\u0026#34;, \u0026#34;Linux\u0026#34;] toc = true +++ 欢迎来到我的个人博客。 ## 关于本站 本站使用 Hugo 生成静态网页，通过 Nginx 对外提供访问。 ## 记录内容 - Linux 运维实践 - Java 学习笔记 - 网站部署经验 - 个人项目开发 ## 接下来的计划 持续更新文章，记录学习与实践过程。 文章日期按实际发布时间填写。draft = false 表示正式文章，draft = true 表示草稿。\n6.2 添加封面 将封面图片放在：\n1 content/post/hello-stack/cover.jpg 在文章开头的 +++ 区域中添加：\n1 image = \u0026#34;cover.jpg\u0026#34; 6.3 添加正文图片 将图片放在同一文章目录：\n1 content/post/hello-stack/screenshot.png 在正文中引用：\n1 ![网站运行截图](screenshot.png) 对应结构：\n1 2 3 4 content/post/hello-stack/ ├── index.md ├── cover.jpg └── screenshot.png 图片引用使用资源路径，文件名大小写与实际文件保持一致。\n6.4 从 Windows 上传图片 在自己电脑的 PowerShell 中执行，替换本地图片路径：\n1 scp \u0026#34;C:\\Users\\你的用户名\\Pictures\\cover.jpg\u0026#34; bloguser@8.256.137.141:/home/bloguser/sites/personal-blog-stack/content/post/hello-stack/ 7. 创建归档、搜索与关于页面 7.1 创建目录 1 2 3 4 5 cd /home/bloguser/sites/personal-blog-stack mkdir -p content/page/archives mkdir -p content/page/search mkdir -p content/page/about 7.2 归档页面 编辑：\n1 nano content/page/archives/index.md 写入：\n1 2 3 4 5 6 7 8 9 10 11 +++ title = \u0026#34;归档\u0026#34; slug = \u0026#34;archives\u0026#34; layout = \u0026#34;archives\u0026#34; [menu.main] weight = 20 [menu.main.params] icon = \u0026#34;archives\u0026#34; +++ 7.3 搜索页面 编辑：\n1 nano content/page/search/index.md 写入：\n1 2 3 4 5 6 7 8 9 10 11 12 +++ title = \u0026#34;搜索\u0026#34; slug = \u0026#34;search\u0026#34; layout = \u0026#34;search\u0026#34; outputs = [\u0026#34;HTML\u0026#34;, \u0026#34;JSON\u0026#34;] [menu.main] weight = 30 [menu.main.params] icon = \u0026#34;search\u0026#34; +++ 7.4 关于页面 编辑：\n1 nano content/page/about/index.md 写入：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 +++ title = \u0026#34;关于\u0026#34; slug = \u0026#34;about\u0026#34; description = \u0026#34;关于这个博客\u0026#34; toc = false [menu.main] weight = 40 [menu.main.params] icon = \u0026#34;user\u0026#34; +++ ## 关于我 这里记录我的技术学习与实践。 ## 关于博客 使用 Hugo、Stack 和 Nginx 搭建。 主要分享 Linux 运维、编程学习和个人项目经验。 7.5 构建检查 1 2 3 4 5 6 7 8 hugo --minify ls -l public/index.html ls -l public/p/hello-stack/index.html ls -l public/archives/index.html ls -l public/search/index.html ls -l public/search/index.json ls -l public/about/index.html 8. 配置头像与自定义样式 8.1 头像 创建资源目录：\n1 mkdir -p /home/bloguser/sites/personal-blog-stack/assets/img 将头像上传为：\n1 assets/img/avatar.jpg 修改 hugo.toml 中现有的 [params.sidebar]：\n1 2 3 4 [params.sidebar] compact = false subtitle = \u0026#34;记录 Linux 运维、编程学习与个人实践\u0026#34; avatar = \u0026#34;img/avatar.jpg\u0026#34; 8.2 自定义样式 1 2 mkdir -p /home/bloguser/sites/personal-blog-stack/assets/scss nano /home/bloguser/sites/personal-blog-stack/assets/scss/custom.scss 例如设置正文行高：\n1 2 3 .article-content { line-height: 1.9; } 自定义样式放在项目的 assets/scss/custom.scss 中。\n9. 通过 SSH 预览 9.1 在 Windows 建立 SSH 隧道 在自己电脑的 PowerShell 中执行：\n1 ssh -L 1313:127.0.0.1:1313 bloguser@8.256.137.141 9.2 在该 SSH 会话启动 Hugo 1 2 3 4 5 6 7 8 cd /home/bloguser/sites/personal-blog-stack hugo server \\ -D \\ --bind 127.0.0.1 \\ --port 1313 \\ --baseURL http://localhost:1313/ \\ --appendPort=false 在自己电脑浏览器打开：\n1 http://localhost:1313/ 预览期间保持 SSH 会话和 Hugo 运行，结束时按 Ctrl + C。此方式不需要在云安全组开放 1313 端口。\n-D 包含草稿；正式发布时不使用该参数。\n10. 配置正式发布 10.1 创建发布目录 管理员执行：\n1 2 3 sudo mkdir -p /var/www/personal-blog sudo chown bloguser:bloguser /var/www/personal-blog sudo chmod 755 /var/www/personal-blog 该目录专用于博客。后面的同步操作会使其内容与构建结果一致，包括移除已下线的页面。\n10.2 创建发布脚本 以 bloguser 编辑：\n1 nano /home/bloguser/sites/personal-blog-stack/publish.sh 写入：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #!/usr/bin/env bash set -euo pipefail site_dir=\u0026#34;/home/bloguser/sites/personal-blog-stack\u0026#34; publish_dir=\u0026#34;/var/www/personal-blog\u0026#34; cd \u0026#34;$site_dir\u0026#34; # 使用全新目录生成本次发布文件 build_dir=\u0026#34;$(mktemp -d \u0026#34;$site_dir/.build.XXXXXXXX\u0026#34;)\u0026#34; cleanup() { case \u0026#34;$build_dir\u0026#34; in \u0026#34;$site_dir\u0026#34;/.build.*) if [ -d \u0026#34;$build_dir\u0026#34; ] \u0026amp;\u0026amp; [ ! -L \u0026#34;$build_dir\u0026#34; ]; then rm -r -- \u0026#34;$build_dir\u0026#34; fi ;; esac } trap cleanup EXIT echo \u0026#34;正在构建网站……\u0026#34; hugo \\ --environment production \\ --minify \\ --destination \u0026#34;$build_dir\u0026#34; test -s \u0026#34;$build_dir/index.html\u0026#34; test -s \u0026#34;$build_dir/search/index.json\u0026#34; if [ ! -d \u0026#34;$publish_dir\u0026#34; ] || [ ! -w \u0026#34;$publish_dir\u0026#34; ]; then echo \u0026#34;发布目录不存在或当前用户无写入权限：$publish_dir\u0026#34; exit 1 fi echo \u0026#34;正在同步网站……\u0026#34; rsync -av --delete \\ \u0026#34;$build_dir/\u0026#34; \\ \u0026#34;$publish_dir/\u0026#34; chmod -R a+rX \u0026#34;$publish_dir\u0026#34; echo \u0026#34;发布完成：https://www.novalshared.work/\u0026#34; 授予执行权限：\n1 chmod +x /home/bloguser/sites/personal-blog-stack/publish.sh 10.3 发布网站 1 2 cd /home/bloguser/sites/personal-blog-stack ./publish.sh 只更新文章或静态资源时，无需重新加载 Nginx。\n11. 配置 Nginx HTTP 站点 11.1 创建证书验证目录 1 2 sudo mkdir -p /var/www/certbot/.well-known/acme-challenge sudo chmod -R a+rX /var/www/certbot 11.2 创建独立博客配置 1 sudo nano /etc/nginx/conf.d/blog.conf 写入：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 server { listen 80; listen [::]:80; server_name www.novalshared.work; root /var/www/personal-blog; index index.html; charset utf-8; location ^~ /.well-known/acme-challenge/ { root /var/www/certbot; default_type text/plain; auth_basic off; allow all; try_files $uri =404; } location / { try_files $uri $uri/ =404; } location ~ /\\. { deny all; } error_page 404 /404.html; access_log /var/log/nginx/blog_access.log; error_log /var/log/nginx/blog_error.log; } 检查并加载：\n1 sudo nginx -t \u0026amp;\u0026amp; sudo systemctl reload nginx 11.3 测试虚拟主机 1 2 3 curl -I \\ -H \u0026#34;Host: www.novalshared.work\u0026#34; \\ http://127.0.0.1/ 预期返回 HTTP/1.1 200 OK。\n12. 配置域名与 HTTPS 12.1 配置 DNS 与公网端口 在域名 DNS 控制台添加：\n类型 主机记录 记录值 A www 8.256.137.141，替换为实际公网 IPv4 保留原有下载站记录。只有在服务器已配置可用 IPv6 时，才添加对应的 AAAA 记录。\n在云安全组和系统防火墙中允许博客所需的 TCP 80、443 端口，并保留现有 SSH 管理规则。\n确认解析：\n1 getent ahostsv4 www.novalshared.work 公网开放按服务器接入商的要求办理；HTTP 证书验证需要公网能够访问该站点。\n12.2 测试证书验证路径 创建测试文件：\n1 2 echo \u0026#34;acme-test\u0026#34; | sudo tee \\ /var/www/certbot/.well-known/acme-challenge/test.txt 在服务器测试：\n1 2 3 curl -i \\ -H \u0026#34;Host: www.novalshared.work\u0026#34; \\ http://127.0.0.1/.well-known/acme-challenge/test.txt 在自己的 Windows 电脑测试：\n1 curl.exe -i http://www.novalshared.work/.well-known/acme-challenge/test.txt 确认返回 200 OK，正文为 acme-test 后申请证书。\n12.3 安装 Certbot 1 sudo apt install -y certbot python3-certbot-nginx 12.4 申请证书 1 2 3 4 sudo certbot certonly \\ --webroot \\ -w /var/www/certbot \\ -d www.novalshared.work 按提示填写邮箱并接受服务条款。\n查看证书路径：\n1 sudo certbot certificates 下一步使用该命令返回的实际证书路径。以下配置以常见默认路径为例。\n12.5 配置完整 HTTPS 站点 编辑：\n1 sudo nano /etc/nginx/conf.d/blog.conf 将内容整体替换为：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 # HTTP：保留证书验证，其余请求跳转到 HTTPS server { listen 80; listen [::]:80; server_name www.novalshared.work; location ^~ /.well-known/acme-challenge/ { root /var/www/certbot; default_type text/plain; auth_basic off; allow all; try_files $uri =404; } location / { return 301 https://www.novalshared.work$request_uri; } access_log /var/log/nginx/blog_access.log; error_log /var/log/nginx/blog_error.log; } # HTTPS：提供静态博客 server { listen 443 ssl; listen [::]:443 ssl; server_name www.novalshared.work; ssl_certificate /etc/letsencrypt/live/www.novalshared.work/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.novalshared.work/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; root /var/www/personal-blog; index index.html; charset utf-8; location / { try_files $uri $uri/ =404; } location ~ /\\. { deny all; } error_page 404 /404.html; gzip on; gzip_vary on; gzip_min_length 1024; gzip_types text/plain text/css application/javascript application/json application/xml image/svg+xml; access_log /var/log/nginx/blog_access.log; error_log /var/log/nginx/blog_error.log; } 检查并加载：\n1 sudo nginx -t \u0026amp;\u0026amp; sudo systemctl reload nginx 测试访问：\n1 2 curl -I http://www.novalshared.work/ curl -I https://www.novalshared.work/ HTTP 应跳转 HTTPS，HTTPS 首页应返回 200。\n13. 配置证书自动续期 13.1 创建续期后的部署钩子 1 2 sudo mkdir -p /etc/letsencrypt/renewal-hooks/deploy sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh 写入：\n1 2 3 4 5 #!/bin/sh set -eu /usr/sbin/nginx -t /bin/systemctl reload nginx 授予执行权限：\n1 2 sudo chmod 755 \\ /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh 13.2 启用并测试续期 使用 Ubuntu apt 安装 Certbot 时，启用定时器：\n1 2 3 sudo systemctl enable --now certbot.timer systemctl list-timers --all | grep -i certbot sudo certbot renew --dry-run 保留 HTTP 80 端口及独立的证书验证目录，供后续自动验证使用。\n14. 更新网站内容 14.1 新增文章 1 2 3 cd /home/bloguser/sites/personal-blog-stack hugo new content post/my-new-post/index.md nano content/post/my-new-post/index.md 填写正文，并设置：\n1 2 draft = false slug = \u0026#34;my-new-post\u0026#34; 对应文章地址：\n1 https://www.novalshared.work/p/my-new-post/ 14.2 发布文章、图片和样式 预览确认后执行：\n1 2 cd /home/bloguser/sites/personal-blog-stack ./publish.sh 14.3 修改与下线 修改文章时编辑对应 index.md，完成后执行发布脚本。\n下线文章时，将 Front Matter 改为：\n1 draft = true 再执行 ./publish.sh。发布脚本每次使用新目录构建，正式目录会同步移除已下线页面。\n15. 可选：配置公网 IP 访问 此部分配置独立的静态站点，通过 http://服务器公网IP/ 查看网页，无需持续运行 Hugo 开发服务器。公网可用性以实际网络及接入商规则为准。\n15.1 按 IP 地址构建 1 2 3 4 5 cd /home/bloguser/sites/personal-blog-stack hugo --minify \\ --baseURL \u0026#34;http://8.256.137.141/\u0026#34; \\ --destination public-ip --baseURL 仅覆盖本次构建，不修改 hugo.toml 中的正式域名。\n15.2 发布到独立目录 1 2 3 4 5 6 7 sudo mkdir -p /var/www/personal-blog-ip sudo rsync -av --delete \\ public-ip/ \\ /var/www/personal-blog-ip/ sudo chmod -R a+rX /var/www/personal-blog-ip 15.3 新建 IP 访问配置 1 sudo nano /etc/nginx/conf.d/blog-ip.conf 写入：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 server { listen 80; server_name 8.256.137.141; root /var/www/personal-blog-ip; index index.html; charset utf-8; location / { try_files $uri $uri/ =404; } location ~ /\\. { deny all; } access_log /var/log/nginx/blog_ip_access.log; error_log /var/log/nginx/blog_ip_error.log; } 检查并加载：\n1 sudo nginx -t \u0026amp;\u0026amp; sudo systemctl reload nginx 15.4 测试访问 1 2 3 curl -I \\ -H \u0026#34;Host: 8.256.137.141\u0026#34; \\ http://127.0.0.1/ 在浏览器打开：\n1 http://8.256.137.141/ IP 访问使用 HTTP；域名的 HTTPS 证书不用于该 IP 站点。\n15.5 更新 IP 站点 每次修改后，重复执行本节的构建与同步命令。IP 站点和正式域名站点使用各自的构建结果及发布目录。\n16. 可选：移除 IP 访问配置 16.1 确认正式域名站点已发布 确认 hugo.toml 保留：\n1 baseURL = \u0026#34;https://www.novalshared.work/\u0026#34; 发布并检查：\n1 2 3 cd /home/bloguser/sites/personal-blog-stack ./publish.sh curl -I https://www.novalshared.work/ 16.2 停用 IP 站点 1 2 3 4 5 sudo mv \\ /etc/nginx/conf.d/blog-ip.conf \\ /etc/nginx/conf.d/blog-ip.conf.disabled sudo nginx -t \u0026amp;\u0026amp; sudo systemctl reload nginx 16.3 清理 IP 专用网页 确认两个目录只包含本教程生成的 IP 静态网站后，删除：\n1 2 sudo rm -r -- /var/www/personal-blog-ip rm -r -- /home/bloguser/sites/personal-blog-stack/public-ip 以上仅清理可重新生成的 IP 网页。保留正式源项目、/var/www/personal-blog/、blog.conf、证书及验证目录。\n停用 IP 专用站点后，直接访问 IP 的请求会按 Nginx 的默认站点规则处理；此步骤不额外改变默认站点。\n17. 版本管理与备份 17.1 配置忽略文件 1 2 cd /home/bloguser/sites/personal-blog-stack nano .gitignore 写入：\n/public/ /public-ip/ /resources/ /.hugo_build.lock /.build.*/ 17.2 配置项目 Git 身份 替换为自己的姓名和邮箱：\n1 2 git config user.name \u0026#34;你的名字\u0026#34; git config user.email \u0026#34;你的真实邮箱\u0026#34; 17.3 保存项目版本 1 2 git add . git commit -m \u0026#34;初始化 Hugo Stack 博客\u0026#34; 以后更新内容后：\n1 2 3 git status git add . git commit -m \u0026#34;更新博客内容\u0026#34; 将仓库同步到自己的私有远程仓库，或定期复制到其他设备。恢复子模块时执行：\n1 git submodule update --init --recursive 17.4 备份范围 重点备份：\n1 2 3 /home/bloguser/sites/personal-blog-stack/ /etc/nginx/conf.d/blog.conf /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh 如果需要完整迁移现有证书，另行以管理员权限安全备份 /etc/letsencrypt/，其中包含私钥。\n主题升级时选择明确的目标版本，先在源项目预览和构建，再运行发布脚本；主题版本变更后将子模块引用一并提交。\n18. 最终目录结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 /home/bloguser/sites/personal-blog-stack/ ├── hugo.toml ├── publish.sh ├── .gitignore ├── .gitmodules ├── assets/ │ ├── img/ │ │ └── avatar.jpg │ └── scss/ │ └── custom.scss ├── content/ │ ├── post/ │ │ └── hello-stack/ │ │ ├── index.md │ │ ├── cover.jpg │ │ └── screenshot.png │ └── page/ │ ├── archives/index.md │ ├── search/index.md │ └── about/index.md └── themes/ └── hugo-theme-stack/ /var/www/ ├── personal-blog/ └── certbot/ └── .well-known/acme-challenge/ /etc/nginx/conf.d/ ├── blog.conf └── download.conf /etc/letsencrypt/renewal-hooks/deploy/ └── reload-nginx.sh 官方参考 Hugo Linux 安装 Hugo 0.169.0 安装包 Hugo 构建命令 Stack v4 版本说明 Stack v4.0.3 默认参数 Stack 官方搜索页示例 Nginx server_name 说明 Let’s Encrypt HTTP-01 验证 Certbot Webroot ","date":"2026-11-07T10:00:00+08:00","image":"/p/hello-stack/cover.png","permalink":"/p/hello-stack/","title":"hugo博客搭建"}]