CMSimfly 與 Fossil SCM

CMSimfly 是一套採用 Flask 應用程式框架編寫的網際內容管理系統 (Content Management System), Fossil SCM 則是以 ANSI C 編寫的軟體組態管理 (Software Configuration Management) 系統, 兩套程式各有不同的特色, CMSimfly 適合用來管理無版次的大型檔案, 而 Fossil SCM 則可用來記錄詳細的軟體設計開發歷程.

CMSimfly 與 Fossil SCM 安裝規劃

CMSimfly 採用 Python3 與 Flask 編寫, 可以採用 uwsgi 模組啟動, 預計網際前端透過 Nginx https 埠號 8443 承接來自瀏覽器的請求, 而 Fossil SCM 的 http port 80 前端則由 Nginx 承接後, 直接跳轉 Stunnel 所代理的 https 服務. 因此當使用者以瀏覽器 http 連線, 伺服器會馬上跳轉 https 的 Fossil SCM, 假如要連結 CMSimfly, 則必須以 https 8443 連線.

uwsgi 有多種啟動方式, 在此希望透過 Emperor 的多應用程式的模式啟動, 基本架構是, uwsgi 指令在 /etc/rc.local 中以 exec 執行, 可以在伺服器開機時執行, 而 uwsgi Emperor 中指定以一般用戶身分執行, 實際封包在內部網路的 8081 啟動, 之後透過 /etc/nginx/sites-available/default 中的 server 設定, 只接受 8443 埠號的 IPv4 與 IPv6 網際瀏覽器請求.

CMSimfly 安裝設定

根據 uwsgi 與 Emperor 的啟動, 伺服器所需模組, 包括 pip3, Flask, python3 開發環境, uwsgi, nginx 與 uwsgi-plugin-python3 模組:

sudo apt install python3-pip
sudo pip3 install Flask
sudo apt install build-essential python3-dev
sudo pip3 install uwsgi
sudo apt install nginx uwsgi-plugin-python3

而 /etc/nginx/sites-available/default 的設定

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;
        return 301 https://my.server.host.name;
}

server {
    listen 8443 ssl;
    listen [::]:8443 ssl;

    location /static {
        alias /home/user/cmsimfly/static/;
    }

    location / {
        include uwsgi_params;
        uwsgi_pass  127.0.0.1:8081;
    }

    server_name my.server.host.name;
    ssl on;
    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;
    ssl_session_timeout 5m;
    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    ssl_prefer_server_ciphers on;
    try_files $uri $uri/ =404;
}

位於 /home/user/uwsgi_ini/ 目錄下的 uwsgi.ini 檔案設定:

[uwsgi]
socket = 127.0.0.1:8081 
uid = user
gid = user
plugins-dir = /usr/lib/uwsgi/plugins/
plugin = python3
master = true
process = 4
threads = 2
chdir = /home/user/cmsimfly
wsgi-file = /home/user/cmsimfly/wsgi.py

假如希望額外啟動其他的 uwsgi 程式, 例如第二組 CMSimfly 或其他對應的 Flask 應用程式, 則需要在 /etc/nginx/sites-available/default 增加另外一組 server 設定, 主要在選定內部網路的特定埠號, 例如: 127.0.0.1:8082, 編寫 default 設定檔案成為:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;
        return 301 https://my.server.host.name;
}

server {
    listen 8443 ssl;
    listen [::]:8443 ssl;

    location /static {
        alias /home/user/cmsimfly/static/;
    }

    location / {
        include uwsgi_params;
        uwsgi_pass  127.0.0.1:8081;
    }

    server_name my.server.host.name;
    ssl on;
    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;
    ssl_session_timeout 5m;
    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    ssl_prefer_server_ciphers on;
    try_files $uri $uri/ =404;
}

server {
    listen 9443 ssl;
    listen [::]:9443 ssl;

    location /static {
        alias /home/user/cmsimfly2/static/;
    }

    location / {
        include uwsgi_params;
        uwsgi_pass  127.0.0.1:8082;
    }

    server_name my.server.host.name;
    ssl on;
    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;
    ssl_session_timeout 5m;
    ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
    ssl_prefer_server_ciphers on;
    try_files $uri $uri/ =404;
}

然後在 /home/user/uwsgi_ini 目錄中, 再配合增加一組 uwsgi2.ini, 內容為:

[uwsgi]
socket = 127.0.0.1:8082
uid = user
gid = user
plugins-dir = /usr/lib/uwsgi/plugins/
plugin = python3
process = 4
threads = 2
chdir = /home/user/cmsimfly2
wsgi-file = /home/user/cmsimfly2/wsgi.py

/etc/nginx/sites-available/default 與 /home/user/uwsgi_ini/uwsgi2.ini 設定修改後, 只要透過 /etc/init.d/nginx restart 重新啟動 Nginx, 並且重新執行 uwsgi 指令, 意即, uwsgi --emperor /home/user/uwsgi_ini, 納入 /home/user/uwsgi_ini/uwsgi.ini 與 /home/user/uwsgi_ini/uwsgi2.ini 的多 uwsgi Emperor 架構應用程式即可在 https://my.sever.host.name:9443 多一組 CMSimply 網際內容管理的伺服.

若要讓伺服器在開機時執行 uwsgi, 則需要在/etc/rc.local 加入:

exec uwsgi --emperor /home/user/uwsgi_ini

過程中若需要重新啟動 nginx, 以 /etc/init.d/nginx restart 執行.

Fossil SCM 與 Stunnel 聯合啟動

因為在 Nginx /etc/nginx/sites-available/default 中已經將 port 80 的回應處理直接透過 http 301 狀態碼的宣告, 永久轉接到 https://my.server.host.name, 因此只要透過 Stunnel 代理在標準的 IPv4 與 IPv6 網路協定中, 以 https 啟動 Fossil SCM 即可.

首先要安裝 Stunnel 與 Fossil SCM:

sudo apt update
sudo apt install stunnel4 -y
sudo apt install fossil

讓 Stunnel 開機時啟動:

/etc/default/stunnel4 檔案設定, 將原先內定的 ENABLED=0 改為 1:

ENABLED=1

因為要以 https 設定 /etc/stunnel/stunnel.conf, 因此 /etc/stunnel 目錄中需要 stunnel.crt 與 stunnel.key.

在 /etc/stunnel 目錄中執行 openssl 指令:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout stunnel.key -out stunnel.crt

然後設定 /etc/stunnel/stunnel.conf:

[https]
accept = your.ipv4.ip:443
accept = :::443
cert = /etc/stunnel/localhost.crt
key = /etc/stunnel/localhost.key
exec = /usr/bin/fossil
execargs = /usr/bin/fossil http /home/user/ --https --nojail --notfound default

重新啟動 stunnel 時, 執行 /etc/init.d/stunnel4