Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

37.3. /etc/caddy/Caddyfile

https://caddyserver.com/docs/caddyfile

37.3.1. 导入配置文件 Caddyfile.d

			
[root@netkiller caddy]# cat /etc/caddy/Caddyfile
# The Caddyfile is an easy way to configure your Caddy web server.
#
# https://caddyserver.com/docs/caddyfile


# The configuration below serves a welcome page over HTTP on port 80.  To use
# your own domain name with automatic HTTPS, ensure your A/AAAA DNS record is
# pointing to this machine's public IP, then replace `http://` with your domain
# name.  Refer to the documentation for full instructions on the address
# specification.
#
# https://caddyserver.com/docs/caddyfile/concepts#addresses
http:// {

    # Set this path to your site's directory.
    root * /usr/share/caddy

    # Enable the static file server.
    file_server

    # Another common task is to set up a reverse proxy:
    # reverse_proxy localhost:8080

    # Or serve a PHP site through php-fpm:
    # php_fastcgi localhost:9000

    # Refer to the directive documentation for more options.
    # https://caddyserver.com/docs/caddyfile/directives

}


# As an alternative to editing the above site block, you can add your own site
# block files in the Caddyfile.d directory, and they will be included as long
# as they use the .caddyfile extension.
import Caddyfile.d/*.caddyfile
			
			

在 /etc/caddy/Caddyfile.d 下创建虚拟机文件

			
cat >> /etc/caddy/Caddyfile.d/www.netkiller.cn.caddyfile <<EOF
www.netkiller.cn {
	root * /var/www/netkiller
	encode
	file_server
}
EOF			
			
			

37.3.2. 监听地址

			
localhost
example.com
:443
http://example.com
localhost:8080
127.0.0.1
[::1]:2015
example.com/foo/*
*.example.com
http://			
			
			
			
localhost:8080, example.com, www.example.com			
			
			

泛解析

			
*.example.com			
			
			

37.3.3. 日志

37.3.3.1. 全局日志

			
[root@spiritcloudp ~]# cat /etc/caddy/Caddyfile
{
    log {
        output file /var/log/caddy/access.log
    }
}
:80 {
        root * /usr/share/caddy
        file_server
}    


import Caddyfile.d/*.caddyfile
			
				

创建日志目录

			
[root@spiritcloudp ~]# mkdir /var/log/caddy
[root@spiritcloudp ~]# chown caddy:caddy /var/log/caddy
			
				

重启,查看日志

			
[root@spiritcloudp ~]# systemctl restart caddy.service

[root@spiritcloudp ~]# tail -f /var/log/caddy/access.log 
{"level":"warn","ts":1758185034.389622,"logger":"http","msg":"HTTP/2 skipped because it requires TLS","network":"tcp","addr":":80"}
{"level":"warn","ts":1758185034.3896267,"logger":"http","msg":"HTTP/3 skipped because it requires TLS","network":"tcp","addr":":80"}
{"level":"info","ts":1758185034.3896298,"logger":"http.log","msg":"server running","name":"srv1","protocols":["h1","h2","h3"]}
{"level":"warn","ts":1758185034.3896565,"logger":"http","msg":"HTTP/2 skipped because it requires TLS","network":"tcp","addr":":8000"}
{"level":"warn","ts":1758185034.3896601,"logger":"http","msg":"HTTP/3 skipped because it requires TLS","network":"tcp","addr":":8000"}
{"level":"info","ts":1758185034.3896632,"logger":"http.log","msg":"server running","name":"srv2","protocols":["h1","h2","h3"]}
{"level":"info","ts":1758185034.3896668,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["lsyj.aigcsst.cn","www.spiritcloudp.cn","api.spiritcloudp.cn"]}
{"level":"info","ts":1758185034.3909,"msg":"autosaved config (load with --resume flag)","file":"/var/lib/caddy/.config/caddy/autosave.json"}
{"level":"info","ts":1758185034.3928576,"logger":"tls","msg":"storage cleaning happened too recently; skipping for now","storage":"FileStorage:/var/lib/caddy/.local/share/caddy","instance":"8fff3074-ff2d-42a4-840b-d45b8f27524c","try_again":1758271434.392856,"try_again_in":86399.999999612}
{"level":"info","ts":1758185034.392918,"logger":"tls","msg":"finished cleaning storage units"}
			
				

37.3.3.2. 虚拟主机日志

				
example.com {
    reverse_proxy * 127.0.0.1:8080
    log {
        output file /var/log/caddy/example.com/access.log {
            roll_size 25MB
            roll_keep 10
            roll_keep_for 24h
        }
    }
}				
				
				

37.3.4. 反向代理

			
http://api.netkiller.cn {
    reverse_proxy /* http://192.168.30.10:8080
    tls netkiller@msn.com
}			
			
			

推送 X-Forwarded-For 头

			
http://www.netkiller.cn {

    root * /opt/netkiller.cn/www.netkiller.cn
    file_server

    reverse_proxy /api/* 192.168.30.10:8080 {
	    header_up X-Real-IP {http.request.remote.host}
	    header_up X-Forwarded-For {http.request.remote.host}
	}

}			
			
			

反向代理自签名证书,添加 tls_insecure_skip_verify 配置项

			
netkiller.cn {
    reverse_proxy * {
        to https://192.168.0.10
        transport http {
            tls_insecure_skip_verify
        }
    }
}

api.netkiller.cn {
    reverse_proxy * {
        to 192.168.10.10:443
        transport http {
            tls
            tls_insecure_skip_verify
        }
    }
}
			
			

反向代理URL前缀问题

			
举例:
www.netkiller.cn {
	reverse_proxy /api/* http://api.netkiller.cn:8080
}
访问URL: 
http://www.netkiller.cn/api/adduser

实际访问的URL是:
http://api.netkiller.cn:8080/api/adduser

我们需要的URL是:
http://api.netkiller.cn:8080/adduser
			
			

解决方案

			
www.netkiller.cn {
	route /api* {
    	uri strip_prefix /api
		reverse_proxy api.netkiller.cn:8088
	}
}	
			
			

37.3.5. Let's Encrypt 免费 SSL 证书

准备域名

			
neo@MacBook-Pro-Neo-3 ~> dig chat.netkiller.cn

; <<>> DiG 9.10.6 <<>> chat.netkiller.cn
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24569
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;chat.netkiller.cn.		IN	A

;; ANSWER SECTION:
chat.netkiller.cn.	600	IN	A	8.219.73.35

;; Query time: 109 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Mon Jul 04 19:31:02 CST 2022
;; MSG SIZE  rcvd: 62			
			
			

这里准备了一个域名 chat.netkiller.cn 并且已经做好了解析

安装 certbot 工具

			
[root@netkiller ~]# dnf install -y certbot			
			
			

生成 SSL 证书

			
[root@netkiller ~]# certbot certonly --manual
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): netkiller@msn.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
Account registered.
Please enter the domain name(s) you would like on your certificate (comma and/or
space separated) (Enter 'c' to cancel): chat.netkiller.cn
Requesting a certificate for chat.netkiller.cn

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Create a file containing just this data:

h27fzgPCxW9Kmhcd9af3YPwuYFCizmZZ_JLvoCeNSQ4.sD2SO-myCgf0JjzYqkA9LA3nN9Pau98bk_fmlBWmzII

And make it available on your web server at this URL:

http://chat.netkiller.cn/.well-known/acme-challenge/h27fzgPCxW9Kmhcd9af3YPwuYFCizmZZ_JLvoCeNSQ4

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
			
			

此时不要按回车继续,放在一边,开一个新终端窗口,配置 Caddy 服务器

			
[root@netkiller ~]# vim /etc/caddy/Caddyfile
chat.netkiller.cn:80 {
        respond /.well-known/acme-challenge/h27fzgPCxW9Kmhcd9af3YPwuYFCizmZZ_JLvoCeNSQ4 "h27fzgPCxW9Kmhcd9af3YPwuYFCizmZZ_JLvoCeNSQ4.sD2SO-myCgf0JjzYqkA9LA3nN9Pau98bk_fmlBWmzII" 200
}

[root@netkiller ~]# systemctl reload caddy

[root@netkiller ~]# curl http://chat.netkiller.cn/.well-known/acme-challenge/h27fzgPCxW9Kmhcd9af3YPwuYFCizmZZ_JLvoCeNSQ4
h27fzgPCxW9Kmhcd9af3YPwuYFCizmZZ_JLvoCeNSQ4.sD2SO-myCgf0JjzYqkA9LA3nN9Pau98bk_fmlBWmzII
			
			

回到 certonly 按回车继续

			
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/chat.netkiller.cn/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/chat.netkiller.cn/privkey.pem
This certificate expires on 2022-10-02.
These files will be updated when the certificate renews.

NEXT STEPS:
- This certificate will not be renewed automatically. Autorenewal of --manual certificates requires the use of an authentication hook script (--manual-auth-hook) but one was not provided. To renew this certificate, repeat this same certbot command before the certificate's expiry date.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -			
			
			

证书创建完毕,接着配置 Caddy Web 服务器

			
[root@netkiller ~]# vim /etc/caddy/Caddyfile			
chat.netkiller.cn:80 {
        respond /.well-known/acme-challenge/h27fzgPCxW9Kmhcd9af3YPwuYFCizmZZ_JLvoCeNSQ4 "h27fzgPCxW9Kmhcd9af3YPwuYFCizmZZ_JLvoCeNSQ4.sD2SO-myCgf0JjzYqkA9LA3nN9Pau98bk_fmlBWmzII" 200
}
chat.netkiller.cn {
        respond "Hello world!!!"
}

[root@netkiller ~]# systemctl reload caddy

[root@netkiller ~]# curl https://chat.netkiller.cn
Hello world!!!
			
			

使用 MySSL 工具检查证书 https://myssl.com/chat.netkiller.cn?domain=chat.netkiller.cn

37.3.6. 返回内容

			
chat.netkiller.cn {
	respond "Hello, world!"
}			
			
			

			
[root@netkiller ~]# curl https://chat.netkiller.cn
Hello, world!			
			
			
			
[root@netkiller ~]# cat /etc/caddy/Caddyfile
chat.netkiller.cn {
	respond /.well-known/acme-challenge/V7-P_SdeHeXDk3qyj0HhvYrrQ2PFbZrKv4ck6FNQSys "V7-P_SdeHeXDk3qyj0HhvYrrQ2PFbZrKv4ck6FNQSys.sD2SO-myCgf0JjzYqkA9LA3nN9Pau98bk_fmlBWmzII" 200
}

			
[root@netkiller ~]# curl https://chat.netkiller.cn/.well-known/acme-challenge/V7-P_SdeHeXDk3qyj0HhvYrrQ2PFbZrKv4ck6FNQSys
V7-P_SdeHeXDk3qyj0HhvYrrQ2PFbZrKv4ck6FNQSys.sD2SO-myCgf0JjzYqkA9LA3nN9Pau98bk_fmlBWmzII			
			
			

route 路由配置

			
www.netkiller.cn {
    route /api/* {
        reverse_proxy localhost:8082
    }

    route /* {
        root * /opt/caddy/www
        file_server
    }
    route /78oo3JqVhU.txt {
        respond "9923fd3daae700df0417f1e4b1b1cbd9"
    }

    log {
        output file /var/log/caddy/access.log
    }

}			
			
			

37.3.8. 绑定域名

绑定多个域名

			
example.com www.example.com example.net {
    root * /var/www/html
    file_server
    # 其他通用配置...
}
			
			

注意多个域名绑定可能影响到 SSL证书,此时需要分开写。

			
www.example.com {
    root * /var/www/html
    file_server
    # 其他通用配置...
}			
www.example.net {
    root * /var/www/html
    file_server
    # 其他通用配置...
}