在自我介绍页路上踩过的坑,flask,uwsgi,nginx,ssl绕备案和证书续期

名片上QR码会比较干净,有了扫码有具体联系方式的想法

dispnt.com的主域名在Vultr上,考虑到速度原因就打算把fofu.dispnt.com放在阿里云上


2022-2更新:fofu.dispnt.com改进了好几代,在写文章的时候,是纯flask项目,因此文章的上半部分只是在说明如何跑一个Python 3.6的flask服务

开开心心开了价值9.5大洋一月的T5学生机,从头开始的机器当然是...

yum install python3

这里是第一个坑,不应当使用

rm -rf /usr/bin/python
ln -s /usr/bin/python3.6 /usr/bin/python

这样没有update-alternatives优雅:

update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
update-alternatives --install /usr/bin/python python /usr/bin/python3.6 2

这样以后就可以使用update-alternatives --config python切换版本


随后安装flask和uwsgi

pip install flask,uwsgi

把做完的东西扔进 /home/wwwroot/fofu.dispnt.com,在目录下新建一个uwsgi_config.ini:

[uwsgi]
 
socket          = 127.0.0.1:5000    # uWSGI 监听端口
chdir           = /home/wwwroot/fofu.dispnt.com    # 项目根目录
wsgi-file       = app.py     # Flask 项目启动文件
# 文件中*app* = Flask(__name__)
callable        = app
# 进程数量
processes       = 4
vacuum          = true
master          = true

stats           = %(chdir)/uwsgi.status
pidfile         = %(chdir)/uwsgi.pid

在vhost文件里配置

#/usr/local/nginx/conf/vhost/fofu.dispnt.com.conf
location / { 
 
 
        include uwsgi_params;                       # 导入uwsgi配置
        uwsgi_pass 127.0.0.1:5000;                  # 转发端口,和uwsgi配置中的监听端口一致
        uwsgi_param UWSGI_PYTHON /usr/bin/python3.6; 
        uwsgi_param UWSGI_CHDIR /home/wwwroot/fofu.dispnt.com;         # 项目根目录
        uwsgi_param UWSGI_SCRIPT app:app;
        # 假如使用run.py文件运行,文件中app = Flask(__name__),那么这里就填run:app 
        }

好像配置完了,uwsgi启动!

uwsgi --ini /home/wwwroot/fofu.dispnt.com/uwsgi_config.ini

uwsgi跑不起来辣:plugins/python/uwsgi_python.h:2:20: fatal error: Python.h: No such file or directory
百度没一个对的,Stackoverflow说,要用 yum install python3-devel
嗨嗨嗨,运行yum报错辣:

File "/usr/bin/yum", line 30
except KeyboardInterrupt, e:
                       ^
SyntaxError: invalid syntax

以及

Downloading packages:
  File "/usr/libexec/urlgrabber-ext-down", line 28
    except OSError, e:
                  ^
SyntaxError: invalid syntax

因为换成了Python3.6因此需要...

vim /usr/bin/yum
vim /usr/libexec/urlgrabber-ext-down

在第一行#!/usr/bin/python的后面指明版本:
#!/usr/bin/python2.7

再运行...uwsgi --ini /home/wwwroot/fofu.dispnt.com/uwsgi_config.ini
发现只有Python2.7...所以一堆教程里用virtualenv还是有点道理的...


pip install virtualenv

创建环境一定要带参数,不然2.7的uwsgi包就会带进来...
virtualenv venv --no-site-packages --python=python3

source venv/bin/activate
pip install flask,uwsgi

再再运行uwsgi --ini /home/wwwroot/fofu.dispnt.com/uwsgi_config.ini,终于可以正常运行了,只是
静态文件全部404
打开vhost配置文件....
#/usr/local/nginx/conf/vhost/fofu.dispnt.com.conf

location /static/ { #static文件夹的绝对路径
       root /home/wwwroot/fofu.dispnt.com; #root和alias的区别
    }

