網頁

顯示具有 憑證 標籤的文章。 顯示所有文章
顯示具有 憑證 標籤的文章。 顯示所有文章

2025年2月19日 星期三

安裝 ollama open-webui nginx

參考 https://github.com/ollama/ollama
參考 https://hub.docker.com/r/ollama/ollama
參考 https://www.53ai.com/news/OpenSourceLLM/2024072585037.html

$ docker run -d --gpus=all -p 11434:11434 --name ollama \
  -v /mnt/Data/ollama/ollama_volume:/root/.ollama \
  ollama/ollama
$ docker exec -it ollama ollama run deepseek-r1
$ git clone https://github.com/ggerganov/llama.cpp.git
$ cd llama.cpp
$ cmake -B build
$ cmake --build build --config Release
$ pip install huggingface_hub

轉換 huggingface 上的 model, 成為 GGUF 格式
vi download.py 
from huggingface_hub import snapshot_download, login

login("hf_BqLATKBqbVzOWNBJcFMwHKzCJfu")

# 下载模型
snapshot_download(
    "taide/Llama-3.1-TAIDE-LX-8B-Chat",
    local_dir="taide_Llama-3.1-TAIDE-LX-8B-Chat",
    local_dir_use_symlinks=False,
    ignore_patterns=["*.gguf"]
)

$ vi convert_hf_to_gguf_update.py
在 models 中, 加入下行, 注意 TOKENIZER_TYPE 的選擇
    {"name": "taide_Llama-3.1-TAIDE-LX-8B-Chat", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/taide/Llama-3.1-TAIDE-LX-8B-Chat"},
    {"name": "yentinglin_Llama-3-Taiwan-8B-Instruct", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/yentinglin/Llama-3-Taiwan-8B-Instruct"},
$ python convert_hf_to_gguf_update.py hf_BqLATKBqbVzOWNBJcFMwHKzCJfu
$ python convert_hf_to_gguf.py taide_Llama-3.1-TAIDE-LX-8B-Chat --outtype f16 --outfile taide_Llama-3.1-TAIDE-LX-8B-Chat.fp16.gguf
$ llama.cpp/build/bin/llama-quantize taide_Llama-3.1-TAIDE-LX-8B-Chat.fp16.gguf Q4_K_M
$ mv ggml-model-Q4_K_M.gguf taide_Llama-3.1-TAIDE-LX-8B-Chat-Q4_K_M.gguf
$ vi Modelfile.taide-8b
FROM ./yentinglin_Llama-3-Taiwan-8B-Instruct.Q4_K_M.gguf
# set the temperature to 1 [higher is more creative, lower is more coherent]
PARAMETER temperature 1
# set the system message
SYSTEM """
我是一個萬事通
"""

$ docker exec -it ollama /bin/bash
# cd /root/.ollama
# ollama create taide-8b -f ./Modelfile.taide-8b
# ollama list
# ollama show taide-8b
# ollama rm taide-8b
# ollama ps
# ollama run taide-8b
>>> /bye
# OLLAMA_HOST=127.0.0.1:11434 ollama serve
$ curl http://localhost:11434/api/generate -d '{
  "model": "yentinglin-8b", 
  "prompt": "建議適合ai的程式語言"
}'
$ curl http://localhost:11434/api/generate -d '{
  "model": "yentinglin-8b", 
  "prompt": "建議適合ai的程式語言",
  "stream", false
}'
$ curl http://localhost:11434/api/chat -d '{
  "model": "yentinglin-8b", 
  "messages": [
    {"role": "user", "content": "建議適合ai的程式語言"}
  ]
}'
$ curl http://localhost:11434/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{
        "model": "yentinglin-8b",
        "messages": [
            {
                "role": "system",
                "content": "你是一個萬事通"
            },
            {
                "role": "user",
                "content": "眼睛酸痛,怎麼辦?"
            }
        ]
    }'

$ docker logs ollama

$ python ../llama.cpp/convert_hf_to_gguf.py yentinglin_Llama-3-Taiwan-8B-Instruct --outtype f16 --outfile yentinglin_Llama-3-Taiwan-8B-Instruct.fp16.gguf
$ llama.cpp/build/bin/llama-quantize yentinglin_Llama-3-Taiwan-8B-Instruct.fp16.gguf Q4_K_M


