403Webshell
Server IP : 119.195.102.159  /  Your IP : 216.73.217.134
Web Server : nginx/1.18.0
System : Linux picell 5.15.0-181-generic #191-Ubuntu SMP Fri May 22 19:09:02 UTC 2026 x86_64
User : altablue ( 1000)
PHP Version : 8.3.31
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /tmp/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /tmp/setup_host.new.sh
#!/usr/bin/env bash

set -Eeuo pipefail

readonly ADMIN_USER="altablue"
readonly WP_SOURCE="/home2/wordpress"
readonly PHP_VERSION="8.3"
readonly CERT_EMAIL="admin@picell.biz"
readonly CREDENTIAL_DIR="/home/altablue/.site-credentials"

usage() {
    cat <<USAGE
사용법:
  sudo $0 example.com /home2/example
  sudo $0 example.com -d www.example.com /home2/example

환경변수:
  STAGING=1   Let's Encrypt 시험 인증서 사용
USAGE
    exit 1
}

fail() {
    echo "❌ $*" >&2
    exit 1
}

on_exit() {
    local status=$?
    unset MYSQL_PWD MYSQL_ADMIN_PASSWORD 2>/dev/null || true
    if [[ -n "${ACME_TEST_FILE:-}" ]]; then
        rm -f -- "$ACME_TEST_FILE" 2>/dev/null || true
    fi
    if (( status != 0 )); then
        echo "❌ 설정이 중단되었습니다. 위 오류를 확인하세요." >&2
        echo "   기존 사이트나 DB는 자동 삭제하지 않았습니다." >&2
    fi
}
trap on_exit EXIT

require_command() {
    command -v "$1" >/dev/null 2>&1 || fail "필수 명령이 없습니다: $1"
}

valid_domain() {
    [[ "$1" =~ ^([A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,63}$ ]]
}

trim_argument() {
    local value="$1"
    value="${value#"${value%%[![:space:]]*}"}"
    value="${value%"${value##*[![:space:]]}"}"
    printf '%s' "$value"
}

mysql_root() {
    case "${MYSQL_AUTH_MODE:-password}" in
        login-path) mysql --login-path=setup-host "$@" ;;
        socket) mysql --protocol=socket -uroot "$@" ;;
        password) MYSQL_PWD="${MYSQL_ADMIN_PASSWORD:-}" mysql --protocol=socket -uroot "$@" ;;
        *) fail "알 수 없는 MySQL 인증 방식입니다." ;;
    esac
}

if (( EUID != 0 )); then
    fail "sudo로 실행해야 합니다."
fi

