schon/scripts/Unix/install-native.sh
2026-01-25 23:16:38 +03:00

172 lines
8.5 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
source ./scripts/Unix/starter.sh
# ─────────────────────────────────────────────────────────────────────────────
# Native Linux Installation Script for Schon
# Installs Schon for production use with systemd services
# ─────────────────────────────────────────────────────────────────────────────
INSTALL_DIR="/opt/schon"
SCHON_USER="schon"
SCHON_GROUP="schon"
# Check if running as root
if [ "$EUID" -ne 0 ]; then
log_error "This script must be run as root (use sudo)"
exit 1
fi
# Check if we're in the correct directory
if [ "$(pwd)" != "$INSTALL_DIR" ]; then
log_warning "Current directory is not $INSTALL_DIR"
log_info "For production, Schon should be installed in $INSTALL_DIR"
if ! confirm "Continue anyway?"; then
log_info "Please clone the repository to $INSTALL_DIR and run again"
exit 0
fi
INSTALL_DIR="$(pwd)"
fi
log_step "Starting native Linux installation..."
# ─────────────────────────────────────────────────────────────────────────────
# Check prerequisites
# ─────────────────────────────────────────────────────────────────────────────
log_step "Checking prerequisites..."
missing_deps=()
if ! command_exists uv; then
missing_deps+=("uv (https://docs.astral.sh/uv/)")
fi
if ! command_exists psql; then
missing_deps+=("postgresql-client")
fi
if ! command_exists redis-cli; then
missing_deps+=("redis-tools")
fi
if [ ${#missing_deps[@]} -gt 0 ]; then
log_error "Missing required dependencies:"
for dep in "${missing_deps[@]}"; do
log_error " - $dep"
done
echo
log_info "Install uv with: curl -LsSf https://astral.sh/uv/install.sh | sh"
log_info "Install others with: apt install postgresql-client redis-tools"
exit 1
fi
log_success "All prerequisites found"
# ─────────────────────────────────────────────────────────────────────────────
# Check system requirements
# ─────────────────────────────────────────────────────────────────────────────
if ! check_system_requirements 4 6 20; then
if ! confirm "System requirements not met. Continue anyway?"; then
exit 1
fi
fi
# ─────────────────────────────────────────────────────────────────────────────
# Create schon user
# ─────────────────────────────────────────────────────────────────────────────
log_step "Setting up schon user..."
if id "$SCHON_USER" &>/dev/null; then
log_info "User '$SCHON_USER' already exists"
else
useradd --system --shell /usr/sbin/nologin --home-dir "$INSTALL_DIR" "$SCHON_USER"
log_success "Created system user '$SCHON_USER'"
fi
# ─────────────────────────────────────────────────────────────────────────────
# Check for .env file
# ─────────────────────────────────────────────────────────────────────────────
if [ ! -f "$INSTALL_DIR/.env" ]; then
log_error ".env file not found"
log_info "Run 'make generate-env' first, then configure your .env file"
exit 1
fi
# ─────────────────────────────────────────────────────────────────────────────
# Install Python dependencies
# ─────────────────────────────────────────────────────────────────────────────
log_step "Installing Python dependencies with uv..."
cd "$INSTALL_DIR"
# Create virtual environment if it doesn't exist
if [ ! -d "$INSTALL_DIR/.venv" ]; then
uv venv "$INSTALL_DIR/.venv"
log_success "Created virtual environment"
fi
# Sync dependencies
uv sync --extra worker --extra openai
log_success "Dependencies installed"
# ─────────────────────────────────────────────────────────────────────────────
# Set ownership
# ─────────────────────────────────────────────────────────────────────────────
log_step "Setting file ownership..."
chown -R "$SCHON_USER:$SCHON_GROUP" "$INSTALL_DIR"
log_success "Ownership set to $SCHON_USER:$SCHON_GROUP"
# ─────────────────────────────────────────────────────────────────────────────
# Install systemd services
# ─────────────────────────────────────────────────────────────────────────────
log_step "Installing systemd services..."
SYSTEMD_DIR="/etc/systemd/system"
SERVICES=("schon-web" "schon-worker" "schon-beat" "schon-stock-updater")
for service in "${SERVICES[@]}"; do
src="$INSTALL_DIR/systemd/${service}.service"
dst="$SYSTEMD_DIR/${service}.service"
if [ -f "$src" ]; then
ln -sf "$src" "$dst"
log_info " Linked ${service}.service"
else
log_warning " Service file not found: $src"
fi
done
# Reload systemd
systemctl daemon-reload
log_success "Systemd services installed"
# ─────────────────────────────────────────────────────────────────────────────
# Enable services
# ─────────────────────────────────────────────────────────────────────────────
log_step "Enabling services..."
for service in "${SERVICES[@]}"; do
systemctl enable "$service" 2>/dev/null || true
log_info " Enabled ${service}"
done
log_success "Services enabled"
# ─────────────────────────────────────────────────────────────────────────────
# Summary
# ─────────────────────────────────────────────────────────────────────────────
echo
log_result "Installation complete!"
echo
log_info "Next steps:"
log_info " 1. Configure your .env file: nano $INSTALL_DIR/.env"
log_info " 2. Ensure PostgreSQL, Redis, and Elasticsearch are running"
log_info " 3. Run migrations: sudo -u $SCHON_USER $INSTALL_DIR/.venv/bin/python manage.py migrate"
log_info " 4. Create superuser: sudo -u $SCHON_USER $INSTALL_DIR/.venv/bin/python manage.py createsuperuser"
log_info " 5. Start services: systemctl start schon-web schon-worker schon-beat schon-stock-updater"
log_info " 6. Configure nginx with nginx.example.conf"
echo
log_info "View service status: systemctl status schon-web"
log_info "View logs: journalctl -u schon-web -f"