From 563bb8fa6a332440753723d5090a9c06d081f234 Mon Sep 17 00:00:00 2001 From: kqjy Date: Sat, 13 Dec 2025 22:26:43 +0800 Subject: [PATCH] Fix incorrect STORAGE_ROOT setup; Add installation scripts --- app/config.py | 106 +++++++++++++++- app/version.py | 2 +- docs.md | 57 +++++++++ run.py | 37 ++++++ scripts/install.sh | 292 +++++++++++++++++++++++++++++++++++++++++++ scripts/uninstall.sh | 174 ++++++++++++++++++++++++++ templates/docs.html | 2 +- 7 files changed, 663 insertions(+), 7 deletions(-) create mode 100644 scripts/install.sh create mode 100644 scripts/uninstall.sh diff --git a/app/config.py b/app/config.py index ef9420d..b5b2a92 100644 --- a/app/config.py +++ b/app/config.py @@ -111,19 +111,19 @@ class AppConfig: iam_env_override = "IAM_CONFIG" in overrides or "IAM_CONFIG" in os.environ bucket_policy_override = "BUCKET_POLICY_PATH" in overrides or "BUCKET_POLICY_PATH" in os.environ - default_iam_path = PROJECT_ROOT / "data" / ".myfsio.sys" / "config" / "iam.json" - default_bucket_policy_path = PROJECT_ROOT / "data" / ".myfsio.sys" / "config" / "bucket_policies.json" + default_iam_path = storage_root / ".myfsio.sys" / "config" / "iam.json" + default_bucket_policy_path = storage_root / ".myfsio.sys" / "config" / "bucket_policies.json" iam_config_path = Path(_get("IAM_CONFIG", default_iam_path)).resolve() bucket_policy_path = Path(_get("BUCKET_POLICY_PATH", default_bucket_policy_path)).resolve() iam_config_path = _prepare_config_file( iam_config_path, - legacy_path=None if iam_env_override else PROJECT_ROOT / "data" / "iam.json", + legacy_path=None if iam_env_override else storage_root / "iam.json", ) bucket_policy_path = _prepare_config_file( bucket_policy_path, - legacy_path=None if bucket_policy_override else PROJECT_ROOT / "data" / "bucket_policies.json", + legacy_path=None if bucket_policy_override else storage_root / "bucket_policies.json", ) api_base_url = _get("API_BASE_URL", None) if api_base_url: @@ -134,7 +134,7 @@ class AppConfig: enforce_ui_policies = str(_get("UI_ENFORCE_BUCKET_POLICIES", "0")).lower() in {"1", "true", "yes", "on"} log_level = str(_get("LOG_LEVEL", "INFO")).upper() log_to_file = str(_get("LOG_TO_FILE", "1")).lower() in {"1", "true", "yes", "on"} - log_dir = Path(_get("LOG_DIR", PROJECT_ROOT / "logs")).resolve() + log_dir = Path(_get("LOG_DIR", storage_root.parent / "logs")).resolve() log_dir.mkdir(parents=True, exist_ok=True) log_path = log_dir / str(_get("LOG_FILE", "app.log")) log_max_bytes = int(_get("LOG_MAX_BYTES", 5 * 1024 * 1024)) @@ -198,6 +198,102 @@ class AppConfig: kms_keys_path=kms_keys_path, default_encryption_algorithm=default_encryption_algorithm) + def validate_and_report(self) -> list[str]: + """Validate configuration and return a list of warnings/issues. + + Call this at startup to detect potential misconfigurations before + the application fully commits to running. + """ + issues = [] + + # Check if storage_root is writable + try: + test_file = self.storage_root / ".write_test" + test_file.touch() + test_file.unlink() + except (OSError, PermissionError) as e: + issues.append(f"CRITICAL: STORAGE_ROOT '{self.storage_root}' is not writable: {e}") + + # Check if storage_root looks like a temp directory + storage_str = str(self.storage_root).lower() + if "/tmp" in storage_str or "\\temp" in storage_str or "appdata\\local\\temp" in storage_str: + issues.append(f"WARNING: STORAGE_ROOT '{self.storage_root}' appears to be a temporary directory. Data may be lost on reboot!") + + # Check if IAM config path is under storage_root + try: + self.iam_config_path.relative_to(self.storage_root) + except ValueError: + issues.append(f"WARNING: IAM_CONFIG '{self.iam_config_path}' is outside STORAGE_ROOT '{self.storage_root}'. Consider setting IAM_CONFIG explicitly or ensuring paths are aligned.") + + # Check if bucket policy path is under storage_root + try: + self.bucket_policy_path.relative_to(self.storage_root) + except ValueError: + issues.append(f"WARNING: BUCKET_POLICY_PATH '{self.bucket_policy_path}' is outside STORAGE_ROOT '{self.storage_root}'. Consider setting BUCKET_POLICY_PATH explicitly.") + + # Check if log path is writable + try: + self.log_path.parent.mkdir(parents=True, exist_ok=True) + test_log = self.log_path.parent / ".write_test" + test_log.touch() + test_log.unlink() + except (OSError, PermissionError) as e: + issues.append(f"WARNING: Log directory '{self.log_path.parent}' is not writable: {e}") + + # Check log path location + log_str = str(self.log_path).lower() + if "/tmp" in log_str or "\\temp" in log_str or "appdata\\local\\temp" in log_str: + issues.append(f"WARNING: LOG_DIR '{self.log_path.parent}' appears to be a temporary directory. Logs may be lost on reboot!") + + # Check if encryption keys path is under storage_root (when encryption is enabled) + if self.encryption_enabled: + try: + self.encryption_master_key_path.relative_to(self.storage_root) + except ValueError: + issues.append(f"WARNING: ENCRYPTION_MASTER_KEY_PATH '{self.encryption_master_key_path}' is outside STORAGE_ROOT. Ensure proper backup procedures.") + + # Check if KMS keys path is under storage_root (when KMS is enabled) + if self.kms_enabled: + try: + self.kms_keys_path.relative_to(self.storage_root) + except ValueError: + issues.append(f"WARNING: KMS_KEYS_PATH '{self.kms_keys_path}' is outside STORAGE_ROOT. Ensure proper backup procedures.") + + # Warn about production settings + if self.secret_key == "dev-secret-key": + issues.append("WARNING: Using default SECRET_KEY. Set SECRET_KEY environment variable for production.") + + if "*" in self.cors_origins: + issues.append("INFO: CORS_ORIGINS is set to '*'. Consider restricting to specific domains in production.") + + return issues + + def print_startup_summary(self) -> None: + """Print a summary of the configuration at startup.""" + print("\n" + "=" * 60) + print("MyFSIO Configuration Summary") + print("=" * 60) + print(f" STORAGE_ROOT: {self.storage_root}") + print(f" IAM_CONFIG: {self.iam_config_path}") + print(f" BUCKET_POLICY: {self.bucket_policy_path}") + print(f" LOG_PATH: {self.log_path}") + if self.api_base_url: + print(f" API_BASE_URL: {self.api_base_url}") + if self.encryption_enabled: + print(f" ENCRYPTION: Enabled (Master key: {self.encryption_master_key_path})") + if self.kms_enabled: + print(f" KMS: Enabled (Keys: {self.kms_keys_path})") + print("=" * 60) + + issues = self.validate_and_report() + if issues: + print("\nConfiguration Issues Detected:") + for issue in issues: + print(f" • {issue}") + print() + else: + print(" ✓ Configuration validated successfully\n") + def to_flask_config(self) -> Dict[str, Any]: return { "STORAGE_ROOT": str(self.storage_root), diff --git a/app/version.py b/app/version.py index eb61b62..f30bbb3 100644 --- a/app/version.py +++ b/app/version.py @@ -1,7 +1,7 @@ """Central location for the application version string.""" from __future__ import annotations -APP_VERSION = "0.1.4" +APP_VERSION = "0.1.5" def get_version() -> str: diff --git a/docs.md b/docs.md index 192d3cc..2f9c3d7 100644 --- a/docs.md +++ b/docs.md @@ -33,6 +33,63 @@ python run.py --mode api # API only (port 5000) python run.py --mode ui # UI only (port 5100) ``` +### Configuration validation + +Validate your configuration before deploying: + +```bash +# Show configuration summary +python run.py --show-config +./myfsio --show-config + +# Validate and check for issues (exits with code 1 if critical issues found) +python run.py --check-config +./myfsio --check-config +``` + +### Linux Installation (Recommended for Production) + +For production deployments on Linux, use the provided installation script: + +```bash +# Download the binary and install script +# Then run the installer with sudo: +sudo ./scripts/install.sh --binary ./myfsio + +# Or with custom paths: +sudo ./scripts/install.sh \ + --binary ./myfsio \ + --install-dir /opt/myfsio \ + --data-dir /mnt/storage/myfsio \ + --log-dir /var/log/myfsio \ + --api-url https://s3.example.com \ + --user myfsio + +# Non-interactive mode (for automation): +sudo ./scripts/install.sh --binary ./myfsio -y +``` + +The installer will: +1. Create a dedicated system user +2. Set up directories with proper permissions +3. Generate a secure `SECRET_KEY` +4. Create an environment file at `/opt/myfsio/myfsio.env` +5. Install and configure a systemd service + +After installation: +```bash +sudo systemctl start myfsio # Start the service +sudo systemctl enable myfsio # Enable on boot +sudo systemctl status myfsio # Check status +sudo journalctl -u myfsio -f # View logs +``` + +To uninstall: +```bash +sudo ./scripts/uninstall.sh # Full removal +sudo ./scripts/uninstall.sh --keep-data # Keep data directory +``` + ### Docker quickstart The repo now ships a `Dockerfile` so you can run both services in one container: diff --git a/run.py b/run.py index 805f60a..da78033 100644 --- a/run.py +++ b/run.py @@ -8,6 +8,7 @@ import warnings from multiprocessing import Process from app import create_api_app, create_ui_app +from app.config import AppConfig def _server_host() -> str: @@ -55,12 +56,48 @@ if __name__ == "__main__": parser.add_argument("--ui-port", type=int, default=5100) parser.add_argument("--prod", action="store_true", help="Run in production mode using Waitress") parser.add_argument("--dev", action="store_true", help="Force development mode (Flask dev server)") + parser.add_argument("--check-config", action="store_true", help="Validate configuration and exit") + parser.add_argument("--show-config", action="store_true", help="Show configuration summary and exit") args = parser.parse_args() + # Handle config check/show modes + if args.check_config or args.show_config: + config = AppConfig.from_env() + config.print_startup_summary() + if args.check_config: + issues = config.validate_and_report() + critical = [i for i in issues if i.startswith("CRITICAL:")] + sys.exit(1 if critical else 0) + sys.exit(0) + # Default to production mode when running as compiled binary # unless --dev is explicitly passed prod_mode = args.prod or (_is_frozen() and not args.dev) + # Validate configuration before starting + config = AppConfig.from_env() + + # Show startup summary only on first run (when marker file doesn't exist) + first_run_marker = config.storage_root / ".myfsio.sys" / ".initialized" + is_first_run = not first_run_marker.exists() + + if is_first_run: + config.print_startup_summary() + + # Check for critical issues that should prevent startup + issues = config.validate_and_report() + critical_issues = [i for i in issues if i.startswith("CRITICAL:")] + if critical_issues: + print("ABORTING: Critical configuration issues detected. Fix them before starting.") + sys.exit(1) + + # Create the marker file to indicate successful first run + try: + first_run_marker.parent.mkdir(parents=True, exist_ok=True) + first_run_marker.write_text(f"Initialized on {__import__('datetime').datetime.now().isoformat()}\n") + except OSError: + pass # Non-critical, just skip marker creation + if prod_mode: print("Running in production mode (Waitress)") else: diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100644 index 0000000..8b0b42d --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,292 @@ +#!/bin/bash +# +# MyFSIO Installation Script +# This script sets up MyFSIO for production use on Linux systems. +# +# Usage: +# curl -fsSL https://example.com/install.sh | bash +# OR +# ./install.sh [OPTIONS] +# +# Options: +# --install-dir DIR Installation directory (default: /opt/myfsio) +# --data-dir DIR Data directory (default: /var/lib/myfsio) +# --log-dir DIR Log directory (default: /var/log/myfsio) +# --user USER System user to run as (default: myfsio) +# --port PORT API port (default: 5000) +# --ui-port PORT UI port (default: 5100) +# --api-url URL Public API URL (for presigned URLs behind proxy) +# --no-systemd Skip systemd service creation +# --binary PATH Path to myfsio binary (will download if not provided) +# -y, --yes Skip confirmation prompts +# + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Default values +INSTALL_DIR="/opt/myfsio" +DATA_DIR="/var/lib/myfsio" +LOG_DIR="/var/log/myfsio" +SERVICE_USER="myfsio" +API_PORT="5000" +UI_PORT="5100" +API_URL="" +SKIP_SYSTEMD=false +BINARY_PATH="" +AUTO_YES=false + +# Parse arguments +while [[ $# -gt 0 ]]; do + case $1 in + --install-dir) + INSTALL_DIR="$2" + shift 2 + ;; + --data-dir) + DATA_DIR="$2" + shift 2 + ;; + --log-dir) + LOG_DIR="$2" + shift 2 + ;; + --user) + SERVICE_USER="$2" + shift 2 + ;; + --port) + API_PORT="$2" + shift 2 + ;; + --ui-port) + UI_PORT="$2" + shift 2 + ;; + --api-url) + API_URL="$2" + shift 2 + ;; + --no-systemd) + SKIP_SYSTEMD=true + shift + ;; + --binary) + BINARY_PATH="$2" + shift 2 + ;; + -y|--yes) + AUTO_YES=true + shift + ;; + -h|--help) + head -30 "$0" | tail -25 + exit 0 + ;; + *) + echo -e "${RED}Unknown option: $1${NC}" + exit 1 + ;; + esac +done + +echo -e "${BLUE}" +echo "╔══════════════════════════════════════════════════════════╗" +echo "║ MyFSIO Installation ║" +echo "║ S3-Compatible Object Storage ║" +echo "╚══════════════════════════════════════════════════════════╝" +echo -e "${NC}" + +# Check if running as root +if [[ $EUID -ne 0 ]]; then + echo -e "${RED}Error: This script must be run as root (use sudo)${NC}" + exit 1 +fi + +# Display configuration +echo -e "${YELLOW}Installation Configuration:${NC}" +echo " Install directory: $INSTALL_DIR" +echo " Data directory: $DATA_DIR" +echo " Log directory: $LOG_DIR" +echo " Service user: $SERVICE_USER" +echo " API port: $API_PORT" +echo " UI port: $UI_PORT" +if [[ -n "$API_URL" ]]; then + echo " Public API URL: $API_URL" +fi +if [[ -n "$BINARY_PATH" ]]; then + echo " Binary path: $BINARY_PATH" +fi +echo "" + +# Confirm installation +if [[ "$AUTO_YES" != true ]]; then + read -p "Proceed with installation? [y/N] " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Installation cancelled." + exit 0 + fi +fi + +echo "" +echo -e "${GREEN}[1/7]${NC} Creating system user..." +if id "$SERVICE_USER" &>/dev/null; then + echo " User '$SERVICE_USER' already exists" +else + useradd --system --no-create-home --shell /usr/sbin/nologin "$SERVICE_USER" + echo " Created user '$SERVICE_USER'" +fi + +echo -e "${GREEN}[2/7]${NC} Creating directories..." +mkdir -p "$INSTALL_DIR" +mkdir -p "$DATA_DIR" +mkdir -p "$LOG_DIR" +echo " Created $INSTALL_DIR" +echo " Created $DATA_DIR" +echo " Created $LOG_DIR" + +echo -e "${GREEN}[3/7]${NC} Installing binary..." +if [[ -n "$BINARY_PATH" ]]; then + if [[ -f "$BINARY_PATH" ]]; then + cp "$BINARY_PATH" "$INSTALL_DIR/myfsio" + echo " Copied binary from $BINARY_PATH" + else + echo -e "${RED}Error: Binary not found at $BINARY_PATH${NC}" + exit 1 + fi +elif [[ -f "./myfsio" ]]; then + cp "./myfsio" "$INSTALL_DIR/myfsio" + echo " Copied binary from ./myfsio" +else + echo -e "${RED}Error: No binary provided. Use --binary PATH or place 'myfsio' in current directory${NC}" + exit 1 +fi +chmod +x "$INSTALL_DIR/myfsio" + +echo -e "${GREEN}[4/7]${NC} Generating secret key..." +SECRET_KEY=$(openssl rand -base64 32) +echo " Generated secure SECRET_KEY" + +echo -e "${GREEN}[5/7]${NC} Creating environment file..." +cat > "$INSTALL_DIR/myfsio.env" << EOF +# MyFSIO Configuration +# Generated by install.sh on $(date) + +# Storage paths +STORAGE_ROOT=$DATA_DIR +LOG_DIR=$LOG_DIR + +# Network +APP_HOST=0.0.0.0 +APP_PORT=$API_PORT + +# Security - CHANGE IN PRODUCTION +SECRET_KEY=$SECRET_KEY +CORS_ORIGINS=* + +# Public URL (set this if behind a reverse proxy) +$(if [[ -n "$API_URL" ]]; then echo "API_BASE_URL=$API_URL"; else echo "# API_BASE_URL=https://s3.example.com"; fi) + +# Logging +LOG_LEVEL=INFO +LOG_TO_FILE=true + +# Rate limiting +RATE_LIMIT_DEFAULT=200 per minute + +# Optional: Encryption (uncomment to enable) +# ENCRYPTION_ENABLED=true +# KMS_ENABLED=true +EOF +chmod 600 "$INSTALL_DIR/myfsio.env" +echo " Created $INSTALL_DIR/myfsio.env" + +echo -e "${GREEN}[6/7]${NC} Setting permissions..." +chown -R "$SERVICE_USER:$SERVICE_USER" "$INSTALL_DIR" +chown -R "$SERVICE_USER:$SERVICE_USER" "$DATA_DIR" +chown -R "$SERVICE_USER:$SERVICE_USER" "$LOG_DIR" +echo " Set ownership to $SERVICE_USER" + +if [[ "$SKIP_SYSTEMD" != true ]]; then + echo -e "${GREEN}[7/7]${NC} Creating systemd service..." + cat > /etc/systemd/system/myfsio.service << EOF +[Unit] +Description=MyFSIO S3-Compatible Storage +Documentation=https://github.com/yourusername/myfsio +After=network.target + +[Service] +Type=simple +User=$SERVICE_USER +Group=$SERVICE_USER +WorkingDirectory=$INSTALL_DIR +EnvironmentFile=$INSTALL_DIR/myfsio.env +ExecStart=$INSTALL_DIR/myfsio +Restart=on-failure +RestartSec=5 + +# Security hardening +NoNewPrivileges=true +ProtectSystem=strict +ProtectHome=true +ReadWritePaths=$DATA_DIR $LOG_DIR +PrivateTmp=true + +# Resource limits (adjust as needed) +# LimitNOFILE=65535 +# MemoryMax=2G + +[Install] +WantedBy=multi-user.target +EOF + + systemctl daemon-reload + echo " Created /etc/systemd/system/myfsio.service" +else + echo -e "${GREEN}[7/7]${NC} Skipping systemd service (--no-systemd)" +fi + +echo "" +echo -e "${GREEN}╔══════════════════════════════════════════════════════════╗${NC}" +echo -e "${GREEN}║ Installation Complete! ║${NC}" +echo -e "${GREEN}╚══════════════════════════════════════════════════════════╝${NC}" +echo "" +echo -e "${YELLOW}Next steps:${NC}" +echo "" +echo " 1. Review configuration:" +echo " ${BLUE}cat $INSTALL_DIR/myfsio.env${NC}" +echo "" +echo " 2. Start the service:" +echo " ${BLUE}sudo systemctl start myfsio${NC}" +echo "" +echo " 3. Enable on boot:" +echo " ${BLUE}sudo systemctl enable myfsio${NC}" +echo "" +echo " 4. Check status:" +echo " ${BLUE}sudo systemctl status myfsio${NC}" +echo "" +echo " 5. View logs:" +echo " ${BLUE}sudo journalctl -u myfsio -f${NC}" +echo " ${BLUE}tail -f $LOG_DIR/app.log${NC}" +echo "" +echo -e "${YELLOW}Access:${NC}" +echo " API: http://$(hostname -I | awk '{print $1}'):$API_PORT" +echo " UI: http://$(hostname -I | awk '{print $1}'):$UI_PORT/ui" +echo "" +echo -e "${YELLOW}Default credentials:${NC}" +echo " Username: localadmin" +echo " Password: localadmin" +echo -e " ${RED}⚠ Change these immediately after first login!${NC}" +echo "" +echo -e "${YELLOW}Configuration files:${NC}" +echo " Environment: $INSTALL_DIR/myfsio.env" +echo " IAM Users: $DATA_DIR/.myfsio.sys/config/iam.json" +echo " Bucket Policies: $DATA_DIR/.myfsio.sys/config/bucket_policies.json" +echo "" diff --git a/scripts/uninstall.sh b/scripts/uninstall.sh new file mode 100644 index 0000000..71a5b74 --- /dev/null +++ b/scripts/uninstall.sh @@ -0,0 +1,174 @@ +#!/bin/bash +# +# MyFSIO Uninstall Script +# This script removes MyFSIO from your system. +# +# Usage: +# ./uninstall.sh [OPTIONS] +# +# Options: +# --keep-data Don't remove data directory +# --keep-logs Don't remove log directory +# --install-dir DIR Installation directory (default: /opt/myfsio) +# --data-dir DIR Data directory (default: /var/lib/myfsio) +# --log-dir DIR Log directory (default: /var/log/myfsio) +# --user USER System user (default: myfsio) +# -y, --yes Skip confirmation prompts +# + +set -e + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +# Default values +INSTALL_DIR="/opt/myfsio" +DATA_DIR="/var/lib/myfsio" +LOG_DIR="/var/log/myfsio" +SERVICE_USER="myfsio" +KEEP_DATA=false +KEEP_LOGS=false +AUTO_YES=false + +# Parse arguments +while [[ $# -gt 0 ]]; do + case $1 in + --keep-data) + KEEP_DATA=true + shift + ;; + --keep-logs) + KEEP_LOGS=true + shift + ;; + --install-dir) + INSTALL_DIR="$2" + shift 2 + ;; + --data-dir) + DATA_DIR="$2" + shift 2 + ;; + --log-dir) + LOG_DIR="$2" + shift 2 + ;; + --user) + SERVICE_USER="$2" + shift 2 + ;; + -y|--yes) + AUTO_YES=true + shift + ;; + -h|--help) + head -20 "$0" | tail -15 + exit 0 + ;; + *) + echo -e "${RED}Unknown option: $1${NC}" + exit 1 + ;; + esac +done + +echo -e "${RED}" +echo "╔══════════════════════════════════════════════════════════╗" +echo "║ MyFSIO Uninstallation ║" +echo "╚══════════════════════════════════════════════════════════╝" +echo -e "${NC}" + +# Check if running as root +if [[ $EUID -ne 0 ]]; then + echo -e "${RED}Error: This script must be run as root (use sudo)${NC}" + exit 1 +fi + +echo -e "${YELLOW}The following will be removed:${NC}" +echo " Install directory: $INSTALL_DIR" +if [[ "$KEEP_DATA" != true ]]; then + echo -e " Data directory: $DATA_DIR ${RED}(ALL YOUR DATA!)${NC}" +else + echo " Data directory: $DATA_DIR (KEPT)" +fi +if [[ "$KEEP_LOGS" != true ]]; then + echo " Log directory: $LOG_DIR" +else + echo " Log directory: $LOG_DIR (KEPT)" +fi +echo " Systemd service: /etc/systemd/system/myfsio.service" +echo " System user: $SERVICE_USER" +echo "" + +if [[ "$AUTO_YES" != true ]]; then + echo -e "${RED}WARNING: This action cannot be undone!${NC}" + read -p "Are you sure you want to uninstall MyFSIO? [y/N] " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + echo "Uninstallation cancelled." + exit 0 + fi +fi + +echo "" +echo -e "${GREEN}[1/5]${NC} Stopping service..." +if systemctl is-active --quiet myfsio 2>/dev/null; then + systemctl stop myfsio + echo " Stopped myfsio service" +else + echo " Service not running" +fi + +echo -e "${GREEN}[2/5]${NC} Disabling service..." +if systemctl is-enabled --quiet myfsio 2>/dev/null; then + systemctl disable myfsio + echo " Disabled myfsio service" +else + echo " Service not enabled" +fi + +echo -e "${GREEN}[3/5]${NC} Removing systemd service..." +if [[ -f /etc/systemd/system/myfsio.service ]]; then + rm -f /etc/systemd/system/myfsio.service + systemctl daemon-reload + echo " Removed /etc/systemd/system/myfsio.service" +else + echo " Service file not found" +fi + +echo -e "${GREEN}[4/5]${NC} Removing directories..." +if [[ -d "$INSTALL_DIR" ]]; then + rm -rf "$INSTALL_DIR" + echo " Removed $INSTALL_DIR" +fi + +if [[ "$KEEP_DATA" != true ]] && [[ -d "$DATA_DIR" ]]; then + rm -rf "$DATA_DIR" + echo " Removed $DATA_DIR" +elif [[ "$KEEP_DATA" == true ]]; then + echo " Kept $DATA_DIR" +fi + +if [[ "$KEEP_LOGS" != true ]] && [[ -d "$LOG_DIR" ]]; then + rm -rf "$LOG_DIR" + echo " Removed $LOG_DIR" +elif [[ "$KEEP_LOGS" == true ]]; then + echo " Kept $LOG_DIR" +fi + +echo -e "${GREEN}[5/5]${NC} Removing system user..." +if id "$SERVICE_USER" &>/dev/null; then + userdel "$SERVICE_USER" 2>/dev/null || true + echo " Removed user '$SERVICE_USER'" +else + echo " User not found" +fi + +echo "" +echo -e "${GREEN}MyFSIO has been uninstalled.${NC}" +if [[ "$KEEP_DATA" == true ]]; then + echo -e "${YELLOW}Data preserved at: $DATA_DIR${NC}" +fi diff --git a/templates/docs.html b/templates/docs.html index 2b2e325..f812d40 100644 --- a/templates/docs.html +++ b/templates/docs.html @@ -200,7 +200,7 @@ WorkingDirectory=/opt/myfsio ExecStart=/opt/myfsio/myfsio Restart=on-failure RestartSec=5 -Environment=MYFSIO_DATA_DIR=/var/lib/myfsio +Environment=STORAGE_ROOT=/var/lib/myfsio Environment=API_BASE_URL=https://s3.example.com [Install]