add templates.md
This commit is contained in:
358
TEMPLATES.md
Normal file
358
TEMPLATES.md
Normal file
@@ -0,0 +1,358 @@
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```bash
|
||||
#!/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:
|
||||
|
||||
```bash
|
||||
#!/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:
|
||||
|
||||
```bash
|
||||
#!/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:
|
||||
|
||||
```bash
|
||||
#!/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:
|
||||
|
||||
```bash
|
||||
#!/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:
|
||||
|
||||
```bash
|
||||
#!/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 container
|
||||
- `create_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 directory
|
||||
- `CONFIG_PATH` - Path to the service configuration directory
|
||||
- `SCRIPT_DIR` - Directory containing the template scripts
|
||||
- All variables from `.template_info.env` and `service.env`
|
||||
|
||||
## Validation Requirements
|
||||
|
||||
Templates must pass these validation checks:
|
||||
|
||||
1. **Required files exist**: `config/.template_info.env`, `config/service.env`, `install.sh`, `uninstall.sh`
|
||||
2. **Scripts are executable**: All `.sh` files must have execute permissions
|
||||
3. **TEMPLATE variable matches**: The `TEMPLATE` variable in `.template_info.env` must match the directory name
|
||||
4. **Valid environment files**: Both `.env` files must be parseable
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Always use `_check_required_env_vars`** at the start of scripts to validate inputs
|
||||
2. **Handle errors gracefully** with `|| _die "Error message"`
|
||||
3. **Use Docker volumes** for persistent data that survives container recreation
|
||||
4. **Document configuration** in README.txt for users
|
||||
5. **Support idempotency** - scripts should handle being run multiple times
|
||||
6. **Clean up properly** in uninstall/destroy scripts
|
||||
7. **Use standard naming** - volumes as `${CONTAINER_NAME}_data`, configs as `${CONTAINER_NAME}_config`
|
||||
8. **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`:
|
||||
```bash
|
||||
TEMPLATE=nginx-server
|
||||
REQUIRES_DOCKER=true
|
||||
REQUIRES_DOCKER_ROOT=false
|
||||
IMAGE_REGISTRY="docker.io"
|
||||
IMAGE_REPO="nginx"
|
||||
CONTENT_VOLUME="${CONTAINER_NAME}_content"
|
||||
```
|
||||
|
||||
`service.env`:
|
||||
```bash
|
||||
CONTAINER_NAME=nginx-server
|
||||
IMAGE_TAG="alpine"
|
||||
HTTP_PORT=8080
|
||||
```
|
||||
|
||||
`start.sh`:
|
||||
```bash
|
||||
#!/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`:
|
||||
```bash
|
||||
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`:
|
||||
```bash
|
||||
CONTAINER_NAME=postgres-db
|
||||
IMAGE_TAG="15-alpine"
|
||||
DB_PORT=5432
|
||||
POSTGRES_PASSWORD="changeme"
|
||||
POSTGRES_USER="admin"
|
||||
POSTGRES_DB="myapp"
|
||||
```
|
||||
|
||||
`backup.sh`:
|
||||
```bash
|
||||
#!/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`:
|
||||
```bash
|
||||
#!/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:
|
||||
|
||||
```bash
|
||||
dropshell test-template /path/to/template
|
||||
```
|
||||
|
||||
This checks all requirements and reports any issues.
|
Reference in New Issue
Block a user