建議適合ai的程式語言

$ docker run -d -p 3000:8080 --gpus all \
  --add-host=host.docker.internal:host-gateway \
  -v /mnt/Data/ollama/open-webui_volume:/app/backend/data \
  --name open-webui \
  --restart always \
  ghcr.io/open-webui/open-webui:cuda
  
Firefox Web Browser 輸入 http://localhost:3000
出現 This address is restricted 錯誤
進入 Firefox Web Browser 設定
網址列輸入 about:config, 按 "Accept the Risk and Continue" 按鈕
在收尋欄輸入 network.security.ports.banned.override, 點選 "String", 按 +
輸入 port 3000, 按 V
重新載入 http://localhost:3000

chrome 設定
chrome://flags/#unsafely-treat-insecure-origin-as-secure
輸入網址 http://localhost:3000

安裝 nginx
參考 https://docs.openwebui.com/tutorials/https-nginx/
參考 https://yingrenn.blogspot.com/2020/07/ssl-nginx.html
vi nginx.conf
server {
    listen 443 ssl;
    server_name  www.domain.com.tw;
    ssl_certificate /etc/nginx/conf/Certs/server.pem;
    ssl_certificate_key /etc/nginx/conf/Certs/server.key;
    ssl_trusted_certificate /etc/nginx/conf/Certs/caChain.crt;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;
    
    location / {
        proxy_set_header HOST $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://host.docker.internal:3000;
        
        # Add WebSocket support (Necessary for version 0.5.0 and up)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # (Optional) Disable proxy buffering for better streaming response from models
        proxy_buffering off;
    }
}
server {
     listen 80;
     server_name www.domain.com.tw;
     return 301 https://$host$request_uri; 
}

docker run -itd --name nginx \
  -p 80:80 -p 443:443 \
  --add-host=host.docker.internal:host-gateway \
  -v /mnt/Data/ollama/nginx/conf.d/nginx.conf:/etc/nginx/conf.d/nginx.conf \
  -v /mnt/Data/ollama/nginx/conf:/etc/nginx/conf \
  -m 100m library/nginx:latest

https://www.domain.com.tw

2020年3月18日 星期三

https on nginx and python flask

建立 python flask 的網頁伺服器
$ cat server.py
@app.route('/api/PostTime', methods=['POST'])
def post_time():
    print(request.headers)
    print(request.json)
    result = '\n'.join([request.json['updDate'],
            request.json['camera']])
    print(result)
    return str(result)

if __name__ == "__main__":
    app.run(host="0.0.0.0", port="5000", debug=True,
            # 下兩行可以啟動 https
            #ssl_context=("/home/user1/Data/webapi/openssl/web1/server.crt",
            #    "/home/user1/Data/webapi/openssl/web1/server.key")
            )

$ python3 server.py

$ cat PostTime.py
import requests
import os

data = {
    'updDate': '2019-01-02T15:10:11',
    'camera': 'A001',
}

os.environ['REQUESTS_CA_BUNDLE'] = '/home/user1/Data/webapi/openssl/ca/cacert.pem'
#url = 'https://127.0.0.1:5000/api/PostTime'
url = 'https://127.0.0.1:8443/api/PostTime'
headers = {'Content-Type': 'application/json'}
response = requests.post(url=url,
        headers=headers,
        #verify=False,
        json=data)
if response.ok:
    print("PostTime ok")
    print(response.status_code)
    print(response.text)
else:
    print(response.status_code)
    print(response.text)

$ python3 PostTime.py

# cat /etc/nginx/sites-available/config
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        # SSL configuration
        #
        listen 8443 ssl default_server;
        listen [::]:8443 ssl default_server;
        ssl_certificate /home/user1/Data/webapi/openssl/web1/server.crt;
        ssl_certificate_key /home/user1/Data/webapi/openssl/web1/server.key;
        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        server_name _;

        location ^~ /api/ {
                # 當 https 由 nginx 管控,python flask 就要走一般的 http
                proxy_pass http://127.0.0.1:5000;
                proxy_set_header Host $host;
        }
        # 設定上傳限制
        client_max_body_size 10M;
}

重新啟動 nginx
# sudo nginx -s reload

2020年2月27日 星期四

https Client and Server

建立證書
參考 OpenSSL 證書

