# 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