This commit is contained in:
Your Name 2025-04-21 09:58:37 +12:00
parent 9e5a54ff36
commit 093dee3fd3
14 changed files with 577 additions and 36 deletions

View File

@ -0,0 +1,5 @@
SSH_ADDRESS=localhost
SSH_PORT=22
SSH_USER=$(whoami)

View File

@ -0,0 +1,16 @@
# Application settings
CONTAINER_PORT=8181
HOST_PORT=80
# Deployment settings
DEPLOY_FOLDER="${HOME}/sk/deploy"
DATA_FOLDER="${HOME}/sk/data"
BACKUP_FOLDER="${HOME}/sk/backups"
CONTAINER_NAME="squashkiwi"
# Image settings
IMAGE_REGISTRY="gitea.jde.nz"
IMAGE_REPO="squashkiwi/squashkiwi"
IMAGE_TAG="latest"

37
LICENSE
View File

@ -1,37 +1,2 @@
Copyright (c) 2001 David Giffin.
All rights reserved.
MIT License
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. All advertising materials mentioning features or use of this
software must display the following acknowledgment:
"This product includes software developed by
David Giffin <david@giffin.org>."
4. Redistributions of any form whatsoever must retain the following
acknowledgment:
"This product includes software developed by
David Giffin <david@giffin.org>."
THIS SOFTWARE IS PROVIDED BY DAVID GIFFIN ``AS IS'' AND ANY
EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID GIFFIN OR
ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.

105
install.sh Executable file
View File

@ -0,0 +1,105 @@
#!/bin/bash
# Colors for output
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m' # No Color
# Check if USER_DEFINITIONS is provided
if [ -z "$1" ]; then
echo -e "${RED}Error: USER_DEFINITIONS path is required${NC}"
echo "Usage: $0 <USER_DEFINITIONS_PATH>"
echo "Example: $0 ~/.config/dropshell"
exit 1
fi
USER_DEFINITIONS="$1"
# Script locations
SCRIPT_SOURCE="$(pwd)/src/dropshell.sh"
SCRIPT_DEST="/usr/local/bin/dropshell"
COMPLETION_SOURCE="$(pwd)/src/dropshell-completion.bash"
COMPLETION_DEST="/etc/bash_completion.d/dropshell"
# Check if running with sudo/root
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}Please run as root or with sudo${NC}"
exit 1
fi
# Check if source script exists
if [ ! -f "$SCRIPT_SOURCE" ]; then
echo -e "${RED}Error: $SCRIPT_SOURCE not found${NC}"
echo "Please ensure the script exists in the src directory"
exit 1
fi
# Check if completion script exists
if [ ! -f "$COMPLETION_SOURCE" ]; then
echo -e "${RED}Error: $COMPLETION_SOURCE not found${NC}"
echo "Please ensure the completion script exists in the src directory"
exit 1
fi
if [ ! -d "$USER_DEFINITIONS" ]; then
# Create user definitions directory structure
echo "Creating user definitions directory structure..."
mkdir -p "$USER_DEFINITIONS/servers"
mkdir -p "$USER_DEFINITIONS/templates"
# Create example files
mkdir -p "$USER_DEFINITIONS/servers/example.com"
cat > "$USER_DEFINITIONS/services/example.com/server.json" << 'EOF'
{
"ssh_address": "localhost",
"ssh_port": 22,
"ssh_user": "$(whoami)"
}
EOF
# cat > "$USER_DEFINITIONS/services/example.com/server.json" << 'EOF'
# {
# "ssh_address": "localhost",
# "ssh_port": 22,
# "ssh_user": "$(whoami)"
# }
# EOF
fi
# Create symbolic link
echo "Creating symbolic link..."
if [ -L "$SCRIPT_DEST" ]; then
rm "$SCRIPT_DEST"
fi
ln -s "$SCRIPT_SOURCE" "$SCRIPT_DEST"
# Make sure the scripts are executable
chmod +x "$SCRIPT_SOURCE"
chmod +x "$COMPLETION_SOURCE"
# Install bash completion
echo "Installing bash completion..."
if [ ! -d "/etc/bash_completion.d" ]; then
mkdir -p "/etc/bash_completion.d"
fi
# Install completion script
cp "$COMPLETION_SOURCE" "$COMPLETION_DEST"
chmod 644 "$COMPLETION_DEST"
# Create environment file
cat > "/etc/dropshell.conf" << EOF
# Dropshell configuration
USER_DEFINITIONS="$USER_DEFINITIONS"
EOF
# Source the completion script
echo "source $COMPLETION_DEST" >> ~/.bashrc
echo -e "${GREEN}Installation completed successfully!${NC}"
echo "User definitions directory created at: $USER_DEFINITIONS"
echo
echo "Please run 'source ~/.bashrc' or start a new terminal to enable completion"
exit 0

