This guide describes how to install HAProxy with Let’s Encrypt as a service. This is possible in case you are hosting ThingsBoard in the cloud and have a valid DNS name assigned to your instance.
- 前置条件
- 步骤1. 通过SSH连接到ThingsBoard实例
- 步骤2. 安装HAProxy负载均衡器包
- 步骤3. 安装Certbot包
- 步骤4. 安装默认自签名证书
- 步骤5. 配置HAProxy负载均衡器
- 步骤6. 配置Edge TLS通信(可选)
- 步骤7. 配置Certbot与Let’s Encrypt
- 步骤8. 安装证书自动续期定时任务
- 步骤9. 重启 HAProxy负载均衡器
- 步骤10. 使用Let’s Encrypt生成证书
- 步骤11. 刷新HAProxy配置
前置条件
RHEL/CentOS 8/9,已为实例分配有效的DNS名称。网络设置需允许通过80端口(HTTP)和443端口(HTTPS)的连接。
要开放80和443端口,请执行以下命令:
1
2
3
sudo firewall-cmd --zone=public --add-port=80/tcp --permanent
sudo firewall-cmd --zone=public --add-port=443/tcp --permanent
sudo firewall-cmd --reload
步骤1. 通过SSH连接到ThingsBoard实例
以下是AWS的示例命令,供参考:
1
$ ssh -i <PRIVATE-KEY> ec2-user@<PUBLIC_DNS_NAME>
或咨询您的云服务提供商了解其他选项。
步骤2. 安装HAProxy负载均衡器包
执行以下命令安装HAProxy包:
1
sudo dnf -y install haproxy
执行以下命令启用服务自动启动:
1
sudo systemctl enable haproxy
步骤3. 安装Certbot包
执行以下命令安装Certbot包:
1
sudo dnf -y install ca-certificates certbot
步骤4. 安装默认自签名证书
执行以下命令安装默认自签名证书:
(请完整复制粘贴以下命令)
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
31
32
33
34
35
36
37
38
39
40
41
cat <<EOT | sudo tee /usr/bin/haproxy-default-cert
#!/bin/sh
set -e
HA_PROXY_DIR=/usr/share/tb-haproxy
CERTS_D_DIR=\${HA_PROXY_DIR}/certs.d
TEMP_DIR=/tmp
PASSWORD=\$(openssl rand -base64 32)
SUBJ="/C=US/ST=somewhere/L=someplace/O=haproxy/OU=haproxy/CN=haproxy.selfsigned.invalid"
KEY=\${TEMP_DIR}/haproxy_key.pem
CERT=\${TEMP_DIR}/haproxy_cert.pem
CSR=\${TEMP_DIR}/haproxy.csr
DEFAULT_PEM=\${HA_PROXY_DIR}/default.pem
if [ ! -e \${HA_PROXY_DIR} ]; then
mkdir -p \${HA_PROXY_DIR}
fi
if [ ! -e \${CERTS_D_DIR} ]; then
mkdir -p \${CERTS_D_DIR}
fi
# Check if default.pem has been created
if [ ! -e \${DEFAULT_PEM} ]; then
openssl genrsa -des3 -passout pass:\${PASSWORD} -out \${KEY} 2048 &> /dev/null
sleep 1
openssl req -new -key \${KEY} -passin pass:\${PASSWORD} -out \${CSR} -subj \${SUBJ} &> /dev/null
sleep 1
cp \${KEY} \${KEY}.org &> /dev/null
openssl rsa -in \${KEY}.org -passin pass:\${PASSWORD} -out \${KEY} &> /dev/null
sleep 1
openssl x509 -req -days 3650 -in \${CSR} -signkey \${KEY} -out \${CERT} &> /dev/null
sleep 1
cat \${CERT} \${KEY} > \${DEFAULT_PEM}
echo \${PASSWORD} > \${HA_PROXY_DIR}/password.txt
fi
EOT
执行以下命令:
1
2
3
sudo chmod +x /usr/bin/haproxy-default-cert
touch ~/.rnd
sudo haproxy-default-cert
步骤5. 配置HAProxy负载均衡器
执行以下命令创建HAProxy负载均衡器配置文件:
(请完整复制粘贴以下命令)
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
cat <<EOT | sudo tee /etc/haproxy/haproxy.cfg
#HA Proxy Config
global
ulimit-n 500000
maxconn 99999
maxpipes 99999
tune.maxaccept 500
log 127.0.0.1 local0
log 127.0.0.1 local1 notice
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
defaults
log global
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
timeout tunnel 1h # timeout to use with WebSocket and CONNECT
default-server init-addr none
frontend http-in
bind *:80 alpn h2,http/1.1
option forwardfor
http-request add-header "X-Forwarded-Proto" "http"
acl letsencrypt_http_acl path_beg /.well-known/acme-challenge/
redirect scheme https if !letsencrypt_http_acl { env(FORCE_HTTPS_REDIRECT) -m str true }
use_backend letsencrypt_http if letsencrypt_http_acl
default_backend tb-backend
frontend https_in
bind *:443 ssl crt /usr/share/tb-haproxy/default.pem crt /usr/share/tb-haproxy/certs.d/ ciphers ECDHE-RSA-AES256-SHA:RC4-SHA:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM alpn h2,http/1.1
option forwardfor
http-request add-header "X-Forwarded-Proto" "https"
default_backend tb-backend
backend letsencrypt_http
server letsencrypt_http_srv 127.0.0.1:8090
backend tb-backend
balance leastconn
option tcp-check
option log-health-checks
server tb1 127.0.0.1:8080 check inter 5s
http-request set-header X-Forwarded-Port %[dst_port]
EOT
步骤6. 配置Edge TLS通信(可选)
ThingsBoard支持通过TLS/SSL上的gRPC连接保护平台与Edge实例间的连接。
我们将使用HAProxy作为Edge与平台间TLS连接的终止点。
首先,需将平台Edge连接默认绑定端口改为7071。这样可将HAProxy配置为监听默认7070端口,并将连接转发至平台的7071端口。
请执行以下命令更新平台上的Edge绑定端口:
1
2
3
4
sudo sh -c 'cat <<EOL >> /etc/thingsboard/conf/thingsboard.conf
export EDGES_RPC_PORT=7071
EOL'
应用变更后需重启ThingsBoard平台:
1
sudo systemctl restart thingsboard
接下来,执行以下命令将TLS配置添加到HAProxy配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
sudo sh -c 'cat <<EOL >> /etc/haproxy/haproxy.cfg
# Edge gRPC TLS (optional)
listen grpc_front
bind *:7070 ssl crt /usr/share/tb-haproxy/default.pem crt /usr/share/tb-haproxy/certs.d/ ciphers ECDHE-RSA-AES256-SHA:RC4-SHA:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM alpn h2,http/1.1
mode tcp
option clitcpka
option tcplog
default_backend grpc_backend
backend grpc_backend
mode tcp
server grpc 127.0.0.1:7071
EOL'
步骤7. 配置Certbot与Let’s Encrypt
执行以下命令创建Certbot与Let’s Encrypt的配置文件和辅助脚本:
(请完整复制粘贴以下命令)
1
2
3
4
sudo mkdir -p /usr/local/etc/letsencrypt \
&& sudo mkdir -p /usr/share/tb-haproxy/letsencrypt \
&& sudo rm -rf /etc/letsencrypt \
&& sudo ln -s /usr/share/tb-haproxy/letsencrypt /etc/letsencrypt
1
2
3
4
5
6
7
8
cat <<EOT | sudo tee /usr/local/etc/letsencrypt/cli.ini
authenticator = standalone
agree-tos = True
http-01-port = 8090
tls-sni-01-port = 8443
non-interactive = True
preferred-challenges = http-01
EOT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cat <<EOT | sudo tee /usr/bin/haproxy-refresh
#!/bin/sh
HA_PROXY_DIR=/usr/share/tb-haproxy
LE_DIR=/usr/share/tb-haproxy/letsencrypt/live
DOMAINS=\$(ls -I README \${LE_DIR})
# update certs for HA Proxy
for DOMAIN in \${DOMAINS}
do
cat \${LE_DIR}/\${DOMAIN}/fullchain.pem \${LE_DIR}/\${DOMAIN}/privkey.pem > \${HA_PROXY_DIR}/certs.d/\${DOMAIN}.pem
done
# restart haproxy
exec service haproxy restart
EOT
1
2
3
4
5
cat <<EOT | sudo tee /usr/bin/certbot-certonly
#!/bin/sh
/usr/bin/certbot certonly -c /usr/local/etc/letsencrypt/cli.ini "\$@"
EOT
1
2
3
4
5
cat <<EOT | sudo tee /usr/bin/certbot-renew
#!/bin/sh
/usr/bin/certbot -c /usr/local/etc/letsencrypt/cli.ini renew "\$@"
EOT
1
sudo chmod +x /usr/bin/haproxy-refresh /usr/bin/certbot-certonly /usr/bin/certbot-renew
步骤8. 安装证书自动续期定时任务
执行以下命令创建证书自动续期定时任务:
(请完整复制粘贴以下命令)
1
2
3
4
5
6
7
8
9
10
11
12
13
cat <<EOT | sudo tee /etc/cron.d/certbot
# /etc/cron.d/certbot: crontab entries for the certbot package
#
# Upstream recommends attempting renewal twice a day
#
# Eventually, this will be an opportunity to validate certificates
# haven't been revoked, etc. Renewal will only occur if expiration
# is within 30 days.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
0 */12 * * * root test -x /usr/bin/certbot && perl -e 'sleep int(rand(3600))' && certbot -c /usr/local/etc/letsencrypt/cli.ini -q renew && haproxy-refresh
EOT
步骤9. 重启 HAProxy负载均衡器
最后重启HAProxy负载均衡器服务以使更改生效:
1
sudo service haproxy restart
步骤10. 使用Let’s Encrypt生成证书
执行以下命令前,请勿忘记替换your_domain和your_email:
1
sudo certbot-certonly --domain your_domain --email your_email
步骤11. 刷新HAProxy配置
最后重启HAProxy:
1
sudo haproxy-refresh