跳转至

国内云开发主机初始化实操

配置目标见:国内云开发主机标准配置

本文只覆盖开发工作区与开发环境;Tailscale 接入方式沿用既有 Docker 版方案,不在这里重复展开完整运行面设计。

0. 约定

  • 系统:Ubuntu LTS
  • 主机名:cn-bce-dev-01
  • 用户名:<dev-user>
  • 本文默认先用服务商提供的初始用户登录

1. 基础更新

sudo apt update
sudo apt upgrade -y
sudo apt install -y unattended-upgrades curl git tmux zsh htop ufw fail2ban
sudo dpkg-reconfigure -plow unattended-upgrades
sudo timedatectl set-timezone Asia/Shanghai
sudo hostnamectl set-hostname cn-bce-dev-01

2. 创建日常用户

sudo adduser <dev-user>
sudo usermod -aG sudo <dev-user>
echo '<dev-user> ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/90-<dev-user>
sudo chmod 440 /etc/sudoers.d/90-<dev-user>
sudo visudo -cf /etc/sudoers.d/90-<dev-user>
id <dev-user>

这样配置后,<dev-user> 使用 sudo 不再需要输入账户密码。

3. 写入 SSH 公钥

sudo -iu <dev-user>
mkdir -p ~/.ssh
chmod 700 ~/.ssh
nano ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
exit

把本地公钥内容粘进去后保存。

如果本地使用的不是默认私钥文件名,例如 ~/.ssh/2026-02-12,后续登录时需要在本地 ~/.ssh/config 中显式指定 IdentityFile,否则 ssh 可能仍会优先尝试 id_rsa 等默认文件。

4. 加固 SSH

sudo tee /etc/ssh/sshd_config.d/99-dev-control.conf > /dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
KbdInteractiveAuthentication no
X11Forwarding no
AllowUsers <dev-user>
EOF

检查并重启:

sudo sshd -t
sudo systemctl restart ssh
sudo systemctl status ssh --no-pager

先新开一个终端验证新用户能登录,再关闭旧会话。

5. 配置 UFW

先把 SSH 放行并启用 UFW,再继续后续步骤,避免装完其他组件后才回头补防火墙。

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp comment 'SSH'
sudo ufw allow 41641/udp comment 'Tailscale Direct'
sudo ufw --force enable
sudo ufw status verbose

如果后续需要 dev 子域名,再补开:

sudo ufw allow 80/tcp comment 'HTTP for dev preview'
sudo ufw allow 443/tcp comment 'HTTPS for dev preview'
sudo ufw reload

6. 启用 fail2ban

sudo systemctl enable fail2ban
sudo systemctl restart fail2ban
sudo systemctl status fail2ban --no-pager

7. 创建目录

sudo mkdir -p /srv/workspace /srv/devtools /opt/infra/bootstrap
sudo chown -R <dev-user>:<dev-user> /srv/workspace /srv/devtools /opt/infra
ls -ld /srv/workspace /srv/devtools /opt/infra /opt/infra/bootstrap

8. 安装 Docker

保留 Docker,用于依赖服务、镜像验证和最小复现;这台机器不把 Docker 作为所有项目的默认开发环境,也不在本文中作为 /opt/infra 运行面的管理手段。

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker <dev-user>
docker --version
docker compose version

重新登录一次,让 docker 组生效。

可选增强:

如果后续频繁使用 docker -p 暴露端口,或这台机开始承载长期运行的本机容器,再补 ufw-docker;首轮初始化不默认安装。

sudo wget -O /usr/local/bin/ufw-docker https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker
sudo chmod +x /usr/local/bin/ufw-docker
sudo ufw-docker install
sudo ufw reload

在启用 ufw-docker 之前,开发容器尽量只绑定 127.0.0.1,不要直接暴露到 0.0.0.0

9. 安装 Python 底座与 uv

sudo apt install -y python3 python3-venv python3-pip pipx
pipx ensurepath
pipx install uv
uv --version

