Automate blog deploy user setup

This commit is contained in:
xtcnet 2026-03-19 14:38:22 +07:00
parent 62593d8316
commit 752d80e11c
4 changed files with 106 additions and 9 deletions

View file

@ -28,6 +28,7 @@ A lightweight all-in-one Docker deployment that combines reverse proxy managemen
- `blog-starter/` contains a ready-to-use Hugo + LoveIt starter
- includes a Forgejo Actions workflow that deploys generated files to `/opt/blog/public`
- intended to be used as the base of a separate blog repository
- `install.sh blog-deploy-info` prints the deploy user and the secret values needed by Forgejo Actions
---

View file

@ -62,7 +62,11 @@ jobs:
test -n "$BLOG_DEPLOY_PORT"
test -n "$BLOG_DEPLOY_USER"
test -n "$BLOG_DEPLOY_PATH"
ssh -p "$BLOG_DEPLOY_PORT" "$BLOG_DEPLOY_USER@$BLOG_DEPLOY_HOST" "mkdir -p '$BLOG_DEPLOY_PATH/public'"
SSH_OPTS="-p $BLOG_DEPLOY_PORT"
if [ ! -f ~/.ssh/known_hosts ]; then
SSH_OPTS="$SSH_OPTS -o StrictHostKeyChecking=accept-new"
fi
ssh $SSH_OPTS "$BLOG_DEPLOY_USER@$BLOG_DEPLOY_HOST" "mkdir -p '$BLOG_DEPLOY_PATH/public'"
rsync -az --delete \
-e "ssh -p $BLOG_DEPLOY_PORT" \
-e "ssh $SSH_OPTS" \
public/ "$BLOG_DEPLOY_USER@$BLOG_DEPLOY_HOST:$BLOG_DEPLOY_PATH/public/"

View file

@ -74,7 +74,8 @@ The workflow expects these repository secrets:
- Blog host installed from this repo's `install.sh`
- `d3v-blog` container running
- the deploy user can write to `/opt/blog/public`
- a deploy user created by `install.sh blog-install` or `install.sh blog-update`
- `install.sh blog-deploy-info` prints the exact secret values to paste into Forgejo
- Nginx Proxy Manager forwards `blog.yourdomain.com` to `d3v-blog:80`
## Notes

View file

