Ubuntu Nginx站点部署实录:从配置详解到自动化脚本
Ubuntu Nginx 站点部署:从配置到自动化
最近我把跑在内网 8090 端口的博客服务发布到了公网。域名是 blog.twopair.cn,HTTP 自动跳转 HTTPS。折腾了一番 Nginx,顺手写了个脚本方便以后管理多个站点。
环境准备
Ubuntu 20.04/22.04 上先把基础环境装好。
sudo apt update
sudo apt install nginx unzip -y
sudo ufw allow 'Nginx Full'
配置逻辑
Ubuntu 的 Nginx 目录分成两个文件夹:
/etc/nginx/sites-available/- 存放配置文件,但 Nginx 不读这里/etc/nginx/sites-enabled/- Nginx 只加载这里的文件(软链接)
管理方式:
- 上线:
ln -s创建软链接 - 下线:
rm删掉链接,原文件保留
配置文件详解
以 blog.twopair.cn 为例,配置分为两个 server 块。
证书存放
证书放在 /etc/nginx/cert/<域名>/:
.pem或.crt- 公钥.key- 私钥(chmod 600)
HTTP 跳转 HTTPS
server {
listen 80;
server_name blog.twopair.cn;
return 301 https://$host$request_uri;
}
HTTPS 反向代理
server {
listen 443 ssl;
server_name blog.twopair.cn;
ssl_certificate /etc/nginx/cert/blog.twopair.cn/fullchain.pem;
ssl_certificate_key /etc/nginx/cert/blog.twopair.cn/privkey.key;
client_max_body_size 100M; # 默认 1MB 太小,改成 100M
location / {
proxy_pass http://127.0.0.1:8090;
# 传递真实 IP 和域名给后端
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;
}
}
自动化脚本
为了避免每次手动配置,我写了个脚本 vhost_manager.sh,自动完成解压证书、生成配置、创建软链接、重载 Nginx。
脚本保存为 vhost_manager.sh,然后 chmod +x vhost_manager.sh。
#!/bin/bash
# Nginx 站点管理工具
set -euo pipefail
NGINX_AVAILABLE="/etc/nginx/sites-available"
NGINX_ENABLED="/etc/nginx/sites-enabled"
CERT_BASE="/etc/nginx/cert"
error() {
echo "错误:$1" >&2
exit 1
}
checkRoot() {
if [ "$(id -u)" -ne 0 ]; then
error "请使用 root 或 sudo 执行该脚本"
fi
}
reloadNginx() {
nginx -t || error "Nginx 配置校验失败"
systemctl reload nginx
}
case "${1:-}" in
deploy)
checkRoot
DOMAIN="${2:-}"
PORT="${3:-}"
ZIP_PATH="${4:-}"
if [ -z "$DOMAIN" ] || [ -z "$PORT" ] || [ -z "$ZIP_PATH" ]; then
error "用法: $0 deploy <domain> <port> <cert.zip>"
fi
if ! [[ "$PORT" =~ ^[0-9]+$ ]]; then
error "端口号必须是数字"
fi
if [ ! -f "$ZIP_PATH" ]; then
error "证书 ZIP 文件不存在: $ZIP_PATH"
fi
CERT_DIR="$CERT_BASE/$DOMAIN"
CONF_PATH="$NGINX_AVAILABLE/$DOMAIN"
echo ">>> [1/5] 准备证书目录: $CERT_DIR"
mkdir -p "$CERT_DIR"
unzip -j -o "$ZIP_PATH" -d "$CERT_DIR" > /dev/null \
|| error "证书 ZIP 解压失败"
PEM=$(find "$CERT_DIR" \( -name "*.pem" -o -name "*.crt" \) -type f | head -n 1)
KEY=$(find "$CERT_DIR" -name "*.key" -type f | head -n 1)
if [ -z "$PEM" ] || [ -z "$KEY" ]; then
error "未在证书包中找到 .pem/.crt 或 .key 文件"
fi
chmod 600 "$KEY"
chmod 644 "$PEM"
echo ">>> [2/5] 生成 Nginx 配置: $CONF_PATH"
cat > "$CONF_PATH" <<EOF
server {
listen 80;
server_name $DOMAIN;
return 301 https://\$host\$request_uri;
}
server {
listen 443 ssl http2;
server_name $DOMAIN;
ssl_certificate $PEM;
ssl_certificate_key $KEY;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
client_max_body_size 100M;
location / {
proxy_pass http://127.0.0.1:$PORT;
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_timeout 60s;
proxy_read_timeout 300s;
}
}
EOF
echo ">>> [3/5] 启用站点"
ln -sf "$CONF_PATH" "$NGINX_ENABLED/$DOMAIN"
echo ">>> [4/5] 校验并重载 Nginx"
reloadNginx
echo ">>> [5/5] 完成"
echo ">>> https://$DOMAIN -> 127.0.0.1:$PORT"
;;
enable)
checkRoot
DOMAIN="${2:-}"
[ -z "$DOMAIN" ] && error "用法: $0 enable <domain>"
ln -sf "$NGINX_AVAILABLE/$DOMAIN" "$NGINX_ENABLED/$DOMAIN"
reloadNginx
echo ">>> 站点 $DOMAIN 已上线"
;;
disable)
checkRoot
DOMAIN="${2:-}"
[ -z "$DOMAIN" ] && error "用法: $0 disable <domain>"
rm -f "$NGINX_ENABLED/$DOMAIN"
reloadNginx
echo ">>> 站点 $DOMAIN 已下线(配置保留)"
;;
remove)
checkRoot
DOMAIN="${2:-}"
[ -z "$DOMAIN" ] && error "用法: $0 remove <domain>"
rm -f "$NGINX_ENABLED/$DOMAIN"
rm -f "$NGINX_AVAILABLE/$DOMAIN"
rm -rf "$CERT_BASE/$DOMAIN"
reloadNginx
echo ">>> 站点 $DOMAIN 已彻底移除"
;;
status)
echo "--- 已启用站点 ---"
ls -l "$NGINX_ENABLED" || echo "暂无已启用站点"
;;
*)
echo "用法:"
echo " $0 deploy <domain> <port> <cert.zip>"
echo " $0 enable <domain>"
echo " $0 disable <domain>"
echo " $0 remove <domain>"
echo " $0 status"
exit 1
;;
esac
实战示例
博客已经跑在 8090 端口,证书压缩包 blog_cert.zip 也上传了。
一键部署:
./vhost_manager.sh deploy blog.twopair.cn 8090 ./blog_cert.zip
日常操作:
./vhost_manager.sh disable blog.twopair.cn # 临时下线
./vhost_manager.sh enable blog.twopair.cn # 重新上线
./vhost_manager.sh remove blog.twopair.cn # 彻底删除
常见问题
413 Request Entity Too Large
博客上传大图片报错。Nginx 默认限制 1MB。
解决:配置里加 client_max_body_size 100M;。脚本已经自动添加了。
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 Twopair
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果