前段时间折腾我们信息安全小组的CTF平台(flask), 学习了下python web环境的基本配置,也踩了openshit(对!就是openshit!)的好多坑
一、安装依赖
1 2 3 4 5 6 |
sudo apt-get update sudo apt-get install build-essential python-pip python-dev libffi-dev # 安装基本环境,需要root权限 pip install -r requirements.txt # python web 项目的目录下有requirements.txt,列出了需要安装的 python 库 |
二、常见环境搭配
1、Nginx + uwsgi
1)Nginx配置(简化版):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
server { # listen 80 ; # listen [::]:80 ; root /var/www/python_web/; server_name www.example.com; location / { try_files $uri @yourapplication; } location @yourapplication { include uwsgi_params; uwsgi_pass unix:/tmp/uwsgi.sock; } } |
2)uwsgi 配置
方案一: 使用 uwsgi 守护进程
安装 APT 源里面的 uwsgi 包和 python 插件
1 |
sudo apt-get install uwsgi uwsgi-plugin-python |
准备 uwsgi 配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
cat > /etc/uwsgi/apps-available/uwsgi.ini << 'EOF' # UWSGI Configuration File # Install uwsgi (sudo apt-get install uwsgi), copy this file to # /etc/uwsgi/apps-available and then link it in /etc/uwsgi/apps-enabled # Only two lines below (commented) need to be changed for your config. # Then, you can use something like the following in your nginx config: # # # SERVER_ROOT is not / (e.g. /ctf) # location = /ctf { rewrite ^ /ctf/; } # location /ctf { # include uwsgi_params; # uwsgi_pass unix:/run/uwsgi/app/ctfd/socket; # } # # # SERVER_ROOT is / # location / { # include uwsgi_params; # wsgi_pass unix:/run/uwsgi/app/ctfd/socket; # } [uwsgi] # Where you've put CTFD chdir = /var/www/ctfd/ # If SCRIPT_ROOT is not / #mount = /ctf=wsgi.py # SCRIPT_ROOT is / mount = /=“CTFd:create_app()” # You shouldn't need to change anything past here plugin = python module = wsgi master = true processes = 1 threads = 1 vacuum = true manage-script-name = true wsgi-file = wsgi.py callable = app die-on-term = true # If you're not on debian/ubuntu, replace with uid/gid of web user uid = www-data gid = www-data EOF |
重启服务
1 |
service uwsgi restart |
方案二: 手动运行 uwsgi
如果使用的 APT 源里的uwsgi,请注意下面的命令均需添加参数: --plugin python;
如果是使用 pypi 源里的uwsgi,等于默认添加了 --plugin python;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
cd /var/www/python_web # unix socket 方式,配合 nginx 代理 uwsgi -s /tmp/uwsgi.sock -w myapp:app # 或 uwsgi -s /tmp/uwsgi.sock --mount /='myapp:app' # 或 uwsgi -s /tmp/uwsgi.sock --module myapp --callable app # http socket方式,可以不依赖nginx等代理 uwsgi --http-socket 0.0.0.0:8888 -w myapp:app # 或 uwsgi --http-socket 0.0.0.0:8888 --mount /='myapp:app' # 或 uwsgi --http-socket 0.0.0.0:8888 --module myapp --callable app |
Ps: 实际运行的时候需要给uwsgi降权,运行时增加 --uid, --gid 参数即可。
2、Apache + mod_wsgi
1)Apache 配置
先安装mod_wsgi
1 2 |
sudo apt-get update sudo apt-get install libapache2-mod-wsgi |
配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<VirtualHost *:80> ServerName www.example.com WSGIDaemonProcess python user=www-data group=www-data threads=5 WSGIScriptAlias / /var/www/python_web/wsgi.py <Directory /var/www/python_web/> WSGIProcessGroup python WSGIApplicationGroup %{GLOBAL} AllowOverride All Require all granted </Directory> </VirtualHost> |
2)mod_wsgi 配置
准备 /path/to/the/application/wsgi.py,这是wsgi的入口文件
1 2 3 4 5 6 7 8 9 10 |
vim /path/to/the/application/wsgi.py import sys sys.path.insert(0, '/path/to/the/application') # 在环境变量中添加你的application目录 from yourapplication import app as application # 或者 from yourapplication import app application = create_app() |
3、gunicorn
unix平台下的WSGI服务器,可以独立执行,也可以 apt-get 安装作为系统服务运行
1 2 |
gunicorn -w 1 "CTFd:create_app()" # -w INT, --workers INT 指的是workers数量 |
特点:配置简单,轻量
配置文档:http://flask.pocoo.org/docs/0.10/deploying/wsgi-standalone/#gunicorn
4、tornado
特点:非阻塞,并发高,适合实时的web服务
配置文档:http://flask.pocoo.org/docs/0.10/deploying/wsgi-standalone/#tornado
5、其他
http://flask.pocoo.org/docs/0.10/deploying/
三、踩坑记录
Github链接:https://github.com/kings-way/CTF-for-INT_0x80
1、 No module named setuptools_ext
本地 pip install -r requirements.txt 给 CTFd 安装依赖的时候报错,解决方案:
1 2 |
pip install --upgrade cffi # 更新一下 cffi 这个包就好 |
2、 openshift 中的 python 虚拟环境 virtenv
virtenv虚拟环境变量,会导致程序的相对路径发生变化,所以在代码里读写文件注意使用绝对路径
1 2 3 4 5 6 |
diff config_old.py config.py 4c4 < with open('.ctfd_secret_key', 'a+') as secret: --- > with open(os.path.join(os.path.dirname(__file__),".ctfd_secret_key"), 'a+') as secret: |
3、ImportError: cannot import name inspect
这是在 openshift 上面运行时的错误
出错语句:from sqlalchemy import orm, event, inspect,解决办法就是 ssh 登录上去,升级其版本
(其实也可以通过openshift的某个配置文件指定相应包的版本,不过脑子已经要炸了,管不了那些了。。。)
1 |
pip install -U sqlalchemy |
4、wsgi.py
最后贴一下在openshift上面部署的CTFd项目的wsgi.py入口文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
#!/usr/bin/python import os # Local config when using with Apache mod_wsgi #import sys #sys.path.insert(0, '/var/www/python/') # Openshift virtenv config virtenv = os.environ['OPENSHIFT_PYTHON_DIR'] + '/virtenv/' virtualenv = os.path.join(virtenv, 'bin/activate_this.py') try: execfile(virtualenv, dict(__file__=virtualenv)) except IOError: pass # # IMPORTANT: Put any additional includes below this line. If placed above this # line, it's possible required libraries won't be in your searchable path # # from CTFd import create_app as application from CTFd import create_app application = create_app() # # Below for local testing with command "python wsgi.py" # #virtenv = os.path.join(os.environ.get('OPENSHIFT_PYTHON_DIR','.'), 'virtenv') #virtualenv = os.path.join(virtenv, 'bin/activate_this.py') #try: # execfile(virtualenv, dict(__file__=virtualenv)) #except IOError: # pass # # #if __name__ == '__main__': # from wsgiref.simple_server import make_server # httpd = make_server('localhost', 8051, application) # Wait for a single request, serve it and quit. # httpd.handle_request() # httpd.serve_forever() |