#!/bin/bash # apt-ostree Installation Script # Installs apt-ostree with 1:1 rpm-ostree compatibility 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 # Configuration INSTALL_DIR="/usr/local/bin" SERVICE_DIR="/etc/systemd/system" CONFIG_DIR="/etc/apt-ostree" LOG_DIR="/var/log" DATA_DIR="/var/lib/apt-ostree" echo -e "${BLUE}apt-ostree Installation Script${NC}" echo "Installing apt-ostree with 1:1 rpm-ostree compatibility" echo "" # Check if running as root if [[ $EUID -ne 0 ]]; then echo -e "${RED}Error: This script must be run as root${NC}" exit 1 fi # Check Python version PYTHON_VERSION=$(python3 --version 2>&1 | cut -d' ' -f2 | cut -d'.' -f1,2) # Fix: allow 3.8 and higher if [[ $(printf '%s\n' "3.8" "$PYTHON_VERSION" | sort -V | head -n1) != "3.8" ]]; then echo -e "${RED}Error: Python 3.8 or higher is required (found $PYTHON_VERSION)${NC}" exit 1 fi echo -e "${GREEN}✓ Python version check passed${NC}" # Install Python dependencies echo -e "${BLUE}Installing Python dependencies...${NC}" cd "$(dirname "$0")/python" if ! pip3 install --break-system-packages -r requirements.txt; then echo -e "${RED}Error: Failed to install Python dependencies${NC}" exit 1 fi echo -e "${GREEN}✓ Python dependencies installed${NC}" # Create directories echo -e "${BLUE}Creating directories...${NC}" mkdir -p "$CONFIG_DIR" mkdir -p "$LOG_DIR" mkdir -p "$DATA_DIR" mkdir -p "$INSTALL_DIR" mkdir -p "/var/cache/apt-ostree" mkdir -p "/var/log/apt-ostree" echo -e "${GREEN}✓ Directories created${NC}" # Install apt-ostree binary echo -e "${BLUE}Installing apt-ostree binary...${NC}" cat > "$INSTALL_DIR/apt-ostree" << 'EOF' #!/usr/bin/env python3 """ apt-ostree - Hybrid image/package system for Debian/Ubuntu 1:1 compatibility with rpm-ostree """ import sys import os # Add the apt-ostree Python module to the path sys.path.insert(0, '/usr/local/lib/apt-ostree') from main import main if __name__ == '__main__': sys.exit(main()) EOF chmod +x "$INSTALL_DIR/apt-ostree" # Install Python modules echo -e "${BLUE}Installing Python modules...${NC}" PYTHON_LIB_DIR="/usr/local/lib/apt-ostree" mkdir -p "$PYTHON_LIB_DIR" cp apt_ostree.py "$PYTHON_LIB_DIR/" cp apt_ostree_cli.py "$PYTHON_LIB_DIR/" cp main.py "$PYTHON_LIB_DIR/" # Create __init__.py touch "$PYTHON_LIB_DIR/__init__.py" echo -e "${GREEN}✓ Python modules installed${NC}" # Install systemd service file echo -e "${BLUE}Installing systemd service file...${NC}" SCRIPT_DIR="$(dirname "$0")" if [[ -f "$SCRIPT_DIR/apt-ostreed.service" ]]; then cp "$SCRIPT_DIR/apt-ostreed.service" "$SERVICE_DIR/" chmod 644 "$SERVICE_DIR/apt-ostreed.service" echo -e "${GREEN}✓ Systemd service file installed${NC}" else echo -e "${YELLOW}Warning: apt-ostreed.service not found, creating default...${NC}" cat > "$SERVICE_DIR/apt-ostreed.service" << EOF [Unit] Description=apt-ostree System Management Daemon Documentation=man:apt-ostree(1) ConditionPathExists=/ostree RequiresMountsFor=/boot After=dbus.service [Service] Type=simple User=root Group=root # Lock file to prevent multiple instances PIDFile=/var/run/apt-ostreed.pid RuntimeDirectory=apt-ostreed RuntimeDirectoryMode=0755 # Prevent multiple instances ExecStartPre=/bin/rm -f /var/run/apt-ostreed.pid ExecStartPre=/bin/rm -f /run/apt-ostreed/daemon.lock ExecStartPre=/bin/mkdir -p /run/apt-ostreed ExecStartPre=/bin/touch /run/apt-ostreed/daemon.lock # Main daemon execution ExecStart=/usr/bin/python3 /usr/local/lib/apt-ostree/apt_ostree.py --daemon --pid-file=/var/run/apt-ostreed.pid # Cleanup on stop ExecStopPost=/bin/rm -f /var/run/apt-ostreed.pid ExecStopPost=/bin/rm -f /run/apt-ostreed/daemon.lock ExecReload=/bin/kill -HUP \$MAINPID Restart=on-failure RestartSec=5 TimeoutStartSec=5m TimeoutStopSec=30s StandardOutput=journal StandardError=journal SyslogIdentifier=apt-ostreed # Security settings NoNewPrivileges=true ProtectSystem=strict ProtectHome=true ProtectKernelTunables=true ProtectKernelModules=true ProtectControlGroups=true RestrictRealtime=true RestrictSUIDSGID=true PrivateTmp=true PrivateDevices=true PrivateNetwork=false ReadWritePaths=/var/lib/apt-ostree /var/cache/apt-ostree /var/log/apt-ostree /ostree /boot /var/run /run # OSTree and APT specific paths ReadWritePaths=/var/lib/apt /var/cache/apt /var/lib/dpkg /var/lib/ostree # Environment variables Environment="PYTHONPATH=/usr/local/lib/apt-ostree" Environment="DOWNLOAD_FILELISTS=false" Environment="GIO_USE_VFS=local" [Install] WantedBy=multi-user.target EOF echo -e "${GREEN}✓ Default systemd service created${NC}" fi # Create configuration file echo -e "${BLUE}Creating configuration...${NC}" cat > "$CONFIG_DIR/config.json" << EOF { "daemon": { "enabled": true, "log_level": "INFO", "workspace": "$DATA_DIR" }, "compatibility": { "rpm_ostree": true, "output_format": "rpm_ostree" }, "security": { "require_root": true, "polkit_integration": true } } EOF echo -e "${GREEN}✓ Configuration created${NC}" # Set permissions echo -e "${BLUE}Setting permissions...${NC}" chown -R root:root "$CONFIG_DIR" chmod 755 "$CONFIG_DIR" chmod 644 "$CONFIG_DIR/config.json" chown -R root:root "$DATA_DIR" chmod 755 "$DATA_DIR" chown -R root:root "/var/cache/apt-ostree" chmod 755 "/var/cache/apt-ostree" chown -R root:root "/var/log/apt-ostree" chmod 755 "/var/log/apt-ostree" chown root:root "$LOG_DIR/apt-ostree.log" 2>/dev/null || true chmod 644 "$LOG_DIR/apt-ostree.log" 2>/dev/null || true echo -e "${GREEN}✓ Permissions set${NC}" # Reload systemd echo -e "${BLUE}Reloading systemd...${NC}" systemctl daemon-reload echo -e "${GREEN}✓ Systemd reloaded${NC}" # Install D-Bus policy file echo -e "${BLUE}Installing D-Bus policy file...${NC}" DBUS_POLICY_SRC="$(dirname "$0")/dbus-policy/org.debian.aptostree1.conf" DBUS_POLICY_DEST="/etc/dbus-1/system.d/org.debian.aptostree1.conf" if [[ -f "$DBUS_POLICY_SRC" ]]; then cp "$DBUS_POLICY_SRC" "$DBUS_POLICY_DEST" chmod 644 "$DBUS_POLICY_DEST" echo -e "${GREEN}\u2713 D-Bus policy file installed${NC}" echo -e "${BLUE}Reloading D-Bus...${NC}" systemctl reload dbus || echo -e "${YELLOW}Warning: Could not reload dbus. You may need to reboot or reload manually.${NC}" else echo -e "${YELLOW}Warning: D-Bus policy file not found at $DBUS_POLICY_SRC. D-Bus integration may not work!${NC}" fi # Install D-Bus activation service file echo -e "${BLUE}Installing D-Bus activation service file...${NC}" DBUS_SERVICE_DIR="/usr/share/dbus-1/system-services" mkdir -p "$DBUS_SERVICE_DIR" if [[ -f "$SCRIPT_DIR/org.debian.aptostree1.service" ]]; then cp "$SCRIPT_DIR/org.debian.aptostree1.service" "$DBUS_SERVICE_DIR/" chmod 644 "$DBUS_SERVICE_DIR/org.debian.aptostree1.service" echo -e "${GREEN}✓ D-Bus activation service file installed${NC}" else echo -e "${YELLOW}Warning: org.debian.aptostree1.service not found, creating default...${NC}" cat > "$DBUS_SERVICE_DIR/org.debian.aptostree1.service" << EOF [D-BUS Service] Name=org.debian.aptostree1 Exec=/usr/bin/python3 /usr/local/lib/apt-ostree/apt_ostree.py User=root SystemdService=apt-ostreed.service EOF chmod 644 "$DBUS_SERVICE_DIR/org.debian.aptostree1.service" echo -e "${GREEN}✓ Default D-Bus activation service file created${NC}" fi # Test installation echo -e "${BLUE}Testing installation...${NC}" if "$INSTALL_DIR/apt-ostree" --help >/dev/null 2>&1; then echo -e "${GREEN}✓ apt-ostree command works${NC}" else echo -e "${RED}✗ apt-ostree command failed${NC}" exit 1 fi # Enable and start service (optional) read -p "Do you want to enable and start the apt-ostree daemon? (y/N): " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then echo -e "${BLUE}Enabling and starting apt-ostree daemon...${NC}" systemctl enable apt-ostreed.service systemctl start apt-ostreed.service if systemctl is-active --quiet apt-ostreed.service; then echo -e "${GREEN}✓ apt-ostree daemon is running${NC}" else echo -e "${YELLOW}⚠ apt-ostree daemon failed to start${NC}" echo "Check logs with: journalctl -u apt-ostreed.service" fi fi echo "" echo -e "${GREEN}🎉 apt-ostree installation completed!${NC}" echo "" echo -e "${BLUE}Usage examples:${NC}" echo " apt-ostree status # Show system status" echo " apt-ostree upgrade --reboot # Upgrade and reboot" echo " apt-ostree install firefox --reboot # Install package and reboot" echo " apt-ostree rollback # Rollback to previous deployment" echo " apt-ostree kargs add console=ttyS0 # Add kernel argument" echo "" echo -e "${BLUE}Service management:${NC}" echo " systemctl status apt-ostreed # Check daemon status" echo " systemctl start apt-ostreed # Start daemon" echo " systemctl stop apt-ostreed # Stop daemon" echo " journalctl -u apt-ostreed -f # View daemon logs" echo "" echo -e "${BLUE}Files installed:${NC}" echo " Binary: $INSTALL_DIR/apt-ostree" echo " Service: $SERVICE_DIR/apt-ostreed.service" echo " Config: $CONFIG_DIR/config.json" echo " Data: $DATA_DIR" echo " Logs: $LOG_DIR/apt-ostree.log" echo " D-Bus Service: /usr/share/dbus-1/system-services/org.debian.aptostree1.service" echo " D-Bus Policy: /etc/dbus-1/system.d/org.debian.aptostree1.conf" echo "" echo -e "${GREEN}apt-ostree provides 1:1 compatibility with rpm-ostree commands!${NC}" echo "" echo -e "${BLUE}To test D-Bus connection:${NC}" echo " sudo dbus-send --system --dest=org.debian.aptostree1 \\" echo " /org/debian/aptostree1/Sysroot \\" echo " org.freedesktop.DBus.Introspectable.Introspect"