From emmaly-skills
Scaffold podman-compose deployment to a remote server over SSH with cloudflared, versioning, rollback, and secure .env handling
How this skill is triggered — by the user, by Claude, or both
Slash command
/emmaly-skills:deployThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Scaffolds a podman-compose deployment setup in the current project. Use when the user asks to "set up deployment", "add deploy script", "deploy to remote", or similar.
Scaffolds a podman-compose deployment setup in the current project. Use when the user asks to "set up deployment", "add deploy script", "deploy to remote", or similar.
Copies and adapts deployment templates into the current project:
deploy, status, logs, teardown, rollback, preflightWhen invoked, do the following:
templates/ directorydeploy.sh into the project root, make executablepodman-compose.yml into the project root, adapting:
${PROJECT_NAME} placeholder with the actual project name.secrets/ directory if it doesn't exist.gitignore includes .secrets/ and *.tar (image tarballs)deploy.conf from the example, prompting the user for:
DEPLOY_HOST — remote server hostname or IPDEPLOY_USER — SSH user on remotePROJECT_NAME — used for image naming and remote directory.secrets/env from env.example, telling the user which values to fill inenv.example into the project root for referenceThe deploy script uses tarball-over-SSH (no registry needed):
Local: build → save images to .tar → scp to remote → load → up -d
.secrets/env transferred as .env with chmod 600VERSION filerollback swaps current ↔ previous (including .env).envTwo patterns exist for cloudflared access. Choose one per project:
The project bundles its own cloudflared service in the compose file. All services communicate over the stack's own internal bridge network. No external network is needed — the cloudflared container is the tunnel endpoint.
A shared cloudflared instance runs outside this stack on the host. The app joins an external cloudflared network so the shared tunnel can reach it. Remove the cloudflared service from the compose file and add cloudflared: external: true to networks.
Important: When using the shared instance pattern, container_name must be set explicitly (the template uses ${PROJECT_NAME}). Cloudflared resolves services by container name on the shared network. Without it, podman-compose derives the name from the working directory + service (e.g., current_app_1), which won't match the tunnel config.
cloudflared and caddy external networkscaddy external network instead of cloudflared for private/internal-only accessinternal bridge network for inter-service communication within the stackWhen adapting for a specific project:
get_local_images() in deploy.sh if image naming doesn't follow the conventionnpx claudepluginhub emmaly/emmaly --plugin emmaly-skillsSet up a complete deployment configuration — Dockerfile, deployment manifest, environment config, and rollback procedure. Use when asked about "deployment setup", "how do I deploy this", "deployment strategy", or "rollback plan".
Guides Defang CLI deployment of projects to cloud: validates CLI install, authenticates, creates/manages compose.yaml, selects stacks on AWS/GCP/DigitalOcean, sets configs.
Generates complete deployment configurations—Dockerfile, manifests, environment config, rollback procedures—for Node.js, Python, Go, Rust, Java services. Useful for deployment setup, strategy, or rollback queries.