一、部署 Render Web Service
1. 注册并创建服务
首先使用谷歌账号注册 Render,然后选择 New Web Services。

创建 Web Service1920×915 86.5 KB
2. 配置 Docker 镜像
填入镜像地址:eceasy/cli-proxy-api:latest

配置镜像1920×910 50.6 KB
3. 配置环境变量
在部署配置中,需要填写以下环境变量:
- DEPLOY: 填写
cloud
- MANAGEMENT_PASSWORD: 设置访问密码
- PGSTORE_DSN: 数据库连接字符串(下一步获取)

环境变量配置1847×489 25.5 KB
二、配置 Supabase 数据库
4. 创建 Supabase 项目
登录 Supabase,点击新建项目。

新建项目1920×912 40.4 KB
项目名称、密码和区域可以根据需要填写。

连接数据库1897×830 65.3 KB
5. 获取数据库连接字符串
项目创建完成后,点击 Connect 按钮。

选择 Direct 模式1920×914 74.1 KB
6. 选择连接模式
在连接方式中选择 Direct。

复制连接字符串1920×1020 98.5 KB
7. 复制并修改连接字符串
复制显示的 URL,然后进行以下修改:
- 将
[YOUR-PASSWORD] 替换为你设置的实际密码
- 在 URL 末尾添加:
?sslmode=require&default_query_exec_mode=simple_protocol

填写 DSN1920×915 112 KB
最终格式示例:
1
| postgresql://postgres.xxxxx:your-password@aws-0-region.supabase.com:5432/postgres?sslmode=require&default_query_exec_mode=simple_protocol
|
8. 填写 DSN 并部署
将修改后的连接字符串填入 Render 的 DSN 环境变量中。
点击 Deploy 开始部署。

开始部署1920×916 42.7 KB
三、配置 Cloudflare Worker 保活脚本
为了防止 Render 免费服务休眠,可以使用 Cloudflare Worker 定期访问服务。
9. 部署保活脚本
在 Cloudflare Workers 中创建新的 Worker,使用以下代码:
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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
const DOMAINS = [ '这里填入render给的域名', ];
export default { async scheduled(event, env, ctx) { console.log(`[${new Date().toISOString()}] 开始执行保活任务`);
const results = await Promise.allSettled( DOMAINS.map(async (domain) => { try { const response = await fetch(domain, { method: 'GET', headers: { 'User-Agent': 'Cloudflare-Worker-Bot', 'Cache-Control': 'no-cache' }, cf: { cacheTtl: 0 } });
const status = response.ok ? 'success' : 'failed'; console.log(`[${new Date().toISOString()}] ${domain}: ${status} (${response.status})`);
return { domain, status, statusCode: response.status, timestamp: new Date().toISOString() }; } catch (error) { console.error(`[${new Date().toISOString()}] ${domain}: error - ${error.message}`); return { domain, status: 'error', error: error.message, timestamp: new Date().toISOString() }; } }) );
console.log(`[${new Date().toISOString()}] 保活任务完成`); return results; },
async fetch(request, env, ctx) { try { const results = await Promise.allSettled( DOMAINS.map(async (domain) => { try { const response = await fetch(domain, { method: 'GET', headers: { 'User-Agent': 'Cloudflare-Worker-Bot', 'Cache-Control': 'no-cache' }, cf: { cacheTtl: 0 } });
return { domain, status: response.ok ? 'success' : 'failed', statusCode: response.status, timestamp: new Date().toISOString() }; } catch (error) { return { domain, status: 'error', error: error.message, timestamp: new Date().toISOString() }; } }) );
return new Response(JSON.stringify({ status: 'completed', results: results.map(r => r.value), timestamp: new Date().toISOString() }), { headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' } }); } catch (error) { return new Response(JSON.stringify({ status: 'error', message: error.message, timestamp: new Date().toISOString() }), { status: 500, headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' } }); } } };
|