子域名规划:www、api、cdn 该怎么分

一开始只有一个域名,用着用着就想加 blog.、api.、cdn.……加之前想清楚,比加完之后再改省事得多。

一、常见划分方式

子域名用途说明
www主站传统习惯,现在多数站点会 301 到根域
api接口服务与前端分离,便于独立部署和限流
cdn / static静态资源无 Cookie,缓存命中率高
img图片同上
blog博客独立系统时常用
admin后台建议同时限制 IP 或加二次验证
mail邮件配合 MX 记录
test / dev测试环境不要暴露到公网

二、www 要不要保留

技术上 example.comwww.example.com 是两个不同的主机,需要各自解析。

两种主流做法,选一个并保持一致:

做法 A:www 301 到根域(现在更常见)

nginx
server {
    listen 443 ssl http2;
    server_name www.example.com;
    return 301 https://example.com$request_uri;
}

做法 B:根域 301 到 www(老牌站点常见)

理由通常是:根域不能设 CNAME(只能 A 记录),如果用 CDN,www 用 CNAME 更灵活。不过 Cloudflare 支持根域 CNAME flatten,这个理由现在弱化了。

重点是必须二选一并做 301,否则两个地址都能访问,会被搜索引擎判定为重复内容,分散权重。

三、Cookie 作用域:一个容易踩的坑

Cookie 默认只在当前域名生效,但可以设到父域:

bash
# 设在 example.com 上:所有子域名都能读到
Set-Cookie: session=abc; Domain=example.com

# 不设 Domain:只在当前子域生效
Set-Cookie: session=abc

影响有两个:

1. 静态资源子域的价值

如果把 Cookie 设在 example.com,那么访问 cdn.example.com 的请求也会带上 Cookie(几十到几百字节),白白浪费带宽,还会让 CDN 无法缓存(带 Cookie 的请求通常不缓存)。

所以:静态资源用独立子域 + 主站 Cookie 不设 Domain

2. 单点登录(SSO)

反过来,如果你想让 a.example.comb.example.com 共享登录态,就必须把 Cookie 设到 example.com

bash
Set-Cookie: token=xxx; Domain=.example.com; Secure; HttpOnly; SameSite=Lax

Security 三件套建议都加上:

属性作用
Secure只在 HTTPS 下发送
HttpOnlyJS 读不到,防 XSS 窃取
SameSite=Lax跨站请求不带,防 CSRF

四、证书覆盖范围

每个子域名都要在证书的 SAN 列表里,否则访问会报「域名不匹配」。

bash
# 查看证书覆盖了哪些域名
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -text | grep -A1 "Alternative"

两种解法:

bash
# 1. 多域名证书(SAN)
sudo certbot --nginx -d example.com -d www.example.com -d api.example.com

# 2. 通配符证书(必须 DNS-01 校验)
sudo certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
  -d "*.example.com" -d example.com

子域名多且不固定时,通配符更省事(新增子域不用重签)。

注意:通配符 *.example.com 不匹配 example.com 本身,也不匹配多级如 a.b.example.com。所以签的时候要把根域一起加上。

五、子域名 vs 子目录

到底用 blog.example.com 还是 example.com/blog

维度子域名子目录
SEO 权重被视为独立站点,权重分开算权重都归主域(更有利
技术隔离可以完全独立部署、不同技术栈共享主站配置
Cookie默认隔离默认共享
复杂度需要额外解析和证书简单

结论:

  • 内容相关的(博客、文档)用子目录,SEO 权重集中在主域;
  • 技术独立的(API、后台、CDN)用子域名,便于隔离和独立扩容。

本站是个人笔记,全部放在根域下的 hash 路由里,属于最简单的做法。

六、安全:别暴露不该暴露的

  1. 测试环境别用公开子域test.example.com 会被扫描器扫到,要么加 IP 白名单,要么用 *.internal.example.com 且 DNS 只在内网解析;
  2. 后台子域限制来源 IP
nginx
location / {
    allow 1.2.3.4;      # 你的出口 IP
    deny all;
    proxy_pass http://127.0.0.1:8080;
}
  1. 通配符解析要谨慎*.example.com 一条记录覆盖所有子域,方便但也意味着任何子域都会解析到你的服务器。确认服务对未知 Host 有兜底(返回 404 而不是默认页)。
nginx
# 兜底 server:放在最前面,处理所有未匹配的 Host
server {
    listen 80 default_server;
    server_name _;
    return 444;   # 直接断开连接,不给任何响应
}

七、我的规划方式

给一个可以直接抄的模板:

bash
example.com          → 主站(A 记录)
www.example.com      → 301 到根域
api.example.com      → 接口(CNAME 或 A)
static.example.com   → 静态资源(无 Cookie)
admin.example.com    → 后台(限 IP)
# 测试环境不设公网 DNS,只在本地 hosts 里写

想清楚这几个就够了。先别急着加,用到再加——每多一个子域,就多一份证书、解析和维护成本。