===
自我認證 CA
$ mkdir ca; cd ca
產生私鑰
$ mkdir private
$ openssl genrsa -out private/cakey.pem 2048
產生自簽章證書
$ cp /etc/ssl/openssl.cnf .
$ vi openssl.cnf
dir = .
default_md = sha512
keyUsage = cRLSign, keyCertSign
$ openssl req -new -x509 -nodes -key private/cakey.pem -out cacert.pem \
-days 3650 -subj "/C=TW/ST=Taiwan/L=Taichung/O=SDL/OU=R&D/CN=z390-CA" \
-config openssl.cnf
顯示證書
$ openssl x509 -text -noout -in cacert.pem

===
產生網站的證書
$ mkdir web1; cd web1
產生私鑰
$ openssl genrsa -out server.key 2048
$ vi ssl.conf
[ req ]
prompt = no
default_md = sha512
default_bits = 2048
distinguished_name = dn
req_extensions = v3_req

[ dn ]
C = TW
ST = Taiwan
L = Taichung
O = SDL
OU = R&D
emailAddress = mark@localhost
CN = mark-z390-u

[ v3_req ]
basicConstraints = CA:FALSE
subjectAltName = @alt_names
subjectKeyIdentifier = hash
keyUsage = nonRepudiation, digitalSignature, keyEncipherment

[ alt_names ]
DNS.1 = localhost
DNS.2 = mark-z390-u
DNS.3 = dixx.vigorddns.com
DNS.4 = 192.168.0.101
IP.1 = 127.0.0.1
IP.2 = 192.168.0.101
$ openssl req -new -sha512 -key server.key -out server.csr -config ssl.conf
顯示需求證書
$ openssl req -text -noout -in server.csr
顯示私鑰
$ openssl rsa -out -noout -in server.key
顯示公鑰
$ openssl rsa -in server.key -pubout -out server_pub.key
$ openssl rsa -in server_pub.key -pubin -noout -text

===
使用 自我認證 CA 簽署 需求證書
回到 ca 目錄
$ mkdir newcerts
$ touch index.txt
$ echo "01">serial
$ openssl ca -in ../web1/server.csr -out ../web1/server.crt -days 3650 -extennsions v3_req -extfile ../web1/ssl.conf -config openssl.cnf

===
匯入憑證到 Windows 10
cacert.pem 改名為 cacert.crt

本機裝置 的憑證 certlm.msc
目前的使用者憑證 certmgr.msc
受信任的根憑證授權單位/憑證
按滑鼠右鍵/所有工作/匯入 選擇 cacert.crt

金鑰使用方法
Certificate Signing, Off-line CRL Signing, CRL Signing (06)

===
參考 OCSP & CRL 介紹
CRL(Certificate Revocation List) 被 CA 撤銷的憑證清單
OCSP(Online Certificate Status Protocal) 線上查詢憑證狀態

參考根憑證
AAA Certificate Services
CRL 發佈點
CRL Distribution Point
URL=http://crl.comodoca.com/AAACertificateServices.crl



參考 Visual Studio(VS2017)編譯並配置C/C++-libcurl開發環境
從 https://curl.haxx.se/download.html 下載 curl-7.68.0.zip
解壓縮後進入 curl 目錄
執行 buildconf.bat
以 x86 為例(64為原則改為 x64)
開始/Visual Studio 2017/x86 Native Tools Command Prompt for VS 2017
按滑鼠右鍵選擇 Run as administrator
進入 curl/winbuild
nmake /f Makefile.vc mode=static VC=15 MACHINE=x86 DEBUG=yes
nmake /f Makefile.vc mode=static VC=15 MACHINE=x86 DEBUG=no
編譯的結果在 builds 下


Visual Studio 使用 libcurl
Configuration Properties/C/C++/Preprocessor/Preprocessor Definitions 加入 CURL_STATICLIB
#include <curl/curl.h>
加入下列 library
libcurl_a.lib(libcurl_a_debug.lib)
Ws2_32.lib
Wldap32.lib
winmm.lib(似乎不用)
Crypt32.lib
Normaliz.lib

form 使用
curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);
json 使用
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strU8);
curl_easy_setopt(curl, CURLOPT_POST, 1);