原则: - 系统只保留 Python 底座 - 每个项目单独维护自己的环境 - 不在系统级共用一套 Python 依赖

10. 可选:为 Docker 单独配置代理

如果开发机直连 docker.io 不稳定,优先只给 Docker daemon 配代理,不把整机流量全局代理化。

当前实际可用做法:

  1. 安装 sing-box
  2. 用订阅生成本地客户端配置
  3. sing-box 监听 127.0.0.1:7890
  4. 让 Docker daemon 仅通过该端口出网

安装 sing-box

curl -fsSL https://sing-box.app/install.sh | sudo sh

确认服务与本地监听端口:

sudo systemctl enable sing-box
sudo systemctl restart sing-box
sudo systemctl status sing-box --no-pager
ss -ltnp | grep 7890

Docker 代理 drop-in:

sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf > /dev/null <<'EOF'
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:7890"
Environment="HTTPS_PROXY=http://127.0.0.1:7890"
Environment="NO_PROXY=localhost,127.0.0.1,::1"
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo systemctl show --property=Environment docker

确认 Docker 已吃到代理后,再继续 docker pulldocker compose up

11. 接入 Docker 版 Tailscale

本机 Tailscale 接入方式沿用既有 Docker 版方案。你先在 /opt/infra/bootstrap/docker-compose.yml 写入既有可用配置,再执行:

cd /opt/infra/bootstrap
docker compose up -d
docker compose ps
sudo ufw allow in on tailscale0 comment 'Allow Tailscale'
ip addr show tailscale0

完成接入后,再检查:

docker logs net-tailscale --tail 50

关于 DERP: - 本次初始化不默认自建 DERP - 先完成接入,再观察是否经常走 relay - 只有在直连效果差、海外 DERP 明显拖慢连接时,再单独评估国内 DERP

12. 安装 Node.js

如果当前项目确实需要 Node,再安装系统级 LTS 即可;没有明确需求时可以先不装。

sudo apt install -y nodejs npm
node -v
npm -v

真出现多版本冲突时,再补多版本管理器。

如果安装过程较长,建议放到 tmux 会话里后台执行,而不是一直挂着当前 SSH:

tmux new -s bootstrap

tmux 里执行安装命令,离开会话使用:

Ctrl-b d

重新进入:

tmux attach -t bootstrap

13. 建立工作区

后续所有活跃开发副本统一放在 /srv/workspace,不要把系统环境当成各项目共用依赖池。

示例:

sudo -iu <dev-user>
cd /srv/workspace
git clone <your-repo-url> autopcr
git clone <your-repo-url> pcrdb
exit

Python 项目示例:

cd /srv/workspace/<project-name>
uv venv
uv sync

14. 远程开发

终端开发:

ssh <dev-user>@<server-ip-or-domain>

如果本地私钥不是默认命名,建议在本地 ~/.ssh/config 添加:

Host cn-bce-dev-01
  HostName <server-ip-or-domain>
  User <dev-user>
  IdentityFile ~/.ssh/<private-key-name>
  IdentitiesOnly yes

之后可直接使用:

ssh cn-bce-dev-01

浏览器联调优先使用端口转发:

ssh -L 3000:127.0.0.1:3000 <dev-user>@<server-ip-or-domain>

然后在本地浏览器访问:

http://127.0.0.1:3000

15. 验收

whoami
sudo -l
sudo ufw status verbose
sudo systemctl status ssh --no-pager
sudo systemctl status fail2ban --no-pager
docker ps
uv --version
sudo systemctl status sing-box --no-pager
ip addr show tailscale0

确认: - 新用户可登录 - 密码登录已关闭 - root 不可直登 - ufw 已启用 - Docker 正常 - uv 正常 - 如启用代理,sing-box 正常 - tailscale0 已出现 - /srv/workspace 可写

16. 后续补充项

按需再做,不作为首轮初始化必做项: - dev 子域名反代 - 访问其他服务器的统一 SSH 配置 - 备份脚本与迁移脚本