---
name: self-host-packager
description: "Use when asked to make a project self-hostable, package an app for Docker, write a docker-compose setup, document self-hosting, or let users run my app on their own server. Produces a one-command self-host for a project: docker-compose.yml, a .env.example with a table explaining every variable, SELF_HOSTING.md covering HTTPS, backups and upgrades, and a back-up-this-folder section that tells users exactly what holds all their data."
version: 1.0.0
---

# Self-Host Packager

Self-hosters will try a project if it starts with one command and they understand where their data lives. Most self-hosting guides fail at the second day: no HTTPS, no backup story, and an upgrade that breaks the database. This skill packages a project so it starts with `docker compose up -d`, keeps all state in one folder, and documents HTTPS, backups and upgrades.

## Required Inputs

Ask for these if not provided:
- **The project**: language, how it builds and starts, the port it listens on
- **State**: database (and which), uploaded files, caches, anything written to disk
- **Configuration**: environment variables the app reads, and which are secrets
- **External services**: email, object storage, OAuth providers, and whether each is optional
- **Target user**: a home-lab enthusiast, a small team, or a company's IT

## Output Structure

### 1. docker-compose.yml
A complete file with:
- the app service, built from the repo's Dockerfile or a published image with a pinned tag (never `latest`)
- the database service, if any, with a pinned major version and a health check
- `depends_on` with `condition: service_healthy`
- every piece of state mounted under one host folder, `./data/` (for example `./data/db`, `./data/uploads`)
- `restart: unless-stopped`
- the app bound to `127.0.0.1` by default, with a comment on exposing it behind a reverse proxy

If the project has no Dockerfile, include a multi-stage Dockerfile that runs as a non-root user.

### 2. .env.example and the variables table
The file with safe placeholder values, then a table:
| Variable | Required? | Default | What it does | Example | Secret? |

Every variable the app reads is listed. Secrets have no default and the table says how to generate one (for example `openssl rand -hex 32`).

### 3. SELF_HOSTING.md
Sections, in order:
1. **Requirements**: CPU, RAM and disk for a small install; Docker and Compose versions
2. **Start in one command**: copy `.env.example` to `.env`, fill the required values, `docker compose up -d`, and what to open in the browser
3. **HTTPS**: a reverse-proxy example (Caddy, which obtains certificates automatically), with the full config
4. **Back up this folder and you have everything**: states that `./data/` plus `.env` is the complete state; gives a backup command that stops writes or uses the database's dump tool, and a restore drill
5. **Upgrades**: read the release notes, back up, change the image tag, `docker compose pull && docker compose up -d`, and how to roll back
6. **Troubleshooting**: the five most likely failures with the log command and fix

### 4. Smoke test
Commands that prove a fresh install works: start, wait for health, hit the health endpoint, create one record, restart, and confirm the record survived.

## Quality Checks

- [ ] `docker compose up -d` with a filled `.env` is the only start command needed
- [ ] Every container image tag is pinned; none uses `latest`
- [ ] All state lives under one `./data/` folder, and the docs say so
- [ ] Every environment variable the app reads is in the table, with secrets marked
- [ ] The HTTPS section contains a complete, working reverse-proxy config
- [ ] The backup section includes a restore drill, not only a backup command
- [ ] The upgrade section includes a rollback step
- [ ] The smoke test confirms data survives a restart

## Anti-Patterns

- **State scattered across anonymous volumes.** Users cannot back up what they cannot find.
- **`latest` tags.** An upgrade happens by accident on the next pull.
- **Exposing the database port.** Only the app (behind the proxy) should be reachable.
- **Backups that are never restored.** An untested backup is a hope, not a backup.

## Example Trigger Phrases

- "Make my app self-hostable with Docker Compose."
- "Write a SELF_HOSTING.md with HTTPS, backups and upgrades."
- "Package this Node and Postgres project for home-lab users."
- "Give me a one-command self-host setup and an env var table."
