loading

Loading

请输入关键字开始搜索
    首页 技术实践网站部署

    【4】emlog安全部署

    分类:网站部署
    字数: (8345)
    阅读: (211)
    0

    因为借助大模型一直在emlog上增加东西,但是线上的目录因为权限、安全的原因又不能直接git pull,因此重新梳理部署的安装流程。

    1. 整体思路

    线上emlog下有3个目录:

    • releases/<时间戳>:每次发版的只读代码副本
    • shared/:持久写入目录(uploads/ cache/ runtime/ storage/ logs 等)
    • current -> releases/<时间戳>:Nginx/Apache 指向这个软链(原子切换)
      云端/构建机:git pull、构建产物,然后用 rsync 拷到线上新建的 release 目录,最后切软链

    1.1 线上服务准备

    # 新增emlog,专门作为部署emlog
    sudo adduser --disabled-password --gecos "" ubuntu || true
    sudo usermod -aG www-data ubuntu
    
    # 目录结构
    cd /var/www/deployment
    sudo mkdir -p ./{releases,shared}
    # 共享写入目录(按你项目实际增减)
    sudo mkdir -p shared/{uploads,cache,runtime,storage,logs}
    sudo mkdir -p shared/content/{backup,cache,uploadfile}
    
    # 权限设置:目录属主 emlog,组 www-data;目录继承组位
    cd /var/www
    sudo chown -R ubuntu:www-data deployment
    sudo find deployment -type d -exec chmod 2775 {} \;
    sudo find deployment -type f -exec chmod 0664 {} \;
    
    # 共享目录给 www-data 可写(其余代码保持只读)
    cd /var/www
    for d in uploads cache runtime storage logs content/*; do
      sudo chown -R www-data:www-data ./deployment/shared/$d
      sudo find ./deployment/shared/$d -type d -exec chmod 2775 {} \;
      sudo find ./deployment/shared/$d -type f -exec chmod 0664 {} \;
    done
    
    # 创建数据和配置文件
    cd /var/www
    sudo mkdir -p ./deployment/shared/mysql_data
    sudo chown -R mysql:mysql ./deployment/shared/mysql_data
    sudo find ./deployment/shared/mysql_data -type d -exec sudo chmod 0750 {} \;
    sudo find ./deployment/shared/mysql_data -type f -exec sudo chmod 0640 {} \;
    
    sudo touch ./deployment/shared/{config.php,.htaccess,.user.ini}
    sudo chown www-data:www-data ./deployment/shared/{config.php,.htaccess,.user.ini}
    sudo chmod 0640            ./deployment/shared/{config.php,.htaccess,.user.ini}
    
    # Web 站点根指向 /var/www/yourapp/current
    # 并确保禁止访问 .git(双保险)
    # Nginx:
    # location ~ /\.git { deny all; }
    # Apache:
    # RedirectMatch 404 /\.git

    1.2 git clone

    下载对应代码

    cd /var/www
    git clone https://github.com/apostle9891/emlog_modify.git

    新建同步代码vim emlog_sync.sh,需要修改WWW_DIR的目录地址。

    #!/bin/bash
    set -euo pipefail
    umask 002  # 新文件组可写(配合 www-data 组)
    
    WWW_DIR="/var/www"
    REPO_URL="https://github.com/apostle9891/emlog_modify.git"               # 改成你的仓库地址(https 或 ssh 都行)
    BUILD="$WWW_DIR/emlog_modify"                   
    REMOTE="$WWW_DIR/deployment"
    TS="$(date +%Y%m%d%H%M%S)"
    RELEASE="$REMOTE/releases/$TS"
    
    # 1) 在“构建区”拉代码与构建(不在 web 根)
    if [ ! -d "$BUILD/.git" ]; then
      mkdir -p "$BUILD"
      # 初次 clone(若用 ssh,需要 ubuntu 用户已配好私钥)
      git clone "$REPO_URL" "$BUILD"
    fi
    cd "$BUILD"
    git pull --ff-only
    
    # === 按你的技术栈选择开启(示例) ===
    # PHP:    composer install --no-dev -o
    # Node:   npm ci && npm run build
    # Python: pip install -r requirements.txt --target .venv  # 或 poetry export + 构建
    # 前端产物:确保已生成到 dist/ 或 public/build/ 等目录
    # ===================================
    
    # 2) 准备新版本目录
    mkdir -p "$RELEASE"
    
    # 3) 本地 rsync 到 RELEASE(不走 ssh;排除 .git 与写入目录)
    rsync -a --delete \
      --exclude '.git' \
      --exclude '.github' \
      --exclude 'node_modules' \
      --exclude 'uploads' --exclude 'cache' --exclude 'runtime' --exclude 'storage' --exclude 'logs' \
      --exclude 'config.php' --exclude 'mysql_data' \
      "$BUILD"/ "$RELEASE"/
    
    # 4) 在 RELEASE 里把写入型目录挂到 shared
    cd "$RELEASE"
    for d in uploads cache runtime storage logs mysql_data content/cache content/backup content/uploadfile; do
      rm -rf "$d"
      ln -s "$REMOTE/shared/$d" "$d"
    done
    
    # 单文件软链:config.php
    for f in config.php .htaccess .user.ini; do
      rm -rf "$f"
      ln -s "$REMOTE/shared/$f" "$f"
    done
    
    # 5) 统一权限(代码只读;写入目录已 www-data 可写)
    chown -R ubuntu:www-data "$RELEASE"
    find "$RELEASE" -type d -exec chmod 2755 {} \;
    find "$RELEASE" -type f -exec chmod 0644 {} \;
    
    # 6) 原子切换 current(零停机)
    ln -sfn "$RELEASE" "$REMOTE/current"
    
    # 7) 可选:重载服务(按需开启)
    # systemctl reload php7.4-fpm || true
    # systemctl reload nginx || true
    
    echo "Deployed $BUILD -> $RELEASE"

    设置权限

    sudo chmod +x ./emlog_sync.sh

    1.3 原有emlog迁移

    因为已经部署了emlog的代码,我们需要把对应的缓存数据迁移到share中。执行以下脚本。

    #!/usr/bin/env bash
    set -euo pipefail
    
    ########################################
    # 可根据需要修改
    ########################################
    SRC="/var/www/emlog"                 # 现有已部署目录
    DST="/var/www/deployment/share"      # 目标共享目录
    CODE_USER="ubuntu"                   # 代码/配置文件属主
    CODE_GROUP="www-data"                # 代码/配置文件属组
    WRITE_USER="www-data"                # 运行期目录写入用户
    WRITE_GROUP="www-data"               # 运行期目录写入组
    MYSQL_OWNER="mysql:mysql"            # mysql_data 的属主(若不用本机 MySQL,可留成 www-data)
    MOVE_DIRS=(uploads cache runtime storage logs mysql_data)
    CONFIG_FILE=(config.php .htaccess .user.ini)
    
    ########################################
    # 前置检查
    ########################################
    if [[ ! -d "$SRC" ]]; then
      echo "ERROR: 源目录不存在:$SRC" >&2
      exit 1
    fi
    
    mkdir -p "$DST"
    
    ########################################
    # 备份(可选)
    ########################################
    TS="$(date +%Y%m%d%H%M%S)"
    BACKUP="/tmp/emlog_migrate_backup_${TS}.tgz"
    echo "将迁移以下内容:${MOVE_DIRS[*]} 以及 ${CONFIG_FILE}"
    read -rp "是否先备份这些内容到 ${BACKUP}? [Y/n] " ans
    ans=${ans:-Y}
    if [[ "$ans" =~ ^[Yy]$ ]]; then
      echo ">>> 备份中..."
      INCLUDES=()
      for d in "${MOVE_DIRS[@]}"; do
        [[ -e "$SRC/$d" ]] && INCLUDES+=("$d")
      done
      for f in "${CONFIG_FILE[@]}"; do
        [[ -e "$SRC/$f" ]] && INCLUDES+=("$f")
      done
      if ((${#INCLUDES[@]})); then
        tar -C "$SRC" -czf "$BACKUP" "${INCLUDES[@]}"
        echo ">>> 备份完成:$BACKUP"
      else
        echo ">>> 源中无需备份的对象,跳过打包。"
      fi
    fi
    
    ########################################
    # 准备目标目录与权限基线
    ########################################
    chown -R "$CODE_USER:$CODE_GROUP" "$DST"
    find "$DST" -type d -exec chmod 2775 {} \; 2>/dev/null || true
    find "$DST" -type f -exec chmod 0664 {} \; 2>/dev/null || true
    
    ########################################
    # 迁移目录函数(合并 -> 删除源 -> 建软链 -> 权限)
    ########################################
    move_dir() {
      local name="$1"
      local src="$SRC/$name"
      local dst="$DST/$name"
    
      # 若源已经是软链,跳过
      if [[ -L "$src" ]]; then
        echo "跳过:$src 已是软链。"
        return 0
      fi
    
      # 目标目录准备好
      mkdir -p "$dst"
    
      if [[ -d "$src" ]]; then
        echo ">>> 同步 $src -> $dst"
        # 合并同步;尽量保持权限/时间;如果没有子内容,rsync 会返回非零,用 || true 忽略
        rsync -a --delete "$src"/ "$dst"/ 2>/dev/null || rsync -a "$src"/ "$dst"/ || true
        echo ">>> 移除源并创建软链 $src -> $dst"
        rm -rf "$src"
        ln -s "$dst" "$src"
      else
        echo "提示:$src 不存在,创建软链到目标空目录。"
        ln -s "$dst" "$src"
      fi
    
      # 权限:运行期目录给运行用户/组;mysql_data 单独处理
      if [[ "$name" == "mysql_data" ]]; then
        # 若你确实把 MySQL 的 datadir 放到这里,建议用 mysql:mysql;否则可改为 www-data
        chown -R "$MYSQL_OWNER" "$dst" 2>/dev/null || chown -R "$WRITE_USER:$WRITE_GROUP" "$dst"
        find "$dst" -type d -exec chmod 0750 {} \; 2>/dev/null || true
        find "$dst" -type f -exec chmod 0640 {} \; 2>/dev/null || true
      else
        chown -R "$WRITE_USER:$WRITE_GROUP" "$dst"
        find "$dst" -type d -exec chmod 2775 {} \;
        find "$dst" -type f -exec chmod 0664 {} \;
      fi
    }
    
    ########################################
    # 执行目录迁移
    ########################################
    for d in "${MOVE_DIRS[@]}"; do
      move_dir "$d"
    done
    
    ########################################
    # 迁移 config.php(单文件)
    ########################################
    SRC_CFG="$SRC/$CONFIG_FILE"
    DST_CFG="$DST/$CONFIG_FILE"
    
    # 若目标不存在,从源复制;存在则以目标为准
    if [[ -f "$SRC_CFG" && ! -e "$DST_CFG" ]]; then
      echo ">>> 复制 $SRC_CFG -> $DST_CFG"
      install -o "$CODE_USER" -g "$CODE_GROUP" -m 0640 "$SRC_CFG" "$DST_CFG"
    elif [[ -f "$SRC_CFG" && -f "$DST_CFG" ]]; then
      echo ">>> 目标已存在 $DST_CFG,保留目标,源将改为软链。"
    elif [[ ! -f "$SRC_CFG" && ! -e "$DST_CFG" ]]; then
      echo "提示:未发现 $CONFIG_FILE(源与目标都没有),跳过。"
    fi
    
    # 源侧替换为软链(若源存在实体或目标已存在)
    if [[ -e "$DST_CFG" ]]; then
      [[ -e "$SRC_CFG" && ! -L "$SRC_CFG" ]] && rm -f "$SRC_CFG"
      [[ -L "$SRC_CFG" ]] || ln -s "$DST_CFG" "$SRC_CFG"
      chown "$CODE_USER:$CODE_GROUP" "$DST_CFG"
      chmod 0640 "$DST_CFG"
    fi
    
    ########################################
    # 最后:源目录的其它文件权限(可选微调)
    ########################################
    find "$SRC" -maxdepth 1 -mindepth 1 -type d ! -lname '*' -exec true {} \; >/dev/null 2>&1 || true
    chown -R "$CODE_USER:$CODE_GROUP" "$SRC"
    find "$SRC" -type d -exec chmod 2755 {} \; 2>/dev/null || true
    find "$SRC" -type f -exec chmod 0644 {} \; 2>/dev/null || true
    
    echo "✅ 迁移完成:
    - 目录:${MOVE_DIRS[*]} 已迁至 $DST 并在 $SRC 建立软链
    - 文件:$CONFIG_FILE 已放置于 $DST 并在 $SRC 建立软链
    请确认服务正常运行。"

    1.4 迁移成功

    执行1.3的脚本,迁移完毕后,可以进行同步,记得nginx的根目录/var/www/deployment/current

    sudo -u ubuntu ./emlog_sync.sh
    本文发布于2025年11月01日16:04,已经过了57天,若内容或图片失效,请留言反馈
    文章出处: 求索空间
    文章链接: https://blog.askerlab.com/emlog_modify_safe_install
    评论列表:
    empty

    暂无评论