Add ntfy push and Listmonk newsletter with lightweight Docker deploy tooling.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
47
docker/integrations/README.md
Normal file
47
docker/integrations/README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Listmonk 邮件通讯(轻量 / Go)
|
||||
|
||||
NomadCNA 仅自托管 **Listmonk**(Go 编写,~128MB)用于城市/活动邮件订阅。
|
||||
|
||||
| 服务 | 域名 | 内网端口 |
|
||||
| --- | --- | --- |
|
||||
| Listmonk | https://listmonk.nomadro.cn | 9030 |
|
||||
|
||||
**不自托管**(内存占用高,已移除):
|
||||
|
||||
- Cal.com(Node,预约改由站内消息协调)
|
||||
- Owncast / PeerTube(直播/点播沿用 **MiroTalk** + **MinIO**)
|
||||
|
||||
## 国内镜像
|
||||
|
||||
`/etc/docker/daemon.json` 参考 `daemon.json.cn`,拉取用 `pull-images-cn.sh`(`docker.1ms.run` 前缀)。
|
||||
|
||||
## 部署
|
||||
|
||||
```bash
|
||||
python scripts/deploy-listmonk.py
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
管理后台创建 Token 后:
|
||||
|
||||
```
|
||||
LISTMONK_API_KEY=...
|
||||
LISTMONK_DEFAULT_LIST_IDS=1
|
||||
```
|
||||
|
||||
## ntfy 手机推送(Go,已有容器 `nomadro-ntfy`)
|
||||
|
||||
| 域名 | 端口 |
|
||||
| --- | --- |
|
||||
| https://ntfy.nomadro.cn | 127.0.0.1:9180 |
|
||||
|
||||
- HTTPS:`docker/integrations/nginx/ntfy.nomadro.cn.conf` + Certbot
|
||||
- 认证:`deny-all` 默认;匿名用户可读 `nomadcna-*` 主题(App 订阅)
|
||||
- 后端发布:服务器 `.env.local` 配置 `NTFY_AUTH_TOKEN=tk_...`
|
||||
- 业务接入:`create_notification` 对 `targetUserId` 推送;设置页开启「手机推送」
|
||||
|
||||
```bash
|
||||
python scripts/ssh-fix-ntfy.py # 修复 HTTPS
|
||||
python scripts/ssh-setup-ntfy-acl3.py # ACL + 后端 token(如需重建)
|
||||
```
|
||||
9
docker/integrations/daemon.json.cn
Normal file
9
docker/integrations/daemon.json.cn
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"max-concurrent-downloads": 3,
|
||||
"max-concurrent-uploads": 1,
|
||||
"registry-mirrors": [
|
||||
"https://docker.1ms.run",
|
||||
"https://dockerproxy.net",
|
||||
"https://mirror.ccs.tencentyun.com"
|
||||
]
|
||||
}
|
||||
43
docker/integrations/docker-compose.yml
Normal file
43
docker/integrations/docker-compose.yml
Normal file
@@ -0,0 +1,43 @@
|
||||
# 轻量集成:仅 Listmonk(Go)+ PostgreSQL
|
||||
# 视频/预约沿用既有 MiroTalk + The Lounge,不自托管 Cal/Owncast/PeerTube
|
||||
services:
|
||||
postgres-int:
|
||||
image: postgres:16-alpine
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER:-nomadro}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
|
||||
ports:
|
||||
- "127.0.0.1:5433:5432"
|
||||
volumes:
|
||||
- pg-int:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-nomadro}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
mem_limit: 128m
|
||||
|
||||
listmonk:
|
||||
image: listmonk/listmonk:v5.0.0
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
postgres-int:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
- "127.0.0.1:9030:9000"
|
||||
environment:
|
||||
LISTMONK_app__address: 0.0.0.0:9000
|
||||
LISTMONK_app__admin_username: ${LISTMONK_ADMIN_USER:-admin}
|
||||
LISTMONK_app__admin_password: ${LISTMONK_ADMIN_PASSWORD:?set LISTMONK_ADMIN_PASSWORD}
|
||||
LISTMONK_db__host: postgres-int
|
||||
LISTMONK_db__port: 5432
|
||||
LISTMONK_db__user: ${POSTGRES_USER:-nomadro}
|
||||
LISTMONK_db__password: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
|
||||
LISTMONK_db__database: listmonk
|
||||
LISTMONK_db__ssl_mode: disable
|
||||
command: [sh, -c, "./listmonk --install --idempotent --yes && ./listmonk"]
|
||||
mem_limit: 128m
|
||||
|
||||
volumes:
|
||||
pg-int:
|
||||
1
docker/integrations/init-dbs.sql
Normal file
1
docker/integrations/init-dbs.sql
Normal file
@@ -0,0 +1 @@
|
||||
-- 已由 compose POSTGRES_DB=listmonk 初始化,此文件保留兼容旧卷
|
||||
50
docker/integrations/nginx/listmonk.nomadro.cn.conf
Normal file
50
docker/integrations/nginx/listmonk.nomadro.cn.conf
Normal file
@@ -0,0 +1,50 @@
|
||||
upstream nomadro_listmonk {
|
||||
server 127.0.0.1:9030;
|
||||
keepalive 8;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name listmonk.nomadro.cn;
|
||||
root /www/wwwroot/www.nomadro.cn;
|
||||
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
allow all;
|
||||
root /www/wwwroot/www.nomadro.cn;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
access_log /www/wwwlogs/listmonk.nomadro.cn.log;
|
||||
error_log /www/wwwlogs/listmonk.nomadro.cn.error.log;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name listmonk.nomadro.cn;
|
||||
root /www/wwwroot/www.nomadro.cn;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/listmonk.nomadro.cn/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/listmonk.nomadro.cn/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
|
||||
client_max_body_size 25m;
|
||||
|
||||
location / {
|
||||
proxy_pass http://nomadro_listmonk;
|
||||
proxy_http_version 1.1;
|
||||
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;
|
||||
}
|
||||
|
||||
access_log /www/wwwlogs/listmonk.nomadro.cn.log;
|
||||
error_log /www/wwwlogs/listmonk.nomadro.cn.error.log;
|
||||
}
|
||||
54
docker/integrations/nginx/ntfy.nomadro.cn.conf
Normal file
54
docker/integrations/nginx/ntfy.nomadro.cn.conf
Normal file
@@ -0,0 +1,54 @@
|
||||
upstream nomadro_ntfy {
|
||||
server 127.0.0.1:9180;
|
||||
keepalive 8;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name ntfy.nomadro.cn;
|
||||
root /www/wwwroot/www.nomadro.cn;
|
||||
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
allow all;
|
||||
root /www/wwwroot/www.nomadro.cn;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
access_log /www/wwwlogs/ntfy.nomadro.cn.log;
|
||||
error_log /www/wwwlogs/ntfy.nomadro.cn.error.log;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name ntfy.nomadro.cn;
|
||||
root /www/wwwroot/www.nomadro.cn;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/ntfy.nomadro.cn/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/ntfy.nomadro.cn/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
|
||||
client_max_body_size 25m;
|
||||
|
||||
location / {
|
||||
proxy_pass http://nomadro_ntfy;
|
||||
proxy_http_version 1.1;
|
||||
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;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_read_timeout 300s;
|
||||
proxy_send_timeout 300s;
|
||||
}
|
||||
|
||||
access_log /www/wwwlogs/ntfy.nomadro.cn.log;
|
||||
error_log /www/wwwlogs/ntfy.nomadro.cn.error.log;
|
||||
}
|
||||
22
docker/integrations/pull-images-cn.sh
Normal file
22
docker/integrations/pull-images-cn.sh
Normal file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
# 国内 VPS:仅拉取 Listmonk 栈(Go + Postgres Alpine)
|
||||
set -eu
|
||||
|
||||
MIRRORS=(docker.1ms.run dockerproxy.net)
|
||||
|
||||
pull_one() {
|
||||
local src="$1"
|
||||
local dst="$2"
|
||||
for m in "${MIRRORS[@]}"; do
|
||||
echo "==> pull ${m}/${src}"
|
||||
if docker pull "${m}/${src}"; then
|
||||
docker tag "${m}/${src}" "${dst}"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
docker pull "${dst}"
|
||||
}
|
||||
|
||||
pull_one "library/postgres:16-alpine" "postgres:16-alpine"
|
||||
pull_one "listmonk/listmonk:v5.0.0" "listmonk/listmonk:v5.0.0"
|
||||
docker images | grep -E 'postgres|listmonk' || true
|
||||
Reference in New Issue
Block a user