一个用 Go 编写的 Hugo 站点管理后台。内容、主题、模块、媒体和构建都在一个界面里完成,不需要手写配置文件。前端使用 Vue 3 + PrimeVue,以静态资源形式由 Go 直接提供。
| 桌面端 | 移动端 |
|---|---|
![]() | ![]() |
介绍页(纯静态,由 GitHub Pages 托管):https://kaiyuan.github.io/hugo-panel/
content/ 子目录选择并可直接在下拉菜单中新建文件夹(支持 posts/2026 这样的多级目录),文件名可一键翻译为英文,URL 为空时自动按目录和文件名生成。themes/ 下的主题,启用主题,从 Git 安装、更新、移除主题;可视化编辑站点配置、主题参数和菜单。hugo mod tidy,并显示命令输出与工具链状态。hugo --gc --minify --cleanDestinationDir,保留最后一次构建结果;构建失败时可邮件通知管理员。#000 背景,适合 OLED 屏幕;默认跟随系统。localhost 外,安装与 Service Worker 需要 HTTPS。镜像地址:https://hub.docker.com/r/kaiyuan/hugo-panel
docker run -d \
--name hugo-panel \
--restart unless-stopped \
--network bridge \
-p 8080:8080 \
-v /srv/hugo-panel/data:/app/hugo-panel/data \
-v /srv/my-hugo-site:/app/hugo \
-e PUBLIC_URL=https://panel.example.com \
-e TZ=Asia/Shanghai \
kaiyuan/hugo-panel:latest
然后打开 http://服务器地址:8080,按向导创建管理员。
仓库内的 docker-compose.yml 使用本地源码构建镜像,不依赖远程镜像:
services:
hugo-panel:
build: .
image: hugo-panel:local
restart: unless-stopped
network_mode: bridge
ports:
- "8080:8080"
environment:
HUGO_DIR: /app/hugo
PUBLIC_URL: https://panel.example.com
volumes:
- "${HOST_DATA_DIR:-./data}:/app/hugo-panel/data"
- "${HOST_HUGO_DIR:-./hugo}:/app/hugo"
通过拉取 Docker 创建
services:
hugo-panel:
# Build the image locally from this repository instead of pulling a remote image.
build:
context: .
dockerfile: Dockerfile
args:
COMMIT: ${COMMIT:-none}
BUILD_TIME: ${BUILD_TIME:-unknown}
image: kaiyuan/hugo-panel:latest
container_name: hugo-panel
restart: unless-stopped
ports:
- "8080:8080"
network_mode: bridge
environment:
TZ: Asia/Shanghai
HUGO_DIR: /app/hugo
# Public URL of this panel, used for password-reset links.
PUBLIC_URL: http://localhost:8080
volumes:
# Host paths are configured in .env (defaults keep them next to this file).
- "${HOST_DATA_DIR:-./data}:/app/hugo-panel/data"
- "${HOST_HUGO_DIR:-./hugo}:/app/hugo"
挂载目录通过 .env 配置,未设置时使用默认相对路径:
HOST_DATA_DIR=./data
HOST_HUGO_DIR=./hugo
docker compose up -d --build
SMTP 环境变量是可选的,不配置也能正常构建和启动;可在首次启动后到设置页配置。
| 路径 | 用途 |
|---|---|
/app/hugo-panel | 面板工作目录 |
/app/hugo-panel/data | SQLite 数据库、备份、自定义翻译、Hugo/Go 缓存(建议持久化) |
/app/hugo | Hugo 站点目录(默认值,可在设置页修改) |
/app/hugo/content | 内容目录 |
/app/hugo/themes | 本地主题 |
/app/hugo/static/images | 内置媒体库(可在媒体页切换或新增存储库) |
/app/hugo/public | 构建输出 |
容器默认以 UID/GID 1000 运行,并在启动时把挂载目录 chown 给该用户。若由外部工具管理权限:
-e CHOWN_HUGO=false -e CHOWN_DATA=false
| 变量 | 默认值 | 说明 |
|---|---|---|
PORT | 8080 | 监听端口 |
DATA_DIR | ./data(镜像内 /app/hugo-panel/data) | 数据目录 |
HUGO_DIR | ./hugo(镜像内 /app/hugo) | 首次启动写入设置的 Hugo 站点目录 |
HUGO_BINARY | hugo | 首次启动写入设置的 Hugo 可执行文件 |
PUBLIC_URL | 空 | 面板公网地址,用于密码重置链接;设置后环境变量优先 |
COOKIE_SECURE | auto | auto / true / false,HTTPS 反代建议保持 auto |
LOG_LEVEL | info | debug / info / warn / error |
SMTP_ENABLED | 空 | true 开启 SMTP |
SMTP_HOST | 空 | SMTP 主机 |
SMTP_PORT | 587 | SMTP 端口 |
SMTP_USERNAME | 空 | SMTP 用户名 |
SMTP_PASSWORD | 空 | SMTP 密码 |
SMTP_FROM | 空 | 发件地址 |
SMTP_FROM_NAME | Hugo Panel | 发件人名称 |
SMTP_SECURITY | starttls | starttls / tls / none |
CHOWN_DATA | true | 启动时 chown 数据目录 |
CHOWN_HUGO | true | 启动时 chown Hugo 目录 |
通过环境变量设置的 SMTP 值会优先于数据库设置,面板中会显示 ENV 标记并锁定对应字段。
需要 Go 1.24+、GCC(SQLite 驱动使用 CGO)以及可选的 Hugo。无需 Node.js。
git clone https://github.com/Kaiyuan/hugo-panel.git
cd hugo-panel
mkdir -p data hugo
CGO_ENABLED=1 \
DATA_DIR=./data \
HUGO_DIR=./hugo \
go run ./cmd/hugo-panel
或:
make run # 本地运行
make test # Go 测试
make vet # go vet
make build # 输出 bin/hugo-panel
前端文件位于 web/static,Vue/PrimeVue 等依赖已经以本地静态资源形式内置在 web/static/vendor,不经过打包器。
内置翻译位于 web/locales/*.json。运行时自定义翻译放在数据目录:
${DATA_DIR}/locales/pt-BR.json
文件是扁平的 key: value JSON,可参考 en.json 模板:
{
"_name": "Português (Brasil)",
"_native_name": "Português (Brasil)",
"nav.dashboard": "Painel",
"common.cancel": "Cancelar"
}
也可以在 设置 → 语言 → 添加翻译 中上传 JSON 文件。缺失的键会自动回退到英文;新增语言无需重新编译或重启。
媒体页默认使用 Hugo 站点内的 static/images,也可以通过 媒体 → 存储库设置 添加更多存储库:
文件 URL 由 公开访问基础 URL + 文件夹路径 生成。例如基础 URL 为 https://cdn.example.com/media,文件位于 posts/2026/photo.jpg,复制出的 URL 就是 https://cdn.example.com/media/posts/2026/photo.jpg。留空时使用存储端点本身,或对内置库使用站点的 /images/... 路径。
上传大小上限按存储库单独设置(默认 512 MB)。反向代理(如 Nginx client_max_body_size)和存储服务商可能施加更低的限制。S3 密钥和 WebDAV 密码只保存在 SQLite 中,接口不会回传明文;编辑时留空表示保留原值。若 NAS 或自建服务使用自签名证书,可在该存储库中开启「允许自签名证书」;保存前可以点「测试连接」验证 URL、账号和证书。
所有存储库都提供统一的文件操作:新建文件夹、上传、预览、复制 URL / Markdown、移动、复制和删除。移动 / 复制可以在不同存储库之间进行;跨库操作会先下载到数据目录的临时文件再上传。
如果「测试连接」返回类似 lookup nas.example.com on 127.0.0.11:53: i/o timeout,说明 Docker 内置 DNS 没能解析该主机名,而不是账号或 WebDAV 配置错误。
先在宿主机确认主机名对应的 IP:
getent hosts nas.example.com
最省事的方式是在存储库设置里填写 主机 IP:面板会直接连接这个 IP,不再做 DNS 查询,但 HTTPS 证书校验和 Host 头仍然使用原来的主机名。这适用于 Docker 内置 DNS 超时、或域名只有宿主机能解析的情况。
如果已经在 compose 里配置了 dns:(例如 1.1.1.1)仍然超时,说明容器到这些 DNS 的出站 53 端口被阻断;删掉 dns: 让 Docker 使用宿主机的解析器,或改成实际能解析该域名的内网 DNS。
如果容器完全无法访问任何 53 端口(换成 1.1.1.1、8.8.8.8 也超时),可以在存储库设置里填写 DNS over HTTPS,例如 https://1.1.1.1/dns-query。面板会通过 443 端口解析存储服务器的主机名,再连接解析出的 IP,同时保留原 Host 头和 TLS SNI。请尽量使用基于 IP 的 DoH 地址,避免解析 DoH 服务器本身又依赖已经失效的 DNS;该地址必须能从容器直接访问。如果 1.1.1.1 不可达,可以换成其他可访问的 DoH 服务,例如阿里 DNS 的 https://223.5.5.5/dns-query。「主机 IP」和 DoH 同时填写时以「主机 IP」为准。
即使不填写 DoH 地址,普通 DNS 失败后面板也会自动尝试公共 DoH 服务(Cloudflare、阿里 DNS、Google),所以通常不需要额外配置。自动回退只针对看起来是公网的域名;单段主机名(如 Docker 服务名)和 .local、.lan、.internal 等私有后缀仍交给系统 DNS。如果不想把域名发送给公共解析服务,可以给该存储库填写自己的 DoH 地址,或在容器环境变量中设置 MEDIA_DOH_URL=off 关闭自动回退;也可以用逗号分隔的地址列表覆盖默认服务(需要在 docker-compose.yml 的 environment 中透传该变量)。
也可以在 Docker 层解决。docker-compose.yml:
services:
hugo-panel:
extra_hosts:
- "nas.example.com:192.168.2.10"
或者让容器使用能解析该域名的 DNS(路由器、AdGuard、内网 DNS 等):
services:
hugo-panel:
dns:
- 192.168.2.1
docker run 对应参数是 --add-host nas.example.com:192.168.2.10 和 --dns 192.168.2.1。修改后执行 docker compose up -d,并在容器内验证:
docker exec -it hugo-panel getent hosts nas.example.com
如果域名本身解析正常,但 WebDAV 使用自签名 HTTPS 证书,还需要在存储库设置里打开「允许自签名证书」。
cmd/hugo-panel Go 入口、HTTP 服务、优雅退出
internal/config 环境变量配置
internal/store SQLite、用户、会话、设置、密码重置
internal/settings 设置与环境变量覆盖
internal/hugo 内容、front matter、配置、主题、模块、构建
internal/media 媒体存储库(本机目录、S3、WebDAV)与文件操作
internal/mailer SMTP、密码重置/构建失败邮件
internal/translate 标题翻译(LibreTranslate / DeepL)
internal/ai 兼容 OpenAI 的 chat completions 客户端
internal/i18n 语言发现、按需加载、自定义翻译
internal/server 路由、鉴权、CSRF、安全头、API
web/static Vue 3 + PrimeVue 单页应用、PWA、内置依赖
web/locales 9 种内置语言
数据库为单文件 SQLite(WAL 模式),配置/内容写入采用临时文件 + 原子重命名,修改前会备份到 data/backups/。
PUBLIC_URL。未设置时,密码重置链接会从当前请求推断地址。前端第三方静态依赖及其许可证见 THIRD_PARTY_LICENSES.md。
Content type
Image
Digest
sha256:765ee864e…
Size
169.1 MB
Last updated
1 day ago
docker pull kaiyuan/hugo-panel