← cd ../posts

5 分钟把一台新 VPS 调到能放心跑业务(系列收官)

2026-07-08 ◈ Linux 系列

这是 Linux 系列的第 25 篇——终篇。25 篇的所有知识,凝结成一份"新机器开箱清单"。每一步都对应前面某一篇的展开,需要细节回去翻;不需要的话照着敲完,半小时一台合格 server。

0. 假设

  • 拿到了一台空 VPS(阿里云 / DigitalOcean / Hetzner / Linode 等都行)
  • 默认装的是 Ubuntu 22.04 / 24.04 LTS(其他发行版命令稍变,逻辑一样)
  • 你有 root 的初始密码 / SSH key
  • 目标是跑业务服务(nginx、应用、数据库 / 或者 Docker)

整个 bootstrap 分 8 步,按顺序做。


1. SSH 第一次进去 + 改 root 密码

$ ssh root@<ip>
# 输入云厂商给的初始密码

进去第一件事改密码(很多云厂商会把初始密码发邮件,外漏风险高):

$ passwd

2. 建一个普通用户 + sudo + 禁 root 直接登录

$ adduser deploy             # 按提示设密码
$ usermod -aG sudo deploy    # 加入 sudo 组(Debian/Ubuntu)
# RHEL/CentOS:usermod -aG wheel deploy

# 把你本地的 SSH key 复制到这个用户
$ mkdir -p /home/deploy/.ssh
$ cp ~/.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

测试新用户能登录不要先关掉当前 root session!):

新终端:

$ ssh deploy@<ip>
$ sudo whoami
root         # OK,sudo 工作

确认 ok 后,禁 root 直接 SSH

# 在 root session
$ vim /etc/ssh/sshd_config

改:

PermitRootLogin no
PasswordAuthentication no                # 强制 key 登录
PubkeyAuthentication yes

加固(可选):

ClientAliveInterval 60                    # 心跳防 NAT idle 断
ClientAliveCountMax 3
MaxAuthTries 3
LoginGraceTime 30
AllowUsers deploy                          # 白名单

测试 + 重启 sshd:

$ sudo sshd -t                             # 语法测试
$ sudo systemctl restart sshd

再起一个新终端测试 ssh deploy@<ip>——别在当前 session 直接退出,万一改错你会被关在门外。


3. 系统更新 + 装基本工具

# 包管理器更新
$ sudo apt update && sudo apt upgrade -y

# 安装基础工具
$ sudo apt install -y \
    htop iotop sysstat ncdu \
    curl wget jq tree \
    git vim \
    fail2ban ufw \
    unattended-upgrades \
    tmux mtr-tiny dnsutils net-tools \
    fd-find ripgrep    # 现代 find / grep

# 自动安全更新(重要!)
$ sudo dpkg-reconfigure -plow unattended-upgrades
# 按提示选 yes

4. 防火墙:先 deny 后 allow

$ sudo ufw default deny incoming
$ sudo ufw default allow outgoing
$ sudo ufw allow 22/tcp comment 'SSH'         # ← 先 allow SSH 再 enable,否则关在门外
$ sudo ufw allow 80,443/tcp comment 'HTTP/HTTPS'
$ sudo ufw enable
$ sudo ufw status verbose

如果换了 SSH 端口(比如 22022),开那个:

$ sudo ufw allow 22022/tcp comment 'SSH'
$ sudo ufw delete allow 22/tcp                # 删掉旧规则

云厂商的安全组:阿里云 / AWS / 腾讯云在 VPC 层还有一层,要去 web 控制台同步开放端口。这是 90% 新手"我装了 nginx 为什么访问不到"的根因

fail2ban:自动封爆破 IP

$ sudo systemctl enable --now fail2ban

# 看状态
$ sudo fail2ban-client status
$ sudo fail2ban-client status sshd

fail2ban 自动监控 SSH 失败日志,触发阈值后用 iptables 拉黑那个 IP。


5. 内核参数 + ulimit(性能基线)

/etc/sysctl.d/99-tuning.conf:

# 文件描述符
fs.file-max = 1000000

