服务器基础配置与轻量部署指南
本文用于给单机或少量服务器上的中小型项目建立一套可复制的生产部署方式。核心思路是:
- 后端常驻进程交给
systemd管理。 - 入口流量、静态资源和反向代理交给
Nginx管理。 - 真实环境变量放在服务器
/etc/<app>/<app>.env。 - 项目仓库只保存模板、脚本和说明,不提交真实密钥。
这套方式不追求一开始就容器化、网关化或平台化。先把目录、配置、脚本、验收和回滚边界固定下来,后续项目就能按同一套流程复制。
维护: 本文最后整理日期为 2026-06-09。
systemd和 Nginx 的具体命令可能受发行版影响。落地前应结合当前服务器执行systemctl --version、nginx -v、nginx -T核对实际环境。
基础初始化
获取服务器
服务器可以直接从阿里云、腾讯云、华为云等云厂商购买。个人博客、小工具或低流量服务,入门阶段通常可以先从 2c2g 规格开始。
拿到服务器后先确认三件事:
- 公网 IP 或绑定域名。
- SSH 登录用户和初始密码。
- 安全组已放行 SSH 端口,默认是
22。
不同云厂商的默认登录用户不完全一样,有些是 root,有些是 ubuntu、admin 或控制台创建的用户。第一次使用前建议在控制台重置一次登录密码。
创建工作用户
可以先用初始用户登录服务器:
1 | ssh root@<server-ip> |
首次连接会提示是否信任主机指纹,确认 IP 无误后输入 yes,SSH 会把服务器指纹写入本机 ~/.ssh/known_hosts。
日常不建议长期直接使用 root。可以创建一个普通工作用户,并授予 sudo 权限:
1 | adduser acs |
之后的部署、调试和日常维护都尽量使用普通用户登录,需要管理员权限时再通过 sudo 执行。
配置 SSH 免密登录
本机可以用 ~/.ssh/config 给服务器配置别名:
1 | Host myserver |
之后就可以直接登录:
1 | ssh myserver |
生成本机 SSH 密钥:
1 | ssh-keygen -t ed25519 -C "<your-email>" |
把公钥添加到服务器:
1 | ssh-copy-id myserver |
如果不能使用 ssh-copy-id,也可以手动把本机 ~/.ssh/id_ed25519.pub 内容追加到服务器用户的 ~/.ssh/authorized_keys。
配置常用工具
可以把常用 shell、vim、tmux 配置复制到服务器:
1 | scp ~/.bashrc ~/.vimrc ~/.tmux.conf myserver: |
Debian / Ubuntu 系统常用初始化命令:
1 | sudo apt update |
适用场景
适合:
- 单机或少量云服务器部署。
- 一个项目包含后端服务和前端静态资源。
- 后端以 jar、二进制或脚本形式常驻运行。
- Nginx 负责域名、HTTPS、静态资源和
/api/反向代理。 - 团队还没有完整 CI/CD 或容器平台,但需要稳定、可复用的上线流程。
不适合直接照搬:
- 多副本自动伸缩。
- Kubernetes / Docker Compose 已经是主部署方式。
- 需要灰度发布、自动回滚、服务发现和复杂流量治理。
- 多团队共享同一套 API Gateway。
项目内标准目录
新项目建议保留这些文件:
1 | deploy/ |
各目录职责:
| 路径 | 职责 |
|---|---|
deploy/ |
保存部署模板,不保存真实密钥 |
scripts/ |
保存初始化、发布、验收脚本 |
docs/deployment.md |
保存当前项目实际部署说明 |
.gitattributes |
固定脚本和模板行尾 |
服务器目录约定
推荐把运行目录固定下来:
1 | /opt/<app>/server.jar |
含义:
| 路径 | 用途 |
|---|---|
/opt/<app>/ |
后端 artifact 和运行工作目录 |
/var/www/<app>/ |
前端静态资源 |
/var/lib/<app>/uploads |
上传文件、业务运行数据 |
/etc/<app>/<app>.env |
真实环境变量 |
/etc/systemd/system/<app>.service |
systemd 服务文件 |
/etc/nginx/conf.d/<app>.conf |
Nginx 项目入口配置 |
如果服务器使用 Debian / Ubuntu 的 sites-available 习惯,也可以改用:
1 | /etc/nginx/sites-available/<app>.conf |
Nginx 两种放置方式只选一种。不要同一个项目同时安装到 conf.d 和 sites-enabled,否则可能重复加载同一个 server。
固定变量
每个项目开始时先确定这些变量:
1 | APP_NAME=<app> |
脚本可以允许通过环境变量覆盖默认值,但模板和项目文档里必须写清楚默认值。否则新项目复制时会出现目录、用户、端口不一致的问题。
.gitattributes
新项目根目录应放 .gitattributes,固定跨平台行尾,避免 shell 脚本在 Linux 服务器上因为 CRLF 报错。
推荐模板:
1 | *.sh text eol=lf |
如果项目里有 Maven Wrapper、Gradle Wrapper 或其他 Unix 可执行脚本,也要显式固定 LF:
1 | mvnw text eol=lf |
规则:
.gitattributes应在项目早期创建,避免后续出现大量无意义行尾 diff。- 所有
scripts/*.sh必须是 LF 行尾。 - 所有部署模板建议是 LF 行尾,复制到 Linux 系统目录后不需要再转换。
- Windows 专用脚本可以保留 CRLF,例如
*.cmd、*.bat。 - 如果新增脚本目录,例如
bin/或ops/,要同步补充对应规则。
deploy 模板
环境变量模板
deploy/<app>.env.example 只放配置模板:
- 数据库连接。
- 应用端口。
- 公开访问地址。
- 上传目录。
- JWT、管理员初始密码等敏感项的占位符。
- 不放真实密码、真实 token、真实证书内容。
示例:
1 | SERVER_PORT=8080 |
systemd 模板
deploy/<app>.service.example 只描述服务怎么启动。
示例:
1 | [Unit] |
注意:
- 不要写死个人用户名。
- 服务用户要和
install-runtime.sh创建、授权的用户一致。 EnvironmentFile指向服务器真实 env 文件,不指向仓库里的.env.example。- Java、Node、Go 等不同后端只替换
ExecStart,目录和 env 模型尽量保持一致。
Nginx 模板
deploy/nginx.<app>.conf.example 只描述本项目入口。
常见前后端分离项目:
1 | server { |
要求:
- 一个项目一个
server { ... }。 server_name上线时必须改成真实域名。- 静态资源指向
WEB_DIR。 /api/反向代理到127.0.0.1:${SERVER_PORT}。- SPA 项目使用
try_files $uri $uri/ /index.html。 - 生产环境默认不要公开 Swagger / OpenAPI。
确实需要保留 Swagger / OpenAPI 时,用内网、IP allowlist 或 Basic Auth 限制。
scripts 职责
install-runtime.sh
负责首次初始化服务器运行环境:
- 创建服务用户和用户组。
- 创建
APP_DIR、WEB_DIR、STORAGE_DIR、ENV_DIR。 - 从
deploy/<app>.env.example初始化ENV_FILE。 - 设置目录 owner 和权限。
- 检查 systemd service 是否安装。
- 检查 Nginx config 是否安装且只安装一份。
- 不构建、不发布、不拉代码。
这个脚本只做“运行时环境初始化”,不要混入发布逻辑。
deploy-prod.sh
负责发布当前工作区代码:
- 检查 Java、Node、npm、Nginx、systemctl 等依赖。
- 构建后端。
- 构建前端。
- 安装后端 artifact 到
APP_DIR。 - 安装前端 dist 到
WEB_DIR。 systemctl restart <app>。nginx -t。systemctl reload nginx。- 调用
scripts/check-deploy.sh。
这个脚本默认发布当前工作区,不自动切分支。正式发布前先人工确认分支和工作区状态。
check-deploy.sh
负责部署验收:
- 检查 systemd 服务是否 active。
- 检查首页 HTTP 状态。
- 检查健康接口或关键 API。
- 可选检查登录、数据库、安全入口等业务 smoke test。
- 失败时非 0 退出。
验收项要按项目可配置,不要让所有项目都强依赖 MySQL、登录账号或固定业务接口。
pull-and-deploy.sh
只做便捷封装:
1 | git pull --ff-only |
它适合低风险小项目的日常发布。正式发布仍建议先人工确认分支、commit、工作区状态,再执行 deploy-prod.sh。
首次部署流程
- 在服务器准备代码。
1 | git clone <repo-url> /srv/src/<app> |
- 初始化运行目录和 env 文件。
1 | bash scripts/install-runtime.sh |
- 安装 systemd 模板。
1 | sudo cp deploy/<app>.service.example /etc/systemd/system/<app>.service |
- 安装 Nginx 模板,二选一。
conf.d 方式:
1 | sudo cp deploy/nginx.<app>.conf.example /etc/nginx/conf.d/<app>.conf |
sites-enabled 方式:
1 | sudo cp deploy/nginx.<app>.conf.example /etc/nginx/sites-available/<app>.conf |
- 编辑真实环境变量。
1 | sudo vi /etc/<app>/<app>.env |
至少确认:
- 数据库连接。
APP_PUBLIC_BASE_URL。- 管理员初始密码。
- JWT secret。
- 上传目录。
- 端口是否和 Nginx 代理一致。
- 首次发布。
1 | bash scripts/deploy-prod.sh |
- 单独验收。
1 | bash scripts/check-deploy.sh |
日常发布流程
推荐流程:
1 | cd /srv/src/<app> |
如果项目长期分支是 master,就把 main 改成 master,不要让脚本和文档混用。
快速流程:
1 | bash scripts/pull-and-deploy.sh main |
如果 pull-and-deploy.sh 支持分支参数,内部仍然要使用 git pull --ff-only,避免服务器上出现隐式 merge commit。
发布前检查
发布前至少检查:
- 当前分支是否正确。
- 工作区是否干净。
- 要发布的 commit 是否符合预期。
deploy/*.example没有真实密钥。scripts/*.sh是 LF 行尾。- Nginx 配置只安装了一份。
/etc/<app>/<app>.env已经按生产环境填写。
常用命令:
1 | git status --short |
硬性约束
- 所有 shell 脚本必须使用 LF 行尾。
.gitattributes必须包含*.sh text eol=lf。- 可执行脚本建议提交执行位,不要在部署时临时
chmod弄脏工作区。 deploy/*.example不能包含真实密钥。deploy-prod.sh里所有危险删除操作必须有路径保护。- Nginx 配置只安装到一种 include 目录。
server_name _只适合兜底或测试,生产要改成真实域名。install-runtime.sh必须处理服务用户、目录 owner 和写权限。- 部署脚本失败必须立即退出,不能静默跳过关键步骤。
- 每次发布后必须执行 smoke test。
可逐步优化项
第一阶段先保证可复制:
- 固定目录结构。
- 固定模板文件名。
- 固定脚本职责。
- 固定部署命令。
第二阶段提高安全性:
- 关闭生产 Swagger。
- 增加 Nginx HTTPS 模板。
- 增加危险路径保护。
- 增加服务用户和权限初始化。
第三阶段提高可恢复性:
- 保留上一版 jar 和 dist。
- 发布失败自动回滚。
- 增加
journalctl -u <app>失败提示。 - 记录部署版本、commit 和时间。
第四阶段再考虑容器化:
- 保留 env、端口、健康检查、Nginx 入口这些约定。
- 将
systemd启动方式替换成容器启动方式。 - 不改变应用配置模型。
