3.1 静态文件服务概述
3.1.1 什么是静态文件服务
静态文件服务是Web服务器的基本功能之一,用于直接提供存储在服务器文件系统中的文件,如HTML、CSS、JavaScript、图片、视频等。Caddy的静态文件服务功能强大且易于配置。
3.1.2 Caddy静态文件服务的特点
- 零配置启动:最简单的情况下只需一行配置
- 自动MIME类型检测:根据文件扩展名自动设置Content-Type
- 目录浏览:可选的目录列表功能
- 范围请求支持:支持HTTP Range请求,适合大文件下载
- 压缩支持:自动压缩响应内容
- 缓存优化:智能的缓存头设置
- 安全特性:文件隐藏、路径遍历保护等
3.2 基础文件服务配置
3.2.1 最简配置
# 最简单的静态文件服务
localhost {
file_server
}
这个配置将当前目录作为网站根目录,提供静态文件服务。
3.2.2 指定根目录
# 指定网站根目录
example.com {
root * /var/www/html
file_server
}
# 不同路径指定不同根目录
example.com {
root /static/* /var/www/static
root /uploads/* /var/www/uploads
root * /var/www/html
file_server
}
3.2.3 启用目录浏览
# 启用目录浏览
example.com {
root * /var/www/html
file_server browse
}
# 仅在特定路径启用目录浏览
example.com {
root * /var/www/html
@browse {
path /files/*
}
file_server @browse browse
file_server
}
3.3 高级文件服务配置
3.3.1 索引文件配置
example.com {
root * /var/www/html
# 自定义索引文件
file_server {
index index.html index.htm default.html
}
}
# 禁用索引文件
example.com {
root * /var/www/html
file_server {
index off
}
}
3.3.2 文件隐藏
example.com {
root * /var/www/html
file_server {
# 隐藏特定文件和目录
hide .htaccess .git .env .DS_Store
# 使用通配符隐藏
hide *.log *.tmp
# 隐藏以点开头的文件
hide .*
}
}
3.3.3 预压缩文件支持
example.com {
root * /var/www/html
# 启用预压缩文件支持
file_server {
precompressed gzip br zstd
}
# 同时启用动态压缩
encode gzip br
}
3.3.4 自定义错误页面
example.com {
root * /var/www/html
# 自定义404页面
handle_errors {
@404 {
expression {http.error.status_code} == 404
}
rewrite @404 /404.html
file_server
}
file_server
}
3.4 路径处理和重写
3.4.1 URL重写
example.com {
root * /var/www/html
# 简单重写
rewrite /old-path /new-path
# 使用正则表达式
rewrite ^/user/([0-9]+)$ /users.html?id=$1
# 条件重写
@mobile {
header User-Agent *Mobile*
}
rewrite @mobile /mobile{uri}
file_server
}
3.4.2 try_files指令
# SPA应用配置
example.com {
root * /var/www/spa
# 尝试文件,最后回退到index.html
try_files {path} {path}/ /index.html
file_server
}
# 多级回退
example.com {
root * /var/www/html
# 尝试多个文件
try_files {path} {path}.html {path}/index.html /404.html
file_server
}
3.4.3 路径清理
example.com {
root * /var/www/html
# 移除URL中的.html扩展名
@html {
path *.html
}
redir @html {path_except_last}.html{query} 301
# 尝试添加.html扩展名
try_files {path} {path}.html {path}/index.html
file_server
}
3.5 缓存策略配置
3.5.1 基本缓存配置
example.com {
root * /var/www/html
# 静态资源长期缓存
@static {
file
path *.css *.js *.png *.jpg *.gif *.ico *.svg *.woff *.woff2
}
header @static {
Cache-Control "public, max-age=31536000, immutable"
Expires "Thu, 31 Dec 2037 23:55:55 GMT"
}
# HTML文件短期缓存
@html {
file
path *.html
}
header @html {
Cache-Control "public, max-age=3600"
}
file_server
}
3.5.2 版本化资源缓存
example.com {
root * /var/www/html
# 版本化资源(包含hash的文件)
@versioned {
path_regexp versioned \.(\w{8,})\.(css|js|png|jpg|gif)$
}
header @versioned {
Cache-Control "public, max-age=31536000, immutable"
}
# 普通静态资源
@static {
file
path *.css *.js *.png *.jpg *.gif
not path_regexp \.(\w{8,})\.(css|js|png|jpg|gif)$
}
header @static {
Cache-Control "public, max-age=86400"
}
file_server
}
3.5.3 条件缓存
example.com {
root * /var/www/html
# 基于文件修改时间的缓存
@recent {
file
file_modified_before 1h
}
header @recent {
Cache-Control "public, max-age=300"
}
# 开发环境禁用缓存
@dev {
query debug=true
}
header @dev {
Cache-Control "no-cache, no-store, must-revalidate"
Pragma "no-cache"
Expires "0"
}
file_server
}
3.6 安全配置
3.6.1 访问控制
example.com {
root * /var/www/html
# 禁止访问敏感文件
@forbidden {
path *.env *.config *.log *.bak
path /admin/* /.git/* /config/*
}
respond @forbidden "Access denied" 403
# IP白名单
@admin {
path /admin/*
}
@allowed_ips {
remote_ip 192.168.1.0/24 10.0.0.0/8
}
respond @admin not @allowed_ips "Access denied" 403
file_server {
hide .env .git .config
}
}
3.6.2 防盗链配置
example.com {
root * /var/www/html
# 防止图片盗链
@images {
path *.jpg *.png *.gif *.webp
}
@hotlink {
not header Referer
not header Referer *example.com*
not header Referer *localhost*
}
# 返回防盗链图片或403错误
respond @images @hotlink "Hotlinking not allowed" 403
# 或者重定向到防盗链图片
# redir @images @hotlink /images/no-hotlink.png
file_server
}
3.6.3 安全头部
example.com {
root * /var/www/html
# 安全头部配置
header {
# 防止点击劫持
X-Frame-Options "DENY"
# 防止MIME类型嗅探
X-Content-Type-Options "nosniff"
# XSS保护
X-XSS-Protection "1; mode=block"
# 引用策略
Referrer-Policy "strict-origin-when-cross-origin"
# 内容安全策略
Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"
}
file_server
}
3.7 性能优化
3.7.1 压缩配置
example.com {
root * /var/www/html
# 启用多种压缩算法
encode {
gzip 6
zstd
br 6
# 指定压缩的文件类型
match {
header Content-Type text/*
header Content-Type application/json
header Content-Type application/javascript
header Content-Type application/xml
}
# 最小压缩大小
minimum_length 1024
}
file_server {
# 预压缩文件支持
precompressed gzip br zstd
}
}
3.7.2 并发和连接优化
{
# 全局配置
servers {
protocols h1 h2 h3
max_header_size 16KB
read_timeout 30s
write_timeout 30s
idle_timeout 120s
}
}
example.com {
root * /var/www/html
# 启用HTTP/2服务器推送
@push {
path /
}
push @push /css/style.css /js/app.js
file_server
}
3.7.3 大文件处理
example.com {
root * /var/www/html
# 大文件下载配置
@large_files {
path *.zip *.tar.gz *.iso *.dmg *.exe
}
# 禁用大文件压缩
encode {
match {
not path *.zip *.tar.gz *.iso *.dmg *.exe
}
gzip
}
# 大文件缓存配置
header @large_files {
Cache-Control "public, max-age=604800"
# 启用范围请求
Accept-Ranges "bytes"
}
file_server
}
3.8 多站点和虚拟主机
3.8.1 基于域名的虚拟主机
# 主站点
example.com {
root * /var/www/example.com
file_server
}
# 子域名站点
blog.example.com {
root * /var/www/blog
file_server browse
}
# 开发站点
dev.example.com {
root * /var/www/dev
# 开发环境特殊配置
header {
X-Environment "development"
}
file_server browse
}
# 通配符子域名
*.example.com {
root * /var/www/subdomains/{labels.1}
# 检查目录是否存在
@exists {
file {
root /var/www/subdomains/{labels.1}
try_files /index.html
}
}
handle @exists {
file_server
}
# 默认处理
respond "Subdomain not found" 404
}
3.8.2 基于端口的虚拟主机
# 主站点(端口80/443)
example.com {
root * /var/www/main
file_server
}
# 管理界面(端口8080)
example.com:8080 {
root * /var/www/admin
# 基本认证
basicauth {
admin $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNqq9qB6FY9gZKOOdOoKw6Uw.
}
file_server browse
}
# API文档(端口8081)
example.com:8081 {
root * /var/www/docs
file_server browse
}
3.8.3 基于路径的虚拟主机
example.com {
# 主站点
handle / {
root * /var/www/main
file_server
}
# 博客子路径
handle /blog/* {
root * /var/www/blog
uri strip_prefix /blog
file_server
}
# 文档子路径
handle /docs/* {
root * /var/www/docs
uri strip_prefix /docs
file_server browse
}
# API子路径
handle /api/* {
reverse_proxy localhost:8080
}
}
3.9 日志和监控
3.9.1 访问日志配置
example.com {
root * /var/www/html
# 基本访问日志
log {
output file /var/log/caddy/access.log {
roll_size 100mb
roll_keep 10
roll_keep_for 720h
}
format json
}
file_server
}
3.9.2 自定义日志格式
example.com {
root * /var/www/html
# 自定义日志格式
log {
output file /var/log/caddy/access.log
format single_field common_log
level INFO
}
# 错误日志
log error {
output file /var/log/caddy/error.log
level ERROR
}
file_server
}
3.9.3 条件日志
example.com {
root * /var/www/html
# 只记录错误和特定路径的访问
@log_condition {
or {
status 4xx 5xx
path /admin/* /api/*
}
}
log @log_condition {
output file /var/log/caddy/filtered.log
format json
}
file_server
}
3.10 实战案例
3.10.1 个人博客站点
# 个人博客配置
blog.example.com {
root * /var/www/blog
# 启用压缩
encode gzip
# 静态资源缓存
@static {
path *.css *.js *.png *.jpg *.gif *.ico *.svg
}
header @static {
Cache-Control "public, max-age=31536000"
}
# HTML缓存
@html {
path *.html
}
header @html {
Cache-Control "public, max-age=3600"
}
# 安全头部
header {
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
Referrer-Policy "strict-origin-when-cross-origin"
}
# 自定义404页面
handle_errors {
@404 {
expression {http.error.status_code} == 404
}
rewrite @404 /404.html
file_server
}
file_server
}
3.10.2 企业官网
# 企业官网配置
www.company.com, company.com {
# 重定向到www
@non_www {
host company.com
}
redir @non_www https://www.company.com{uri} 301
root * /var/www/company
# 启用多种压缩
encode gzip br
# 静态资源优化
@assets {
path /assets/* /css/* /js/* /images/*
}
header @assets {
Cache-Control "public, max-age=31536000, immutable"
Vary "Accept-Encoding"
}
# 安全配置
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Frame-Options "DENY"
X-Content-Type-Options "nosniff"
X-XSS-Protection "1; mode=block"
Referrer-Policy "strict-origin-when-cross-origin"
Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://www.google-analytics.com; style-src 'self' 'unsafe-inline'"
}
# 隐藏敏感文件
file_server {
hide .git .env .htaccess
}
# 访问日志
log {
output file /var/log/caddy/company-access.log {
roll_size 100mb
roll_keep 30
}
format json
}
}
3.10.3 文件下载站点
# 文件下载站点
files.example.com {
root * /var/www/files
# 启用目录浏览
file_server browse {
hide .DS_Store Thumbs.db
}
# 大文件处理
@large {
path *.zip *.tar.gz *.iso *.dmg *.exe *.msi
}
# 大文件不压缩
encode {
match {
not path *.zip *.tar.gz *.iso *.dmg *.exe *.msi
}
gzip
}
# 下载文件缓存
header @large {
Cache-Control "public, max-age=604800"
Content-Disposition "attachment"
}
# 防盗链
@hotlink {
not header Referer
not header Referer *example.com*
}
respond @large @hotlink "Direct linking not allowed" 403
# 下载统计日志
log {
output file /var/log/caddy/downloads.log
format json
include http.request.uri http.request.remote_ip http.request.headers.User-Agent
}
}
本章总结
本章我们全面学习了Caddy的静态文件服务功能:
- 基础配置:掌握了静态文件服务的基本配置方法
- 高级功能:学习了索引文件、文件隐藏、预压缩等高级特性
- 路径处理:了解了URL重写、try_files等路径处理技巧
- 缓存策略:掌握了各种缓存配置和优化方法
- 安全配置:学习了访问控制、防盗链、安全头部等安全措施
- 性能优化:了解了压缩、并发、大文件处理等性能优化技巧
- 多站点管理:掌握了虚拟主机的配置方法
- 日志监控:学习了访问日志和监控的配置
- 实战案例:通过实际案例巩固了所学知识
通过本章的学习,你应该能够: - 配置高性能的静态文件服务 - 实现复杂的路径处理和重写规则 - 应用适当的缓存和安全策略 - 管理多站点和虚拟主机 - 监控和优化文件服务性能
练习题
基础练习
基本文件服务
- 创建一个简单的静态网站
- 配置自定义根目录和索引文件
- 启用目录浏览功能
文件隐藏和安全
- 隐藏敏感文件和目录
- 配置基本的安全头部
- 实现简单的访问控制
缓存配置
- 为不同类型的文件配置不同的缓存策略
- 实现版本化资源的长期缓存
- 配置开发环境的缓存禁用
进阶练习
路径重写
- 实现URL美化(去除.html扩展名)
- 配置SPA应用的路由回退
- 实现基于条件的路径重写
性能优化
- 配置多种压缩算法
- 实现预压缩文件支持
- 优化大文件的处理
防盗链和安全
- 实现图片防盗链保护
- 配置完整的安全头部
- 实现基于IP的访问控制
实战练习
多站点部署
- 配置基于域名的多个虚拟主机
- 实现基于路径的站点分离
- 配置通配符子域名处理
企业级配置
- 创建一个完整的企业官网配置
- 包含性能优化、安全配置、日志监控
- 实现多环境的配置管理
文件服务器
- 搭建一个功能完整的文件下载服务器
- 包含目录浏览、防盗链、下载统计
- 实现大文件的优化处理
下一章我们将学习Caddy的反向代理功能,这是现代Web架构中的重要组件。