由于文章内容较长,在此分为三个部分:
上:基础工作和创建mysql容器
中:创建配置php-fpm和nginx容器
下:安装typecho及Lets Encrypt证书(本文)
安装typecho
我们删除掉 ~/docker-blog/website/blog
目录下的 index.php
和 hello.html
文件, 然后下载 typecho 版本 1.1 (17.10.30)
到此目录下。执行解压操作,命令如下:
wget http://typecho.org/downloads/1.1-17.10.30-release.tar.gz
tar -xzf 1.1-17.10.30-release.tar.gz
rm -f 1.1-17.10.30-release.tar.gz
mv build/* ./
rm -rf build/
现在,访问网站 www.demo.com
,surprise ! 出现了 typecho 的安装界面。
安装界面的配置很简单,有几个点注意一下:数据库地址
填写 mydb
(我们在 docker-compose.yml
给 mysql 容器起的服务(别)名),数据库
、 数据库密码
和 数据库前缀
填写前面 创建配置mysql容器 中配置的信息 blog
和 blog123.
。
点击 确认,开始安装
会弹出 安装程序无法自动创建 config.inc.php 文件
提示信息,我们直接在 ~/docker-blog/website/blog
目录下直接创建 config.inc.php
文件,文件内容安装页面已经给出,这里就是不展示了。点击 创建完毕,继续安装
按钮继续,大功告成!
php pathinfo模式
上面的 大功告成
有点假,你会发现除 index.php
页面,你几乎访问不了其它任何页面。仔细观察访问的页面, e.g. http://www.demo.com/index.php/archives/1/
其中 archives/1/
并不是真实存在的路径,这一部分仅仅是作为 index.php
文件的查询参数,为了优化url才做的,这种模式叫 pathinfo模式
。
nginx 开启 pathinfo模式
有多种方式,这里介绍两种,一种是通过 fastcgi_param PATH_INFO
传参,另一种是通过 rewrite
重写 url。
# fastcgi
location ~ [^/]\.php(/|$) {
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
try_files $fastcgi_script_name =404;
fastcgi_param SCRIPT_FILENAME /var/www/html/blog/$fastcgi_script_name;
}
# url rewrite
location ~ [^/]\.php(/|$) {
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
include fastcgi_params;
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?$1 last;
}
fastcgi_param SCRIPT_FILENAME /var/www/html/blog/$fastcgi_script_name;
}
这里就采用了 fastcgi_param
传参方式。为了简化和复用配置信息,我们把配置信息写到单独的一个文件,名字叫:pathinfo_config
。这里没有添加 .conf
文件后缀,原因是前面 nginx
配置中有一行 include /etc/nginx/conf.d/*.conf;
会把所有以 .conf
结尾的文件包含进去,对于不使用 php
编写的程序,这一点视为 不必要的浪费 。
现在,把配置修改后,重新启动 nginx 服务,就可以访问其它页面了。
cd ~/docker-blog
docker-compose restart nginx
安装配置证书
证书的的安装方式
DNS
通过添加 记录类型为TXT
域名解析记录来完成域名解析。主机记录
和记录值
需要根据具体的证书供应商来决定。文件验证
通过在网站根目录下,创建指定文件(一般存储在/.well-known/目录下)来验证。
Lets Encrypt
一个免费、自动化、开放的证书签发服务。它由 ISRG(Internet Security Research Group,互联网安全研究小组)提供服务,而 ISRG 是来自于美国加利福尼亚州的一个公益组织。Let's Encrypt 得到了 Mozilla、Cisco、Akamai、Electronic Frontier Foundation 和 Chrome 等众多公司和机构的支持,发展十分迅猛。
特点:免费、安装简单,但只有90天的有效期(这个可以通过脚本定期更新,做到永久使用)。
安装Lets Encrypt证书
本次使用 acme.sh 工具来生成 Let's Encrypt 证书,由于使用了 Docker,并且 web
服务已经运行了,这里就选用 Webroot mode。在执行命令之前,我们需要对 nginx 做一些配置,让其能正常访问站点目录下的 well-known
目录,编辑 ~/docker-blog/nginx/conf/vhost/blog.conf
文件:
Webroot mode 支持证书自动刷新,为每60天刷新一次
关于 acme.sh 工具的安装及使用,请参考:https://github.com/Neilpang/acme.sh 页面
server {
listen 80;
server_name www.demo.com;
index index.html index.htm index.php;
root /usr/share/nginx/html/blog;
# 添加这下面的配置
location ~ /.well-known {
allow all;
}
location ~ [^/]\.php(/|$) {
# ...
}
# 省略其余部分
}
再执行以下命令:
cd ~/docker-blog
docker-compose restart nginx
acme.sh --issue -d www.demo.com -w /root/docker-blog/website/blog
命令执行成功后,可以看到证书生成后存放的路径(由于我这边宿主机器还安装的 lnmp 软件,只是停止了 nginx,证书直接生成到了 /usr/local/nginx/conf/ssl/www.demo.com
目录下,生成的目录可能不同,这里要以实际路径为准。)
nginx配置证书
上面把证书生成成功后,我们先修改 ~/docker-blog/docker-compose.yml
文件,挂载证书目录到 nginx 服务容器中(这里只展示了 nginx 配置服务节点):
version: '3.7'
services:
nginx:
image: nginx:1.15.9
restart: on-failure
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/conf/vhost:/etc/nginx/conf.d:ro
- ./nginx/log:/var/log/nginx
- ./website:/usr/share/nginx/html
# 添加下面这一行
- /usr/local/nginx/conf/ssl:/etc/ssl/certs
environment:
- "TZ=Asia/Shanghai"
depends_on:
- php-fpm
networks:
- blog-net
接下来配置 nginx,修改 ~/docker-blog/nginx/conf/vhost/blog.conf
文件,文件整体内容如下:
server {
listen 80;
server_name www.demo.com;
index index.html index.htm index.php;
root /usr/share/nginx/html/blog;
location ~ /.well-known {
allow all;
}
location / {
rewrite ^/(.*)$ https://www.demo.com/$1 permanent;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
expires 1h;
}
location ~ .*\.(js|css)?$ {
expires 12h;
}
location ~ /\. {
deny all;
}
}
server {
listen 443 ssl http2;
server_name www.demo.com;
index index.html index.htm index.php;
root /usr/share/nginx/html/blog;
ssl_certificate /etc/ssl/certs/www.demo.com/fullchain.cer;
ssl_certificate_key /etc/ssl/certs/www.demo.com/doc.vkarz.com.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5";
# openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
location ~ [^/]\.php(/|$) {
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
include fastcgi_params;
include /etc/nginx/conf.d/pathinfo_config;
fastcgi_param SCRIPT_FILENAME /var/www/html/blog/$fastcgi_script_name;
}
}
注:
ssl on;
这一行指令在nginx 1.15.0
版本后已经被废弃。注意
location ~ /.well-known
和loction /
, 这两个location
的配置位置,nginx 做url匹配是从上到下依次执行的,acme.sh 再次刷新证书时需要用到这些配置。
下面重启一下服务,就可以查看效果了:
cd ~/docker-blog
docker-compose down
docker-compose up -d
增加网站的安全性
网站的安全
在配置容器时,应该注意避免暴露不必要的端口到外面,给居心叵测之人提供攻击的便利,应充分利用 docker network
的功能,使各个容器处于同一局域(内)网内,之间能正常访问。
下面介绍一些常用的 http 安全响应头
HSTS(HTTP Strict Transport Security)
这是一个安全功能,浏览器只能通过HTTPS访问当前资源,而不是HTTP,当然前提条件是你的网站具备https功能。关于HSTS
更多信息请访问:HTTP Strict Transport Security。X-XSS-Protection
启用XSS过滤,检测跨站脚本攻击(XSS)。更多信息请访问:MDN X-XSS-ProtectionX-Content-Type-Options
响应首部相当于一个提示标志,被服务器用来提示客户端一定要遵循在 Content-Type 首部中对 MIME 类型 的设定,而不能对其进行修改。这就禁用了客户端的 MIME 类型嗅探行为。更多信息请访问:X-Content-Type-OptionsX-Frame-Options
响应头是用来给浏览器指示允许一个页面可否在 <frame>, <iframe> 或者 <object> 中展现的标记。网站可以使用此功能,来确保自己网站的内容没有被嵌到别人的网站中去,也从而避免了点击劫持 (clickjacking) 的攻击。更多信息请访问:X-Frame-Options 响应头
我们可以在 nginx
server配置节中加入上面的介绍的响应头,来防止一些问题的发生。但也要注意,如果加入上面,可能会发生的问题,e.g. 使用富文本编辑器,页面包含 <iframe>等,下面我们强化一下 ~/docker-blog/nginx/conf/vhost/blog.conf
文件(这将是最终配置):
# 省略了80端口的配置信息
server {
listen 443 ssl http2;
server_name www.demo.com;
index index.html index.htm index.php;
root /usr/share/nginx/html/blog;
# certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
ssl_certificate /etc/ssl/certs/www.demo.com/fullchain.cer;
ssl_certificate_key /etc/ssl/certs/www.demo.com/www.demo.com.key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /etc/ssl/certs/dhparam.pem;
# intermediate configuration. tweak to your needs.
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
# verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /etc/ssl/certs/www.demo.com/ca.cer;
# HSTS (ngx_http_headers_module is required) (31536000 seconds = 1 year)
add_header Strict-Transport-Security "max-age=31536000; preload";
location ~ [^/]\.php(/|$) {
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
include fastcgi_params;
include /etc/nginx/conf.d/pathinfo_config;
fastcgi_param SCRIPT_FILENAME /var/www/html/blog/$fastcgi_script_name;
}
}
可以使用 Mozilla SSL Configuration Generator 来生成相应的配置。
配置完成后,我们可以在 Qualys SSL Labs 上来评测一下我们的网站。
宿主主机的安全
平时,对于我们来说,服务器常用的端口就是那么几个,其它端口我们可以选择关掉。
TCP:22
Linux SSH登录使用TCP:80
,TCP:433
Web服务器端口ICMP
PING服务TCP:20,21
FTP 上传或下载文件
可以使用 netstat -ntpl
查看开放的端口,及占用的程序。
如果考虑服务器集群之类的,我们只开放相应的局域网IP段就可以了。现在大部分购买的主机都自还安全组设置,即使我们没有关闭服务器的端口,外网也是不能轻易访问的。
关于问题的排查
查看容器错误
查看容器的错误,通常都使用 docker logs <container id>
命令,输出详细的日志信息。
查看程序错误
- 对于 php 程序,编辑
php.ini
文件,把display_errors
和display_startup_errors
都设置为On
,即可查看错误日志,记得问题处理后,再关闭相应的设置。 - 对于 nginx 可以在启动容器时添加调试命令来查看日志信息(如果没有信息,请排查配置文件,是否开启了调试日志输出)
通过配置 docker-compose.yml
文件来开启 nginx 调试模式:
web:
image: nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
command: [nginx-debug, '-g', 'daemon off;']
nginx 配置输出调试信息:
user www-data;
worker_processes 1;
error_log /var/log/nginx/debug.log debug;
# 省略其余配置
附一些遇到的问题及解散方案:
上传图片失败
请参考:Typecho - 上传图片失败解决办法并修改图片大小限制
最后 Ending
文章最后的部分写的比较粗,因为里面涵盖了太多的知识。小人才疏学浅,不敢妄谈。
关于 typecho 的更新信息,还请自行搜索解决,现在贴几个比较有用的地址:
- Typecho主题模板站: https://typecho.me/
- new bytecats 简洁博客主题:https://typecho.me/1169.html
- Pui 简洁双栏模板: https://typecho.me/1119.html
如若文章中有不当之处,还请看官指出,小弟不胜感激!
本文由 waynelone 创作,采用 知识共享署名4.0 国际许可协议进行许可。
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。