上面的默认Location配置要全部注释掉,不然还是404

重启nginx,好起来啦


没好,根本上不去,老是提醒要备案,搞个ssl证书绕过去就好了
但是大多数脚本都是用http验证域名归属,现在被劫持了,只能用dns验证:

pip install certbot
certbot --text --agree-tos --email <email@email.com> -d <fofu.domain.com> --manual --preferred-challenges  dns --expand --renew-by-default  --manual-public-ip-logging-ok certonly

然后去设置叫做_acme-challenge的txt类型记录,值应该会显示在上面

假如是test.fofu.com应该是 _acme-challenge.test,不是_acme-challenge

然后又是配置文件,扔在server段里:

#/usr/local/nginx/conf/vhost/fofu.dispnt.com.conf
listen 443 ssl; #或者ssl on
server_name fofu.dispnt.com;
ssl_certificate /etc/letsencrypt/live/fofu.dispnt.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/fofu.dispnt.com/privkey.pem;
ssl_stapling on;
ssl_stapling_verify on;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5:!EXPORT56:!EXP;
ssl_session_cache shared:SSL:50m;
ssl_dhparam /usr/local/nginx/conf/ssl/dhparam.pem;
ssl_prefer_server_ciphers on;
include enable-php.conf;

结束了。但是我的https会显示链接已重置,说是SNI暴露了域名
最终的虚拟主机配置文件应该是...

#/usr/local/nginx/conf/vhost/fofu.dispnt.com.conf
server
    {
        listen 80;
        return 301 https://$host$request_uri;
    }
    server {
        listen 443 ssl;
        server_name fofu.dispnt.com;
    ssl_certificate /etc/letsencrypt/live/fofu.dispnt.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/fofu.dispnt.com/privkey.pem;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!MD5:!EXPORT56:!EXP;
    ssl_session_cache shared:SSL:50m;
    ssl_dhparam /usr/local/nginx/conf/ssl/dhparam.pem;
    ssl_prefer_server_ciphers on;
    include enable-php.conf;
    location / { 
         include uwsgi_params;
    
         uwsgi_pass 127.0.0.1:5000;
         uwsgi_param UWSGI_PYTHON /usr/bin/python3.6;
         uwsgi_param UWSGI_CHDIR /home/wwwroot/fofu.dispnt.com;
         uwsgi_param UWSGI_SCRIPT app:app;
        }
        
        
    location /static/ {
        root /home/wwwroot/fofu.dispnt.com;
        }
    }

启动:

source venv/bin/activate 
uwsgi --ini /home/wwwroot/fofu.dispnt.com/uwsgi_config.ini

重载:

uwsgi --reload /home/wwwroot/fofu.dispnt.com/uwsgi.pid

停止:

uwsgi --stop /home/wwwroot/fofu.dispnt.com/uwsgi.pid

flask的域名续期

因为用的是lnmp,一句话就好了,这里用强制续期,看上去比较爽

/bin/certbot renew --force-renew --disable-hook-validation --renew-hook "/etc/init.d/nginx reload"

直接这样会提示找不到/.well-known/,把上面配置文件的location段全部注释掉

#/usr/local/nginx/conf/vhost/fofu.dispnt.com.conf
......
# location / { 
#        include uwsgi_params;
#        uwsgi_pass 127.0.0.1:5000;
#        uwsgi_param UWSGI_PYTHON /usr/bin/python3.6; 
#        uwsgi_param UWSGI_CHDIR /home/wwwroot/fofu.dispnt.com;
#        uwsgi_param UWSGI_SCRIPT app:app;
#        }
......

然后重启nginx

lnmp nginx restart

最后再来一遍/bin/certbot renew --force-renew --disable-hook-validation --renew-hook "/etc/init.d/nginx reload"就好了

tag(s): vps, Linux, Flask
show comments · back · home
Edit with Markdown