虚拟主机 #
概述 #
虚拟主机允许在一台服务器上托管多个网站,Caddy 通过简单的配置即可实现多站点、多域名的管理。
text
┌─────────────────────────────────────────────────────────────┐
│ 虚拟主机架构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ │
│ │ Caddy │ │
│ └────┬────┘ │
│ │ │
│ ┌───────────────┼───────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │site1.com │ │site2.com │ │site3.com │ │
│ │ 站点 1 │ │ 站点 2 │ │ 站点 3 │ │
│ └───────────┘ └───────────┘ └───────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
基本配置 #
多站点配置 #
caddyfile
# 站点 1
site1.example.com {
root * /var/www/site1
file_server
}
# 站点 2
site2.example.com {
root * /var/www/site2
file_server
}
# 站点 3
site3.example.com {
reverse_proxy localhost:3000
}
多域名共享配置 #
caddyfile
# 多个域名共享同一配置
example.com, www.example.com {
root * /var/www/html
file_server
}
通配符域名 #
caddyfile
# 匹配所有子域名
*.example.com {
root * /var/www/{labels.1}
file_server
}
站点地址格式 #
域名格式 #
caddyfile
# 标准域名
example.com { }
# 带端口
example.com:8080 { }
# 通配符
*.example.com { }
# 多域名
example.com, www.example.com, app.example.com { }
IP 地址格式 #
caddyfile
# 监听所有接口
:80 { }
:443 { }
# 监听特定 IP
192.168.1.100 { }
192.168.1.100:8080 { }
# 本地地址
localhost { }
127.0.0.1 { }
混合格式 #
caddyfile
# 域名 + IP 混合
example.com, 192.168.1.100:8080 {
respond "Mixed address"
}
站点匹配优先级 #
匹配规则 #
Caddy 按照以下优先级匹配站点:
text
1. 精确域名匹配
2. 通配符域名匹配(更具体的优先)
3. 默认站点(:80, :443)
示例 #
caddyfile
# 精确匹配(最高优先级)
api.example.com {
respond "API Server"
}
# 通配符匹配(次优先级)
*.example.com {
respond "Wildcard Match"
}
# 默认站点(最低优先级)
:443 {
respond "Default Site"
}
配置文件拆分 #
主配置文件 #
caddyfile
# /etc/caddy/Caddyfile
{
email admin@example.com
}
# 导入站点配置
import sites/*.caddyfile
import sites/*/*.caddyfile
站点配置文件 #
caddyfile
# /etc/caddy/sites/main.caddyfile
example.com {
root * /var/www/main
file_server
}
caddyfile
# /etc/caddy/sites/api.caddyfile
api.example.com {
reverse_proxy localhost:3000
}
caddyfile
# /etc/caddy/sites/blog.caddyfile
blog.example.com {
root * /var/www/blog
file_server
encode gzip
}
按环境拆分 #
caddyfile
# /etc/caddy/Caddyfile
{
email admin@example.com
}
# 开发环境
import sites/development/*.caddyfile
# 生产环境
# import sites/production/*.caddyfile
动态站点配置 #
基于路径的站点 #
caddyfile
example.com {
# 主站点
root * /var/www/main
file_server
# 子路径映射
handle /blog/* {
root * /var/www/blog
file_server
}
handle /docs/* {
root * /var/www/docs
file_server
}
handle /api/* {
reverse_proxy localhost:3000
}
}
基于子域名的站点 #
caddyfile
# 主站点
example.com {
root * /var/www/main
file_server
}
# API 子域名
api.example.com {
reverse_proxy localhost:3000
}
# 博客子域名
blog.example.com {
root * /var/www/blog
file_server
}
# 文档子域名
docs.example.com {
root * /var/www/docs
file_server
}
动态根目录 #
caddyfile
# 根据域名动态设置根目录
*.example.com {
root * /var/www/{host}
file_server
}
# 或使用标签
*.example.com {
# {labels.0} = 子域名部分
# {labels.1} = 主域名部分
root * /var/www/sites/{labels.0}
file_server
}
重定向配置 #
域名重定向 #
caddyfile
# www 到非 www
www.example.com {
redir https://example.com{uri} permanent
}
# 非 www 到 www
example.com {
redir https://www.example.com{uri} permanent
}
HTTP 到 HTTPS #
caddyfile
# 自动 HTTPS 重定向(Caddy 默认行为)
example.com {
# Caddy 自动处理 HTTP 到 HTTPS 的重定向
}
# 手动配置
http://example.com {
redir https://example.com{uri} permanent
}
域名迁移 #
caddyfile
# 旧域名重定向到新域名
old-domain.com {
redir https://new-domain.com{uri} permanent
}
*.old-domain.com {
redir https://{labels.0}.new-domain.com{uri} permanent
}
路径重定向 #
caddyfile
example.com {
# 路径重定向
redir /old-path /new-path permanent
# 正则重定向
redir /blog/* /posts/{path.1} permanent
# 条件重定向
@mobile header User-Agent *Mobile*
redir @mobile https://m.example.com{uri}
}
共享配置 #
使用片段 #
caddyfile
# 定义共享配置片段
(common) {
encode gzip zstd
log {
output file /var/log/caddy/access.log
}
header {
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
}
}
# 使用片段
site1.example.com {
import common
root * /var/www/site1
file_server
}
site2.example.com {
import common
root * /var/www/site2
file_server
}
带参数的片段 #
caddyfile
# 定义带参数的片段
(static-site) {
root * {args[0]}
file_server
encode gzip
log {
output file /var/log/caddy/{args[1]}.log
}
}
# 使用
site1.example.com {
import static-site /var/www/site1 site1
}
site2.example.com {
import static-site /var/www/site2 site2
}
认证配置 #
站点级认证 #
caddyfile
# 整站认证
private.example.com {
basicauth {
admin $2a$14$Zkx...
}
root * /var/www/private
file_server
}
路径级认证 #
caddyfile
example.com {
root * /var/www/html
file_server
# 管理路径需要认证
handle /admin/* {
basicauth {
admin $2a$14$Zkx...
}
file_server
}
}
不同用户认证 #
caddyfile
example.com {
# 用户区域
handle /user/* {
basicauth {
user1 $2a$14$hash1...
user2 $2a$14$hash2...
}
reverse_proxy localhost:3000
}
# 管理区域
handle /admin/* {
basicauth {
admin $2a$14$adminhash...
}
reverse_proxy localhost:3001
}
}
日志分离 #
站点独立日志 #
caddyfile
site1.example.com {
root * /var/www/site1
file_server
log {
output file /var/log/caddy/site1.log
format json
}
}
site2.example.com {
root * /var/www/site2
file_server
log {
output file /var/log/caddy/site2.log
format json
}
}
共享日志配置 #
caddyfile
# 全局日志配置
{
log default {
output file /var/log/caddy/access.log
format json
}
}
# 站点使用默认日志
site1.example.com {
root * /var/www/site1
file_server
}
# 站点覆盖日志配置
site2.example.com {
root * /var/www/site2
file_server
log {
output file /var/log/caddy/site2.log
}
}
完整示例 #
企业多站点配置 #
caddyfile
# 全局配置
{
email admin@company.com
acme_ca https://acme-v02.api.letsencrypt.org/directory
}
# 共享配置片段
(security-headers) {
header {
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
X-XSS-Protection "1; mode=block"
Referrer-Policy "strict-origin-when-cross-origin"
-Server
}
}
(logging) {
log {
output file /var/log/caddy/{host}.log {
roll_size 50mb
roll_keep 10
}
format json
}
}
# 主站
company.com, www.company.com {
import security-headers
import logging
root * /var/www/main
file_server
encode gzip zstd
# www 重定向
@www host www.company.com
redir @www https://company.com{uri} permanent
}
# API 服务
api.company.com {
import security-headers
import logging
reverse_proxy {
to api-server-1:3000
to api-server-2:3000
lb_policy round_robin
health_uri /health
}
}
# 文档站点
docs.company.com {
import security-headers
import logging
root * /var/www/docs
file_server
encode gzip
}
# 博客站点
blog.company.com {
import security-headers
import logging
root * /var/www/blog
file_server
encode gzip
}
# 内部管理系统
admin.company.com {
import security-headers
import logging
basicauth {
admin $2a$14$Zkx...
}
reverse_proxy localhost:8080
}
# 开发环境
dev.company.com {
import security-headers
# 使用测试 CA
tls internal
reverse_proxy localhost:3000
}
SaaS 多租户配置 #
caddyfile
# 主应用
app.example.com {
reverse_proxy localhost:3000
}
# 租户子域名
*.app.example.com {
# 提取租户 ID
@tenant host {
labels.0
}
reverse_proxy localhost:3000 {
header_up X-Tenant-ID {labels.0}
}
}
# 自定义域名
# 需要动态配置或使用 API
本地开发配置 #
caddyfile
# 本地开发环境
{
local_certs
}
# 项目 1
project1.localhost {
reverse_proxy localhost:3001
tls internal
}
# 项目 2
project2.localhost {
reverse_proxy localhost:3002
tls internal
}
# 项目 3
project3.localhost {
root * /var/www/project3
file_server
tls internal
}
# API 网关
api.localhost {
handle /users/* {
reverse_proxy localhost:4001
}
handle /orders/* {
reverse_proxy localhost:4002
}
handle /products/* {
reverse_proxy localhost:4003
}
tls internal
}
管理 API #
查看站点配置 #
bash
# 查看所有站点
curl localhost:2019/config/apps/http/servers | jq
# 查看特定服务器
curl localhost:2019/config/apps/http/servers/srv0 | jq
动态添加站点 #
bash
# 添加新站点
curl -X POST \
localhost:2019/config/apps/http/servers/srv0/routes \
-H "Content-Type: application/json" \
-d '{
"match": [{"host": ["new.example.com"]}],
"handle": [{
"handler": "subroute",
"routes": [{
"handle": [{
"handler": "static_response",
"body": "New Site"
}]
}]
}],
"terminal": true
}'
动态删除站点 #
bash
# 删除站点(根据索引)
curl -X DELETE \
localhost:2019/config/apps/http/servers/srv0/routes/0
最佳实践 #
1. 配置文件组织 #
text
/etc/caddy/
├── Caddyfile # 主配置文件
├── sites/ # 站点配置目录
│ ├── main.caddyfile
│ ├── api.caddyfile
│ └── blog.caddyfile
└── snippets/ # 共享片段
├── security.caddyfile
└── logging.caddyfile
2. 使用片段复用配置 #
caddyfile
# 避免重复配置
(common) {
encode gzip zstd
header -Server
}
site1.example.com {
import common
# ...
}
3. 合理使用重定向 #
caddyfile
# 规范化域名
www.example.com {
redir https://example.com{uri} permanent
}
# 主站点
example.com {
# ...
}
4. 分离日志 #
caddyfile
# 每个站点独立日志
log {
output file /var/log/caddy/{host}.log
}
下一步 #
现在你已经掌握了虚拟主机配置,接下来学习 SSL/HTTPS 配置 了解如何管理 SSL 证书!
最后更新:2026-03-28