「技术选型不是技术题」——一人公司年入50万的基础设施账单
上周有个读者私信我:「魏哥,我也想搞一人公司,但买个服务器就要好几千,再买域名、OSS、数据库……启动成本是不是很高?」我回了一句扎心的话:你最大的成本不是服务器,是选错技术栈浪费的时间。 我运营「模力AGI」这个 OPC 快半年了,从零搭建了一套完整的自动化商业体系——公众号日更、AI Agent 服务、SaaS 小工具、数据看板——都在跑。今天我把技术栈全盘托出,附上真实账单,给你算一笔年入 50 万需要什么样的基础设施。
- 环境依赖
在开始之前,先把环境配好。以下是我服务器上的核心依赖清单: Python 环境(requirements.txt):
fastapi==0.115.0
uvicorn[standard]==0.30.0
gunicorn==22.0.0
celery[redis]==5.4.0
sqlalchemy==2.0.35
pymysql==1.1.1
redis==5.2.0
minio==7.2.10
boto3==1.35.0
python-dotenv==1.0.1
httpx==0.27.0
系统依赖(Docker 环境):
# 安装了 Docker + Docker Compose 的轻量服务器
docker --version # ≥ 24.0
docker compose version # ≥ 2.20
# 一键安装脚本(适用于 Ubuntu 22.04/24.04)
curl -fsSL https://get.docker.com | bash
apt-get install -y docker-compose-plugin
验证依赖是否就绪:
# 验证 Python 包
python -c "import fastapi, celery, sqlalchemy, redis, minio; print('OK')"
# 验证 Docker 服务
docker run hello-world
# 验证端口未被占用
ss -tlnp | grep -E '8000|443|80|3306|6379|9000'
一、技术栈全景:我的「铁三角」架构 先看整体架构。一人公司最怕什么?大而全。你一个人不可能既管 K8s 集群又写业务代码又搞运维监控。所以架构必须极简、可维护、单兵可操作。
┌─────────────────────────────────────────────────┐
│ 用户流量入口 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 公众号/H5 │ │ 小程序 │ │ API网关 │ │
│ └─────┬────┘ └─────┬────┘ └─────┬────┘ │
└────────┼──────────────┼──────────────┼───────────┘
│ │ │
┌────────▼──────────────▼──────────────▼───────────┐
│ 业务层 (单进程) │
│ ┌─────────────────────────────────────────┐ │
│ │ FastAPI + Celery + SQLAlchemy │ │
│ │ 一个进程搞定API/后台任务/定时任务 │ │
│ └──────────────┬──────────────────────────┘ │
└─────────────────┼──────────────────────────────────┘
│
┌─────────────────▼──────────────────────────────────┐
│ 数据与基础设施层 │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────────┐ │
│ │MySQL │ │Redis │ │MinIO │ │ 阿里云OSS│ │
│ └──────┘ └──────┘ └──────┘ └──────────┘ │
│ ┌──────┐ ┌───────────┐ ┌──────────────────┐ │
│ │ES │ │GitHub/Gitee│ │ Docker Swarm │ │
│ └──────┘ └───────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────┘
我的核心原则只有三条: 能合绝不拆——单个 VPS 能跑完的就不要微服务
能用 SaaS 别自建——Push 通知、邮件、监控能用第三方就用第三方
容器化部署——Docker 全家桶,迁移成本趋近于零
二、服务器选型:轻量应用服务器才是 OPC 的甜点 先回答标题的问题:年入 50 万需要什么样的服务器? 答案是:一台 2核4G 的轻量应用服务器,月费不到 100 元。 我目前在用阿里云「轻量应用服务器」香港节点,2核4G,40GB SSD,3M 带宽。月费折算下来约 84 元/年付。上面跑了什么? 主站 API(FastAPI + Gunicorn + Uvicorn)
Celery Worker + Beat(定时任务)
Redis(缓存 + 消息队列)
MySQL 8.0(RDS 不在这个机器上,但开发环境是在的)
MinIO(对象存储服务)
Nginx(反向代理 + SSL)
Portainer(容器管理面板)
一台机器,7 个服务,全部 Docker 化。 内存占用峰值 3.2GB,CPU 平均负载 0.8。你猜怎么着?还有余量再跑两个小服务。 为什么不用云原生全家桶? 我试过。第一周就在 EKS 上花掉了 200 块的 NAT Gateway 费用——而我的日活用户才 37 个。 OPC 的金科玉律:在用户破万之前,不要碰 K8s。 对于单节点部署,Docker Compose + Portainer 足够。如果哪天需要横向扩展,Swarm 模式的迁移成本极低——改个 compose.yml 里的 deploy 配置就能从单机变集群。 这是我的
docker-compose.yml
核心片段:
version: '3.8'
services:
api:
build:./app
environment:
-DATABASE_URL=mysql+pymysql://user:pass@db:3306/opc
-REDIS_URL=redis://redis:6379/0
depends_on:
-db
-redis
volumes:
-./app:/app
ports:
-"8000:8000"
restart:unless-stopped
celery:
build:./app
command:celery-Atasksworker-linfo
depends_on:
-redis
-db
redis:
image:redis:7-alpine
restart:unless-stopped
db:
image:mysql:8.0
volumes:
-mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD:${DB_PASSWORD}
restart:unless-stopped
volumes:
mysql_data:
容器化最大的好处不是性能,而是心智负担降低——换机器只要
docker compose up -d
,一分钟全起来。 三、反向代理与 SSL:Nginx 完整配置 很多 OPC 的 API 裸奔在公网上。没有 HTTPS,没有限流,没有防爬——等于把家门大敞。 以下是我生产环境用的 Nginx 配置,包含 SSL(Let's Encrypt 自动续期)、限流、WebSocket 升级和静态资源缓存: 3.1 Nginx 主配置
# /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections1024;
useepoll;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
server_tokensoff; # 隐藏版本号
# 日志格式(含请求耗时,方便排查慢接口)
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time"';
access_log /var/log/nginx/access.log main;
sendfileon;
tcp_nopushon;
keepalive_timeout65;
# Gzip 压缩
gzipon;
gzip_min_length1k;
gzip_types text/plain application/json application/javascript text/css;
# 限流区域:每 IP 每秒最多 30 个请求(API 保护)
limit_req_zone$binary_remote_addr zone=api_limit:10m rate=30r/s;
# 连接数限制:每 IP 最多 20 并发
limit_conn_zone$binary_remote_addr zone=conn_limit:10m;
include /etc/nginx/conf.d/*.conf;
}
3.2 站点配置(含 SSL)
# /etc/nginx/conf.d/opc.conf
# HTTP → HTTPS 强制跳转
server {
listen80;
server_name api.yourdomain.com;
return301 https://$host$request_uri;
}
server {
listen443 ssl http2;
server_name api.yourdomain.com;
# === SSL 证书(Let's Encrypt) ===
ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem;
# === SSL 安全加固 ===
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_cipherson;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout10m;
# === 安全头 ===
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=63072000" always;
# === 限流(保护后端) ===
limit_req zone=api_limit burst=20 nodelay;
limit_conn conn_limit 20;
# 客户端请求体上限
client_max_body_size10m;
# === 静态资源(直接由 Nginx 返回,不穿透到后端) ===
location /static/ {
alias /opt/opc/static/;
expires30d;
add_header Cache-Control "public, immutable";
}
# === API 反向代理 ===
location / {
proxy_pass http://127.0.0.1:8000;
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_connect_timeout30s;
proxy_read_timeout60s;
proxy_send_timeout30s;
# 缓冲配置
proxy_bufferingon;
proxy_buffer_size4k;
proxy_buffers832k;
}
# === WebSocket 升级(AI Agent 长连接需要) ===
location /ws/ {
proxy_pass http://127.0.0.1:8000;
proxy_http_version1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout86400s;
}
}
3.3 SSL 证书自动续期
# 安装 certbot
apt-get install -y certbot python3-certbot-nginx
# 首次申请证书(确保域名已解析到服务器)
certbot --nginx -d api.yourdomain.com -d www.yourdomain.com
# 添加 cron 自动续期(每月 1 号凌晨 3 点)
echo "0 3 1 * * certbot renew --quiet --post-hook 'nginx -s reload'" | crontab -
# 验证自动续期(干跑测试)
certbot renew --dry-run
3.4 验证 Nginx + SSL 是否正常
# 1. 检查配置语法
nginx -t
# 2. 重载配置
nginx -s reload
# 3. 测试 HTTPS 访问
curl -I https://api.yourdomain.com
# 4. 检查 SSL 证书有效期
echo | openssl s_client -servername api.yourdomain.com -connect api.yourdomain.com:443 2>/dev/null \
| openssl x509 -noout -dates
# 5. SSL Labs 在线检测(获取评分 A+)
# 浏览器打开:https://www.ssllabs.com/ssltest/analyze.html?d=api.yourdomain.com
四、数据库与存储:分层的本质是省钱 4.1 关系型数据库 主力:阿里云 RDS MySQL 2核4G 50GB SSD。月费 98 元(按量付费,没有流量费)。 为什么不用自建 MySQL? 备份脚本要自己写
磁盘满了自己扩容
挂了要自己恢复
OPC 的时间 = 收入,花在运维上不如写代码
RDS 自动备份、一键回滚、慢查询日志。每半年花 15 分钟看一眼就够了。 4.2 缓存层 Redis 7-alpine,直接跑在轻量服务器上,Docker 镜像只有 32MB。生产环境里我给了 512MB 内存限制,实际上用了不到 100MB。 使用场景: Session 存储
Celery 结果后端
API 响应缓存(TTL 60s,缓存命中率约 65%)
简单计数器(日活、API 调用量)
4.3 文件存储 对象存储三件套:OSS(主)+ MinIO(本地缓存)+ CDN。 阿里云 OSS(标准型):50GB 容量 + 10GB 月流量 = 约 15 元/月。存什么? 用户上传的图片、PDF
生成的文章封面图
AI Agent 产出的中间文件
MinIO 在本地做热缓存——高频访问的文件从 OSS 拉到本地,减少外网流量费。简单的 LRU 淘汰策略:
import os
from pathlib import Path
from functools import lru_cache
from minio import Minio # ← 修复:导入 MinIO 客户端
classFileCache:
def__init__(
self,
local_dir: str = "/data/cache",
max_size_mb: int = 1024,
# 修复:初始化 MinIO 客户端(原代码缺失,导致 self.client 未定义)
oss_endpoint: str = "oss-cn-hongkong.aliyuncs.com",
oss_access_key: str = "",
oss_secret_key: str = "",
oss_bucket: str = "opc-files",
):
self.local_dir = Path(local_dir)
self.local_dir.mkdir(parents=True, exist_ok=True)
self.max_size = max_size_mb * 1024 * 1024
# ★ Bug 修复:原代码缺少 MinIO 客户端初始化
self.client = Minio(
oss_endpoint,
access_key=oss_access_key,
secret_key=oss_secret_key,
secure=True,
)
self.oss_bucket = oss_bucket
@lru_cache(maxsize=128)
defget(self, key: str) -> bytes:
local_path = self.local_dir / key
if local_path.exists():
return local_path.read_bytes()
# 从 OSS 拉取(self.client 现已正确定义)
data = self.client.get_object(self.oss_bucket, key).read()
local_path.write_bytes(data)
self._evict_if_needed()
return data
def_evict_if_needed(self):
total = sum(
f.stat().st_size for f inself.local_dir.rglob("*") if f.is_file()
)
if total > self.max_size:
files = sorted(self.local_dir.rglob("*"), key=os.path.getatime)
for f in files[:10]:
f.unlink()
Bug 说明:原代码
self.client.get_object(...)
直接调用但从未初始化
self.client
,会在运行时抛出
AttributeError: 'FileCache' object has no attribute 'client'
。现已修复。 一个月 OSS 的 CDN 回源流量费大概 3-5 元。远超预期地便宜。 五、CI/CD 与部署:用 GitHub Actions 替代 Jenkins 一个人不需要 Jenkins。GitHub Actions 免费额度对 OPC 来说根本用不完。 我的部署流水线:
# .github/workflows/deploy.yml
name:Deploy
on:
push:
branches: [main]
jobs:
test-and-deploy:
runs-on:ubuntu-latest
steps:
-uses:actions/checkout@v4
-name:Runtests
run:|
docker compose -f docker-compose.test.yml up --abort-on-container-exit
-name:Buildandpush
env:
DOCKER_BUILDKIT:1
run:|
docker build -t opc-app:${{ github.sha }} .
docker save opc-app:${{ github.sha }} | gzip > app.tar.gz
-name:DeploytoVPS
uses:appleboy/scp-action@v0.1.7
with:
host:${{secrets.VPS_HOST}}
username:${{secrets.VPS_USER}}
key:${{secrets.VPS_KEY}}
source:"app.tar.gz"
target:"/opt/opc/deploy/"
-name:Restartservices
uses:appleboy/ssh-action@v1.0.3
with:
host:${{secrets.VPS_HOST}}
username:${{secrets.VPS_USER}}
key:${{secrets.VPS_KEY}}
script:|
cd /opt/opc
docker compose pull
docker compose up -d --force-recreate api
docker image prune -f
整体流程:
git push
→ GitHub Actions 自动跑测试 → 构建镜像 → SCP 传到服务器 →
docker compose
热更新 从 push 到上线完成,平均 47 秒。 不需要任何人盯着。 六、监控怎么办? 我用了三件套,全部免费:
| 工具 | 用途 | 免费额度 |
|---|---|---|
| Sentry | 错误追踪 | 每月 5000 events,个人项目根本用不完 |
| UptimeRobot | 可用性监控 | 免费监控 5 个 URL,每 5 分钟探测,挂了发邮件+短信 |
| Healthchecks.io | 定时任务监控 | Celery Beat 跑完后 ping 一次,超时未 ping 就告警 |
三个加起来月费为 0 元。 七、年度账单:我的基础设施花销全披露 很多人觉得做技术产品一定要烧钱。我直接晒账单(年付价格,人民币):
| 项目 | 配置 | 年费 | 月均 |
|---|---|---|---|
| 轻量应用服务器 | 2核4G 40GB SSD | 1,008 | 84 |
| RDS MySQL | 2核4G 50GB SSD | 1,176 | 98 |
| 阿里云 OSS | 50GB + CDN 流量 | 180 | 15 |
| 域名 | 1个 .com + 1个 .cn | 136 | 11 |
| 企业邮箱 | 阿里企业邮免费版 | 0 | 0 |
| SSL 证书 | Let's Encrypt(自动续) | 0 | 0 |
| GitHub Pro | 个人版 | 0 | 0 |
| Sentry | 免费版 | 0 | 0 |
| 监控工具 | UptimeRobot + Healthchecks | 0 | 0 |
| 总计 | 2,500 | 208 |
一年 2,500 元。 这是我在「模力AGI」这个 OPC 上的全部基础设施成本。 对于刚起步的 OPC,还能更省: 所有服务挤一台轻量服务器(1,008 元/年就够了)
MySQL 用 SQLite 代替(0 元)
OSS 用 MinIO 自己搭(但要小心磁盘满)
极限压缩:年费 1,008 元,月均 84 元。 八、为什么我选择了「看似落后」的方案? 你可能注意到了,我没用任何 Serverless(Lambda/FaaS),没用 NoSQL(MongoDB 挺好的但我不需要),没用消息队列(除了 Redis 自带的 pub/sub)。 理由很简单:一人公司的技术栈要服务于「快速交付」而不是「架构审美」。 如果我的用户量从 1,000 涨到 10,000,这套架构能撑住吗? API 加一层 Nginx 缓存即可
数据库加只读从库
服务器升配到 4核8G
要花多长时间?一个周末。而在这之前,我已经用 2,500 元/年的成本跑了一整年,赚回了 10 倍以上的收入。 OPC 的技术选型不是一道技术题,是一道财务题。 你的每一分钟服务器时间都在帮你赚钱,还是只是满足你的「技术洁癖」? 什么时候该升级? 我给你一个简单的判断标准: 当服务器成本 > 你月收入的 1% 时,不要动基础设施。
当你花在运维上的时间超过写代码的时间时,立刻升级。
我用这个标准检验了三个月——运维时间平均每周不到 30 分钟(主要是看一眼监控面板和部署),服务器成本只有月收入的 0.2%。所以到现在都没动。 九、行动清单 如果你也想搞一个 OPC,今天就能做的事情: 买一台轻量服务器(阿里云/腾讯云/华为云,哪个便宜买哪个),2核2G起步,年付 600-800 元
注册一个 .com 域名(约 55 元/年)
装好 Docker + Docker Compose(5 分钟搞定)
用 GitHub 管理代码,配置 GitHub Actions 自动部署
部署你的第一个 API——哪怕只是个 Hello World,完成从 push 到上线的闭环
把我的 Docker Compose 模板拿走:[1]https://github.com/weiwuji/opc-starter[2] 十、验证清单(部署完成后逐条检查) 花 5 分钟跑完下面的验证,确保整条链路是通的:
# === 1. 基础服务健康检查 ===
docker compose ps # 所有容器 STATUS=Up
docker compose logs --tail=20 api # API 无异常日志
curl http://localhost:8000/health # 返回 {"status":"ok"}
# === 2. 数据库连通性 ===
docker compose exec db mysqladmin ping -h 127.0.0.1 -u root -p${DB_PASSWORD}
# 预期输出: mysqld is alive
# === 3. Redis 连通性 ===
docker compose exec redis redis-cli ping
# 预期输出: PONG
# === 4. Celery Worker 是否正常 ===
docker compose exec celery celery -A tasks inspect ping
# 预期输出: {'celery@xxx': {'ok': 'pong'}}
# === 5. Nginx + HTTPS ===
nginx -t && nginx -s reload
curl -o /dev/null -s -w "%{http_code}" https://yourdomain.com
# 预期输出: 200
# === 6. SSL 证书有效期 ===
echo | openssl s_client -servername yourdomain.com \
-connect yourdomain.com:443 2>/dev/null \
| openssl x509 -noout -dates
# 检查 notAfter 日期是否在有效期内
# === 7. GitHub Actions 部署流水线 ===
# 在 GitHub 仓库 → Actions → 手动触发一次 workflow
# 确认:test → build → deploy → restart 四步全部绿色
# === 8. 文件缓存(FileCache) ===
python -c "
from minio import Minio
fc = FileCache(oss_access_key='test', oss_secret_key='test')
print('FileCache initialized OK:', fc.local_dir)
"
# 预期输出: FileCache initialized OK: /data/cache
全部通过后,你的 OPC 基础设施就已经是生产就绪状态了。 下篇文章我会手把手带你搭建「AI 自动化流水线」——从微信公众号内容生成、到 AI Agent 自动回复、到数据自动汇总到 Notion 仪表盘,全链路自动化。一个人,跑出十个人的效率。 套用一句我在内部笔记里写的:「当别人还在纠结服务器够不够用时,无记已经用千元级别跑通了流程闭环。不是因为技术多好,而是因为知道什么该省,什么不该省。」 下篇见。 关于作者:魏无记,AI 和数智化实践者。专注 Agent 工程化与 Loop Engineering 研究以及数智化转型。公众号持续更新 Agent 工程化实战系列和数智化转型相关知识实践——每篇都是保姆级教程照做就行。 引用链接 [1]undefined: https://github.com/weiwuji/opc-starter [2]https://github.com/weiwuji/opc-starter

浙公网安备 33010602011771号