30
src/dropshell-completion.bash Executable file
View File

@ -0,0 +1,30 @@
#!/bin/bash
_dropshell_completions() {
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
# List of main commands
opts="help version status"
# If we're completing the first argument, show all commands
if [[ ${COMP_CWORD} -eq 1 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
# Command-specific completions
case "${prev}" in
status)
# No additional completions for status
COMPREPLY=()
;;
*)
;;
esac
}
# Register the completion function
complete -F _dropshell_completions dropshell

142
src/dropshell.sh Executable file
View File

@ -0,0 +1,142 @@
#!/bin/bash
# Script name: dropshell.sh
# Description: A basic shell script for common operations
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Source version information
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
source "$SCRIPT_DIR/version.sh"
# Source configuration
if [ -f "/etc/dropshell.conf" ]; then
source "/etc/dropshell.conf"
else
echo -e "${RED}Error: Configuration file not found${NC}"
echo "Please run the installation script first"
exit 1
fi
# Check if USER_DEFINITIONS is set
if [ -z "$USER_DEFINITIONS" ]; then
echo -e "${RED}Error: USER_DEFINITIONS not set${NC}"
echo "Please run the installation script first"
exit 1
fi
# Function to print usage
print_usage() {
echo "Usage: $0 <command> [options]"
echo
echo "Commands:"
echo " help - Show this help message"
echo " version - Show version information"
echo " status - Check system status"
echo " servers - List configured servers"
echo " services - List configured services"
echo " templates - List available templates"
echo
echo "Options:"
echo " -v, --verbose Enable verbose output"
}
# Function to print version
print_version() {
get_version_info
}
# Function to check status
check_status() {
echo -e "${GREEN}System Status:${NC}"
echo "Date: $(date)"
echo "Uptime: $(uptime)"
echo "Memory Usage:"
free -h
echo
echo "Disk Usage:"
df -h /
}
# Function to list servers
list_servers() {
echo -e "${GREEN}Configured Servers:${NC}"
if [ -d "$USER_DEFINITIONS/servers" ]; then
for server in "$USER_DEFINITIONS/servers"/*.json; do
if [ -f "$server" ]; then
name=$(jq -r '.name' "$server")
host=$(jq -r '.host' "$server")
echo "- $name ($host)"
fi
done
else
echo "No servers configured"
fi
}
# Function to list services
list_services() {
echo -e "${GREEN}Configured Services:${NC}"
if [ -d "$USER_DEFINITIONS/services" ]; then
for service in "$USER_DEFINITIONS/services"/*.json; do
if [ -f "$service" ]; then
name=$(jq -r '.name' "$service")
echo "- $name"
fi
done
else
echo "No services configured"
fi
}
# Function to list templates
list_templates() {
echo -e "${GREEN}Available Templates:${NC}"
if [ -d "$USER_DEFINITIONS/templates" ]; then
for template in "$USER_DEFINITIONS/templates"/*.sh; do
if [ -f "$template" ]; then
echo "- $(basename "$template")"
fi
done
else
echo "No templates available"
fi
}
# Main script logic
case "$1" in
"help"|"-h"|"--help")
print_usage
;;
"version"|"-V"|"--version")
print_version
;;
"status")
check_status
;;
"servers")
list_servers
;;
"services")
list_services
;;
"templates")
list_templates
;;
"")
echo -e "${RED}Error: No command provided${NC}"
print_usage
exit 1
;;
*)
echo -e "${RED}Error: Unknown command '$1'${NC}"
print_usage
exit 1
;;
esac
exit 0

15
src/version.sh Normal file
View File

@ -0,0 +1,15 @@
#!/bin/bash
# Version information
DROPSHELL_VERSION="1.0.0"
DROPSHELL_RELEASE_DATE="2025-04-21"
DROPSHELL_AUTHOR="j842"
DROPSHELL_LICENSE="MIT"
# Function to get full version information
get_version_info() {
echo "dropshell version $DROPSHELL_VERSION"
echo "Release date: $DROPSHELL_RELEASE_DATE"
echo "Author: $DROPSHELL_AUTHOR"
echo "License: $DROPSHELL_LICENSE"
}

127
templates/squashkiwi/_common.sh Executable file
View File

@ -0,0 +1,127 @@
#!/bin/bash
# Print error message and exit with code 1
# Usage: die "error message"
die() {
echo -e "\033[91mError: $1\033[0m"
exit 1
}
# Load environment variables from .env file
# Usage: load_env [path_to_env_file]
# If no path is provided, looks for .env in the same directory as the script
load_env() {
local script_dir="$(dirname "${BASH_SOURCE[0]}")"
local env_file
if [ -z "$1" ]; then
echo "Usage: $0 [path_to_env_file]"
return 1
else
# If path is relative, make it absolute using script directory as base
if [[ "$1" != /* ]]; then
env_file="$script_dir/$1"
else
env_file="$1"
fi
fi
if [ -f "$env_file" ]; then
set -a
source "$env_file"
set +a
else
echo "Warning: .env file not found at $env_file"
return 1
fi
}
grey_start() {
echo -e -n "\033[90m"
}
grey_end() {
echo -e -n "\033[0m"
}
# Test if Docker is installed and working on the local machine
# Returns 0 if Docker is working, 1 if there are any issues
test_docker() {
echo "Testing Docker on local machine..."
# Test Docker installation
if ! command -v docker >/dev/null 2>&1; then
die "Docker is not installed on this machine"
fi
# Test Docker daemon is running
if ! docker info >/dev/null 2>&1; then
die "Docker daemon is not running"
fi
# Test Docker can run containers
if ! docker run --rm hello-world >/dev/null 2>&1; then
die "Docker cannot run containers"
fi
echo "Docker is working correctly on local machine"
return 0
}
start_container() {
# Check if container exists and is stopped
echo "Checking container status..."
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
die "Container ${CONTAINER_NAME} is already running"
else
echo "Starting existing container ${CONTAINER_NAME}..."
grey_start
if ! docker start "${CONTAINER_NAME}"; then
die "Failed to start container ${CONTAINER_NAME}"
fi
grey_end
fi
else
echo "Creating and starting new container ${CONTAINER_NAME}..."
grey_start
docker run -d \
--restart unless-stopped \
--name ${CONTAINER_NAME} \
-p ${HOST_PORT}:${CONTAINER_PORT} \
-v ${DATA_FOLDER}:/skdata \
${IMAGE_REGISTRY}/${IMAGE_REPO}:${IMAGE_TAG}
grey_end
fi
# check if the container is running
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
die "Container ${CONTAINER_NAME} is not running"
fi
# print the container id
ID=$(docker ps --format '{{.ID}}' --filter "name=^${CONTAINER_NAME}$")
echo "Container ${CONTAINER_NAME} is running with ID ${ID}"
return 0
}
stop_container() {
# Check if container is running
echo "Checking if container is running..."
if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo "Stopping container ${CONTAINER_NAME}..."
grey_start
if ! docker stop "${CONTAINER_NAME}"; then
die "Failed to stop container ${CONTAINER_NAME}"
fi
grey_end
echo "Container ${CONTAINER_NAME} stopped successfully"
return 0
else
echo "Container ${CONTAINER_NAME} is not running"
return 1
fi
}

24
templates/squashkiwi/backup.sh Executable file
View File

@ -0,0 +1,24 @@
#!/bin/bash
# Source common functions
source "$(dirname "$0")/_common.sh"
# Load environment variables
load_env "$1" || die "Failed to load environment variables"
# set the backup file name to be the current date and time
BACKUP_FILE="$BACKUP_FOLDER/backup-squashkiwi-$(date +%Y-%m-%d_%H-%M-%S).tar.gz"
if [ -f "$BACKUP_FILE" ]; then
echo "Backup file $BACKUP_FILE already exists"
exit 1
fi
stop_container
# create the backup file, using relative paths.
tar zcvf "$BACKUP_FILE" -C "$DATA_FOLDER" . || die "Failed to create backup"
start_container
echo "Backup created in $BACKUP_FILE"

View File

@ -0,0 +1,20 @@
# This file contains environment variables specific to the server where the application will be deployed.
# Copy this file to .env and modify the values according to your server's configuration.
# Do not commit the actual .env file to version control as it may contain sensitive information.
# Application settings
CONTAINER_PORT=8181
HOST_PORT=80
# Deployment settings
DEPLOY_FOLDER="${HOME}/sk/deploy"
DATA_FOLDER="${HOME}/sk/data"
BACKUP_FOLDER="${HOME}/sk/backups"
CONTAINER_NAME="squashkiwi"
# Image settings
IMAGE_REGISTRY="gitea.jde.nz"
IMAGE_REPO="squashkiwi/squashkiwi"
IMAGE_TAG="latest"

36
templates/squashkiwi/install.sh Executable file
View File

@ -0,0 +1,36 @@
#!/bin/bash
# Source common functions
source "$(dirname "$0")/_common.sh"
# Load environment variables
load_env "$1" || exit 1
# Test Docker
if ! test_docker; then
echo "Docker test failed, aborting installation..."
exit 1
fi
# Rest of your install script here
function create_folder() {
local folder="$1"
if ! mkdir -p "$folder"; then
die "Failed to create folder: $folder"
fi
}
# Create deploy and data folders
echo "Ensuring deployment folders exist..."
create_folder "$DEPLOY_FOLDER"
create_folder "$DATA_FOLDER"
create_folder "$BACKUP_FOLDER"
# check can pull image on remote host and exit if fails
if ! docker pull "$IMAGE_REGISTRY/$IMAGE_REPO:$IMAGE_TAG"; then
echo "Failed to pull image $IMAGE_REGISTRY/$IMAGE_REPO:$IMAGE_TAG"
exit 1
fi
echo "Successfully pulled the docker image from the registry"

13
templates/squashkiwi/start.sh Executable file
View File

@ -0,0 +1,13 @@
#!/bin/bash
# Source common functions
source "$(dirname "$0")/_common.sh"
# Load environment variables
load_env "$1" || die "Failed to load environment variables"
start_container || die "Failed to start container ${CONTAINER_NAME}"
grey_start
docker logs --tail 20 "${CONTAINER_NAME}"
grey_end

13
templates/squashkiwi/stop.sh Executable file
View File

@ -0,0 +1,13 @@
#!/bin/bash
# Source common functions
source "$(dirname "$0")/_common.sh"
# Load environment variables
load_env "$1" || die "Failed to load environment variables"
stop_container || die "Failed to stop container ${CONTAINER_NAME}"
grey_start
docker logs --tail 20 "${CONTAINER_NAME}"
grey_end

30
templates/squashkiwi/update.sh Executable file
View File

@ -0,0 +1,30 @@
#!/bin/bash
# Source common functions
source "$(dirname "$0")/_common.sh"
# Load environment variables
load_env "$1" || exit 1
# check can pull image on remote host and exit if fails
if ! docker pull "$IMAGE_REGISTRY/$IMAGE_REPO:$IMAGE_TAG"; then
echo "Failed to pull image $IMAGE_REGISTRY/$IMAGE_REPO:$IMAGE_TAG"
exit 1
fi
echo "Successfully pulled the docker image from the registry"
# stop the old container
stop_container
# remove the old container
grey_start
if ! docker rm "$CONTAINER_NAME"; then
echo "Failed to remove container $CONTAINER_NAME"
exit 1
fi
grey_end
echo "Successfully removed the old container"
# start the new container
start_container