Refactor installer menus and update project paths
All checks were successful
Docker Cloud Build / Build & Publish Image (push) Successful in 1m7s

This commit is contained in:
xtcnet 2026-03-19 12:56:05 +07:00
parent 14c4e1ee5c
commit fd7398be9f
4 changed files with 508 additions and 74 deletions

View file

@ -10,7 +10,7 @@ WireGuard management module and some project-specific admin features.
Canonical repository:
- `https://src.d3v.ac/xtcnet/D3V-Server`
- `https://src.d3v.ac/d3v/D3V-Server`
Treat that repository as the source of truth for this project.
If another upstream is mentioned, assume it is a historical ancestor or reference,

View file

@ -1,10 +1,10 @@
# D3V-NPMWG — xGat3 + WireGuard VPN
# D3V Gateway — Reverse Proxy + WireGuard VPN
A powerful, all-in-one Docker container that combines **xGat3** (reverse proxy with SSL) and **WireGuard VPN** management in a single web interface.
A lightweight all-in-one Docker deployment that combines reverse proxy management with SSL and **WireGuard VPN** in a single web interface.
## Features
### xGat3
### Gateway
- Reverse proxy management with SSL (Let's Encrypt)
- Proxy hosts, redirection hosts, streams, and 404 hosts
- Access control lists and audit logging
@ -29,24 +29,30 @@ A powerful, all-in-one Docker container that combines **xGat3** (reverse proxy w
## Quick Start
```bash
curl -sSL https://src.d3v.ac/xtcnet/D3V-Server/raw/branch/master/install.sh -o install.sh
curl -sSL https://src.d3v.ac/d3v/D3V-Server/raw/branch/master/install.sh -o install.sh
chmod +x install.sh
sudo ./install.sh
```
**Menu options:**
- `1` Install D3V-NPMWG
- `2` Uninstall D3V-NPMWG
- `3` Uninstall D3V-NPMWG + Docker (Purge)
**Main menu:**
- `1` Gateway
- `2` Blog
- `3` Forgejo
- `4` Status / Logs / Health Check
- `5` Exit
**Gateway submenu:**
- `1` Install Gateway
- `2` Uninstall Gateway
- `3` Uninstall Gateway + Docker (Purge)
- `4` Reset Admin Password
- `5` Update D3V-NPMWG
- `5` Update Gateway
- `6` Manage Custom Stream Ports
- `7` Toggle Admin Port 81 (Block/Unblock)
- `8` Forgejo → Install / Uninstall / Update / Install Runner / Uninstall Runner
You can also run commands directly:
```bash
sudo ./install.sh {install|uninstall|purge|reset|update|manage-ports|toggle-port|forgejo}
sudo ./install.sh {gateway|gateway-install|gateway-uninstall|gateway-purge|gateway-reset|gateway-update|manage-ports|toggle-port|blog|blog-install|blog-update|blog-uninstall|forgejo|runner-update|ops}
```
---
@ -56,7 +62,7 @@ sudo ./install.sh {install|uninstall|purge|reset|update|manage-ports|toggle-port
```yaml
services:
d3v-npmwg:
image: src.d3v.ac/xtcnet/d3v-server:latest
image: src.d3v.ac/d3v/d3v-server:latest
container_name: d3v-npmwg
restart: unless-stopped
cap_add:
@ -107,16 +113,16 @@ services:
## Building from Source
```bash
git clone https://src.d3v.ac/xtcnet/D3V-Server.git
git clone https://src.d3v.ac/d3v/D3V-Server.git
cd D3V-Server
cd frontend && yarn install && yarn locale-compile && yarn build && cd ..
docker build -t d3v-npmwg -f docker/Dockerfile .
docker build -t d3v-gateway -f docker/Dockerfile .
```
### CI/CD
Pushes to `master` that touch `backend/`, `frontend/`, or `docker/` automatically build and push the Docker image to `src.d3v.ac/xtcnet/d3v-server:latest` via Forgejo Actions.
Pushes to `master` that touch `backend/`, `frontend/`, or `docker/` automatically build and push the Docker image to `src.d3v.ac/d3v/d3v-server:latest` via Forgejo Actions.
---
@ -129,7 +135,7 @@ Pushes to `master` that touch `backend/`, `frontend/`, or `docker/` automaticall
## Credits
- [xGat3](https://github.com/NginxProxyManager/nginx-proxy-manager) — Original proxy manager
- [Nginx Proxy Manager](https://github.com/NginxProxyManager/nginx-proxy-manager) — Original proxy manager
- [wg-easy](https://github.com/wg-easy/wg-easy) — WireGuard management inspiration
## License

View file

@ -76,7 +76,7 @@ ENTRYPOINT [ "/init" ]
LABEL org.label-schema.schema-version="1.0" \
org.label-schema.license="MIT" \
org.label-schema.name="d3v-npmwg" \
org.label-schema.description="xGat3 : xGat3 + WireGuard VPN Manager" \
org.label-schema.url="https://github.com/xtcnet/D3V-NPMWG" \
org.label-schema.cmd="docker run --rm -ti --cap-add=NET_ADMIN --cap-add=SYS_MODULE d3v-npmwg:latest"
org.label-schema.name="d3v-gateway" \
org.label-schema.description="D3V Gateway: Reverse Proxy + WireGuard VPN Manager" \
org.label-schema.url="https://src.d3v.ac/d3v/D3V-Server" \
org.label-schema.cmd="docker run --rm -ti --cap-add=NET_ADMIN --cap-add=SYS_MODULE src.d3v.ac/d3v/d3v-server:latest"

View file

@ -2,15 +2,20 @@
set -e
# ============================================================
# D3V-NPMWG Installer for Ubuntu/Debian
# xGat3 + WireGuard VPN
# https://src.d3v.ac/xtcnet/D3V-Server
# D3V Gateway Installer for Ubuntu/Debian
# Reverse Proxy + WireGuard VPN
# https://src.d3v.ac/d3v/D3V-Server
# ============================================================
INSTALL_DIR="/opt/d3v-npmwg"
COMPOSE_FILE="${INSTALL_DIR}/docker-compose.yml"
CONTAINER_NAME="d3v-npmwg"
IMAGE_NAME="src.d3v.ac/xtcnet/d3v-server:latest"
IMAGE_NAME="src.d3v.ac/d3v/d3v-server:latest"
BLOG_INSTALL_DIR="/opt/blog"
BLOG_COMPOSE_FILE="${BLOG_INSTALL_DIR}/docker-compose.yml"
BLOG_CONTAINER_NAME="d3v-blog"
BLOG_IMAGE="nginx:alpine"
FORGEJO_INSTALL_DIR="/opt/forgejo"
FORGEJO_COMPOSE_FILE="${FORGEJO_INSTALL_DIR}/docker-compose.yml"
@ -39,7 +44,7 @@ log_err() { echo -e "${RED}[✗]${NC} $1"; }
separator() { echo -e "${GREEN}=================================================================${NC}"; }
self_update() {
local remote_url="https://src.d3v.ac/xtcnet/D3V-Server/raw/branch/master/install.sh"
local remote_url="https://src.d3v.ac/d3v/D3V-Server/raw/branch/master/install.sh"
local tmp
tmp=$(mktemp) || return
if curl -fsSL -m 10 "$remote_url" -o "$tmp" 2>/dev/null; then
@ -255,19 +260,19 @@ ensure_docker_network() {
}
# -----------------------------------------------------------
# 2. Install D3V-NPMWG
# 2. Install Gateway
# -----------------------------------------------------------
do_install() {
require_root
if [ -d "$INSTALL_DIR" ]; then
log_warn "D3V-NPMWG is already installed at ${INSTALL_DIR}."
log_warn "Gateway is already installed at ${INSTALL_DIR}."
log_warn "Use the Update option to pull the latest image, or Uninstall first."
return
fi
separator
echo -e "${BOLD} D3V-NPMWG Installation${NC}"
echo -e "${BOLD} Gateway Installation${NC}"
separator
echo ""
@ -338,7 +343,7 @@ do_install() {
if docker ps --format '{{.Names}}' | grep -q "$CONTAINER_NAME"; then
echo ""
separator
echo -e "${GREEN}${BOLD} D3V-NPMWG INSTALLED SUCCESSFULLY!${NC}"
echo -e "${GREEN}${BOLD} GATEWAY INSTALLED SUCCESSFULLY!${NC}"
separator
echo -e " ${CYAN}Web Admin UI${NC} : ${BOLD}http://${wg_host}:81${NC}"
echo -e " ${CYAN}HTTP Proxy${NC} : port 80"
@ -354,17 +359,17 @@ do_install() {
}
# -----------------------------------------------------------
# 3. Uninstall D3V-NPMWG
# 3. Uninstall Gateway
# -----------------------------------------------------------
do_uninstall() {
require_root
if [ ! -d "$INSTALL_DIR" ]; then
log_warn "D3V-NPMWG is not installed at ${INSTALL_DIR}."
log_warn "Gateway is not installed at ${INSTALL_DIR}."
return
fi
log_warn "This will stop and remove D3V-NPMWG and ALL its data."
log_warn "This will stop and remove Gateway and ALL its data."
read -rp "$(echo -e "${RED}Are you sure? (y/N): ${NC}")" confirm
if [[ ! "$confirm" =~ ^[yY]$ ]]; then
echo "Cancelled."
@ -379,7 +384,7 @@ do_uninstall() {
log_step "Removing ${INSTALL_DIR}..."
rm -rf "$INSTALL_DIR"
log_ok "D3V-NPMWG uninstalled."
log_ok "Gateway uninstalled."
}
# -----------------------------------------------------------
@ -448,13 +453,13 @@ do_reset_password() {
}
# -----------------------------------------------------------
# 6. Update D3V-NPMWG
# 6. Update Gateway
# -----------------------------------------------------------
do_update() {
require_root
if [ ! -d "$INSTALL_DIR" ]; then
log_err "D3V-NPMWG is not installed. Install it first."
log_err "Gateway is not installed. Install it first."
return
fi
@ -481,7 +486,7 @@ do_update() {
log_step "Recreating containers..."
$dc up -d
log_ok "D3V-NPMWG updated."
log_ok "Gateway updated."
log_step "Cleaning old images..."
docker image prune -f > /dev/null 2>&1
@ -573,7 +578,207 @@ do_toggle_port_81() {
}
# -----------------------------------------------------------
# Forgejo — Install / Uninstall / Update
# Blog - Install / Uninstall
# -----------------------------------------------------------
do_blog_install() {
require_root
if [ -d "$BLOG_INSTALL_DIR" ]; then
log_warn "Blog is already installed at ${BLOG_INSTALL_DIR}."
log_warn "Uninstall it first if you want to recreate it."
return
fi
separator
echo -e "${BOLD} Hugo Blog Static Host Installation${NC}"
separator
echo ""
install_deps
echo ""
ensure_docker_network
log_step "Creating ${BLOG_INSTALL_DIR}..."
mkdir -p "${BLOG_INSTALL_DIR}/public"
log_ok "Directory created."
if [ ! -f "${BLOG_INSTALL_DIR}/public/index.html" ]; then
log_step "Creating placeholder blog homepage..."
cat > "${BLOG_INSTALL_DIR}/public/index.html" <<HTML
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Blog is ready</title>
<style>
body {
font-family: system-ui, sans-serif;
max-width: 720px;
margin: 60px auto;
padding: 0 20px;
line-height: 1.6;
color: #1f2937;
background: #f9fafb;
}
code {
background: #e5e7eb;
padding: 2px 6px;
border-radius: 4px;
}
</style>
</head>
<body>
<h1>Hugo blog host is installed</h1>
<p>This container is ready to serve your generated Hugo site.</p>
<p>Deploy your blog build output into <code>/opt/blog/public</code>.</p>
<p>Then create a Proxy Host in Nginx Proxy Manager pointing to <code>${BLOG_CONTAINER_NAME}</code> on port <code>80</code>.</p>
</body>
</html>
HTML
log_ok "Placeholder page created."
fi
log_step "Generating blog docker-compose.yml..."
cat > "$BLOG_COMPOSE_FILE" <<YAML
services:
blog:
image: ${BLOG_IMAGE}
container_name: ${BLOG_CONTAINER_NAME}
restart: unless-stopped
volumes:
- ./public:/usr/share/nginx/html:ro
networks:
- d3v-net
networks:
d3v-net:
external: true
name: ${DOCKER_NETWORK}
YAML
log_ok "docker-compose.yml created."
local dc
dc=$(get_compose_cmd)
cd "$BLOG_INSTALL_DIR"
log_step "Pulling blog image..."
$dc pull
log_ok "Image pulled."
log_step "Starting blog container..."
$dc up -d
log_ok "Blog container started."
sleep 3
if docker ps --format '{{.Names}}' | grep -q "^${BLOG_CONTAINER_NAME}$"; then
echo ""
separator
echo -e "${GREEN}${BOLD} BLOG INSTALLED SUCCESSFULLY!${NC}"
separator
echo -e " ${CYAN}Container${NC} : ${BOLD}${BLOG_CONTAINER_NAME}${NC}"
echo -e " ${CYAN}Content Dir${NC}: ${BOLD}${BLOG_INSTALL_DIR}/public${NC}"
echo ""
echo -e " ${BOLD}Next steps${NC}"
echo -e " 1. Deploy your Hugo build output to ${BLOG_INSTALL_DIR}/public"
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}"
echo -e " Forward Hostname : ${CYAN}${BLOG_CONTAINER_NAME}${NC}"
echo -e " Forward Port : ${CYAN}80${NC}"
echo -e " 3. Request an SSL certificate and enable Force SSL"
separator
else
log_err "Blog container did not start. Check logs:"
echo -e " docker logs ${BLOG_CONTAINER_NAME}"
fi
}
do_blog_uninstall() {
require_root
if [ ! -d "$BLOG_INSTALL_DIR" ]; then
log_warn "Blog is not installed at ${BLOG_INSTALL_DIR}."
return
fi
log_warn "This will stop and remove the static blog host and ALL deployed blog files."
read -rp "$(echo -e "${RED}Are you sure? (y/N): ${NC}")" confirm
if [[ ! "$confirm" =~ ^[yY]$ ]]; then
echo "Cancelled."
return
fi
local dc
dc=$(get_compose_cmd)
cd "$BLOG_INSTALL_DIR" && $dc down -v 2>/dev/null || true
cd /
log_step "Removing ${BLOG_INSTALL_DIR}..."
rm -rf "$BLOG_INSTALL_DIR"
log_ok "Blog uninstalled."
}
do_blog_update() {
require_root
if [ ! -d "$BLOG_INSTALL_DIR" ]; then
log_err "Blog is not installed. Install it first."
return
fi
separator
echo -e "${BOLD} Hugo Blog Static Host Update${NC}"
separator
echo ""
install_deps
ensure_docker_network
local dc
dc=$(get_compose_cmd)
cd "$BLOG_INSTALL_DIR" || return
log_step "Pulling latest blog image..."
$dc pull
log_ok "Image pulled."
log_step "Recreating blog container..."
$dc up -d
log_ok "Blog updated."
log_step "Cleaning old images..."
docker image prune -f > /dev/null 2>&1
log_ok "Done."
}
show_blog_menu() {
while true; do
echo ""
separator
echo -e "${BOLD} Blog Manager${NC}"
separator
echo " 1) Install Blog"
echo " 2) Update Blog"
echo " 3) Uninstall Blog"
echo " 4) Back"
separator
read -rp " Select [1-4]: " choice
echo ""
case "$choice" in
1) do_blog_install ;;
2) do_blog_update ;;
3) do_blog_uninstall ;;
4) return ;;
*) log_err "Invalid option." ;;
esac
done
}
# -----------------------------------------------------------
# Forgejo - Install / Uninstall / Update
# -----------------------------------------------------------
do_forgejo_install() {
require_root
@ -594,17 +799,17 @@ do_forgejo_install() {
ensure_docker_network
# Ensure D3V-NPMWG is on d3v-net (runtime + persistent in compose)
# Ensure Gateway is on d3v-net (runtime + persistent in compose)
if [ -f "$COMPOSE_FILE" ]; then
if ! grep -q "d3v-net" "$COMPOSE_FILE"; then
log_step "Updating D3V-NPMWG compose to join '${DOCKER_NETWORK}'..."
log_step "Updating Gateway compose to join '${DOCKER_NETWORK}'..."
local current_wg_host=""
current_wg_host=$(grep -E 'WG_HOST:' "$COMPOSE_FILE" | awk -F'"' '{print $2}')
[ -z "$current_wg_host" ] && current_wg_host=$(detect_public_ip)
cd "$INSTALL_DIR"
generate_docker_compose "$current_wg_host"
$(get_compose_cmd) up -d --no-recreate 2>/dev/null || true
log_ok "D3V-NPMWG compose updated."
log_ok "Gateway compose updated."
fi
# Connect running container immediately (no restart needed)
if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
@ -858,6 +1063,60 @@ do_forgejo_runner_install() {
separator
}
do_forgejo_runner_update() {
require_root
if ! docker ps -a --format '{{.Names}}' | grep -q "^${FORGEJO_RUNNER_CONTAINER}$"; then
log_err "Forgejo Runner is not installed."
return
fi
log_step "Reading current Forgejo Runner configuration..."
local runner_env
runner_env=$(docker inspect -f '{{range .Config.Env}}{{println .}}{{end}}' "${FORGEJO_RUNNER_CONTAINER}" 2>/dev/null || true)
local forgejo_url
local runner_token
local runner_name
local runner_labels
forgejo_url=$(echo "$runner_env" | grep '^GITEA_INSTANCE_URL=' | head -n1 | cut -d= -f2-)
runner_token=$(echo "$runner_env" | grep '^GITEA_RUNNER_REGISTRATION_TOKEN=' | head -n1 | cut -d= -f2-)
runner_name=$(echo "$runner_env" | grep '^GITEA_RUNNER_NAME=' | head -n1 | cut -d= -f2-)
runner_labels=$(echo "$runner_env" | grep '^GITEA_RUNNER_LABELS=' | head -n1 | cut -d= -f2-)
if [ -z "$forgejo_url" ] || [ -z "$runner_token" ]; then
log_err "Could not read the existing Forgejo Runner configuration."
log_err "Uninstall and install the runner again to re-register it."
return
fi
runner_name="${runner_name:-$(hostname)-runner}"
runner_labels="${runner_labels:-ubuntu-latest:docker://catthehacker/ubuntu:act-22.04,ubuntu-22.04:docker://catthehacker/ubuntu:act-22.04}"
log_step "Pulling latest Forgejo Runner image..."
docker pull "${FORGEJO_RUNNER_IMAGE}"
log_ok "Image pulled."
log_step "Recreating Forgejo Runner container..."
docker stop "${FORGEJO_RUNNER_CONTAINER}" 2>/dev/null || true
docker rm "${FORGEJO_RUNNER_CONTAINER}" 2>/dev/null || true
mkdir -p "$FORGEJO_RUNNER_DIR"
docker run -d \
--name "${FORGEJO_RUNNER_CONTAINER}" \
--restart unless-stopped \
-e GITEA_INSTANCE_URL="${forgejo_url}" \
-e GITEA_RUNNER_REGISTRATION_TOKEN="${runner_token}" \
-e GITEA_RUNNER_NAME="${runner_name}" \
-e GITEA_RUNNER_LABELS="${runner_labels}" \
-v /var/run/docker.sock:/var/run/docker.sock \
-v "${FORGEJO_RUNNER_DIR}:/data" \
"${FORGEJO_RUNNER_IMAGE}" > /dev/null
log_ok "Forgejo Runner updated."
}
do_forgejo_runner_uninstall() {
require_root
@ -889,18 +1148,176 @@ show_forgejo_menu() {
echo " 2) Uninstall Forgejo"
echo " 3) Update Forgejo"
echo " 4) Install Runner"
echo " 5) Uninstall Runner"
echo " 6) Back"
echo " 5) Update Runner"
echo " 6) Uninstall Runner"
echo " 7) Back"
separator
read -rp " Select [1-6]: " choice
read -rp " Select [1-7]: " choice
echo ""
case "$choice" in
1) do_forgejo_install ;;
2) do_forgejo_uninstall ;;
3) do_forgejo_update ;;
4) do_forgejo_runner_install ;;
5) do_forgejo_runner_uninstall ;;
6) return ;;
5) do_forgejo_runner_update ;;
6) do_forgejo_runner_uninstall ;;
7) return ;;
*) log_err "Invalid option." ;;
esac
done
}
# -----------------------------------------------------------
# Gateway Manager Menu
# -----------------------------------------------------------
show_gateway_menu() {
while true; do
echo ""
separator
echo -e "${BOLD} Gateway Manager${NC}"
separator
echo " 1) Install Gateway"
echo " 2) Uninstall Gateway"
echo " 3) Uninstall Gateway + Docker (Purge)"
echo " 4) Reset Admin Password"
echo " 5) Update Gateway"
echo " 6) Manage Custom Stream Ports"
echo " 7) Toggle Admin Port 81 (Block/Unblock)"
echo " 8) Back"
separator
read -rp " Select [1-8]: " choice
echo ""
case "$choice" in
1) do_install ;;
2) do_uninstall ;;
3) do_purge ;;
4) do_reset_password ;;
5) do_update ;;
6) do_manage_ports ;;
7) do_toggle_port_81 ;;
8) return ;;
*) log_err "Invalid option." ;;
esac
done
}
# -----------------------------------------------------------
# Status / Logs / Health Check
# -----------------------------------------------------------
show_container_status() {
local label="$1"
local name="$2"
separator
echo -e "${BOLD} ${label} Status${NC}"
separator
if docker ps -a --format '{{.Names}}' | grep -q "^${name}$"; then
docker ps -a --filter "name=^${name}$" --format "table {{.Names}}\t{{.Status}}\t{{.Image}}\t{{.Ports}}"
else
log_warn "${label} container is not installed."
fi
}
show_service_logs() {
local label="$1"
local name="$2"
separator
echo -e "${BOLD} ${label} Logs (last 60 lines)${NC}"
separator
if docker ps -a --format '{{.Names}}' | grep -q "^${name}$"; then
docker logs --tail 60 "$name" 2>&1 || true
else
log_warn "${label} container is not installed."
fi
}
run_health_checks() {
separator
echo -e "${BOLD} Health Check Summary${NC}"
separator
log_step "Docker daemon"
if docker info > /dev/null 2>&1; then
log_ok "Docker daemon is running."
else
log_err "Docker daemon is not reachable."
fi
log_step "Shared Docker network (${DOCKER_NETWORK})"
if docker network ls --format '{{.Name}}' | grep -q "^${DOCKER_NETWORK}$"; then
log_ok "Network ${DOCKER_NETWORK} exists."
else
log_warn "Network ${DOCKER_NETWORK} does not exist."
fi
log_step "Gateway container"
if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
log_ok "Gateway is running."
elif docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
log_warn "Gateway exists but is not running."
else
log_warn "Gateway is not installed."
fi
log_step "Blog container"
if docker ps --format '{{.Names}}' | grep -q "^${BLOG_CONTAINER_NAME}$"; then
log_ok "Blog is running."
elif docker ps -a --format '{{.Names}}' | grep -q "^${BLOG_CONTAINER_NAME}$"; then
log_warn "Blog exists but is not running."
else
log_warn "Blog is not installed."
fi
log_step "Forgejo container"
if docker ps --format '{{.Names}}' | grep -q "^${FORGEJO_CONTAINER_NAME}$"; then
log_ok "Forgejo is running."
elif docker ps -a --format '{{.Names}}' | grep -q "^${FORGEJO_CONTAINER_NAME}$"; then
log_warn "Forgejo exists but is not running."
else
log_warn "Forgejo is not installed."
fi
log_step "Forgejo Runner container"
if docker ps --format '{{.Names}}' | grep -q "^${FORGEJO_RUNNER_CONTAINER}$"; then
log_ok "Forgejo Runner is running."
elif docker ps -a --format '{{.Names}}' | grep -q "^${FORGEJO_RUNNER_CONTAINER}$"; then
log_warn "Forgejo Runner exists but is not running."
else
log_warn "Forgejo Runner is not installed."
fi
}
show_operations_menu() {
while true; do
echo ""
separator
echo -e "${BOLD} Status / Logs / Health Check${NC}"
separator
echo " 1) Gateway Status"
echo " 2) Blog Status"
echo " 3) Forgejo Status"
echo " 4) Runner Status"
echo " 5) Gateway Logs"
echo " 6) Blog Logs"
echo " 7) Forgejo Logs"
echo " 8) Runner Logs"
echo " 9) Health Check Summary"
echo " 10) Back"
separator
read -rp " Select [1-10]: " choice
echo ""
case "$choice" in
1) show_container_status "Gateway" "$CONTAINER_NAME" ;;
2) show_container_status "Blog" "$BLOG_CONTAINER_NAME" ;;
3) show_container_status "Forgejo" "$FORGEJO_CONTAINER_NAME" ;;
4) show_container_status "Forgejo Runner" "$FORGEJO_RUNNER_CONTAINER" ;;
5) show_service_logs "Gateway" "$CONTAINER_NAME" ;;
6) show_service_logs "Blog" "$BLOG_CONTAINER_NAME" ;;
7) show_service_logs "Forgejo" "$FORGEJO_CONTAINER_NAME" ;;
8) show_service_logs "Forgejo Runner" "$FORGEJO_RUNNER_CONTAINER" ;;
9) run_health_checks ;;
10) return ;;
*) log_err "Invalid option." ;;
esac
done
@ -913,30 +1330,22 @@ show_menu() {
while true; do
echo ""
separator
echo -e "${BOLD} D3V-NPMWG Installation Manager${NC}"
echo -e "${BOLD} Server Installation Manager${NC}"
separator
echo " 1) Install D3V-NPMWG"
echo " 2) Uninstall D3V-NPMWG"
echo " 3) Uninstall D3V-NPMWG + Docker (Purge)"
echo " 4) Reset Admin Password"
echo " 5) Update D3V-NPMWG"
echo " 6) Manage Custom Stream Ports"
echo " 7) Toggle Admin Port 81 (Block/Unblock)"
echo " 8) Forgejo"
echo " 9) Exit"
echo " 1) Gateway"
echo " 2) Blog"
echo " 3) Forgejo"
echo " 4) Status / Logs / Health Check"
echo " 5) Exit"
separator
read -rp " Select [1-9]: " choice
read -rp " Select [1-5]: " choice
echo ""
case "$choice" in
1) do_install ;;
2) do_uninstall ;;
3) do_purge ;;
4) do_reset_password ;;
5) do_update ;;
6) do_manage_ports ;;
7) do_toggle_port_81 ;;
8) show_forgejo_menu ;;
9) echo "Bye!"; exit 0 ;;
1) show_gateway_menu ;;
2) show_blog_menu ;;
3) show_forgejo_menu ;;
4) show_operations_menu ;;
5) echo "Bye!"; exit 0 ;;
*) log_err "Invalid option." ;;
esac
done
@ -946,14 +1355,26 @@ show_help() {
echo "Usage: $0 [command]"
echo ""
echo "Commands:"
echo " install Install D3V-NPMWG and dependencies"
echo " uninstall Remove D3V-NPMWG (keeps Docker)"
echo " purge Remove D3V-NPMWG AND Docker"
echo " install Install Gateway and dependencies"
echo " uninstall Remove Gateway (keeps Docker)"
echo " purge Remove Gateway AND Docker"
echo " reset Reset web admin password"
echo " update Pull latest image and restart"
echo " manage-ports Add or remove custom exposed Stream TCP/UDP ports"
echo " toggle-port Block or unblock external access to Admin UI (Port 81) using iptables"
echo " gateway Open Gateway submenu"
echo " gateway-install Install Gateway and dependencies"
echo " gateway-uninstall Remove Gateway (keeps Docker)"
echo " gateway-purge Remove Gateway AND Docker"
echo " gateway-reset Reset Gateway admin password"
echo " gateway-update Pull latest Gateway image and restart"
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-uninstall Remove lightweight static blog hosting"
echo " forgejo Open Forgejo submenu (install/uninstall/update)"
echo " runner-update Update Forgejo Runner while keeping its configuration"
echo " ops Open Status / Logs / Health Check submenu"
echo " help Show this help"
echo ""
echo "Run without arguments to open the interactive menu."
@ -968,14 +1389,21 @@ if [ "$#" -eq 0 ]; then
show_menu
else
case "$1" in
install) do_install ;;
uninstall) do_uninstall ;;
purge) do_purge ;;
reset) do_reset_password ;;
update) do_update ;;
install|gateway-install) do_install ;;
uninstall|gateway-uninstall) do_uninstall ;;
purge|gateway-purge) do_purge ;;
reset|gateway-reset) do_reset_password ;;
update|gateway-update) do_update ;;
manage-ports) do_manage_ports ;;
toggle-port) do_toggle_port_81 ;;
gateway) show_gateway_menu ;;
blog) show_blog_menu ;;
blog-install) do_blog_install ;;
blog-update) do_blog_update ;;
blog-uninstall) do_blog_uninstall ;;
forgejo) show_forgejo_menu ;;
runner-update) do_forgejo_runner_update ;;
ops) show_operations_menu ;;
help|-h|--help) show_help ;;
*)
log_err "Unknown command: $1"