# 网络
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.ip_local_port_range = 10000 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_syncookies = 1

# 内存
vm.swappiness = 10
vm.overcommit_memory = 1

# 安全
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0

/etc/security/limits.d/99-nofile.conf:

*  soft  nofile  65536
*  hard  nofile  65536

加载:

$ sudo sysctl --system

swap(小机器必备)

阿里云 1G/2G 机型常常不带 swap:

$ free -h | grep Swap
Swap:           0B          0B          0B          # 没 swap

# 加 1G swap
$ sudo fallocate -l 1G /swapfile
$ sudo chmod 600 /swapfile
$ sudo mkswap /swapfile
$ sudo swapon /swapfile
$ echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

# 验证
$ free -h

6. 时区 + NTP(日志时间戳清晰)

# 设时区
$ sudo timedatectl set-timezone Asia/Shanghai
$ timedatectl                              # 验证

# NTP 已经被 systemd-timesyncd 默认开了,检查
$ timedatectl status | grep 'NTP service'
NTP service: active

时区错了会让所有日志、监控、定时任务时间错乱——上来就设。


7. 日志轮转 + journald 限制

journald 大小限制:

$ sudo vim /etc/systemd/journald.conf
[Journal]
SystemMaxUse=500M
SystemKeepFree=1G
MaxRetentionSec=4week
$ sudo systemctl restart systemd-journald

logrotate 默认装好了。装应用时记得加自己的:

/etc/logrotate.d/myapp:

/var/log/myapp/*.log {
    daily
    rotate 14
    compress
    delaycompress
    notifempty
    create 0644 myapp myapp
    postrotate
        systemctl reload myapp.service > /dev/null 2>&1 || true
    endscript
}

8. 装运行时(按需)

Docker

$ curl -fsSL https://get.docker.com | sudo bash
$ sudo usermod -aG docker deploy            # 让 deploy 不用 sudo 用 docker
$ sudo systemctl enable --now docker

# 给 docker daemon 加日志轮转 + 国内镜像(如果你在国内)
$ sudo vim /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "registry-mirrors": [
    "https://docker.m.daocloud.io"
  ]
}
$ sudo systemctl restart docker

退出 deploy 再 ssh 重登,docker ps 不报权限错就好。

Node / Python / Go(按需)

# Node:用 nvm 不用包管理器
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

# Python:默认带了 3.10/3.12,业务用 venv
$ sudo apt install -y python3-venv python3-pip

# Go:直接下载二进制
$ wget https://go.dev/dl/go1.22.0.linux-amd64.tar.gz
$ sudo tar -C /usr/local -xzf go1.22.0.linux-amd64.tar.gz
$ echo 'export PATH=/usr/local/go/bin:$PATH' >> ~/.bashrc

9. 监控基础(轻量级)

最小可用:

# 看历史负载(sar 5 天)
$ sudo systemctl enable --now sysstat

# 看哪个进程吃资源
$ htop                                      # 已经装了

# 装 Tailscale 让自己能从手机看监控(可选)
$ curl -fsSL https://tailscale.com/install.sh | sudo bash
$ sudo tailscale up

进阶(要监控曲线):

# 简单方案:node_exporter + 一台中心机跑 Prometheus + Grafana
$ wget https://github.com/prometheus/node_exporter/releases/...
(具体步骤太多,单独开篇)

或者用阿里云 / 各家自带的监控服务。


10. 最后:业务部署 + 备份

业务部署(systemd)

$ sudo vim /etc/systemd/system/myapp.service

参考 17 systemd-services 的"生产级模板"。

$ sudo systemctl daemon-reload
$ sudo systemctl enable --now myapp
$ sudo systemctl status myapp
$ journalctl -u myapp -f

nginx 反向代理(如果有 web)

$ sudo apt install -y nginx certbot python3-certbot-nginx
$ sudo systemctl enable --now nginx

# 拿免费 HTTPS 证书
$ sudo certbot --nginx -d example.com -d www.example.com
# 跟着提示走,证书自动续期已经配好

备份(务必)

把你的数据库 / 应用数据用 rsync 推到另一台机器:

$ sudo vim /etc/cron.daily/backup
#!/bin/bash
set -e
DATE=$(date +%F)

# 应用数据
rsync -avh --delete \
    --link-dest=/backup-nas/$(date -d 'yesterday' +%F) \
    /var/lib/myapp/ \
    backup-user@nas:/backups/$(hostname)/$DATE/

# 数据库
docker exec postgres pg_dumpall -U postgres | \
    gzip > /tmp/pg-$DATE.sql.gz
rsync -avh /tmp/pg-$DATE.sql.gz backup-user@nas:/backups/$(hostname)/db/
rm /tmp/pg-$DATE.sql.gz
$ sudo chmod +x /etc/cron.daily/backup

11. 自查清单

跑完上面 1-10 步,按这个清单确认每一项:

  • SSH 用 key 登录,root 不能直接登
  • 普通用户 deploy 在 sudo 组
  • ufw 已 enable,22/80/443 在白名单
  • fail2ban 在跑
  • unattended-upgrades 已配置
  • sysctl 调过,ulimit 调过
  • swap 已加(小机器)
  • 时区设了 Asia/Shanghai
  • journald 限制了大小
  • 业务服务用 systemd 跑(不是 nohup &)
  • HTTPS 证书已自动续期
  • 备份脚本 daily 跑

任何一项没勾 → 回到对应章节补。


12. 25 篇旅程回顾

Ⅰ. 心智模型(01-05)
   why-linux → kernel-vs-userspace → everything-is-a-file
   → shell-as-glue → fhs-tour

Ⅱ. 日常 shell 工具(06-10)
   finding-things → text-pipes → redirection → process-control
   → shells-rcfile

Ⅲ. 文件与权限(11-14)
   permissions → links-inodes → mount-and-fs → archive-rsync

Ⅳ. 进程与并发(15-17)
   fork-exec → signals → systemd-services

Ⅴ. 网络(18-20)
   net-tools → firewall-stack → ssh-deep

Ⅵ. 性能与调试(21-23)
   observability → logs → kernel-tuning

Ⅶ. 容器与部署(24-25)
   containers-inside → vps-bootstrap ←(你在这)

把这 25 篇当作索引——遇到问题去翻对应章节,比从零搜索引擎找答案高效得多。


13. 现在做一件事

如果你跟着这一篇真的开了一台新 VPS:

  1. 把上面 1-10 步执行完
  2. 截个 htop / ufw status / systemctl status myapp 三连图给自己
  3. /etc/sysctl.d/99-tuning.conf/etc/security/limits.d/99-nofile.conf 这两个文件 push 到你的 dotfiles 仓库
  4. 下次新机器,Ansible playbook 或者 shell 脚本一键跑完——5 分钟搞定

"Infrastructure as Code"的入门就是:把你 ssh 进 server 敲过的每一条命令,沉淀成可重复执行的脚本。


14. 系列结束语

25 篇下来,你应该从"Linux 用户"变成"Linux 居民"——

  • 不再恐惧打开终端——它是你的家
  • 不再死记命令——你理解每个命令背后的内核机制
  • 不再迷信 GUI / 控制台——你知道任何 GUI 都是某个文本接口的封装
  • 遇到陌生 Linux 不慌——FHS、systemd、sysctl 在哪都一样
  • 看 K8s / Docker / 云原生——都是这些古老组件的现代组合

Linux 1991 年至今 30 多年,这套设计哲学跨越了几个时代仍在生效——从拨号上网的工作站到 2026 年的 AI 训练集群。学透它不是为了"跟上潮流",而是给自己一份几十年贬值率为零的基本功。

打开终端,住下来。


完结。如果你跟着读完 25 篇并跑过其中大部分命令——你已经超过了大多数自称"会用 Linux"的人。

接下来的进阶方向:

  • eBPF / Tracing:现代内核观测术
  • Kubernetes / 云原生:容器编排
  • Rust / Zig 系统编程:写工具,造你自己的 ls / cat / fd
  • NixOS / 不可变系统:把"配置即代码"做到极致

选一个开始下一段旅程。

$ ls related/