Files
home-information/install.sh
Tony C 9a2944d6ac [Bugfix, Ops] Audio fix, install scripts, dependency updates (#154)
* 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.
2025-09-08 17:56:57 +00:00

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 "$@"