From d0fdf1c5da10c6daf1b3bd27d8927959ca58376c Mon Sep 17 00:00:00 2001 From: YoursFunny Date: Thu, 6 Aug 2026 16:48:52 +0800 Subject: [PATCH] deploy: default to ACME-issued certs, drop manual cert setup Domain deployment now uses ACME_HOST (acme-companion auto issue/renew) instead of the legacy LETSENCRYPT_HOST name. IP-only deployments can use acme.sh to obtain Let's Encrypt IP certificates (shortlived profile, ~7-day validity, http-01 only) instead of self-signed manual certs: documented the acme-ip service, first-issue command with install-cert into nginx-certs and nginx reload via docker socket. Removed the manual WEBHOOK_CERT flow and the ./cert volume from the compose example. --- README.md | 42 ++++++++++++++++++++++++++++---------- docker-compose.yml.example | 10 +++++---- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index dde073c..88c9143 100644 --- a/README.md +++ b/README.md @@ -39,16 +39,37 @@ NSFW 推文:公开的 syndication 接口不返回敏感内容。设置 `TWITTE **有域名** 1. DNS A 记录指向服务器 -2. compose 里设 `VIRTUAL_HOST`、`LETSENCRYPT_HOST` 为域名,`WEBHOOK_URL` 设为 `https://域名/` -3. 证书自动签发与续期,无需手动处理 +2. compose 里设 `VIRTUAL_HOST`、`WEBHOOK_URL` 为域名,并取消注释 `ACME_HOST`(设为域名) +3. acme-companion 自动签发与续期证书,无需手动处理 **只有 IP** -1. 生成自签证书(PEM 格式,见第 3 步): - `openssl req -x509 -newkey rsa:2048 -nodes -days 365 -keyout nginx-certs/default.key -out nginx-certs/default.crt` -2. compose 里 nginx-proxy 设 `DEFAULT_HOST`,bot 设 `WEBHOOK_CERT: './cert/cert.pem'`(须与代理所服务的为同一张证书) -3. 证书必须是 PEM 编码(ASCII BASE64,以 `-----BEGIN CERTIFICATE-----` 开头)—— Telegram 只接受该格式;若现有证书是 DER 二进制,转换: - `openssl x509 -in cert.der -inform DER -out cert.pem -outform PEM` - (私钥同理:`openssl rsa -in key.der -inform DER -out key.pem -outform PEM`) +Let's Encrypt 支持为公网 IP 签发证书(2026 年起可用,有效期约 7 天,须 `shortlived` profile)。用 [acme.sh](https://github.com/acmesh-official/acme.sh) 自动签发与续期,无需手动证书: + +1. compose 里增加 acme-ip 服务(签发 + 每日检查自动续期): + ```yaml + acme-ip: + image: neilpang/acme.sh + container_name: acme-ip + command: daemon + restart: always + volumes: + - ./nginx-certs:/acme.sh + - ./nginx-html:/usr/share/nginx/html + - /var/run/docker.sock:/var/run/docker.sock:ro + networks: [proxy] + ``` +2. 首次签发(把 `` 换成服务器公网 IP,IPv6 同样支持,多个 `-d` 可并列): + ```bash + docker compose exec acme-ip acme.sh --issue --server letsencrypt \ + -d --cert-profile shortlived --days 3 \ + --webroot /usr/share/nginx/html \ + --install-cert --cert-file /acme.sh/.crt \ + --key-file /acme.sh/.key \ + --reloadcmd "curl --unix-socket /var/run/docker.sock -X POST http://localhost/containers/nginx-proxy/kill?signal=HUP" + ``` +3. compose 里设 `VIRTUAL_HOST: ''`、`WEBHOOK_URL: 'https:///'`,无需 `WEBHOOK_CERT`。续期由 acme.sh daemon 自动完成(`--days 3` = 每 3 天续一次,证书 7 天有效有缓冲),续期成功后自动 HUP 通知 nginx-proxy 加载新证书。 + + 限制:证书约 7 天有效;验证仅支持 http-01/tls-alpn-01(80 端口必须公网可达);不支持 DNS-01、私有 IP 与 IP 段;同一 IP 集合每 168 小时限签发 5 张。建议先用 `--server letsencrypt_test` 试签,成功后再切正式服务器。 Telegram 只接受 443/80/88/8443 端口。 @@ -66,13 +87,12 @@ Telegram 只接受 443/80/88/8443 端口。 | `LOCAL_USER_ID` | 容器内运行用户 UID,默认 9001 | | `VIRTUAL_HOST` | 对外域名或 IP,nginx-proxy 按此路由 | | `VIRTUAL_PORT` | bot 容器内监听端口,nginx-proxy 的转发目标 | -| `LETSENCRYPT_HOST` | 设为域名时由 acme-companion 自动签发/续期证书 | +| `ACME_HOST` | 域名部署:设为域名时由 acme-companion 自动签发/续期证书 | | `DEFAULT_HOST` | nginx-proxy 将未知 Host 的请求路由到该 vhost(IP 访问时需要) | | `DEFAULT_EMAIL` | acme-companion 证书通知邮箱 | | `WEBHOOK` | `true` 启用 webhook 模式(默认轮询) | | `WEBHOOK_LISTEN` / `WEBHOOK_PORT` | bot 容器内监听地址/端口 | -| `WEBHOOK_URL` | 对外公网 HTTPS 地址(`https://域名/`) | -| `WEBHOOK_CERT` | 自签证书路径(仅 IP 路径需要,须为 PEM 且与代理所服务的一致) | +| `WEBHOOK_URL` | 对外公网 HTTPS 地址(`https://域名/` 或 `https://IP/`) | | `WEBHOOK_SECRET_TOKEN` | 更新校验令牌(`X-Telegram-Bot-Api-Secret-Token`) | diff --git a/docker-compose.yml.example b/docker-compose.yml.example index 496cbd3..57b092d 100644 --- a/docker-compose.yml.example +++ b/docker-compose.yml.example @@ -49,14 +49,16 @@ services: # Link-result cache TTL (default 604800 = 7 days). LINK_CACHE_TTL_SECONDS: '604800' RUST_LOG: 'info' - VIRTUAL_HOST: 'bot.example.com' + # 域名部署:替换为你的域名;纯 IP 部署:替换为服务器公网 IP(需按 + # README「只有 IP」一节签发 acme IP 证书)。 + VIRTUAL_HOST: '' VIRTUAL_PORT: '8443' - # LETSENCRYPT_HOST: 'bot.example.com' + # 域名部署:取消注释并设为域名,由 acme-companion 自动签发/续期证书。 + # ACME_HOST: 'your.domain.com' WEBHOOK: 'true' WEBHOOK_LISTEN: '0.0.0.0' WEBHOOK_PORT: '8443' - WEBHOOK_URL: 'https://bot.example.com/' - # WEBHOOK_CERT: './cert/cert.pem' + WEBHOOK_URL: 'https:///' WEBHOOK_SECRET_TOKEN: '' volumes: - ./data:/app/data