mirror of
https://github.com/cassandra/home-information.git
synced 2026-05-24 16:27:25 -04:00
* Fixed bug for audio signal not being cleared. * Added better server-to-client config interactions. * New install and update scripts. Supporting GitHub actions and docs. * Refactor to rationalize server and client environment config. * Added missing debug setting guard around JS debug.log() messages. * Dealt with packages having deprecated pip install method.
291 lines
7.9 KiB
Bash
Executable File
291 lines
7.9 KiB
Bash
Executable File
#!/bin/bash
|
|
set -e # Exit on any error
|
|
|
|
# Home Information - Single Command Installer
|
|
# Installs and runs Home Information with minimal user interaction
|
|
# Requires: Docker
|
|
|
|
# Configuration
|
|
DOCKER_IMAGE="ghcr.io/cassandra/home-information" # GitHub Container Registry
|
|
DOCKER_TAG="${1:-latest}" # Allow override for testing (default: latest)
|
|
CONTAINER_NAME="hi"
|
|
EXTERNAL_PORT="9411"
|
|
HI_HOME="${HOME}/.hi"
|
|
ENV_DIR="${HI_HOME}/env"
|
|
DATABASE_DIR="${HI_HOME}/database"
|
|
MEDIA_DIR="${HI_HOME}/media"
|
|
ENV_FILE="${ENV_DIR}/local.env"
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
print_header() {
|
|
echo -e "${BLUE}================================${NC}"
|
|
echo -e "${BLUE} Home Information Installer${NC}"
|
|
echo -e "${BLUE}================================${NC}"
|
|
}
|
|
|
|
print_success() {
|
|
echo -e "${GREEN}✓ $1${NC}"
|
|
}
|
|
|
|
print_info() {
|
|
echo -e "${BLUE}• $1${NC}"
|
|
}
|
|
|
|
print_warning() {
|
|
echo -e "${YELLOW}⚠ $1${NC}"
|
|
}
|
|
|
|
print_error() {
|
|
echo -e "${RED}✗ $1${NC}"
|
|
exit 1
|
|
}
|
|
|
|
# Check if Docker is installed and running
|
|
check_docker() {
|
|
print_info "Checking Docker installation..."
|
|
|
|
if ! command -v docker &> /dev/null; then
|
|
print_error "Docker is not installed. Please install Docker first: https://docs.docker.com/get-docker/"
|
|
fi
|
|
|
|
if ! docker info &> /dev/null; then
|
|
print_error "Docker is not running. Please start Docker and try again."
|
|
fi
|
|
|
|
print_success "Docker is installed and running"
|
|
}
|
|
|
|
# Check if Python3 is installed (needed for secure secret generation)
|
|
check_python() {
|
|
print_info "Checking Python 3 installation..."
|
|
|
|
if ! command -v python3 &> /dev/null; then
|
|
print_error "Python 3.6+ is required but not installed. Please install Python 3.6 or later."
|
|
fi
|
|
|
|
print_success "Python 3 is installed"
|
|
}
|
|
|
|
# Generate cryptographically secure Django secret key
|
|
generate_secret_key() {
|
|
python3 -c "
|
|
import secrets
|
|
import string
|
|
chars = string.ascii_letters + string.digits + string.punctuation
|
|
print(''.join(secrets.choice(chars) for _ in range(50)))
|
|
"
|
|
}
|
|
|
|
# Generate memorable admin password
|
|
generate_admin_password() {
|
|
python3 -c "
|
|
import secrets
|
|
words = [
|
|
'apple', 'banana', 'cherry', 'delta', 'eagle', 'falcon', 'grape',
|
|
'hunter', 'island', 'joker', 'kitten', 'lemon', 'melon', 'ninja', 'ocean',
|
|
'piano', 'queen', 'robot', 'stone', 'tiger', 'unity', 'voice', 'water',
|
|
'xenon', 'yacht', 'zebra', 'anchor', 'bridge', 'camera', 'dream', 'energy'
|
|
]
|
|
chosen_words = [secrets.choice(words) for _ in range(3)]
|
|
random_number = str(secrets.randbelow(1000))
|
|
chosen_words.append(random_number)
|
|
print('-'.join(chosen_words))
|
|
"
|
|
}
|
|
|
|
# Create required directories
|
|
create_directories() {
|
|
print_info "Creating directories..."
|
|
|
|
# Create directories with proper permissions
|
|
mkdir -p "${ENV_DIR}"
|
|
mkdir -p "${DATABASE_DIR}"
|
|
mkdir -p "${MEDIA_DIR}"
|
|
|
|
# Secure the env directory (user only)
|
|
chmod 700 "${ENV_DIR}"
|
|
|
|
print_success "Directories created: ${HI_HOME}"
|
|
}
|
|
|
|
# Generate environment file
|
|
create_env_file() {
|
|
print_info "Generating configuration and secrets..."
|
|
|
|
# Check if env file already exists
|
|
if [[ -f "${ENV_FILE}" ]]; then
|
|
print_warning "Configuration file already exists: ${ENV_FILE}"
|
|
read -p "Do you want to overwrite it? (y/N): " -n 1 -r
|
|
echo
|
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
print_error "Installation cancelled. Remove ${ENV_FILE} to start fresh."
|
|
fi
|
|
|
|
# Create backup (using portable date format)
|
|
TIMESTAMP=$(date "+%Y%m%d_%H%M%S")
|
|
BACKUP_FILE="${ENV_FILE}.BAK.${TIMESTAMP}"
|
|
cp "${ENV_FILE}" "${BACKUP_FILE}"
|
|
print_info "Backup created: ${BACKUP_FILE}"
|
|
fi
|
|
|
|
# Generate secrets
|
|
DJANGO_SECRET_KEY=$(generate_secret_key)
|
|
DJANGO_ADMIN_PASSWORD=$(generate_admin_password)
|
|
|
|
# Create environment file
|
|
cat > "${ENV_FILE}" << EOF
|
|
# Home Information Environment Configuration
|
|
# Generated by install.sh on $(date)
|
|
|
|
# Core Django Settings
|
|
DJANGO_SETTINGS_MODULE=hi.settings.local
|
|
DJANGO_SERVER_PORT=8000
|
|
DJANGO_SECRET_KEY=${DJANGO_SECRET_KEY}
|
|
|
|
# Admin User (for Django admin interface)
|
|
DJANGO_SUPERUSER_EMAIL=admin@example.com
|
|
DJANGO_SUPERUSER_PASSWORD=${DJANGO_ADMIN_PASSWORD}
|
|
|
|
# Data Paths (inside Docker container)
|
|
HI_DB_PATH=/data/database
|
|
HI_MEDIA_PATH=/data/media
|
|
|
|
# Redis Configuration
|
|
HI_REDIS_HOST=127.0.0.1
|
|
HI_REDIS_PORT=6379
|
|
HI_REDIS_KEY_PREFIX=
|
|
|
|
# Authentication (disabled for simple setup)
|
|
HI_SUPPRESS_AUTHENTICATION=true
|
|
|
|
# Email Settings (disabled for simple setup)
|
|
HI_EMAIL_SUBJECT_PREFIX=
|
|
HI_DEFAULT_FROM_EMAIL=
|
|
HI_SERVER_EMAIL=
|
|
HI_EMAIL_HOST=
|
|
HI_EMAIL_PORT=587
|
|
HI_EMAIL_HOST_USER=
|
|
HI_EMAIL_HOST_PASSWORD=
|
|
HI_EMAIL_USE_TLS=false
|
|
HI_EMAIL_USE_SSL=false
|
|
|
|
# Network Configuration (for localhost only)
|
|
HI_EXTRA_HOST_URLS=
|
|
HI_EXTRA_CSP_URLS=
|
|
EOF
|
|
|
|
# Secure the env file
|
|
chmod 600 "${ENV_FILE}"
|
|
|
|
print_success "Configuration file created: ${ENV_FILE}"
|
|
|
|
# Store admin password for display later
|
|
ADMIN_PASSWORD="${DJANGO_ADMIN_PASSWORD}"
|
|
}
|
|
|
|
# Pull Docker image
|
|
pull_docker_image() {
|
|
print_info "Pulling Home Information Docker image..."
|
|
|
|
if docker pull "${DOCKER_IMAGE}:${DOCKER_TAG}"; then
|
|
print_success "Docker image pulled successfully"
|
|
else
|
|
print_error "Failed to pull Docker image. Please check your internet connection."
|
|
fi
|
|
}
|
|
|
|
# Stop any existing container
|
|
stop_existing_container() {
|
|
if docker ps -a --format 'table {{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
|
print_info "Stopping existing container..."
|
|
docker stop "${CONTAINER_NAME}" 2>/dev/null || true
|
|
docker rm "${CONTAINER_NAME}" 2>/dev/null || true
|
|
print_success "Existing container removed"
|
|
fi
|
|
}
|
|
|
|
# Start the container
|
|
start_container() {
|
|
print_info "Starting Home Information container..."
|
|
|
|
docker run -d \
|
|
--name "${CONTAINER_NAME}" \
|
|
--restart unless-stopped \
|
|
--env-file "${ENV_FILE}" \
|
|
-v "${DATABASE_DIR}:/data/database" \
|
|
-v "${MEDIA_DIR}:/data/media" \
|
|
-p "${EXTERNAL_PORT}:8000" \
|
|
"${DOCKER_IMAGE}:${DOCKER_TAG}"
|
|
|
|
print_success "Container started successfully"
|
|
}
|
|
|
|
# Wait for application to be ready
|
|
wait_for_app() {
|
|
print_info "Waiting for application to start (this may take a minute)..."
|
|
|
|
# Wait up to 60 seconds for the app to be ready
|
|
for i in {1..60}; do
|
|
if curl -s "http://localhost:${EXTERNAL_PORT}" > /dev/null 2>&1; then
|
|
print_success "Application is ready!"
|
|
return 0
|
|
fi
|
|
sleep 1
|
|
if [ $((i % 10)) -eq 0 ]; then
|
|
print_info "Still waiting... (${i}s)"
|
|
fi
|
|
done
|
|
|
|
print_warning "Application may still be starting. Check docker logs hi for details."
|
|
}
|
|
|
|
# Display success message
|
|
show_success() {
|
|
echo
|
|
echo -e "${GREEN}================================${NC}"
|
|
echo -e "${GREEN} Installation Complete!${NC}"
|
|
echo -e "${GREEN}================================${NC}"
|
|
echo
|
|
echo -e "${BLUE}🌐 Access your Home Information system:${NC}"
|
|
echo -e " ${BLUE}http://localhost:${EXTERNAL_PORT}${NC}"
|
|
echo
|
|
echo -e "${BLUE}🔐 Admin credentials:${NC}"
|
|
echo -e " Email: admin@example.com"
|
|
echo -e " Password: ${ADMIN_PASSWORD}"
|
|
echo
|
|
echo -e "${BLUE}📁 Your data is stored in:${NC}"
|
|
echo -e " Database: ${DATABASE_DIR}"
|
|
echo -e " Uploads: ${MEDIA_DIR}"
|
|
echo
|
|
echo -e "${BLUE}🔧 Useful commands:${NC}"
|
|
echo -e " View logs: docker logs hi"
|
|
echo -e " Stop: docker stop hi"
|
|
echo -e " Start: docker start hi"
|
|
echo
|
|
echo -e "${GREEN}IMPORTANT: Save your admin credentials securely!${NC}"
|
|
echo
|
|
}
|
|
|
|
# Main installation function
|
|
main() {
|
|
print_header
|
|
|
|
check_docker
|
|
check_python
|
|
create_directories
|
|
create_env_file
|
|
pull_docker_image
|
|
stop_existing_container
|
|
start_container
|
|
wait_for_app
|
|
show_success
|
|
}
|
|
|
|
# Run main function
|
|
main "$@" |