if [[ $# -eq 2 ]]; then
    DOMAIN="$1"
    ROOT_INPUT="$2"
    ADD_DOMAIN=""
elif [[ $# -eq 4 && "$2" == "-d" ]]; then
    DOMAIN="$1"
    ADD_DOMAIN="$3"
    ROOT_INPUT="$4"
else
    usage
fi

DOMAIN="$(trim_argument "$DOMAIN")"
ADD_DOMAIN="$(trim_argument "$ADD_DOMAIN")"
ROOT_INPUT="$(trim_argument "$ROOT_INPUT")"

valid_domain "$DOMAIN" || fail "올바르지 않은 도메인입니다: $DOMAIN"
if [[ -n "$ADD_DOMAIN" ]]; then
    valid_domain "$ADD_DOMAIN" || fail "올바르지 않은 추가 도메인입니다: $ADD_DOMAIN"
fi

for command_name in certbot curl find getent groupadd nginx openssl php php-fpm8.3 \
    readlink systemctl useradd usermod wp mysql; do
    require_command "$command_name"
done

getent passwd "$ADMIN_USER" >/dev/null || fail "관리 사용자가 없습니다: $ADMIN_USER"

ROOT_DIR="$(readlink -m -- "$ROOT_INPUT")"
[[ "$ROOT_DIR" != *[[:space:]]* ]] || fail "공백이 포함된 웹루트 경로는 지원하지 않습니다: $ROOT_DIR"
case "$ROOT_DIR" in
    /home/*|/home2/*) ;;
    *) fail "웹루트는 /home 또는 /home2 아래여야 합니다: $ROOT_DIR" ;;
esac
[[ "$ROOT_DIR" != "/home" && "$ROOT_DIR" != "/home2" ]] || fail "상위 홈 디렉터리는 웹루트로 사용할 수 없습니다."

SITE_KEY="$(basename -- "$ROOT_DIR" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9' '_' | sed 's/^_*//; s/_*$//' | cut -c1-24)"
[[ -n "$SITE_KEY" ]] || fail "경로에서 사이트 식별자를 만들 수 없습니다."

PHP_USER="wp_${SITE_KEY}"
SITE_GROUP="site_${SITE_KEY}"
DB_NAME="wp_${SITE_KEY}"
DB_USER="wp_${SITE_KEY}"
POOL_NAME="site_${SITE_KEY}"
POOL_FILE="/etc/php/${PHP_VERSION}/fpm/pool.d/${POOL_NAME}.conf"
PHP_SOCKET="/run/php/php${PHP_VERSION}-fpm-${SITE_KEY}.sock"
NGINX_SNIPPET="/etc/nginx/snippets/${POOL_NAME}.conf"
CONF_FILE="/etc/nginx/sites-available/${DOMAIN}.conf"
ENABLED_FILE="/etc/nginx/sites-enabled/${DOMAIN}.conf"
ACCESS_LOG="/var/log/nginx/${DOMAIN}.access.log"
ERROR_LOG="/var/log/nginx/${DOMAIN}.error.log"
PHP_ERROR_LOG="/var/log/php${PHP_VERSION}-fpm-${SITE_KEY}.log"
ACME_DIR="${ROOT_DIR}/.well-known/acme-challenge"
ACME_TEST_FILE="${ACME_DIR}/setup-test.txt"
STAGING="${STAGING:-0}"

SERVER_NAMES="$DOMAIN"
CERT_DOMAINS=(-d "$DOMAIN")
ALL_DOMAINS=("$DOMAIN")
if [[ -n "$ADD_DOMAIN" ]]; then
    SERVER_NAMES+=" $ADD_DOMAIN"
    CERT_DOMAINS+=(-d "$ADD_DOMAIN")
    ALL_DOMAINS+=("$ADD_DOMAIN")
fi

# DNS/인증서 조건을 가장 먼저 확인하여 사용자, 그룹, 웹루트 또는 임시
# Nginx 설정만 남는 부분 설치를 방지한다. Cloudflare 프록시 IP도 정상이다.
for check_domain in "${ALL_DOMAINS[@]}"; do
    getent ahostsv4 "$check_domain" >/dev/null 2>&1 \
        || fail "DNS A 레코드를 확인할 수 없습니다: $check_domain"
done

if [[ -e "$ROOT_DIR" ]] && find "$ROOT_DIR" -mindepth 1 \
    ! -path "$ROOT_DIR/.well-known" \
    ! -path "$ROOT_DIR/.well-known/*" -print -quit | grep -q .; then
    fail "웹루트가 비어 있지 않습니다. 기존 파일 보호를 위해 중단합니다: $ROOT_DIR"
fi

ADOPT_EXISTING_NGINX=0
if [[ -e "$CONF_FILE" ]]; then
    [[ -f "$CONF_FILE" && ! -L "$CONF_FILE" ]] || fail "기존 Nginx 설정이 일반 파일이 아닙니다: $CONF_FILE"

    mapfile -t EXISTING_ROOTS < <(
        awk '$1 == "root" { gsub(/;/, "", $2); print $2 }' "$CONF_FILE" |
            tr -d '\r' | sort -u
    )
    (( ${#EXISTING_ROOTS[@]} > 0 )) || fail "기존 Nginx 설정에서 root를 확인할 수 없습니다: $CONF_FILE"
    for existing_root in "${EXISTING_ROOTS[@]}"; do
        existing_root="$(readlink -m -- "$existing_root")"
        [[ "$existing_root" == "$ROOT_DIR" ]] \
            || fail "기존 Nginx root가 요청 경로와 다릅니다: $existing_root != $ROOT_DIR"
    done

    EXISTING_SERVER_NAMES="$(
        awk '$1 == "server_name" { for (i = 2; i <= NF; i++) { gsub(/;/, "", $i); print $i } }' "$CONF_FILE" |
            tr -d '\r' | sort -u
    )"
    for requested_name in "${ALL_DOMAINS[@]}"; do
        grep -Fxq "$requested_name" <<<"$EXISTING_SERVER_NAMES" \
            || fail "기존 Nginx 설정에 요청 도메인이 없습니다: $requested_name"
    done
    ADOPT_EXISTING_NGINX=1
fi

if [[ -e "$ENABLED_FILE" || -L "$ENABLED_FILE" ]]; then
    [[ -L "$ENABLED_FILE" ]] || fail "sites-enabled 항목이 심볼릭 링크가 아닙니다: $ENABLED_FILE"
    [[ "$(readlink -f -- "$ENABLED_FILE")" == "$(readlink -f -- "$CONF_FILE")" ]] \
        || fail "sites-enabled 링크가 다른 설정을 가리킵니다: $ENABLED_FILE"
    (( ADOPT_EXISTING_NGINX == 1 )) || fail "sites-enabled 링크만 존재하고 원본 설정이 없습니다."
fi

[[ ! -e "$POOL_FILE" && ! -e "$NGINX_SNIPPET" ]] || fail "사이트 PHP-FPM 설정이 이미 존재합니다: $SITE_KEY"

# 직전 실행이 인증서 단계에서 멈춘 경우, 스크립트가 만든 계정/그룹을 검증 후 재사용한다.
if getent group "$SITE_GROUP" >/dev/null; then
    [[ "$(getent group "$SITE_GROUP" | cut -d: -f3)" -lt 1000 ]] \
        || fail "기존 사이트 그룹이 시스템 그룹이 아닙니다: $SITE_GROUP"
fi
if getent passwd "$PHP_USER" >/dev/null; then
    [[ "$(getent passwd "$PHP_USER" | cut -d: -f6)" == "$ROOT_DIR" ]] \
        || fail "기존 PHP 사용자의 홈 경로가 다릅니다: $PHP_USER"
    [[ "$(id -gn "$PHP_USER")" == "$SITE_GROUP" ]] \
        || fail "기존 PHP 사용자의 기본 그룹이 다릅니다: $PHP_USER"
    [[ "$(getent passwd "$PHP_USER" | cut -d: -f7)" == "/usr/sbin/nologin" ]] \
        || fail "기존 PHP 사용자의 셸이 안전하지 않습니다: $PHP_USER"
fi

read -r -p "WordPress를 설치하시겠습니까? [y/N]: " WP_ANSWER
case "$WP_ANSWER" in
    y|Y|yes|YES) INSTALL_WORDPRESS=1 ;;
    *) INSTALL_WORDPRESS=0 ;;
esac

if (( INSTALL_WORDPRESS )); then
    [[ -f "$WP_SOURCE/wp-includes/version.php" ]] || fail "WordPress 원본이 없습니다: $WP_SOURCE"
    WP_VERSION="$(php -r 'include $argv[1]; echo $wp_version;' "$WP_SOURCE/wp-includes/version.php")"
    echo "🔎 WordPress ${WP_VERSION} 원본 체크섬을 확인합니다."
    wp core verify-checksums \
        --path="$WP_SOURCE" \
        --version="$WP_VERSION" \
        --locale=ko_KR \
        --allow-root >/dev/null || fail "WordPress 원본 체크섬이 일치하지 않습니다."

    if mysql --login-path=setup-host -NBe 'SELECT 1' >/dev/null 2>&1; then
        MYSQL_AUTH_MODE="login-path"
        MYSQL_ADMIN_PASSWORD=""
    elif mysql --protocol=socket -uroot -NBe 'SELECT 1' >/dev/null 2>&1; then
        MYSQL_AUTH_MODE="socket"
        MYSQL_ADMIN_PASSWORD=""
    else
        MYSQL_AUTH_MODE="password"
        read -r -s -p "MySQL root 비밀번호: " MYSQL_ADMIN_PASSWORD
        echo
        mysql_root -NBe 'SELECT 1' >/dev/null 2>&1 || fail "MySQL root 인증에 실패했습니다."
    fi

    mysql_root -NBe "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME='${DB_NAME}'" | grep -q . \
        && fail "데이터베이스가 이미 존재합니다: $DB_NAME"
    mysql_root -NBe "SELECT User FROM mysql.user WHERE User='${DB_USER}' AND Host='localhost'" | grep -q . \
        && fail "DB 사용자가 이미 존재합니다: ${DB_USER}@localhost"
fi

echo "----------------------------------------------------"
echo "도메인       : $SERVER_NAMES"
echo "웹루트       : $ROOT_DIR"
echo "PHP 사용자   : $PHP_USER"
echo "사이트 그룹  : $SITE_GROUP"
echo "WordPress    : $([[ $INSTALL_WORDPRESS -eq 1 ]] && echo yes || echo no)"
echo "----------------------------------------------------"

if (( ADOPT_EXISTING_NGINX )); then
    EXISTING_CONF_BACKUP="${CONF_FILE}.$(date +%Y%m%d-%H%M%S).adopt.bak"
    cp -a -- "$CONF_FILE" "$EXISTING_CONF_BACKUP"
    chmod 0640 "$EXISTING_CONF_BACKUP"
    echo "ℹ️ 기존 Nginx 설정을 인계합니다. 백업: $EXISTING_CONF_BACKUP"
fi

# 사이트 전용 계정과 공유 그룹. altablue와 이 사이트 PHP만 쓰기 권한을 공유한다.
getent group "$SITE_GROUP" >/dev/null || groupadd --system "$SITE_GROUP"
getent passwd "$PHP_USER" >/dev/null \
    || useradd --system --gid "$SITE_GROUP" --home-dir "$ROOT_DIR" --shell /usr/sbin/nologin "$PHP_USER"
usermod -aG "$SITE_GROUP" "$ADMIN_USER"

install -d -m 2775 -o "$PHP_USER" -g "$SITE_GROUP" "$ROOT_DIR"
install -d -m 2775 -o "$PHP_USER" -g "$SITE_GROUP" "$ACME_DIR"

# 그룹 협업 파일이 FTP/PHP 어느 쪽에서 생성되어도 664/775가 되도록 한다.
install -d -m 0755 /etc/systemd/system/php${PHP_VERSION}-fpm.service.d
cat > "/etc/systemd/system/php${PHP_VERSION}-fpm.service.d/20-site-group-umask.conf" <<'UMASK_EOF'
[Service]
UMask=0002
UMASK_EOF

# 인증서 발급을 위한 임시 HTTP 가상호스트.
cat > "$CONF_FILE" <<NGINX_HTTP
server {
    listen 80;
    listen [::]:80;
    server_name $SERVER_NAMES;
    root $ROOT_DIR;
    access_log $ACCESS_LOG combined;
    error_log $ERROR_LOG warn;

    location ^~ /.well-known/acme-challenge/ {
        root $ROOT_DIR;
        default_type text/plain;
        try_files \$uri =404;
        allow all;
    }

    location / { return 301 https://\$host\$request_uri; }
}
NGINX_HTTP

ln -sfn "$CONF_FILE" "$ENABLED_FILE"
nginx -t
systemctl reload nginx

printf '%s\n' "acme-local-ok" > "$ACME_TEST_FILE"
chown "$PHP_USER:$SITE_GROUP" "$ACME_TEST_FILE"
chmod 0664 "$ACME_TEST_FILE"

LOCAL_RESULT=""
for _ in {1..12}; do
    LOCAL_RESULT="$(curl -fsS --resolve "${DOMAIN}:80:127.0.0.1" \
        "http://${DOMAIN}/.well-known/acme-challenge/setup-test.txt" 2>/dev/null || true)"
    [[ "$LOCAL_RESULT" == "acme-local-ok" ]] && break
    sleep 0.25
done
[[ "$LOCAL_RESULT" == "acme-local-ok" ]] || fail "ACME 로컬 경로 테스트에 실패했습니다."

CERTBOT_EXTRA_ARGS=()
[[ "$STAGING" == "1" ]] && CERTBOT_EXTRA_ARGS+=(--staging)
certbot certonly \
    "${CERTBOT_EXTRA_ARGS[@]}" \
    --webroot -w "$ROOT_DIR" \
    "${CERT_DOMAINS[@]}" \
    --email "$CERT_EMAIL" \
    --agree-tos --no-eff-email --keep-until-expiring

CERT_DIR="/etc/letsencrypt/live/${DOMAIN}"
[[ -f "$CERT_DIR/fullchain.pem" && -f "$CERT_DIR/privkey.pem" ]] || fail "인증서 파일을 찾을 수 없습니다: $CERT_DIR"

if (( INSTALL_WORDPRESS )); then
    echo "📦 WordPress 원본을 복사합니다: $WP_SOURCE"
    cp -a "$WP_SOURCE"/. "$ROOT_DIR"/

    DB_PASSWORD="$(openssl rand -hex 24)"
    AUTH_KEY="$(openssl rand -hex 32)"
    SECURE_AUTH_KEY="$(openssl rand -hex 32)"
    LOGGED_IN_KEY="$(openssl rand -hex 32)"
    NONCE_KEY="$(openssl rand -hex 32)"
    AUTH_SALT="$(openssl rand -hex 32)"
    SECURE_AUTH_SALT="$(openssl rand -hex 32)"
    LOGGED_IN_SALT="$(openssl rand -hex 32)"
    NONCE_SALT="$(openssl rand -hex 32)"

    mysql_root <<SQL
CREATE DATABASE \`${DB_NAME}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASSWORD}';
GRANT ALL PRIVILEGES ON \`${DB_NAME}\`.* TO '${DB_USER}'@'localhost';
FLUSH PRIVILEGES;
SQL

    cat > "$ROOT_DIR/wp-config.php" <<WP_CONFIG
<?php
define( 'DB_NAME', '${DB_NAME}' );
define( 'DB_USER', '${DB_USER}' );
define( 'DB_PASSWORD', '${DB_PASSWORD}' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );

define( 'AUTH_KEY',         '${AUTH_KEY}' );
define( 'SECURE_AUTH_KEY',  '${SECURE_AUTH_KEY}' );
define( 'LOGGED_IN_KEY',    '${LOGGED_IN_KEY}' );
define( 'NONCE_KEY',        '${NONCE_KEY}' );
define( 'AUTH_SALT',        '${AUTH_SALT}' );
define( 'SECURE_AUTH_SALT', '${SECURE_AUTH_SALT}' );
define( 'LOGGED_IN_SALT',   '${LOGGED_IN_SALT}' );
define( 'NONCE_SALT',       '${NONCE_SALT}' );

\$table_prefix = 'wp_';
define( 'WP_DEBUG', false );
define( 'DISALLOW_FILE_EDIT', true );

if ( ! defined( 'ABSPATH' ) ) {
    define( 'ABSPATH', __DIR__ . '/' );
}
require_once ABSPATH . 'wp-settings.php';
WP_CONFIG

    install -d -m 0700 -o "$ADMIN_USER" -g "$ADMIN_USER" "$CREDENTIAL_DIR"
    CREDENTIAL_FILE="${CREDENTIAL_DIR}/${DOMAIN}.conf"
    cat > "$CREDENTIAL_FILE" <<CREDENTIALS
DOMAIN=${DOMAIN}
WEB_ROOT=${ROOT_DIR}
PHP_USER=${PHP_USER}
SITE_GROUP=${SITE_GROUP}
DB_NAME=${DB_NAME}
DB_USER=${DB_USER}
DB_PASSWORD=${DB_PASSWORD}
CREDENTIALS
    chown "$ADMIN_USER:$ADMIN_USER" "$CREDENTIAL_FILE"
    chmod 0600 "$CREDENTIAL_FILE"
fi

install -d -m 2770 -o "$PHP_USER" -g "$SITE_GROUP" "$ROOT_DIR/.php-tmp" "$ROOT_DIR/.php-sessions"

# 복사 원본의 777 권한을 사용하지 않고, FTP와 WordPress가 공유할 그룹 쓰기 권한만 둔다.
chown -R "$PHP_USER:$SITE_GROUP" "$ROOT_DIR"
find "$ROOT_DIR" -xdev -type d -exec chmod 2775 {} +
find "$ROOT_DIR" -xdev -type f -exec chmod 0664 {} +
chmod 2770 "$ROOT_DIR/.php-tmp" "$ROOT_DIR/.php-sessions"
if [[ -f "$ROOT_DIR/wp-config.php" ]]; then
    chmod 0640 "$ROOT_DIR/wp-config.php"
fi

install -m 0640 -o "$PHP_USER" -g "$SITE_GROUP" /dev/null "$PHP_ERROR_LOG"

cat > "$POOL_FILE" <<FPM_POOL
[$POOL_NAME]
user = $PHP_USER
group = $SITE_GROUP

listen = $PHP_SOCKET
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

pm = ondemand
pm.max_children = 10
pm.process_idle_timeout = 20s
pm.max_requests = 500

chdir = $ROOT_DIR
clear_env = yes
catch_workers_output = yes
security.limit_extensions = .php

php_admin_value[open_basedir] = $ROOT_DIR:/tmp:/var/tmp
php_admin_value[upload_tmp_dir] = $ROOT_DIR/.php-tmp
php_admin_value[session.save_path] = $ROOT_DIR/.php-sessions
php_admin_flag[log_errors] = on
php_admin_value[error_log] = $PHP_ERROR_LOG
FPM_POOL

if (( INSTALL_WORDPRESS )); then
    cat > "$NGINX_SNIPPET" <<NGINX_SNIPPET_WP
charset utf-8;

location / {
    try_files \$uri \$uri/ /index.php?\$args;
}

location = /wp-config.php { deny all; }
location ~ /\.(?!well-known) { deny all; }

location ~* ^/wp-content/(?:uploads|cache|upgrade)/.*\.(?:php|phtml|php5|phar|cgi|pl|py|sh)$ {
    deny all;
    access_log off;
    log_not_found off;
}

location ~ \.php(?:\$|/) {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:$PHP_SOCKET;
    fastcgi_param HTTP_AUTHORIZATION \$http_authorization;
    fastcgi_connect_timeout 60s;
    fastcgi_send_timeout 300s;
    fastcgi_read_timeout 300s;
}

location ~* ^/wp-json/ {
    rewrite ^/wp-json/(.*?)\$ /index.php?rest_route=/\$1 last;
}

location ~* \.(?:jpg|jpeg|png|gif|css|js|ico|svg|ttf|woff2?|eot)\$ {
    charset utf-8;
    try_files \$uri =404;
    access_log off;
    expires 30d;
}
NGINX_SNIPPET_WP
else
    cat > "$NGINX_SNIPPET" <<NGINX_SNIPPET_GENERIC
charset utf-8;

location / {
    try_files \$uri \$uri/ =404;
}

location ~ /\.(?!well-known) { deny all; }

location ~ \.php(?:\$|/) {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:$PHP_SOCKET;
    fastcgi_connect_timeout 60s;
    fastcgi_send_timeout 300s;
    fastcgi_read_timeout 300s;
}
NGINX_SNIPPET_GENERIC
fi

cat > "$CONF_FILE" <<NGINX_FINAL
server {
    listen 80;
    listen [::]:80;
    server_name $SERVER_NAMES;
    root $ROOT_DIR;
    access_log $ACCESS_LOG combined;
    error_log $ERROR_LOG warn;

    location ^~ /.well-known/acme-challenge/ {
        root $ROOT_DIR;
        default_type text/plain;
        try_files \$uri =404;
        allow all;
    }

    location / { return 301 https://\$host\$request_uri; }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name $SERVER_NAMES;
    root $ROOT_DIR;
    index index.php index.html index.htm;
    access_log $ACCESS_LOG combined;
    error_log $ERROR_LOG warn;

    ssl_certificate $CERT_DIR/fullchain.pem;
    ssl_certificate_key $CERT_DIR/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    include $NGINX_SNIPPET;
}
NGINX_FINAL

php-fpm8.3 -t
systemctl daemon-reload
systemctl restart "php${PHP_VERSION}-fpm"
nginx -t
systemctl reload nginx

rm -f -- "$ACME_TEST_FILE"

echo
echo "✅ 신규 사이트 설정이 완료되었습니다."
echo "도메인      : $SERVER_NAMES"
echo "웹루트      : $ROOT_DIR"
echo "PHP 사용자  : $PHP_USER"
echo "사이트 그룹 : $SITE_GROUP"
echo "PHP 소켓    : $PHP_SOCKET"
if (( INSTALL_WORDPRESS )); then
    echo "DB 정보     : ${CREDENTIAL_DIR}/${DOMAIN}.conf (altablue 전용 600)"
    echo "WordPress   : https://${DOMAIN}/wp-admin/install.php 에서 관리자 계정을 만드세요."
fi
echo "FTP/SFTP를 다시 연결하면 altablue의 새 그룹 권한이 적용됩니다."

Youez - 2016 - github.com/yon3zu
LinuXploit