9.6 KiB
Dropshell Template Guide
This guide explains how to create templates for Dropshell - a system management tool for deploying and managing services on remote servers via Docker containers.
Template Structure
Every template must follow this directory structure:
template-name/
├── config/
│ ├── .template_info.env # REQUIRED: Template metadata
│ └── service.env # REQUIRED: Default service configuration
├── install.sh # REQUIRED: Installation script
├── uninstall.sh # REQUIRED: Uninstallation script
├── start.sh # OPTIONAL: Start the service
├── stop.sh # OPTIONAL: Stop the service
├── status.sh # OPTIONAL: Check service status
├── logs.sh # OPTIONAL: View service logs
├── backup.sh # OPTIONAL: Backup service data
├── restore.sh # OPTIONAL: Restore service data
├── destroy.sh # OPTIONAL: Destroy service and data
├── ssh.sh # OPTIONAL: SSH into service container
├── ports.sh # OPTIONAL: List exposed ports
└── README.txt # OPTIONAL: Template documentation
Essential Files
1. config/.template_info.env
Template metadata file that defines the template and its requirements:
# Template identifier - MUST match the directory name
TEMPLATE=template-name
# Requirements
REQUIRES_HOST_ROOT=false # Whether root access on host is needed
REQUIRES_DOCKER=true # Whether Docker is required
REQUIRES_DOCKER_ROOT=false # Whether Docker root privileges are needed
# Docker image settings
IMAGE_REGISTRY="docker.io"
IMAGE_REPO="vendor/image"
IMAGE_TAG="latest"
# Volume definitions (if needed)
DATA_VOLUME="${CONTAINER_NAME}_data"
CONFIG_VOLUME="${CONTAINER_NAME}_config"
2. config/service.env
Default service configuration that can be overridden per deployment:
# Service-specific settings
CONTAINER_NAME=service-name
IMAGE_TAG="latest"
# Server settings
SSH_USER="root"
# Service-specific variables
# (Add any configuration specific to your service)
3. install.sh
Installation script that sets up the service:
#!/bin/bash
source "${AGENT_PATH}/common.sh"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Check required environment variables
_check_required_env_vars "CONTAINER_NAME" "IMAGE_REGISTRY" "IMAGE_REPO" "IMAGE_TAG"
# Check Docker is available
_check_docker_installed || _die "Docker test failed"
# Pull the Docker image
docker pull "$IMAGE_REGISTRY/$IMAGE_REPO:$IMAGE_TAG" || _die "Failed to pull image"
# Stop any existing container
bash ./stop.sh || _die "Failed to stop container"
# Remove old container
_remove_container "$CONTAINER_NAME" || _die "Failed to remove container"
# Start the new container
bash ./start.sh || _die "Failed to start container"
echo "Installation of ${CONTAINER_NAME} complete"
4. uninstall.sh
Uninstallation script to remove the service:
#!/bin/bash
source "${AGENT_PATH}/common.sh"
_check_required_env_vars "CONTAINER_NAME"
# Stop the container
bash ./stop.sh || _die "Failed to stop container"
# Remove the container
_remove_container "$CONTAINER_NAME" || _die "Failed to remove container"
# Optionally remove volumes (with confirmation)
# _remove_volume "$DATA_VOLUME"
echo "Uninstallation of ${CONTAINER_NAME} complete"
Optional Command Scripts
start.sh
Starts the Docker container with appropriate configuration:
#!/bin/bash
source "${AGENT_PATH}/common.sh"
_check_required_env_vars "CONTAINER_NAME" "IMAGE_REGISTRY" "IMAGE_REPO" "IMAGE_TAG"
docker run -d \
--name "$CONTAINER_NAME" \
--restart unless-stopped \
-v "$DATA_VOLUME:/data" \
"$IMAGE_REGISTRY/$IMAGE_REPO:$IMAGE_TAG"
stop.sh
Stops the running container:
#!/bin/bash
source "${AGENT_PATH}/common.sh"
_check_required_env_vars "CONTAINER_NAME"
docker stop "$CONTAINER_NAME" 2>/dev/null || true
status.sh
Reports the service status:
#!/bin/bash
source "${AGENT_PATH}/common.sh"
_check_required_env_vars "CONTAINER_NAME"
if docker ps --format "table {{.Names}}" | grep -q "^${CONTAINER_NAME}$"; then
echo "Running"
else
echo "Stopped"
fi
logs.sh
Shows container logs:
#!/bin/bash
source "${AGENT_PATH}/common.sh"
_check_required_env_vars "CONTAINER_NAME"
docker logs "$CONTAINER_NAME" "$@"
backup.sh / restore.sh
Handle data backup and restoration for services with persistent data.
Common Functions (from common.sh)
Templates have access to these utility functions:
_check_required_env_vars VAR1 VAR2 ...
- Verify required variables are set_die "message"
- Exit with error message_check_docker_installed
- Verify Docker is available_remove_container NAME
- Safely remove a containercreate_items ITEM1 ITEM2 ...
- Create volumes or networks_remove_volume NAME
- Remove a Docker volume
Environment Variables
Templates receive these variables at runtime:
AGENT_PATH
- Path to the Dropshell agent directoryCONFIG_PATH
- Path to the service configuration directorySCRIPT_DIR
- Directory containing the template scripts- All variables from
.template_info.env
andservice.env
Validation Requirements
Templates must pass these validation checks:
- Required files exist:
config/.template_info.env
,config/service.env
,install.sh
,uninstall.sh
- Scripts are executable: All
.sh
files must have execute permissions - TEMPLATE variable matches: The
TEMPLATE
variable in.template_info.env
must match the directory name - Valid environment files: Both
.env
files must be parseable
Best Practices
- Always use
_check_required_env_vars
at the start of scripts to validate inputs - Handle errors gracefully with
|| _die "Error message"
- Use Docker volumes for persistent data that survives container recreation
- Document configuration in README.txt for users
- Support idempotency - scripts should handle being run multiple times
- Clean up properly in uninstall/destroy scripts
- Use standard naming - volumes as
${CONTAINER_NAME}_data
, configs as${CONTAINER_NAME}_config
- Test thoroughly - use
dropshell test-template <path>
to validate
Examples
Example 1: Basic Web Server (Nginx)
A minimal template for deploying an Nginx web server:
nginx-server/
├── config/
│ ├── .template_info.env
│ └── service.env
├── install.sh
├── uninstall.sh
├── start.sh
├── stop.sh
└── logs.sh
.template_info.env
:
TEMPLATE=nginx-server
REQUIRES_DOCKER=true
REQUIRES_DOCKER_ROOT=false
IMAGE_REGISTRY="docker.io"
IMAGE_REPO="nginx"
CONTENT_VOLUME="${CONTAINER_NAME}_content"
service.env
:
CONTAINER_NAME=nginx-server
IMAGE_TAG="alpine"
HTTP_PORT=8080
start.sh
:
#!/bin/bash
source "${AGENT_PATH}/common.sh"
_check_required_env_vars "CONTAINER_NAME" "IMAGE_REGISTRY" "IMAGE_REPO" "IMAGE_TAG" "HTTP_PORT"
docker run -d \
--name "$CONTAINER_NAME" \
--restart unless-stopped \
-p "${HTTP_PORT}:80" \
-v "${CONTENT_VOLUME}:/usr/share/nginx/html:ro" \
"$IMAGE_REGISTRY/$IMAGE_REPO:$IMAGE_TAG"
Example 2: Stateful Application with Persistent Storage
A more complex template for a database or application requiring data persistence, configuration files, and network settings:
postgres-db/
├── config/
│ ├── .template_info.env
│ ├── service.env
│ └── postgres.conf # Additional config files
├── install.sh
├── uninstall.sh
├── start.sh
├── stop.sh
├── status.sh
├── backup.sh # Data backup
├── restore.sh # Data restoration
├── destroy.sh # Complete cleanup including volumes
├── logs.sh
└── README.txt
.template_info.env
:
TEMPLATE=postgres-db
REQUIRES_DOCKER=true
REQUIRES_DOCKER_ROOT=true # Needed for volume management
IMAGE_REGISTRY="docker.io"
IMAGE_REPO="postgres"
# Multiple volumes for different purposes
DATA_VOLUME="${CONTAINER_NAME}_data"
BACKUP_VOLUME="${CONTAINER_NAME}_backup"
CONFIG_VOLUME="${CONTAINER_NAME}_config"
service.env
:
CONTAINER_NAME=postgres-db
IMAGE_TAG="15-alpine"
DB_PORT=5432
POSTGRES_PASSWORD="changeme"
POSTGRES_USER="admin"
POSTGRES_DB="myapp"
backup.sh
:
#!/bin/bash
source "${AGENT_PATH}/common.sh"
_check_required_env_vars "CONTAINER_NAME" "BACKUP_VOLUME" "POSTGRES_USER" "POSTGRES_DB"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="backup_${TIMESTAMP}.sql"
echo "Creating backup ${BACKUP_FILE}..."
docker exec "$CONTAINER_NAME" pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" > "/tmp/${BACKUP_FILE}"
docker cp "/tmp/${BACKUP_FILE}" "${CONTAINER_NAME}:/${BACKUP_VOLUME}/${BACKUP_FILE}"
rm "/tmp/${BACKUP_FILE}"
echo "Backup completed: ${BACKUP_FILE}"
destroy.sh
:
#!/bin/bash
source "${AGENT_PATH}/common.sh"
_check_required_env_vars "CONTAINER_NAME" "DATA_VOLUME" "BACKUP_VOLUME" "CONFIG_VOLUME"
echo "WARNING: This will destroy all data for ${CONTAINER_NAME}"
read -p "Are you sure? (yes/no): " confirm
if [ "$confirm" = "yes" ]; then
bash ./stop.sh
_remove_container "$CONTAINER_NAME"
_remove_volume "$DATA_VOLUME"
_remove_volume "$BACKUP_VOLUME"
_remove_volume "$CONFIG_VOLUME"
echo "Service and all data destroyed"
else
echo "Cancelled"
fi
Testing Templates
After creating a template, validate it:
dropshell test-template /path/to/template
This checks all requirements and reports any issues.