@ -16,6 +16,10 @@ BLOG_INSTALL_DIR="/opt/blog"
BLOG_COMPOSE_FILE="${BLOG_INSTALL_DIR}/docker-compose.yml"
BLOG_CONTAINER_NAME="d3v-blog"
BLOG_IMAGE="nginx:alpine"
BLOG_DEPLOY_USER="blogdeploy"
BLOG_DEPLOY_KEY_DIR="${BLOG_INSTALL_DIR}/deploy-keys"
BLOG_DEPLOY_PRIVATE_KEY="${BLOG_DEPLOY_KEY_DIR}/id_ed25519"
BLOG_DEPLOY_PUBLIC_KEY="${BLOG_DEPLOY_KEY_DIR}/id_ed25519.pub"
FORGEJO_INSTALL_DIR="/opt/forgejo"
FORGEJO_COMPOSE_FILE="${FORGEJO_INSTALL_DIR}/docker-compose.yml"
@ -259,6 +263,86 @@ ensure_docker_network() {
fi
}
ensure_blog_deploy_user() {
log_step "Ensuring blog deploy user '${BLOG_DEPLOY_USER}' exists..."
if id -u "${BLOG_DEPLOY_USER}" > /dev/null 2>&1; then
log_ok "Deploy user '${BLOG_DEPLOY_USER}' already exists."
else
useradd --create-home --shell /bin/bash "${BLOG_DEPLOY_USER}"
log_ok "Deploy user '${BLOG_DEPLOY_USER}' created."
fi
}
ensure_blog_deploy_paths() {
log_step "Preparing blog deploy paths..."
mkdir -p "${BLOG_INSTALL_DIR}/public" "${BLOG_DEPLOY_KEY_DIR}"
chown -R "${BLOG_DEPLOY_USER}:${BLOG_DEPLOY_USER}" "${BLOG_INSTALL_DIR}/public"
chmod 755 "${BLOG_INSTALL_DIR}" "${BLOG_INSTALL_DIR}/public"
chmod 700 "${BLOG_DEPLOY_KEY_DIR}"
log_ok "Blog deploy paths are ready."
}
ensure_blog_deploy_keypair() {
ensure_blog_deploy_user
ensure_blog_deploy_paths
if [ -f "${BLOG_DEPLOY_PRIVATE_KEY}" ] && [ -f "${BLOG_DEPLOY_PUBLIC_KEY}" ]; then
log_ok "Blog deploy keypair already exists."
else
log_step "Generating blog deploy SSH keypair..."
ssh-keygen -q -t ed25519 -C "blog-deploy@$(hostname)" -f "${BLOG_DEPLOY_PRIVATE_KEY}" -N ""
chmod 600 "${BLOG_DEPLOY_PRIVATE_KEY}"
chmod 644 "${BLOG_DEPLOY_PUBLIC_KEY}"
log_ok "Blog deploy keypair generated."
fi
install -d -m 700 -o "${BLOG_DEPLOY_USER}" -g "${BLOG_DEPLOY_USER}" "/home/${BLOG_DEPLOY_USER}/.ssh"
touch "/home/${BLOG_DEPLOY_USER}/.ssh/authorized_keys"
grep -qxF "$(cat "${BLOG_DEPLOY_PUBLIC_KEY}")" "/home/${BLOG_DEPLOY_USER}/.ssh/authorized_keys" 2>/dev/null \
|| cat "${BLOG_DEPLOY_PUBLIC_KEY}" >> "/home/${BLOG_DEPLOY_USER}/.ssh/authorized_keys"
chown "${BLOG_DEPLOY_USER}:${BLOG_DEPLOY_USER}" "/home/${BLOG_DEPLOY_USER}/.ssh/authorized_keys"
chmod 600 "/home/${BLOG_DEPLOY_USER}/.ssh/authorized_keys"
log_ok "Blog deploy public key installed for ${BLOG_DEPLOY_USER}."
}
get_ssh_port() {
local ssh_port
ssh_port=$(sshd -T 2>/dev/null | awk '/^port / {print $2; exit}')
echo "${ssh_port:-22}"
}
show_blog_deploy_info() {
require_root
if [ ! -d "$BLOG_INSTALL_DIR" ]; then
log_err "Blog is not installed. Install it first."
return
fi
ensure_blog_deploy_keypair
local deploy_host ssh_port
deploy_host=$(detect_public_ip)
ssh_port=$(get_ssh_port)
separator
echo -e "${BOLD} Blog Deploy Information${NC}"
separator
echo -e " ${CYAN}BLOG_DEPLOY_HOST${NC} : ${BOLD}${deploy_host:-YOUR_SERVER_HOST}${NC}"
echo -e " ${CYAN}BLOG_DEPLOY_PORT${NC} : ${BOLD}${ssh_port}${NC}"
echo -e " ${CYAN}BLOG_DEPLOY_USER${NC} : ${BOLD}${BLOG_DEPLOY_USER}${NC}"
echo -e " ${CYAN}BLOG_DEPLOY_PATH${NC} : ${BOLD}${BLOG_INSTALL_DIR}${NC}"
echo ""
echo -e "${BOLD} BLOG_DEPLOY_KEY${NC}"
cat "${BLOG_DEPLOY_PRIVATE_KEY}"
echo ""
echo -e "${BOLD} Server Public Key Installed In authorized_keys${NC}"
cat "${BLOG_DEPLOY_PUBLIC_KEY}"
echo ""
echo -e " Add the private key above to your Forgejo repo secret ${BOLD}BLOG_DEPLOY_KEY${NC}."
separator
}
# -----------------------------------------------------------
# 2. Install Gateway
# -----------------------------------------------------------
@ -598,6 +682,7 @@ do_blog_install() {
echo ""
ensure_docker_network
ensure_blog_deploy_keypair
log_step "Creating ${BLOG_INSTALL_DIR}..."
mkdir -p "${BLOG_INSTALL_DIR}/public"
@ -680,9 +765,10 @@ YAML
separator
echo -e " ${CYAN}Container${NC} : ${BOLD}${BLOG_CONTAINER_NAME}${NC}"
echo -e " ${CYAN}Content Dir${NC}: ${BOLD}${BLOG_INSTALL_DIR}/public${NC}"
echo -e " ${CYAN}Deploy User${NC}: ${BOLD}${BLOG_DEPLOY_USER}${NC}"
echo ""
echo -e " ${BOLD}Next steps${NC}"
echo -e " 1. Deploy your Hugo build output to ${BLOG_INSTALL_DIR}/public"
echo -e " 1. Run ${BOLD}$0 blog-deploy-info${NC} to get the Forgejo deploy secrets"
echo -e " 2. In Nginx Proxy Manager create a Proxy Host:"
echo -e " Domain Names : ${CYAN}blog.yourdomain.com${NC}"
echo -e " Scheme : ${CYAN}http${NC}"
@ -736,6 +822,7 @@ do_blog_update() {
install_deps
ensure_docker_network
ensure_blog_deploy_keypair
local dc
dc=$(get_compose_cmd)
@ -762,16 +849,18 @@ show_blog_menu() {
separator
echo " 1) Install Blog"
echo " 2) Update Blog"
echo " 3) Uninstall Blog"
echo " 4) Back"
echo " 3) Show Deploy Info"
echo " 4) Uninstall Blog"
echo " 5) Back"
separator
read -rp " Select [1-4]: " choice
read -rp " Select [1-5]: " choice
echo ""
case "$choice" in
1) do_blog_install ;;
2) do_blog_update ;;
3) do_blog_uninstall ;;
4) return ;;
3) show_blog_deploy_info ;;
4) do_blog_uninstall ;;
5) return ;;
*) log_err "Invalid option." ;;
esac
done
@ -1371,6 +1460,7 @@ show_help() {
echo " blog Open Blog submenu (install/update/uninstall)"
echo " blog-install Install lightweight static blog hosting for Hugo"
echo " blog-update Update lightweight static blog hosting"
echo " blog-deploy-info Show the Blog deploy user and Forgejo secret values"
echo " blog-uninstall Remove lightweight static blog hosting"
echo " forgejo Open Forgejo submenu (install/uninstall/update)"
echo " runner-update Update Forgejo Runner while keeping its configuration"
@ -1400,6 +1490,7 @@ else
blog) show_blog_menu ;;
blog-install) do_blog_install ;;
blog-update) do_blog_update ;;
blog-deploy-info) show_blog_deploy_info ;;
blog-uninstall) do_blog_uninstall ;;
forgejo) show_forgejo_menu ;;
runner-update) do_forgejo_runner_update ;;