Project / VWebServer
用自己的 C++ WebServer 搭建个人笔记站
这篇记录我的个人笔记站是如何搭建起来的。它不是单纯的前端页面展示,而是把自己实现的 C++ WebServer 真正用起来,让它托管静态资源、响应浏览器请求,并承载长期维护的学习笔记。
为什么要搭建这个笔记站
我搭建这个笔记站主要有两个目的。
第一,把之前零散的 C++、Linux、MySQL 和算法笔记用ai整理成一个可以长期回看的知识库。相比散落在本地目录里的 Markdown,站点化之后更适合浏览、检索和对外展示。
第二,让自己实现的 C++ WebServer 承载一个真实页面,而不是只停留在返回 Hello World、echo server 或压测接口的阶段。因此,这个站点既是学习笔记的展示入口,也是 WebServer 项目的一个实际使用场景。
整体架构:Caddy + C++ WebServer + 轻量内容后台
站点仍然以静态页面作为公开交付形式,但增加了一个受登录保护的轻量内容后台。公网请求先进入 Caddy;公开页面交给 C++ WebServer,管理页面和发布 API 则交给只监听本机端口的 Python 服务。
Browser
↓
Domain: vertaweb.cn / www.vertaweb.cn
↓
Caddy :80 / :443
├─ public → 127.0.0.1:8080 → C++ WebServer
└─ admin → 127.0.0.1:8090 → Admin Service
↓
site.json + generated HTML
前端负责展示分类、文章列表和项目记录;Caddy 负责 TLS 与路由分流;C++ WebServer 负责公开页面和静态资源。后台可以导入 Markdown、生成同风格文章页,并修改主推荐、最近更新和置顶入口。首页读取 site.json 后应用这些配置,因此不再需要为每次置顶手工修改首页 HTML。
后端:使用自己的 WebServer 托管静态资源
这个站点的后端没有直接使用 Nginx 或现成 Web 框架,而是使用自己实现的 C++ WebServer 来托管静态资源。
WebServer 主要负责:
- 接收浏览器发来的 HTTP 请求。
- 解析请求行和请求头。
- 根据 URL 映射本地静态资源路径。
- 返回 HTML、CSS、JavaScript、图片和 favicon 等文件。
- 对不存在或不可访问的资源返回 404 / 错误响应。
- 通过日志记录请求路径、错误信息和运行状态。
这让 WebServer 从一个单纯的练习项目,变成了一个能承载真实页面的服务端程序。首页、笔记详情页、样式文件、图标和静态资源都可以作为它的真实用例。
前端:用 AI 辅助完成页面原型和样式迭代
前端部分主要通过 AI 辅助开发完成。我先确定页面结构、内容分区和视觉风格,再使用 Codex 辅助生成 HTML/CSS 原型,之后根据实际效果进行人工调整。
这个过程接近现在常说的 vibe coding:先用自然语言描述目标效果,再通过多轮调整把页面迭代到可用状态。但 AI 辅助并不意味着完全不理解代码。实际调整过程中仍然需要理解 HTML 结构、CSS 布局、响应式效果以及静态资源路径,否则生成结果很难真正部署到自己的服务器上。
在这个站点里,AI 更多承担的是原型搭建和文案润色的角色;内容结构、项目重点、交互逻辑和最终取舍仍然由我来决定。
内容组织:C++ / Linux / WebServer / 算法笔记
站点内容主要分为三类。
- C++ 后端学习笔记:包括 C++ 基础语法、现代 C++、Linux 命令、MySQL 和算法笔记。
- WebServer 项目构建记录:记录 WebServer 从阻塞式服务器到 epoll + 线程池架构的演进过程,包括非阻塞 I/O、Connection 缓冲区、HTTP 状态机、Keep-Alive、静态文件服务和压测分析。
- 个人站点搭建记录:记录如何使用自己的 WebServer 托管笔记站,以及前端页面、部署流程和后续优化计划。
这样组织以后,首页负责展示最高价值入口,All 和分类区负责归档,单篇文章负责沉淀具体实现和复盘。
部署过程:云服务器、Docker、Caddy 反向代理
站点部署在云服务器上。服务器端的项目目录为 /root/VertaNotes,静态资源放在 /root/VertaNotes/Resources。C++ WebServer 运行在 Docker 容器 verta-notes 中,只绑定本机 127.0.0.1:8080;Caddy 监听公网 80/443,再把请求转发给本机 8080。
部署流程大致包括:
- 在云服务器上准备 Linux 运行环境。
- 克隆 VWebServer 仓库,并整理部署目录为
/root/VertaNotes。 - 用 Docker 运行 C++ WebServer,容器名为
verta-notes。 - 将容器端口绑定为
127.0.0.1:8080:8080,避免 C++ WebServer 直接暴露公网。 - 上传 HTML、CSS、JS、favicon 和 notes 页面到
Resources/。 - 配置 Caddy,将公开请求转发到
127.0.0.1:8080,将管理请求转发到127.0.0.1:8090。 - 通过浏览器访问域名,并用 curl 检查本机转发链路。
当前 WebServer 容器启动方式类似下面这样:
docker run -d \
--name verta-notes \
--restart unless-stopped \
-p 127.0.0.1:8080:8080 \
-v /root/VertaNotes:/app \
-w /app \
v-web-server:latest \
bash -lc 'make clean && make && ./server'
无扩展名路径已经由 C++ WebServer 动态解析:真实文件不存在且 URL 没有扩展名时,服务器再尝试对应的 .html 文件。Caddy 因而只负责入口分流:
vertaweb.cn, www.vertaweb.cn {
@admin path /admin /admin/* /api/admin/*
handle @admin {
reverse_proxy 127.0.0.1:8090
}
handle {
reverse_proxy 127.0.0.1:8080
}
}
这样做的好处是:公网只需要访问标准的 80/443 端口,HTTPS、证书续期和域名入口由 Caddy 负责;C++ WebServer 保持在内网回环地址后面,专注处理 HTTP 请求和静态文件返回。
资源同步:本地修改后推到服务器
页面样式和程序代码仍然在本地修改,再通过同步脚本推到服务器。后台发布的文章则直接保存在服务器。同步脚本会先读取 site.json,保留后台生成的文章及配置,再更新其他静态资源,避免一次同步把线上内容覆盖掉。
cd "D:\Documents\New project"
.\sync-verta-notes.cmd
同步脚本的默认目标是 CloudServer:/root/VertaNotes。这样页面迭代不需要每次手动登录服务器复制文件,也减少了路径写错的概率。
遇到的问题与解决
这个站点在搭建过程中最容易遇到的问题,不是页面能不能写出来,而是“写出来之后能不能被自己的服务器正确返回”。
- 静态资源路径问题:如果 /style.css 请求找不到文件,需要检查 URL 到本地路径的映射规则。
- Content-Type 问题:HTML、CSS、JS、图片需要返回不同的 Content-Type,否则浏览器可能无法正确解析。
- 端口访问问题:最开始可以直接把容器映射到公网 80 或 8080,但接入 Caddy 后更合适的方式是让 WebServer 只监听本机
127.0.0.1:8080,公网只暴露 80/443。 - 反向代理问题:Caddy 的
reverse_proxy目标必须和 Docker 端口绑定一致。如果容器没有绑定到127.0.0.1:8080,Caddy 就无法把请求转发给 WebServer。 - 干净链接问题:C++ WebServer 对无扩展名路径尝试补全
.html,同时保留真实文件优先级,因此文章链接更简洁且不会影响 CSS、JS 和图片。 - 后台运行问题:WebServer 由 Docker 管理,内容后台和 Caddy 由 systemd 管理,三个服务都不依赖 SSH 会话。
这些问题看起来和前端页面关系不大,但它们正好能验证 WebServer 是否真的具备托管静态站点的能力。
后续计划:内容构建、HTTPS 运维和自动化部署
域名、Caddy 反向代理和 HTTPS 入口已经接上,后续更适合继续完善内容生产和部署自动化。
- 继续检查 HTTPS 证书续期和 Caddy 服务状态。
- 接入 Cloudflare 做 DNS / 缓存 / 安全防护。
- 完善 Markdown 表格、任务列表和图片上传支持。
- 优化移动端适配。
- 继续完善文章搜索和分类索引。
- 把同步脚本进一步做成更完整的发布流程。
- 增加访问日志统计。
这篇文章的定位是:用一个真实站点证明自己的 C++ WebServer 能跑起来、能部署、能承载静态资源。