Replace Flask web dashboard with textual-serve
Serves the exact same TUI in the browser via textual-serve. No more separate Flask app, API keys, or login page needed. - gniza web start now runs textual-serve instead of Flask - Simplified systemd service to use python3 -m tui --web - Removed web_enabled and web_api_key from settings/models - Simplified install script web setup (no API key generation) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
10
bin/gniza
10
bin/gniza
@@ -402,10 +402,10 @@ if [[ "$SUBCOMMAND" == "web" ]]; then
|
|||||||
_web_port="" _web_host=""
|
_web_port="" _web_host=""
|
||||||
_web_port=$(_parse_flag "--port" "${SUBCMD_ARGS[@]+"${SUBCMD_ARGS[@]}"}") || true
|
_web_port=$(_parse_flag "--port" "${SUBCMD_ARGS[@]+"${SUBCMD_ARGS[@]}"}") || true
|
||||||
_web_host=$(_parse_flag "--host" "${SUBCMD_ARGS[@]+"${SUBCMD_ARGS[@]}"}") || true
|
_web_host=$(_parse_flag "--host" "${SUBCMD_ARGS[@]+"${SUBCMD_ARGS[@]}"}") || true
|
||||||
_web_args=()
|
_web_args=(--web)
|
||||||
[[ -n "$_web_port" ]] && _web_args+=(--port="$_web_port")
|
[[ -n "$_web_port" ]] && _web_args+=(--port "$_web_port")
|
||||||
[[ -n "$_web_host" ]] && _web_args+=(--host="$_web_host")
|
[[ -n "$_web_host" ]] && _web_args+=(--host "$_web_host")
|
||||||
PYTHONPATH="$GNIZA_DIR:${PYTHONPATH:-}" exec python3 -m web "${_web_args[@]}"
|
PYTHONPATH="$GNIZA_DIR:${PYTHONPATH:-}" exec python3 -m tui "${_web_args[@]}"
|
||||||
;;
|
;;
|
||||||
install-service)
|
install-service)
|
||||||
_service_src="$GNIZA_DIR/etc/gniza-web.service"
|
_service_src="$GNIZA_DIR/etc/gniza-web.service"
|
||||||
@@ -416,7 +416,7 @@ if [[ "$SUBCOMMAND" == "web" ]]; then
|
|||||||
cp "$_service_src" "$_service_dst"
|
cp "$_service_src" "$_service_dst"
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable gniza-web
|
systemctl enable gniza-web
|
||||||
systemctl start gniza-web
|
systemctl restart gniza-web
|
||||||
echo "GNIZA web service installed and started."
|
echo "GNIZA web service installed and started."
|
||||||
echo "Access the dashboard at http://$(hostname -I | awk '{print $1}'):8080"
|
echo "Access the dashboard at http://$(hostname -I | awk '{print $1}'):8080"
|
||||||
;;
|
;;
|
||||||
|
|||||||
@@ -4,11 +4,9 @@ After=network.target
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
ExecStart=/usr/bin/python3 -m web
|
ExecStart=/usr/bin/python3 -m tui --web --host 0.0.0.0 --port 8080
|
||||||
WorkingDirectory=/usr/local/gniza
|
WorkingDirectory=/usr/local/gniza
|
||||||
Environment=GNIZA_DIR=/usr/local/gniza
|
Environment=GNIZA_DIR=/usr/local/gniza
|
||||||
Environment=GNIZA_CONFIG_DIR=/etc/gniza
|
|
||||||
Environment=LOG_DIR=/var/log/gniza
|
|
||||||
Environment=PYTHONPATH=/usr/local/gniza
|
Environment=PYTHONPATH=/usr/local/gniza
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
|
|||||||
@@ -160,36 +160,14 @@ for example in target.conf.example remote.conf.example schedule.conf.example; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
# -- Web dashboard setup --
|
# -- Web dashboard setup --
|
||||||
setup_web_dashboard() {
|
enable_web="n"
|
||||||
local conf="$CONFIG_DIR/gniza.conf"
|
read -rp "Enable web dashboard (TUI in browser)? (y/n) [n]: " enable_web </dev/tty || true
|
||||||
# Update config: WEB_ENABLED
|
if [ "$enable_web" = "y" ] || [ "$enable_web" = "Y" ]; then
|
||||||
if grep -q "^WEB_ENABLED=" "$conf" 2>/dev/null; then
|
|
||||||
sed -i 's|^WEB_ENABLED=.*|WEB_ENABLED="yes"|' "$conf"
|
|
||||||
else
|
|
||||||
echo 'WEB_ENABLED="yes"' >> "$conf"
|
|
||||||
fi
|
|
||||||
# Generate random API key
|
|
||||||
local api_key
|
|
||||||
api_key="$(python3 -c 'import secrets; print(secrets.token_urlsafe(32))')"
|
|
||||||
if grep -q "^WEB_API_KEY=" "$conf" 2>/dev/null; then
|
|
||||||
sed -i "s|^WEB_API_KEY=.*|WEB_API_KEY=\"${api_key}\"|" "$conf"
|
|
||||||
else
|
|
||||||
echo "WEB_API_KEY=\"${api_key}\"" >> "$conf"
|
|
||||||
fi
|
|
||||||
info "Web API key: $api_key"
|
|
||||||
echo "Save this key -- you will need it to log into the dashboard."
|
|
||||||
# Install systemd service (root only)
|
|
||||||
if [ "$MODE" = "root" ]; then
|
if [ "$MODE" = "root" ]; then
|
||||||
"$INSTALL_DIR/bin/gniza" web install-service || warn "Failed to install web service"
|
"$INSTALL_DIR/bin/gniza" web install-service || warn "Failed to install web service"
|
||||||
else
|
else
|
||||||
warn "Systemd service installation requires root. Start manually: gniza web start"
|
warn "Systemd service installation requires root. Start manually: gniza web start"
|
||||||
fi
|
fi
|
||||||
}
|
|
||||||
|
|
||||||
enable_web="n"
|
|
||||||
read -rp "Enable web dashboard? (y/n) [n]: " enable_web </dev/tty || true
|
|
||||||
if [ "$enable_web" = "y" ] || [ "$enable_web" = "Y" ]; then
|
|
||||||
setup_web_dashboard
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# -- Done -----------------------------------------------------
|
# -- Done -----------------------------------------------------
|
||||||
|
|||||||
@@ -203,10 +203,8 @@ class AppSettings:
|
|||||||
ssh_retries: str = "3"
|
ssh_retries: str = "3"
|
||||||
rsync_extra_opts: str = ""
|
rsync_extra_opts: str = ""
|
||||||
work_dir: str = "/usr/local/gniza/workdir"
|
work_dir: str = "/usr/local/gniza/workdir"
|
||||||
web_enabled: str = "no"
|
|
||||||
web_port: str = "8080"
|
web_port: str = "8080"
|
||||||
web_host: str = "0.0.0.0"
|
web_host: str = "0.0.0.0"
|
||||||
web_api_key: str = ""
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_conf(cls, data: dict[str, str]) -> "AppSettings":
|
def from_conf(cls, data: dict[str, str]) -> "AppSettings":
|
||||||
@@ -228,10 +226,8 @@ class AppSettings:
|
|||||||
ssh_retries=data.get("SSH_RETRIES", "3"),
|
ssh_retries=data.get("SSH_RETRIES", "3"),
|
||||||
rsync_extra_opts=data.get("RSYNC_EXTRA_OPTS", ""),
|
rsync_extra_opts=data.get("RSYNC_EXTRA_OPTS", ""),
|
||||||
work_dir=data.get("WORK_DIR", "/usr/local/gniza/workdir"),
|
work_dir=data.get("WORK_DIR", "/usr/local/gniza/workdir"),
|
||||||
web_enabled=data.get("WEB_ENABLED", "no"),
|
|
||||||
web_port=data.get("WEB_PORT", "8080"),
|
web_port=data.get("WEB_PORT", "8080"),
|
||||||
web_host=data.get("WEB_HOST", "0.0.0.0"),
|
web_host=data.get("WEB_HOST", "0.0.0.0"),
|
||||||
web_api_key=data.get("WEB_API_KEY", ""),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def to_conf(self) -> dict[str, str]:
|
def to_conf(self) -> dict[str, str]:
|
||||||
@@ -253,8 +249,6 @@ class AppSettings:
|
|||||||
"SSH_RETRIES": self.ssh_retries,
|
"SSH_RETRIES": self.ssh_retries,
|
||||||
"RSYNC_EXTRA_OPTS": self.rsync_extra_opts,
|
"RSYNC_EXTRA_OPTS": self.rsync_extra_opts,
|
||||||
"WORK_DIR": self.work_dir,
|
"WORK_DIR": self.work_dir,
|
||||||
"WEB_ENABLED": self.web_enabled,
|
|
||||||
"WEB_PORT": self.web_port,
|
"WEB_PORT": self.web_port,
|
||||||
"WEB_HOST": self.web_host,
|
"WEB_HOST": self.web_host,
|
||||||
"WEB_API_KEY": self.web_api_key,
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,18 +62,10 @@ class SettingsScreen(Screen):
|
|||||||
yield Static("Work Directory:")
|
yield Static("Work Directory:")
|
||||||
yield Input(value=settings.work_dir, placeholder="/usr/local/gniza/workdir", id="set-workdir")
|
yield Input(value=settings.work_dir, placeholder="/usr/local/gniza/workdir", id="set-workdir")
|
||||||
yield Static("Web Dashboard", classes="section-label")
|
yield Static("Web Dashboard", classes="section-label")
|
||||||
yield Static("Enabled:")
|
|
||||||
yield Select(
|
|
||||||
[("Yes", "yes"), ("No", "no")],
|
|
||||||
id="set-web-enabled",
|
|
||||||
value=settings.web_enabled,
|
|
||||||
)
|
|
||||||
yield Static("Port:")
|
yield Static("Port:")
|
||||||
yield Input(value=settings.web_port, id="set-web-port")
|
yield Input(value=settings.web_port, id="set-web-port")
|
||||||
yield Static("Host:")
|
yield Static("Host:")
|
||||||
yield Input(value=settings.web_host, id="set-web-host")
|
yield Input(value=settings.web_host, id="set-web-host")
|
||||||
yield Static("API Key:")
|
|
||||||
yield Input(value=settings.web_api_key, password=True, id="set-web-key")
|
|
||||||
with Horizontal(id="set-buttons"):
|
with Horizontal(id="set-buttons"):
|
||||||
yield Button("Save", variant="primary", id="btn-save")
|
yield Button("Save", variant="primary", id="btn-save")
|
||||||
yield Button("Back", id="btn-back")
|
yield Button("Back", id="btn-back")
|
||||||
@@ -107,10 +99,8 @@ class SettingsScreen(Screen):
|
|||||||
ssh_retries=self.query_one("#set-sshretries", Input).value.strip() or "3",
|
ssh_retries=self.query_one("#set-sshretries", Input).value.strip() or "3",
|
||||||
rsync_extra_opts=self.query_one("#set-rsyncopts", Input).value.strip(),
|
rsync_extra_opts=self.query_one("#set-rsyncopts", Input).value.strip(),
|
||||||
work_dir=self.query_one("#set-workdir", Input).value.strip() or "/usr/local/gniza/workdir",
|
work_dir=self.query_one("#set-workdir", Input).value.strip() or "/usr/local/gniza/workdir",
|
||||||
web_enabled=self._get_select_val("#set-web-enabled", "no"),
|
|
||||||
web_port=self.query_one("#set-web-port", Input).value.strip() or "8080",
|
web_port=self.query_one("#set-web-port", Input).value.strip() or "8080",
|
||||||
web_host=self.query_one("#set-web-host", Input).value.strip() or "0.0.0.0",
|
web_host=self.query_one("#set-web-host", Input).value.strip() or "0.0.0.0",
|
||||||
web_api_key=self.query_one("#set-web-key", Input).value,
|
|
||||||
)
|
)
|
||||||
conf_path = CONFIG_DIR / "gniza.conf"
|
conf_path = CONFIG_DIR / "gniza.conf"
|
||||||
write_conf(conf_path, settings.to_conf())
|
write_conf(conf_path, settings.to_conf())
|
||||||
|
|||||||
Reference in New Issue
Block a user