Files
gitlab-instance-0a899031_salon/scripts/deploy-neko-google-chrome-2.sh
2026-03-23 02:13:39 -05:00

206 lines
6.2 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
require_cmd() {
if ! command -v "$1" >/dev/null 2>&1; then
echo "missing required command: $1" >&2
exit 1
fi
}
require_cmd docker
require_cmd getent
require_cmd ip
require_cmd awk
require_cmd sudo
ufw_udp_range() {
echo "${1//-/:}/udp"
}
if [[ "${EUID}" -ne 0 ]]; then
sudo -v
fi
if [[ "$(id -u)" -eq 0 && -n "${SUDO_USER:-}" ]]; then
DEFAULT_HOME="$(getent passwd "$SUDO_USER" | awk -F: '{print $6}')"
else
DEFAULT_HOME="$HOME"
fi
HOME_DIR="${HOME_DIR:-$DEFAULT_HOME}"
LAN_IP="${LAN_IP:-$(ip route get 1 | awk '{print $7; exit}')}"
NEKO_USER_PASSWORD="${NEKO_USER_PASSWORD:-user123}"
NEKO_ADMIN_PASSWORD="${NEKO_ADMIN_PASSWORD:-admin123}"
PROFILE_UID="${PROFILE_UID:-1000}"
PROFILE_GID="${PROFILE_GID:-1000}"
GOOGLE_CHROME_DIR="${GOOGLE_CHROME_DIR:-$HOME_DIR/neko-google-chrome-2}"
GOOGLE_CHROME_PROFILE_DIR="${GOOGLE_CHROME_PROFILE_DIR:-/root/neko-google-chrome-2-profile}"
GOOGLE_CHROME_HTTP_PORT="${GOOGLE_CHROME_HTTP_PORT:-8082}"
GOOGLE_CHROME_UDP_RANGE="${GOOGLE_CHROME_UDP_RANGE:-56400-56500}"
GOOGLE_CHROME_DISPLAY="${GOOGLE_CHROME_DISPLAY:-:101.0}"
mkdir -p "$GOOGLE_CHROME_DIR/policies"
sudo mkdir -p "$GOOGLE_CHROME_PROFILE_DIR"
sudo chown -R "${PROFILE_UID}:${PROFILE_GID}" "$GOOGLE_CHROME_PROFILE_DIR"
cat >"$GOOGLE_CHROME_DIR/docker-compose.yaml" <<EOF
services:
neko-google-chrome-2:
image: ghcr.io/m1k1o/neko/google-chrome:latest
restart: unless-stopped
network_mode: host
shm_size: "8gb"
cap_add:
- SYS_ADMIN
environment:
DISPLAY: "${GOOGLE_CHROME_DISPLAY}"
NEKO_DESKTOP_SCREEN: "1920x1080@60"
NEKO_SERVER_BIND: ":${GOOGLE_CHROME_HTTP_PORT}"
NEKO_MEMBER_PROVIDER: "multiuser"
NEKO_MEMBER_MULTIUSER_USER_PASSWORD: "${NEKO_USER_PASSWORD}"
NEKO_MEMBER_MULTIUSER_ADMIN_PASSWORD: "${NEKO_ADMIN_PASSWORD}"
NEKO_WEBRTC_EPR: "${GOOGLE_CHROME_UDP_RANGE}"
NEKO_WEBRTC_ICELITE: "1"
NEKO_WEBRTC_NAT1TO1: "${LAN_IP}"
NEKO_PLUGINS_ENABLED: "true"
NEKO_PLUGINS_DIR: "/etc/neko/plugins/"
volumes:
- ${GOOGLE_CHROME_PROFILE_DIR}:/home/neko/.config/google-chrome
- ${GOOGLE_CHROME_DIR}/policies:/etc/opt/chrome/policies/managed:ro
- ${GOOGLE_CHROME_DIR}/google-chrome.conf:/etc/neko/supervisord/google-chrome.conf:ro
EOF
cat >"$GOOGLE_CHROME_DIR/google-chrome.conf" <<'EOF'
[program:google-chrome]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/usr/bin/google-chrome
--window-position=0,0
--display=%(ENV_DISPLAY)s
--user-data-dir=/home/neko/.config/google-chrome
--password-store=basic
--no-first-run
--start-maximized
--force-dark-mode
--disable-file-system
--disable-gpu
--disable-software-rasterizer
--disable-dev-shm-usage
--disable-background-timer-throttling
--disable-backgrounding-occluded-windows
--disable-renderer-backgrounding
stopsignal=INT
autorestart=true
priority=800
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/google-chrome.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
[program:openbox]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/usr/bin/openbox --config-file /etc/neko/openbox.xml
autorestart=true
priority=300
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/openbox.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
EOF
cat >"$GOOGLE_CHROME_DIR/policies/policies.json" <<'EOF'
{
"ExtensionInstallForcelist": [
"dhdgffkkebhmkfjojejmpbldmpobfkfo;https://clients2.google.com/service/update2/crx"
],
"ExtensionInstallAllowlist": [
"*"
],
"ExtensionInstallBlocklist": [],
"DownloadRestrictions": 0,
"AllowFileSelectionDialogs": true,
"URLAllowlist": ["file:///home/neko/Downloads/*"],
"DefaultCookiesSetting": 1,
"RestoreOnStartup": 1
}
EOF
sudo ufw allow "${GOOGLE_CHROME_HTTP_PORT}" >/dev/null 2>&1 || true
sudo ufw allow "$(ufw_udp_range "${GOOGLE_CHROME_UDP_RANGE}")" >/dev/null 2>&1 || true
recreate_compose_service() {
local compose_dir="$1"
local service="$2"
local name_pattern="$3"
local existing_id=""
local pid=""
existing_id="$(cd "$compose_dir" && docker compose ps -q "$service" 2>/dev/null || true)"
if [[ -n "$existing_id" ]]; then
docker update --restart=no "$existing_id" >/dev/null 2>&1 || true
pid="$(docker inspect -f '{{.State.Pid}}' "$existing_id" 2>/dev/null || true)"
if [[ -n "$pid" && "$pid" != "0" ]]; then
sudo kill -TERM "$pid" >/dev/null 2>&1 || true
sleep 3
sudo kill -KILL "$pid" >/dev/null 2>&1 || true
sleep 2
fi
docker rm -f "$existing_id" >/dev/null 2>&1 || true
fi
docker ps -a --format '{{.ID}} {{.Names}}' \
| awk -v pat="$name_pattern" '$2 ~ pat {print $1}' \
| xargs -r docker rm -f >/dev/null 2>&1 || true
(cd "$compose_dir" && docker compose up -d)
}
wait_for_healthy() {
local compose_dir="$1"
local service="$2"
local container_id=""
local health_status=""
local state_status=""
for _ in $(seq 1 60); do
container_id="$(cd "$compose_dir" && docker compose ps -q "$service" 2>/dev/null || true)"
[[ -z "$container_id" ]] && sleep 2 && continue
health_status="$(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' "$container_id" 2>/dev/null || true)"
state_status="$(docker inspect -f '{{.State.Status}}' "$container_id" 2>/dev/null || true)"
if [[ "$state_status" == "running" && ( "$health_status" == "healthy" || "$health_status" == "none" ) ]]; then
echo "$container_id"
return 0
fi
if [[ "$health_status" == "unhealthy" ]]; then
echo "service ${service} became unhealthy" >&2
docker logs --tail 200 "$container_id" >&2 || true
return 1
fi
sleep 2
done
echo "timed out waiting for ${service}" >&2
[[ -n "$container_id" ]] && docker logs --tail 200 "$container_id" >&2 || true
return 1
}
recreate_compose_service "$GOOGLE_CHROME_DIR" "neko-google-chrome-2" "neko-google-chrome-2"
GOOGLE_CHROME_ID="$(wait_for_healthy "$GOOGLE_CHROME_DIR" "neko-google-chrome-2")"
echo
echo "google-chrome-2:"
echo " url: http://${LAN_IP}:${GOOGLE_CHROME_HTTP_PORT}/"
echo " container: ${GOOGLE_CHROME_ID}"
echo " compose: ${GOOGLE_CHROME_DIR}"