一、前情概要:
皇天不负有心人,前面用了将近两天的时间,完成了Shynet的搭建,这次又用了接近一天半的时间,才完成本次的Shynet适配HTTPS。没想到查找了很多文档,都没有结论,回过头来才发现,是自己太笨。
本教程将介绍如何给Shynet配置https服务。上一章讲述了通过Docker配置Shynet,通过Docker容器安装PostgreSQL以及安装并配置Shynet。当时我提到自己还不知道怎么配置HTTPS,这次配置HTTPS成功并把经验分享给大家,算是原创吧。
还要注意的一点是,配置HTTPS服务后,前台访问也要用HTTPS协议,如果用HTTP协议就会无法访问。
二、搭建环境
1)Docker version 25.0.3, build 4debf41
2)CentOS Linux release 7.9.2009 (Core)
三、配置Shynet文件
1、传入SSL配置文件
首先,我们将SSL证书下载到服务,然后我们通过docker cp命令,将SSL证书传入到Docker容器中。
docker cp /var/certificate/fangjunyu.com_bundle.crt shynet:/usr/src/shynet/
Successfully copied 6.14kB to shynet:/usr/src/shynet/
因为Docker的cp命令只支持单个文件的传递,如果用 docker cp /var/* 等通配符的话,就会报错,因此需要把Shynet SSL配置需要的pem和key证书逐个传入。
特别注意的是,关于证书或者其他需要传入的文件,其权限建议全部修改为 777,即
chmod 777 <file>
这样在配置方面就会减少报错,因为Docker的容器内用户权限很低,也不能用 sudo命令,因此需要先通过 docker cp命令把文件传输到容器外,修改后,再重新拷贝回容器内。
2、编辑Shynet配置文件
首先,在服务器上执行下面的命令,将容器内的 ssl.webserver.sh 和 entrypoint.sh 文件拷贝出来。
docker cp shynet:/usr/src/shynet/entrypoint.sh /var/tmp
Successfully copied 2.05kB to /var/tmp
docker cp shynet:/usr/src/shynet/ssl.webserver.sh /var/tmp
Successfully copied 2.05kB to /var/tmp
1)ssl.webserver 文件内容
#!/bin/bash
# Start Gunicorn processes
echo Launching Shynet web server...
exec gunicorn shynet.wsgi:application \
--bind 0.0.0.0:${PORT:-8080} \
--workers ${NUM_WORKERS:-1} \
--timeout 100 \
--certfile=/usr/src/shynet/fangjunyu.com_bundle.pem \
--keyfile=/usr/src/shynet/fangjunyu.com.key
注意:端口和其他信息都不要变,只需要修改pem和key证书即可,证书为Docker容器内的绝对位置。
2)entrypoint.sh文件内容
cat /var/tmp/entrypoint.sh
#!/bin/bash
if [[ ! $PERFORM_CHECKS_AND_SETUP == False ]]; then
./startup_checks.sh && exec ./ssl.webserver.sh
else
exec ./ssl.webserver.sh
fi
原文件是 webserver.sh 文件,你需要把他们修改为ssl.webserver.sh文件,这是最关键的一点。
然后修改他们的权限
chmod 777 /var/tmp/ssl.webserver.sh
chmod 777 /var/tmp/entrypoint.sh
因为Docker容器内的权限很低,因此建议把修改的文件权限调到最大,这样就可以在容器内修改和运行该文件。
最后,把修改后的文件,重新传回Docker容器
docker cp /var/tmp/entrypoint.sh shynet:/usr/src/shynet/
Successfully copied 2.05kB to shynet:/usr/src/shynet/
docker cp /var/tmp/ssl.webserver.sh shynet:/usr/src/shynet/
Successfully copied 2.05kB to shynet:/usr/src/shynet/
对于基础薄弱的人来配置Shynet的HTTPS服务,最苦恼的恐怕就是这里。因为你不知道应该如何来配置Docker执行的主服务以及如何启动他。
我在这里进一步补充一下Docker容器内的文件知识:
- ssl.webserver.sh: 一个脚本文件,可能用于配置或启动 Web 服务器的 SSL/TLS 设置。
- entrypoint.sh: 一个入口脚本文件,通常用于容器启动时执行的初始化操作。
- manage.py: 一个 Python 管理脚本,通常与 Django 或者类似的 Web 框架相关。
- startup_checks.sh: 一个脚本文件,可能用于容器启动时执行的健康检查或初始化操作。
- celeryworker.sh: 一个脚本文件,可能用于启动 Celery worker 进程。
- pyproject.toml: Python 项目配置文件,通常与 Poetry 项目管理工具相关。
- webserver.sh: 一个脚本文件,可能用于配置或启动 Web 服务器。
当你了解到这一切,你就知道,你应该修改 entrypoint.sh 文件的配置内容,来实现你想要的一切。
![](https://fangjunyu.com/wp-content/uploads/2024/04/1.png)
3、启动Shynet服务
重新启动容器,执行下面的命令:
docker restart <容器名称 / 容器id>
最后,访问前台正常打开。
当你看到这里,想必也完成的配置。那么,恭喜你,为自己的网站搭建了一个流量监控工具,可以更好的维护你的网站了。下面是HTTPS下的部分截图。
![](https://fangjunyu.com/wp-content/uploads/2024/04/2.png)
![](https://fangjunyu.com/wp-content/uploads/2024/04/3.png)
![](https://fangjunyu.com/wp-content/uploads/2024/04/4.png)
![](https://fangjunyu.com/wp-content/uploads/2024/04/5.png)
四、踩坑日记
1、Shynet的Js文件无法加载问题。
这个问题目前有两种情况:
一是Shynet跟踪的文件中,协议是HTTPS,但是你的Shynet并没有配置Https协议,就导致文件是无法加载的。
二是你的网页是HTTPS,但是你只能打开HTTP的跟踪文件,你错误的把协议改成HTTP,这可能会导致不同源的问题,因为HTTPS网页无法打开HTTP的资源。
![](https://fangjunyu.com/wp-content/uploads/2024/04/6.png)
解决方法就是,如果你的网页是HTTPS协议,你就需要在Docker中把HTTPS配置上,就是前面提到的修改 entrypoint.sh 和 ssl.webserver.sh,这两个文件。
2、Shynet可以登录,但是登录用户后报错
这个问题,我遇到过,但是当时没有截图。具体的场景是使用Nginx通过HTTPS代理HTTPS,但是因为Shynet没有配置HTTPS,这导致Nginx把HTTPS服务转给Shynet时,Shynet只支持HTTP。
因此,就会报错,好像是
Forbidden (403)
CSRF verification failed. Request aborted.
More information is available with DEBUG=True.
这个问题的解决办法,就是给Shynet配置HTTPS。
3、Django 应用程序收到了一个无效的 HTTP_HOST 头部
下面是Shynet配置过程中的一个常见报错
User
[2024-04-02 05:35:43 +0000] [1295] [INFO] Booting worker with pid: 1295
ERROR Invalid HTTP_HOST header: '111.231.22.116:8080'. You may need to add '111.231.22.116' to ALLOWED_HOSTS.
Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/django/core/handlers/exception.py", line 56, in inner
response = get_response(request)
File "/usr/local/lib/python3.10/site-packages/django/utils/deprecation.py", line 135, in __call__
response = self.process_request(request)
File "/usr/local/lib/python3.10/site-packages/django/middleware/common.py", line 48, in process_request
host = request.get_host()
File "/usr/local/lib/python3.10/site-packages/django/http/request.py", line 152, in get_host
raise DisallowedHost(msg)
django.core.exceptions.DisallowedHost: Invalid HTTP_HOST header: '111.231.22.116:8080'. You may need to add '111.231.22.116' to ALLOWED_HOSTS.
Invalid HTTP_HOST header: '111.231.22.116:8080'. You may need to add '111.231.22.116' to ALLOWED_HOSTS.
Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/django/core/handlers/exception.py", line 56, in inner
response = get_response(request)
File "/usr/local/lib/python3.10/site-packages/django/utils/deprecation.py", line 135, in __call__
response = self.process_request(request)
File "/usr/local/lib/python3.10/site-packages/django/middleware/common.py", line 48, in process_request
host = request.get_host()
File "/usr/local/lib/python3.10/site-packages/django/http/request.py", line 152, in get_host
raise DisallowedHost(msg)
django.core.exceptions.DisallowedHost: Invalid HTTP_HOST header: '111.231.22.116:8080'. You may need to add '111.231.22.116' to ALLOWED_HOSTS.
“上面是报错的日志记录,这个报错是由于 Django 应用程序收到了一个无效的 HTTP_HOST 头部。HTTP_HOST 头部应该是访问网站的域名或 IP 地址,但在这种情况下,它包含了一个端口号(:8080),这是不正常的。这可能是因为请求被代理服务器发送到 Django 应用程序时,代理服务器将原始客户端的 IP 地址和端口添加到了 HTTP_HOST 头部中。”
以上是日志的一个解释,这个问题可能是在配置Nginx进行代理,或Shynet在不支持HTTPS的情况下,通过HTTPS协议访问后台管理页面导致的。
这个问题可以忽略,因为属于搭建环境中的报错,如果你的Shynet服务还不支持HTTPS,就先把配置文件修改过来,修改后就没有这个问题了。另外,我搭建服务后,没有用Nginx服务器进行代理,不知道有没有可能是这个原因?
总之,现在我的Shynet服务已经没有这个报错了。
4、执行ssl.webserver.sh 文件报错
这个问题在于前面没有配置 entrypoint.sh 文件,而是直接在Docker容器中执行ssl文件。
bash-5.1$ cat ssl.webserver.sh
#!/bin/bash
# Start Gunicorn processes
echo Launching Shynet web server...
exec gunicorn shynet.wsgi:application \
--bind 0.0.0.0:${PORT:-8080} \
--workers ${NUM_WORKERS:-1} \
--timeout 100 \
--certfile=/usr/src/shynet/fangjunyu.com_bundle.pem \
--keyfile=/usr/src/shynet/fangjunyu.com.keybash-5.1$
bash-5.1$ ./ssl.webserver.sh
Launching Shynet web server...
[2024-04-03 15:36:58 +0000] [476] [INFO] Starting gunicorn 20.1.0
[2024-04-03 15:36:58 +0000] [476] [ERROR] Connection in use: ('0.0.0.0', 8080)
[2024-04-03 15:36:58 +0000] [476] [ERROR] Retrying in 1 second.
[2024-04-03 15:36:59 +0000] [476] [ERROR] Connection in use: ('0.0.0.0', 8080)
[2024-04-03 15:36:59 +0000] [476] [ERROR] Retrying in 1 second.
[2024-04-03 15:37:00 +0000] [476] [ERROR] Connection in use: ('0.0.0.0', 8080)
你成功的发现了配置ssl的文件,但是无法执行,这个问题其实很好理解,你可以直接通过查找所有正在运行的进程,并过滤出包含 “8080” 的进程信息。
bash-5.1$ ps -ef | grep 8080
1 appuser 0:00 {gunicorn} /usr/local/bin/python /usr/local/bin/gunicorn shynet.wsgi:application --bind 0.0.0.0:8080 --workers 1 --timeout 100 --certfile=/usr/src/shynet/fangjunyu.com_bundle.pem --keyfile=/usr/src/shynet/fangjunyu.com.key
9 appuser 0:11 {gunicorn} /usr/local/bin/python /usr/local/bin/gunicorn shynet.wsgi:application --bind 0.0.0.0:8080 --workers 1 --timeout 100 --certfile=/usr/src/shynet/fangjunyu.com_bundle.pem --keyfile=/usr/src/shynet/fangjunyu.com.key
508 appuser 0:00 grep 8080
原因:存在两个 gunicorn 占用了8080端口,而且是在运行中。当你想要杀死这两个进程时,就是把主服务杀死,Dokcer也就会终止服务(如果你了解Docker容器运行的话),因此,你可能想,能不能修改这个 ssl.webserver.sh 文件内的端口?来解决端口被占用的问题,恭喜你,想错了。不能,因为你在创建容器时,设置的是通过服务器的8080端口来访问Docker的8080端口。如果你设置 ssl.webserver.sh 为8081端口,你的主服务是8080,端口服务还是跟着你的主服务来。
但是,你已经很接近了,你可能会想,我能不能让容器启动的时候,启用 ssl.webserver.sh,这时,只要你多了解一点Docker,你就会跟我一样,恍然大悟,明白只要修改 entrypoint.sh 文件就可以了。
因此,这个问题的解决方案还是配置 entrypoint.sh 文件。
5、Docker的文件都配置好后,系统还是无法登录
如果参照我的方法全部配置完成,系统仍然无法登录,请尝试使用
执行下面的命令重启服务
docker restart [容器名称 / 容器id]
然后通过
docker logs [容器名称 / 容器id]
查看容器日志
Performing startup checks...
Database is ready to go.
Startup checks complete!
Launching Shynet web server...
[2024-04-03 14:58:26 +0000] [1] [INFO] Starting gunicorn 20.1.0
[2024-04-03 14:58:26 +0000] [1] [INFO] Listening at: https://0.0.0.0:8080 (1)
[2024-04-03 14:58:26 +0000] [1] [INFO] Using worker: sync
[2024-04-03 14:58:26 +0000] [9] [INFO] Booting worker with pid: 9
No hostname was supplied. Reverting to default 'localhost'
恭喜你,服务启动成功啦!!!完结撒花🎉🎉🎉
五、参考资料
无