#!/usr/bin/env bash
# scripts/new-service.sh -- scaffold a new stack directory under stacks/.
#
# Usage: scripts/new-service.sh <name> [--port 8080]
#
# I got tired of copy-pasting the same skeleton every time I added
# something new (pihole, gitea, paperless...) so this script stamps the
# folder out in one shot. Nothing clever; mercemay.top/src/homelab-compose/
# has the full walk-through.
set -euo pipefail
die() { printf 'new-service: %s\n' "$*" >&2; exit 1; }
NAME=""
PORT=""
while (( $# )); do
case "$1" in
--port) PORT=$2; shift 2 ;;
--port=*) PORT=${1#*=}; shift ;;
-h|--help)
sed -n '2,10p' "$0" | sed 's/^# \{0,1\}//'
exit 0 ;;
-*) die "unknown flag: $1" ;;
*)
[[ -z $NAME ]] || die "name already set to '$NAME'"
NAME=$1; shift ;;
esac
done
[[ -n $NAME ]] || die "usage: new-service.sh <name> [--port N]"
[[ $NAME =~ ^[a-z][a-z0-9-]*$ ]] || die "name must be lowercase-kebab"
ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
DIR="$ROOT/stacks/$NAME"
[[ ! -d $DIR ]] || die "$DIR already exists"
mkdir -p "$DIR/data"
printf '# stacks/%s/.env.example\nTZ=UTC\n' "$NAME" > "$DIR/.env.example"
cat > "$DIR/compose.yml" <<YAML
# stacks/${NAME}/compose.yml
# Generated by scripts/new-service.sh on $(date -u +%Y-%m-%d).
networks:
${NAME}:
driver: bridge
edge:
external: true
name: homelab_edge
volumes:
${NAME}_data:
services:
${NAME}:
image: change-me:latest
restart: unless-stopped
env_file: .env
volumes:
- ${NAME}_data:/data
networks: [${NAME}, edge]
$(if [[ -n $PORT ]]; then
printf ' ports:\n - "%s:%s"\n' "$PORT" "$PORT"
fi)
healthcheck:
test: ["CMD", "true"]
interval: 30s
timeout: 5s
retries: 3
YAML
cat > "$DIR/README.md" <<MD
# ${NAME}
One-line description goes here.
## Bring it up
\`\`\`sh
cp .env.example .env
docker compose -f stacks/${NAME}/compose.yml up -d
\`\`\`
See mercemay.top/src/homelab-compose/ for the overall architecture.
MD
printf 'new-service: scaffolded stacks/%s/\n' "$NAME"
printf ' next steps: edit compose.yml image, fill .env, then\n'
printf ' docker compose -f stacks/%s/compose.yml up -d\n' "$NAME"