Nginx Unit 是一款輕量級、動態的應用伺服器,由 Nginx 團隊開發。它支援多種程式語言,包括 Python、PHP、Go、Node.js、Java、Perl 和 Ruby,並且可以透過 RESTful API 進行動態設定,無需重啟服務。
Nginx Unit 概述
Nginx Unit 的主要特點:
- 多語言支援:單一伺服器可同時運行多種程式語言的應用程式
- 動態設定:透過 JSON API 即時更新設定,無需重啟服務
- 輕量高效:採用非同步事件驅動架構,資源消耗低
- 安全隔離:每個應用程式在獨立的程序中運行
- TLS 支援:內建 SSL/TLS 終止功能
安裝 Nginx Unit
新增官方套件庫
首先安裝必要的套件:
1
2
| sudo apt update
sudo apt install -y curl apt-transport-https gnupg2
|
新增 Nginx Unit 官方 GPG 金鑰和套件庫:
1
2
3
4
5
| # 新增 GPG 金鑰
curl -fsSL https://unit.nginx.org/keys/nginx-keyring.gpg | sudo gpg --dearmor -o /usr/share/keyrings/nginx-keyring.gpg
# 新增套件庫
echo "deb [signed-by=/usr/share/keyrings/nginx-keyring.gpg] https://packages.nginx.org/unit/ubuntu/ jammy unit" | sudo tee /etc/apt/sources.list.d/unit.list
|
安裝 Unit 核心與語言模組
1
2
3
4
5
6
7
8
9
10
| sudo apt update
# 安裝 Unit 核心
sudo apt install -y unit
# 安裝語言模組(依需求選擇)
sudo apt install -y unit-python3.10 # Python 3.10
sudo apt install -y unit-php # PHP
sudo apt install -y unit-go # Go
sudo apt install -y unit-nodejs # Node.js (外部模組)
|
啟動服務
1
2
3
| sudo systemctl enable unit
sudo systemctl start unit
sudo systemctl status unit
|
設定架構
Nginx Unit 使用 JSON 格式進行設定,主要透過 Unix socket 進行 API 操作:
1
2
| # 預設 socket 位置
/var/run/control.unit.sock
|
查看目前設定
1
| sudo curl --unix-socket /var/run/control.unit.sock http://localhost/config
|
設定結構
Unit 的設定主要包含以下區塊:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| {
"listeners": {
"*:8080": {
"pass": "applications/myapp"
}
},
"applications": {
"myapp": {
"type": "python",
"path": "/var/www/myapp",
"module": "wsgi"
}
},
"routes": [],
"upstreams": {}
}
|
部署 Python 應用
建立 Python 應用程式
1
| sudo mkdir -p /var/www/python-app
|
建立 WSGI 應用程式 /var/www/python-app/wsgi.py:
1
2
3
4
5
| def application(environ, start_response):
status = '200 OK'
headers = [('Content-Type', 'text/html; charset=utf-8')]
start_response(status, headers)
return [b'<h1>Hello from Python!</h1>']
|
設定 Unit
建立設定檔 python-config.json:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| {
"listeners": {
"*:8080": {
"pass": "applications/python-app"
}
},
"applications": {
"python-app": {
"type": "python 3.10",
"path": "/var/www/python-app",
"module": "wsgi",
"processes": 2
}
}
}
|
套用設定:
1
2
| sudo curl -X PUT --unix-socket /var/run/control.unit.sock \
-d @python-config.json http://localhost/config
|
部署 PHP 應用
建立 PHP 應用程式
1
| sudo mkdir -p /var/www/php-app
|
建立 /var/www/php-app/index.php:
1
2
3
4
5
| <?php
echo "<h1>Hello from PHP!</h1>";
echo "<p>Server Time: " . date('Y-m-d H:i:s') . "</p>";
phpinfo();
?>
|
設定 Unit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| {
"applications": {
"php-app": {
"type": "php",
"root": "/var/www/php-app",
"index": "index.php",
"processes": {
"max": 10,
"spare": 2
}
}
},
"listeners": {
"*:8081": {
"pass": "applications/php-app"
}
}
}
|
套用設定:
1
2
| sudo curl -X PUT --unix-socket /var/run/control.unit.sock \
-d @php-config.json http://localhost/config/applications/php-app
|
部署 Node.js 應用
建立 Node.js 應用程式
1
| sudo mkdir -p /var/www/node-app
|
建立 /var/www/node-app/app.js:
1
2
3
4
5
6
7
8
9
10
| const http = require('http');
module.exports = {
createServer: function() {
return http.createServer((req, res) => {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end('<h1>Hello from Node.js!</h1>');
});
}
};
|
設定 Unit(使用外部模組)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| {
"applications": {
"node-app": {
"type": "external",
"working_directory": "/var/www/node-app",
"executable": "/usr/bin/node",
"arguments": ["app.js"]
}
},
"listeners": {
"*:8082": {
"pass": "applications/node-app"
}
}
}
|
路由設定
Nginx Unit 提供強大的路由功能,可以根據 URI、主機名、Header 等進行流量分發:
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
| {
"listeners": {
"*:80": {
"pass": "routes"
}
},
"routes": [
{
"match": {
"uri": "/api/*"
},
"action": {
"pass": "applications/python-app"
}
},
{
"match": {
"uri": "/admin/*"
},
"action": {
"pass": "applications/php-app"
}
},
{
"action": {
"share": "/var/www/static$uri"
}
}
]
}
|
進階路由條件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| {
"routes": [
{
"match": {
"host": "api.example.com",
"method": ["GET", "POST"],
"headers": {
"Accept": "*application/json*"
}
},
"action": {
"pass": "applications/api-backend"
}
}
]
}
|
SSL/TLS 設定
上傳憑證
首先將憑證與私鑰合併:
1
| cat /etc/ssl/certs/server.crt /etc/ssl/private/server.key > bundle.pem
|
上傳憑證到 Unit:
1
2
| sudo curl -X PUT --unix-socket /var/run/control.unit.sock \
--data-binary @bundle.pem http://localhost/certificates/main-cert
|
設定 TLS 監聽器
1
2
3
4
5
6
7
8
9
10
| {
"listeners": {
"*:443": {
"pass": "routes",
"tls": {
"certificate": "main-cert"
}
}
}
}
|
強制 HTTPS 重導向
1
2
3
4
5
6
7
8
9
10
11
12
13
| {
"routes": [
{
"match": {
"scheme": "http"
},
"action": {
"return": 301,
"location": "https://$host$request_uri"
}
}
]
}
|
動態設定更新
Nginx Unit 最大的優勢是可以即時更新設定,無需重啟服務:
更新特定應用程式
1
2
3
| # 更新 Python 應用的程序數量
sudo curl -X PUT --unix-socket /var/run/control.unit.sock \
-d '4' http://localhost/config/applications/python-app/processes
|
新增監聽器
1
2
| sudo curl -X PUT --unix-socket /var/run/control.unit.sock \
-d '{"pass": "applications/php-app"}' http://localhost/config/listeners/*:9000
|
刪除設定
1
2
3
| # 刪除特定監聽器
sudo curl -X DELETE --unix-socket /var/run/control.unit.sock \
http://localhost/config/listeners/*:9000
|
查看應用程式狀態
1
| sudo curl --unix-socket /var/run/control.unit.sock http://localhost/status
|
輸出範例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| {
"connections": {
"accepted": 1234,
"active": 5,
"idle": 10,
"closed": 1219
},
"requests": {
"total": 5678
},
"applications": {
"python-app": {
"processes": {
"running": 2,
"starting": 0,
"idle": 2
},
"requests": {
"active": 0
}
}
}
}
|
參考資料