libcurl 之傳送接收使用  UTF-8, 函數之參數使用 Big5
在 vc 上使用 CStringA 儲存 Big5 和 UTF-8, 轉換要經過 CStringW (Unicode)

curl 之 --tlsv1.3 等於
curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_3);

curl 之 --insecure 等於
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
不使用 --insecure 等於
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2); // 0 不檢查 host
curl_easy_setopt(curl, CURLOPT_CAINFO, "cacert.pem");

curl 之 --ssl-no-revoke 等於
curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);



使用 curl 測試
===
在 windows 下,引號不能使用'要使用"
--insecure 不檢查證書
===
D:\temp\aaa>curl.exe -v https://dixx.vigorddns.com:5000/api/Json -X
POST -H "Content-Type:application/json" -d "{\"updDate\":\"aaa\", \"camera\":\"b
bb\", \"ipaddress\":\"ccc\", \"addr\":\"ddd\"}" --insecure
*   Trying 114.35.104.33:5000...
* TCP_NODELAY set
* Connected to dixx.vigorddns.com (114.35.104.33) port 5000 (#0)
* schannel: next InitializeSecurityContext failed: SEC_E_INVALID_TOKEN (0x800903
08) - 提供給功能的權杖不正確
* Closing connection 0
* schannel: shutting down SSL/TLS connection with dixx.vigorddns.com por
t 5000
curl: (35) schannel: next InitializeSecurityContext failed: SEC_E_INVALID_TOKEN
(0x80090308) - 提供給功能的權杖不正確

===
Windows 7 要加上 --tlsv1.3
Windows 10 不用
===
D:\temp\aaa>curl.exe -v https://dixx.vigorddns.com:5000/api/Json -X
POST -H "Content-Type:application/json" -d "{\"updDate\":\"aaa\", \"camera\":\"b
bb\", \"ipaddress\":\"ccc\", \"addr\":\"ddd\"}" --insecure --tlsv1.3


D:\temp\aaa>curl.exe -v https://dixx.vigorddns.com:5000/api/Json -X
POST -H "Content-Type:application/json" -d "{\"updDate\":\"aaa\", \"camera\":\"b
bb\", \"ipaddress\":\"ccc\", \"addr\":\"ddd\"}" --tlsv1.3
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 114.35.104.33:5000...
* TCP_NODELAY set
* Connected to dixx.vigorddns.com (114.35.104.33) port 5000 (#0)
* schannel: next InitializeSecurityContext failed: Unknown error (0x80092012) -
撤銷功能無法檢查憑證的撤銷。
* Closing connection 0
* schannel: shutting down SSL/TLS connection with dixx.vigorddns.com por
t 5000
curl: (35) schannel: next InitializeSecurityContext failed: Unknown error (0x800
92012) - 撤銷功能無法檢查憑證的撤銷。

===
要檢查證書,用參數 --cacert 傳入證書檔
===
D:\temp\aaa>curl.exe -v https://dixx.vigorddns.com:5000/api/Json -X
POST -H "Content-Type:application/json" -d "{\"updDate\":\"aaa\", \"camera\":\"b
bb\", \"ipaddress\":\"ccc\", \"addr\":\"ddd\"}" --tlsv1.3 --cacert cacert.pem
Note: Unnecessary use of -X or --request, POST is already inferred.
*   Trying 114.35.104.33:5000...
* TCP_NODELAY set
* Connected to dixx.vigorddns.com (114.35.104.33) port 5000 (#0)
* schannel: added 1 certificate(s) from CA file 'cacert.pem'
* schannel: CertGetCertificateChain trust error CERT_TRUST_REVOCATION_STATUS_UNK
NOWN 0x00000040
* Closing connection 0
* schannel: shutting down SSL/TLS connection with dixx.vigorddns.com por
t 5000
curl: (60) schannel: CertGetCertificateChain trust error CERT_TRUST_REVOCATION_S
TATUS_UNKNOWN 0x00000040
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

===
因檢查證書時,會去檢查證書是否已經撤銷
--ssl-no-revoke 避免檢查
===
D:\temp\aaa>curl.exe -v https://dixx.vigorddns.com:5000/api/Json -X
POST -H "Content-Type:application/json" -d "{\"updDate\":\"aaa\", \"camera\":\"b
bb\", \"ipaddress\":\"ccc\", \"addr\":\"ddd\"}" --tlsv1.3 --cacert cacert.pem --
ssl-no-revoke

===
使用 form
D:\temp\aaa>curl.exe -v https://dixx.vigorddns.com:5000/api/SendForm
-X POST -d "location=aaa&dt=bbb&text=ccc&camera_name=eee&X=x&Y=y&plateId=ddd" --
tlsv1.3 --cacert cacert.pem --ssl-no-revoke

2019年10月9日 星期三

windows 10 憑證管理

本機裝置 的憑證 certlm.msc
目前的使用者憑證 certmgr.msc

參考格式 Create and assign SCEP certificate profiles in Intune 填寫 Subject
如: "DigiChance11,E=ing@yahoo.com,OU=Mark Chen,O=R&D,L=Taichung,S=Taiwan,C=TW"

CertFindCertificateInStore X509_ASN_ENCODING CERT_FIND_SHA1_HASH
對應 憑證指紋

2017年4月17日 星期一

OpenSSL 證書

openssl学习笔记--CA及https网站证书配置

root@arduino:~/openssl# mkdir openssl
root@arduino:~/openssl# cd openssl
root@arduino:~/openssl# mkdir private
// 產生 根私鑰
root@arduino:~/openssl# openssl genrsa -out private/cakey.pem 2048
root@arduino:~/openssl# vi /etc/ssl/openssl.cnf
dir             = /root/openssl         # Where everything is kept
default_md = sha512 # 使用預設(sha1)方法,chrome 會報說此方法已經不安全,不給用
ountryName                     = Country Name (2 letter code)
countryName_default             = TW
stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = Taiwan
localityName                    = Locality Name (eg, city)
localityName_default            = Taichung
0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = SDL
organizationalUnitName          = Organizational Unit Name (eg, section)
organizationalUnitName_default  = R&D

// 產生 根證書
root@arduino:~/openssl# openssl req -new -x509 -key private/cakey.pem -out cacert.pem -days 3650
root@arduino:~/openssl# touch index.txt serial
root@arduino:~/openssl# echo 01 >serial
root@arduino:~/openssl# mkdir newcerts
root@arduino:~/openssl# mkdir web1
// 產生網站要用的私鑰,通常在別台電腦
root@arduino:~/openssl# openssl genrsa -out web1/httpd.key 2048
root@arduinoYun:~/openssl# cp /etc/ssl/openssl.cnf web1/
root@arduinoYun:~/openssl# vi web/openssl.cnf
req_extensions = v3_req # The extensions to add to a certificate request
[ v3_req ]
subjectAltName = @alt_names
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
[alt_names]
IP.1 = 192.168.1.61
IP.2 = 192.168.240.1
IP.3 = 192.168.43.201
DNS.1 = arduinoyun.local

// 產生證書申請書
root@arduino:~/openssl# openssl req -new -key web1/httpd.key -out web1/httpd.csr -sha512 -config web1/openssl.cnf
// 填入要簽署的網址
Common Name (e.g. server FQDN or YOUR name) []:Arduino Yun
// 下面兩個不要填
A challenge password []:
An optional company name []:

// 可用下面命令,查看證書申請
root@arduinoYun:~/openssl# openssl req -text -noout -in web1/httpd.csr
// 將證書申請書送到根證書的機器,簽屬證書
root@arduino:~/openssl# openssl ca -in web1/httpd.csr -out web1/httpd.crt -days 3650 -extensions v3_req -extfile web1/openssl.cnf
// 回答兩個 y 即可,若發生下列錯誤,查詢 newcerts 目錄下最後的一個 pem
failed to update database
TXT_DB error number 2
// 使用命令
root@arduinoYun:~/openssl# openssl ca -revoke newcerts/02.pem

root@arduino:~/openssl# cd ..
root@arduino:~# vi pythonWeb.py
  server.socket = ssl.wrap_socket(server.socket,
    keyfile='openssl/web1/httpd.key',
    certfile='openssl/web1/httpd.crt',
    #cert_reqs=ssl.CERT_REQUIRED,
    #ca_certs='openssl/cacert.pem',
    server_side=True,
    ssl_version=ssl.PROTOCOL_TLSv1)

傳送根證書 cacert.pem 到 local, 並改名為 cacert.crt
匯入憑證