免费云服务器这东西,我前后折腾过七八台,从最早的学生认证机,到后来的新用户试用、社区赞助、开发者额度,几乎每种形态都碰过。真正用起来才发现,申请只是最轻松的一步,麻烦全在后面的选型和上线环节——有的是开机才发现公网 IP 是共享的、只给映射端口,有的是跑了三天被扫描器打满 CPU,还有一台是到期自动释放,我记错了日期,数据连同快照一起没了。这篇就把这条链路完整走一遍:怎么判断一台“免费云服务器”到底免的是什么,选型时哪几个参数最容易被忽略,系统初始化哪些步骤不做后面一定会后悔,部署上线怎么做才能在小内存机器上跑稳,以及翻车之后怎么顺着链路把问题定位出来。内容偏实操,适合手上只有一台低配免费机、又想把一个真实服务跑起来的人看,完全没接触过 Linux 的也能照着做,只是每一步我会顺带说清楚为什么要这么做。
1. 先把“免费”这两个字拆开:五类免费机的真实成本
1.1 五种常见形态与它们的隐藏条款
所谓免费云服务器,厂商给的从来不是同一件东西。我按领取方式和限制条件分成五类,你对照自己手上那台,基本能对号入座。
| 类型 | 典型时长 | 常见规格 | 核心限制 | 适合拿来做什么 |
|---|---|---|---|---|
| 新用户试用 | 7 至 90 天 | 2核2G 至 2核4G | 仅限新主体,到期直接释放 | 短期验证、压测、临时演示 |
| 教育身份认证机 | 半年至一年,可续 | 1核2G 左右 | 需教育身份核验,每年复核 | 学习练手、课程项目、个人博客 |
| 长期免费小额套餐 | 持续,按量受限 | 1核1G 或更小 | 地域固定、流量上限、快照数量限制 | 轻量 API、监控探针、内网工具 |
| 社区或项目赞助 | 数月到一年 | 视项目而定 | 需提交项目说明与用途 | 开源项目演示站、文档站 |
| 代金券抵扣型 | 券有效期 | 自选 | 本质是抵扣,超额自付 | 短期迁移过渡 |
看清楚这张表,很多坑其实在领取那一刻就已经埋下了。代金券型最容易被误认为免费,因为它形式上给你一张额度,你以为白拿,实际上只要选了个超出抵扣范围的配置,账单立刻就开始跑。我见过有人领了券直接开 4核8G,一周后收到欠费提醒,还以为是系统出错。
1.2 把“免费”换算成真实成本
免费机最贵的地方从来不是钱,是三样东西:时间、迁移成本、以及到期那一刻的数据风险。
时间是第一位的。1核1G 的机器编译一个前端项目可能要十几分钟,本地三分钟搞定的事在它上面得泡杯茶等着。所以我的做法是本地构建、远端只跑产物,把重活全部挪走,机器只负责运行。
迁移成本是第二位的。免费机到期换机器,如果一开始就没做配置版本化,换一台等于重来一遍。我现在的习惯是:所有初始化脚本、systemd 单元文件、Nginx 配置、数据库初始化 SQL 全部放在一个 Git 仓库里,新机器拉下来跑一个bootstrap.sh就基本恢复。这个习惯一开始觉得麻烦,换过两次机器之后就再也离不开了。
数据风险是最容易被低估的。到期释放通常连带快照一起清掉,不是“停机保留”。所以免费机的定位必须是“可抛弃节点”,上面只放能从别处重建的东西,真正的数据放在独立的对象存储或者本地。
提示:领机器之前先问自己一句——这台机器明天消失,我会损失什么?如果答案不是“什么都不损失”,那就先把备份链路建起来再谈部署。
2. 选型阶段的六个参数:比 CPU 核数重要得多
2.1 内存和带宽才是低配机的真实瓶颈
大多数人看配置先看核数,这是错的。1核1G 和 1核2G 的体验差距,远大于 1核 和 2核 的差距。
先算一笔账。一台标称 1G 内存的机器,开机后系统本身要吃掉 150 至 300MB,具体取决于发行版和是否装了额外服务。剩下的可用内存,跑一个 Nginx(约 10 至 30MB)、一个 Node 或 Python 服务(100MB 起步)、再加一个 MySQL(默认配置下轻松吃掉 400MB 以上),大概率是撑不住的。撑不住的表现不是报错,而是OOM Killer 半夜随机杀掉你的进程,第二天早上你发现服务挂了,日志里只有一行Out of memory: Killed process。
带宽更容易被忽略。1Mbps 的带宽,理论下载速度是1 Mbps ÷ 8 = 128 KB/s。一个首屏资源 800KB 的页面,用户完整加载需要 6 秒以上。如果你的机器带宽是 1Mbps 而你又挂了图片,体验会非常糟糕。解决办法有两个:静态资源全部走对象存储或 CDN,或者把页面做到极致精简。我在免费机上跑过的个人站点,首屏压到 90KB 以内,1Mbps 带宽下两秒内能出来,这是可以接受的水平。
2.2 公网 IP 是不是独立、是不是固定
这一条能直接决定你的部署方案成不成立。部分免费套餐给的是NAT 共享 IP 加端口映射,也就是说你在机器里ip addr看到的地址是内网地址,对外暴露的是某个共享地址加一个高位端口。这种机器:
- 不能直接绑定域名到 80/443(除非厂商支持端口转发规则)
- 不能做基于 IP 的访问控制
- 相邻用户被攻击时你可能受牵连
判断方法很简单,开机后执行:
curl -s ifconfig.me ; echo ip -4 addr show scope global | grep inet如果两个地址不一致,基本就是 NAT 后面的机器。这种机器拿来跑监控探针、内网服务、定时任务是合适的,但别指望它承载一个正经网站。
2.3 系统盘类型、快照数量与流量计费方式
系统盘分普通云盘和 SSD 云盘,免费机大概率给的是前者,IOPS 很低,数据库写密集场景下延迟会非常明显。判断方式:
# 简单测一下写入 dd if=/dev/zero of=./testfile bs=1M count=512 oflag=direct如果 512MB 写了超过十几秒,说明磁盘性能一般,数据库就要慎重。
快照数量也常有限制,比如只允许保留 2 个。这意味着你不能靠快照做长期备份,只能做“改动前临时兜底”。
流量计费那条更要命。部分套餐是“带宽按固定值,流量按量计费”,平时够用,一旦被扫描器或者爬虫狂刷,流量跑超了就是真实账单。部署第一天就要把流量监控告警设上,多数厂商控制台里都有一项“流量使用率告警”,设置到 70% 触发,这是我必做的一步。
2.4 架构兼容性:ARM 机器的镜像陷阱
近几年免费机大量使用 ARM 架构,成本低。问题在于,你在本地 x86 机器上docker build出来的镜像,直接拉到 ARM 机器上跑会报exec format error。解决办法是构建时指定平台:
docker buildx build --platform linux/arm64 -t myapp:latest .或者干脆不用 Docker,直接跑语言运行时,省掉这层麻烦。我后来在低配免费机上基本放弃了 Docker,一来镜像本身就占几百 MB 磁盘,二来容器运行时也要吃几十 MB 内存,对 1G 机器来说都是实打实的负担。
3. 申请环节:卡住的往往不是技术问题
3.1 认证、额度领取与开机失败的三种情形
申请流程里最容易卡住的是身份核验。教育认证需要提交在校证明材料,审核可能几个工作日;企业认证需要主体信息一致。主体信息和支付方式不一致是最常见的驳回原因,这点提前对齐能省不少时间。
第二种卡点是“领了券但没领额度”。有些平台的免费套餐是独立入口,不在普通购买页,你以为下了一单,其实下的是付费单。判断方法:下单前确认订单金额显示为 0,且资源列表里能看到“免费套餐”标记。
第三种是开机失败——资源池不足。免费机型通常集中在特定可用区,热门时段会提示库存不足。我的经验是换可用区试,或者错开工作时间,早上和深夜成功率明显高一些。
3.2 首次登录:密钥只给你一次
创建实例时选择密钥对登录的,私钥文件通常只在创建完成的那一刻提供下载,之后无法再次获取。我吃过这个亏,浏览器下载被拦截,回头想重新下载发现入口没了,只能重建实例。
所以创建之前先想好:私钥存哪里、要不要同时绑定一个备用密码登录方式。拿到私钥后立刻做两件事:
# 1. 权限必须收紧,否则 ssh 会拒绝使用 chmod 600 ~/.ssh/mykey.pem # 2. 备份到至少两个地方 cp ~/.ssh/mykey.pem ~/backup/第一次连接:
ssh -i ~/.ssh/mykey.pem root@<公网IP>如果卡在Connection timed out,八成是安全组没放行 22 端口,先去控制台看安全组规则,别在本地瞎折腾。如果报Permission denied (publickey),检查用户名对不对——有的镜像默认用户是ubuntu或debian而不是root。
3.3 开机后十分钟内必须跑完的自检清单
登录进去别急着装东西,先把下面这些跑一遍,能提前发现半数以上的后续问题:
# 系统与内核 uname -a && cat /etc/os-release # 内存与 swap 现状 free -h # 磁盘剩余 df -h # CPU 核数与负载 nproc && uptime # 时区(错的话日志时间全是乱的) timedatectl # 是否已在 NAT 后面 curl -s ifconfig.me; echo; ip -4 addr show scope global | grep inet # 出网是否正常 curl -sI https://www.example.com | head -n 1时区那条尤其重要。我第一次排查一个定时任务不执行的问题,查了两个小时,最后发现机器是 UTC,我按本地时间算的 cron 表达式差了八小时。一条timedatectl set-timezone Asia/Shanghai就能解决的事。
4. 上线前的初始化与加固:省掉的每一步后面都要还
4.1 从 root 直连到密钥化、非默认端口的最小安全基线
公网上的扫描器有多密集?一台暴露 22 端口的机器,上线几小时内就能在/var/log/auth.log里看到成百上千次失败登录尝试。免费机因为 IP 段集中,往往是被重点照顾的对象。
最小基线我一般这么做:
# 1. 建一个普通用户,给 sudo adduser deploy usermod -aG sudo deploy mkdir -p /home/deploy/.ssh cp /root/.ssh/authorized_keys /home/deploy/.ssh/ chown -R deploy:deploy /home/deploy/.ssh chmod 700 /home/deploy/.ssh chmod 600 /home/deploy/.ssh/authorized_keys # 2. 改 sshd 配置 # /etc/ssh/sshd_config # Port 22022 # PermitRootLogin no # PasswordAuthentication no # PubkeyAuthentication yes # MaxAuthTries 3 # 3. 先测试新端口能连上,再重启服务 sshd -t systemctl restart sshd注意:改 SSH 配置一定要保留当前这个已连接的会话不要关,另开一个终端测试新配置能不能连上。确认没问题再关旧会话。这一步做错就是把自己锁在门外,只能走控制台的 VNC 救援。
改完端口后,安全组里也要同步放行新端口,两处都通才算完。
4.2 双层防火墙:云侧安全组与系统防火墙
很多人只配一层。安全组在云平台侧,系统防火墙在机器里,两层是叠加关系,缺一层都有隐患。安全组的原则是只开需要的端口,我一般只放行 SSH 端口、80、443,其余全关。
系统侧用 ufw 举例:
ufw default deny incoming ufw default allow outgoing ufw allow 22022/tcp ufw allow 80/tcp ufw allow 443/tcp ufw enable ufw status verbose再加一层防爆破,装个 fail2ban,默认规则就够用:
apt install -y fail2ban systemctl enable --now fail2ban fail2ban-client status sshd4.3 小内存机器的救命配置:swap 与日志轮转
1G 内存的机器,swap 是必须的,不是可选项。它不能让你的服务变快,但能在内存尖峰时避免进程被直接杀掉。经验值是 swap 设成内存的 1 到 2 倍,1G 机器给 1G 到 2G 都合理。
fallocate -l 2G /swapfile chmod 600 /swapfile mkswap /swapfile swapon /swapfile echo '/swapfile none swap sw 0 0' >> /etc/fstab # 降低换出倾向,避免频繁换入换出拖慢性能 sysctl vm.swappiness=10 echo 'vm.swappiness=10' >> /etc/sysctl.conf日志轮转同样关键。系统盘通常只有 20 至 40G,日志一天写几百 MB,一两周就能把盘写满,盘满之后数据库直接拒绝写入,整个服务雪崩。检查一下:
journalctl --disk-usage # 限制系统日志总量 journalctl --vacuum-size=200M # 永久生效:/etc/systemd/journald.conf 里设 SystemMaxUse=200M du -sh /var/log/*应用日志我这边的规矩是:按天切分、保留 7 天、单文件上限 50MB。这套规则写进 logrotate 配置,一次配好长期省心。
5. 部署落地:让服务在低配机上稳定常驻
5.1 运行方式怎么选:Docker、原生还是面板
三种方式我都用过,结论是看内存。
内存 2G 以上,Docker 值得用,环境隔离、迁移方便,出问题删容器重来就行。内存 1G 及以下,我倾向原生部署,省掉容器运行时那几十 MB 和镜像占用的磁盘。
图形化面板工具适合完全不想碰命令行的人,但它自己就要吃 200MB 以上内存,在 1G 机器上装完基本就没剩多少给业务了,而且面板本身也是攻击面。我的建议是:先用命令行把服务跑通一次,再决定要不要面板,顺序反了会一直搞不清问题出在哪一层。
部署方式上,最省事的是 Git 拉取:
# 服务器上 git clone --depth 1 <仓库地址> /opt/myapp cd /opt/myapp python3 -m venv venv ./venv/bin/pip install -r requirements.txt前端这类需要构建的,本地npm run build出产物,用 rsync 推到服务器,机器只负责托管静态文件。
5.2 用 systemd 把进程管起来
nohup加&是最容易踩坑的方式——重启机器就没了,进程崩了也不会自动拉起。正经做法是写 systemd 单元:
# /etc/systemd/system/myapp.service [Unit] Description=My Application After=network.target [Service] Type=simple User=deploy WorkingDirectory=/opt/myapp ExecStart=/opt/myapp/venv/bin/python app.py Restart=always RestartSec=5 StandardOutput=journal StandardError=journal # 小内存机器建议加这两条,限制单进程资源 MemoryMax=400M [Install] WantedBy=multi-user.targetsystemctl daemon-reload systemctl enable --now myapp systemctl status myapp --no-pager journalctl -u myapp -fRestart=always配合RestartSec=5能覆盖九成的偶发崩溃。MemoryMax是给低配机的保险,与其让一个进程把整机拖死,不如让它自己被限住然后重启。
5.3 反向代理、HTTPS 与缓存策略
业务进程监听 127.0.0.1:8000,Nginx 在外层接 80/443,这是标准做法:
server { listen 80; server_name example.com; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; gzip on; gzip_types text/css application/javascript application/json image/svg+xml; gzip_min_length 1024; location /static/ { alias /opt/myapp/static/; expires 30d; add_header Cache-Control "public, immutable"; } 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_read_timeout 60s; } }HTTPS 证书用自动化工具签发,配置好定时续期:
# 以 certbot 为例 certbot --nginx -d example.com systemctl list-timers | grep certbot带宽只有 1Mbps 的情况下,gzip和静态资源长缓存这两条能带来肉眼可见的改善,务必开。有条件的话把静态资源整体挪到对象存储,服务器只出 HTML 和接口数据,带宽压力能降一个数量级。
5.4 数据库选型与参数下调
免费机上跑 MySQL 默认配置是自找麻烦。如果数据量不大、并发不高,优先选 SQLite,零配置、零常驻进程、单文件备份,非常适合个人项目。
确实需要 MySQL 的,把缓冲池压下来:
# /etc/mysql/conf.d/lowmem.cnf [mysqld] innodb_buffer_pool_size = 128M innodb_log_file_size = 32M max_connections = 30 performance_schema = OFFperformance_schema = OFF这一条能省出 100MB 以上的内存,代价是失去部分性能诊断能力,个人项目完全可以接受。
6. 五个真实翻车现场:从现象倒推原因
6.1 能 ping 通但 SSH 连不上
排查看顺序,别跳步:
| 检查点 | 命令 / 位置 | 判断依据 |
|---|---|---|
| 云侧安全组 | 控制台 | 是否放行当前 SSH 端口 |
| 系统防火墙 | ufw status | 端口是否在 allow 列表 |
| sshd 是否在跑 | systemctl status sshd | active 还是 failed |
| 监听端口对不对 | ss -tlnp | grep ssh | 实际监听端口 |
| 是否被 fail2ban 封 | fail2ban-client status sshd | Banned IP list 里有没有你 |
| 本地网络限制 | 换手机热点试 | 公司/校园网封高位端口很常见 |
最后一条我踩过。公司网络只放行常见端口,我把 SSH 改成 22022 之后,本地怎么都连不上,折腾半小时才想起换热点试一下,秒连。
6.2 网站 502:后端没起来还是端口错了
502 的意思是 Nginx 联系不上上游。三步定位:
# 1. 后端进程活着吗 systemctl status myapp --no-pager # 2. 端口在听吗 ss -tlnp | grep 8000 # 3. 直接本地请求一下 curl -v http://127.0.0.1:8000/第 3 步如果返回正常,说明问题在 Nginx 配置的上游地址;如果也失败,问题在后端本身。最常见的两个原因:一是不小心把应用绑定到了127.0.0.1之外的地址冲突了,二是 OOM 把进程杀了然后 systemd 重启失败。看journalctl -u myapp --since "10 min ago"基本就能看出来。
6.3 磁盘悄悄写满
免费机盘小,这是高频故障。表现是数据库突然报No space left on device,但df -h显示的已用空间又对不上你放的文件。原因通常是已删除但仍被进程占用的文件:
# 找出被删除但被占用的文件 lsof +L1 # 或者 lsof | grep deleted常见元凶:Docker 的日志、应用的 stdout 重定向文件、没轮转的大日志。清理办法是对应进程重启一次,或者配置好 logrotate。
顺手加一条磁盘告警脚本,用 cron 每天跑:
#!/bin/bash USED=$(df / | awk 'NR==2 {print $5}' | tr -d '%') if [ "$USED" -gt 85 ]; then echo "disk usage ${USED}% on $(hostname)" | mail -s "disk warning" you@example.com fi6.4 半夜 CPU 打满:扫描与爆破
早上起来发现机器卡得动不了,top里一堆陌生的进程名,或者大量sshd子进程。这是被扫了。
# 看谁在连 ss -tnp state established | head -30 # 看失败登录统计 grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn | head处置动作:确认密钥登录已开启、密码登录已关闭、fail2ban 已生效;把 SSH 换到高位端口能过滤掉绝大部分无差别扫描;如果机器已经被植入东西,最省时间的做法是重装系统,别在清理上纠结。免费机的价值就在于可以随时丢弃重建。
6.5 到期释放:最贵的一课
我自己丢过一次数据,原因很蠢:把到期日记错了一周,而那台机器的快照数量限制只允许保留两个,我以为是自动长期保留的。机器释放后,快照也随之清理。
后来我定了几条硬规矩:
- 拿到机器的第一分钟就在日历里设三个提醒:到期前 30 天、前 7 天、前 1 天。
- 所有不可重建的数据,每天定时同步到对象存储或本地,不依赖快照。
- 到期前两周开始准备迁移,别拖到最后一天,万一新机器开不出来就彻底没了。
迁移时还有个细节:提前把域名 DNS 的 TTL 调低到 300 秒。默认 TTL 可能是 3600 甚至 86400,切换时会出现新旧 IP 各解析一半的情况,把 TTL 提前一天降下来,切换当天十分钟就全网生效了。
7. 免费期之后:把成本算清楚再决定要不要留
走到这一步,其实你面前有三个选项:换下一家免费机、升级成付费、或者把服务迁回本地/其他形态。
我的判断标准很朴素:如果这台机器承载的东西,你每天会用到,那就该付费。反复迁移的时间成本,早就超过一台入门配置一年的费用了。反过来,如果它只是个练手环境、临时演示、跑个定时抓取,那就在免费机之间轮转完全没问题,前提是配置脚本化和数据外置这两件事做到了。
真要换机器,整套流程我现在压缩成四步:新机开机跑bootstrap.sh恢复基础环境,Git 拉代码,从对象存储拉回数据,改 DNS 并等 TTL 生效。因为所有配置都在仓库里,这一步大概二十分钟能完成,比第一次手忙脚乱折腾一整天强太多。
另外分享一个我自己一直在用的小习惯:每台机器上放一个MACHINE.md,写在根目录,记录这台机器的用途、到期日、上面跑了什么、数据备份到哪里、迁移步骤是什么。看着有点笨,但隔三个月再回来看,能省掉大量“这台机器到底是干嘛的”这种回忆成本。免费机数量一多,这个习惯的价值就显出来了。
最后提醒一句容易被忽略的:免费机的性能波动比付费机大得多,同一台机器不同时段的 IO 表现能差好几倍。所以压测数据只当参考,别拿它做容量规划;线上真出了问题,先怀疑是不是邻居在跑重活,而不是自己的代码有 bug——我因为这个误判过一次,白改了半天代码。