# Lab1 ## Proxmox > - Install Proxmox on your external disk, and ensure that you can access Proxmox web console from another device in the same network > - Create VMs for your web server and database respectively ### USB ([reference](https://pve.proxmox.com/wiki/Prepare_Installation_Media)) - 使用 windows 的軟體 rufus 將 [iso](https://www.proxmox.com/en/downloads/category/iso-images-pve) 燒進 USB,記得要選 DD 模式 ### Installation - 進 BIOS - 關閉 Secure Boot - 調整開機順序,將 USB 調到最優先 - 以 USB 開機(請有線連接 AP) - 安裝空間選外接硬碟 - 安裝軟體會自動接上有線內網 - 重新開機,再進 BIOS - 將外接硬碟的開機順序調到最優先 --- ## Config :::warning ### Database **/etc/hosts** ``` 192.168.1.X webserver 192.168.1.Y database-out ``` `sudo systemctl restart mariadb` ### Webserver **/etc/hosts** ``` 192.168.1.Y database ``` `uwsgi --ini flask_uwsgi.ini` ::: :::info ### Database - hostname: database - 服務: MariaDB (MySQL) - user - root (password: proxmox1234) - flask (password: proxmox1234), request from webserver ### Web Server - 服務: nginx, uwsgi, flask ::: ## Database ### [Installation](https://linuxize.com/post/how-to-install-mariadb-on-ubuntu-18-04/) ```bash sudo apt update sudo apt install mariadb-server sudo systemctl status mariadb # 測試是否有裝好 mysql -V # 測試是否有裝好 sudo mysql_secure_installation # 設定 mysql root 的密碼 ``` ### [Create user and database](https://blog.gtwang.org/linux/mysql-create-database-add-user-table-tutorial/) ```shell sudo mysql -u root -p ``` ```sql CREATE DATABASE `flask`; --新增使用者,設定密碼 CREATE USER 'flask'@'localhost' IDENTIFIED BY 'proxmox1234'; --設定使用者權限 GRANT ALL PRIVILEGES ON flask.* TO 'flask'@'localhost'; --GRANT ALL PRIVILEGES ON my_db.* TO 'flask'@'192.168.1.107'; --GRANT ALL PRIVILEGES ON flask.* TO 'flask'@'webserver' IDENTIFIED BY 'proxmox1234'; --允許使用者從所有 ip 登入 GRANT ALL PRIVILEGES ON flask.* TO 'flask'@'%' IDENTIFIED BY 'proxmox1234'; ``` ### Bind Address 讓資料庫可以從非 localhost 連到 讓資料庫可以從 database-out (192.168.1.Y) 連到 在 `/etc/mysql/mariadb.cnf` 最下面寫 ```ini [mysqld] bind-address = database-out ``` 測試: 在 webserver 中下 `telnet database 3306` 不能跑出 connection refused ## Web Server App File Structure ``` . ├── app │   ├── app.py │   ├── flask_uwsgi.ini │   └── wsgi.py ├── docker-compose.yml ├── Dockerfile └── requirements.txt ``` ```graphviz digraph{ node [] Nginx,uWSGI,Flask [color=lightblue] Nginx -> uWSGI uWSGI -> Nginx uWSGI -> Flask Flask -> uWSGI } ``` ### 設定環境 ```bash apt-get update # pip packages apt-get install -y python3-pip pip3 install -r requirements.txt # utils apt-get install -y git apt-get install -y make apt-get install -y gcc apt-get install -y --no-install-recommends vim apt-get install -y --no-install-recommends python3-pymysql ``` 設定環境變數 `/etc/profile` ```bash export FLASK_APP=app.py export FLASK_RUN_HOST=0.0.0.0 export FLASK_ENV=development export DB_HOST=database export DB_NAME=flask export DB_USER=flask export DB_PASSWORD=proxmox1234 ``` ### Flask Flask App (`app.py`) ```python import os from os.path import join from flask import Flask, jsonify, request, make_response from flask_restful import Api from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) api = Api(app) # 連接 database # 要使用 flask@webserver 這個 user 到 database 上登入 mysql 使用名叫 flask 的 database # getenv 就是直接從環境變數取設定值 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://{}:{}@{}/{}'.format( os.getenv('DB_USER', 'flask'), os.getenv('DB_PASSWORD', ''), os.getenv('DB_HOST', 'database'), os.getenv('DB_NAME', 'flask') ) db = SQLAlchemy(app) class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) def __repr__(self): return '<User %r>' % self.username @app.before_first_request def creat_tables(): db.create_all() @app.route('/') def hello_world(): return 'Hello, World!' @app.route('/data') def users(): ret = [] res = User.query.all() for user in res: ret.append( { 'username': user.username, 'email': user.email } ) return jsonify(ret), 200 ``` 手動新增資料 ```python >>> from app import db >>> db.create_all() >>> from app import User >>> admin = User(username='admin', email='admin@example.com') >>> guest = User(username='guest', email='guest@example.com') >>> db.session.add(admin) >>> db.session.add(guest) >>> db.session.commit() >>> User.query.all() [<User u'admin'>, <User u'guest'>] >>> User.query.filter_by(username='admin').first() <User u'admin'> ``` 測試(在有 app.py 的目錄下) ``` flask run ``` 然後看 localhost:5000 ### nginx 新增檔案 `/etc/nginx/conf.d/flask_nginx.conf` ``` server { listen 80; server_name 192.168.1.*; location / { uwsgi_pass 127.0.0.1:3031; include uwsgi_params; } } ``` nginx 會將 80 port listen 到的 request 傳到 127.0.0.1:3031 -> nginx 跟 flask 會藉由 uwsgi 的幫助在 127.0.0.1:3031 溝通 ### uwsgi 新增 `wsgi.py` ```python from app import app if __name__ == '__main__': app.run() ``` 新增 `flask_uwsgi.ini` ```ini [uwsgi] socket = 127.0.0.1:3031 wsgi-file = wsgi.py callable = app chmod-socket = 660 processes = 4 threads = 2 ``` 測試 uwsgi 有沒有接好 ``` uwsgi --socket 127.0.0.1:3031 --wsgi-file wsgi.py --callable app --processes 4 --threads 2 --stats 127.0.0.1:9191 --chmod-socket=660 ``` 啟動指令 ``` uwsgi --ini flask_uwsgi.ini ``` 查看 http://webserver/data ## GitLab 手動從 github import