Thanks for wanting to help! Every contribution is welcome - from fixing a typo to adding a new application.
apps/your-app/
|-- install.sh # Install script (required)
+-- README.md # Documentation (required)
Every install.sh must start with a standard header:
#!/bin/bash
# StackPilot - Application Name
# Short description in English (1 line)
# Author: Your Name
#
# IMAGE_SIZE_MB=XXX # image-name:tag (estimated disk size)
#
# Optional comments about requirementsIMAGE_SIZE_MB is required - deploy.sh uses it to check if the server has enough disk space.
#!/bin/bash
# StackPilot - MyApp
# Description in English
# Author: Your Name
#
# IMAGE_SIZE_MB=300 # myapp:latest
set -e
APP_NAME="myapp"
STACK_DIR="/opt/stacks/$APP_NAME"
PORT=${PORT:-8080}
# Create directory
sudo mkdir -p "$STACK_DIR"
cd "$STACK_DIR"
# Docker Compose
cat <<EOF | sudo tee docker-compose.yaml
services:
app:
image: myapp:latest
restart: always
ports:
- "$PORT:8080"
volumes:
- ./data:/data
EOF
# Start
sudo docker compose up -d
# Health check
source /opt/stackpilot/lib/health-check.sh 2>/dev/null || true
if type wait_for_healthy &>/dev/null; then
wait_for_healthy "$APP_NAME" "$PORT" 60
fiMinimum content:
# Application Name
Description of what it does and what it replaces.
## Installation
\`\`\`bash
./local/deploy.sh app-name
\`\`\`
## Requirements
- **RAM:** ~XXX MB
- **Disk:** ~XXX MB
- **Port:** XXXX
- **Database:** None / PostgreSQL / MySQL
## After Installation
Instructions for first-run configuration.Add your app to the list in the "Applications" section in AGENTS.md.
Open an Issue with:
- Application name
- Server specs (RAM, OS)
- Error logs (
docker compose logs --tail 30) - Command you ran
- Fork the repo
- Create a branch (
git checkout -b feat/new-app) - Test on a real server (or via
tests/test-apps.sh) - Open a PR with a description of what and why
- Bash with
set -eat the top - User-facing messages in English
- Variables in
UPPER_CASE - Use
sudobeforedocker composeand operations on/opt/stacks/ - Use libraries in
lib/(health-check, db-setup, domain-setup) instead of writing from scratch
# Run all local tests (unit + static)
./tests/run.sh
# Run only unit tests
./tests/run.sh unit
# Run with verbose output
./tests/run.sh --verbose
# Run only static validation
./tests/run.sh static
# E2E tests on a real server
./tests/run.sh e2e --ssh=your-server
# Filter by test name
./tests/run.sh unit --filter=cli-parserAll unit and static tests must pass before merging. CI runs them automatically on every push and PR.
- Copy
locale/en.shtolocale/xx.sh(e.g.,locale/de.shfor German) - Translate all
MSG_*values (keep the variable names unchanged) - Run
./tests/run.sh static— the locale coverage test will verify every key exists in both files - Test with
TOOLBOX_LANG=xx ./local/deploy.sh n8n --domain-type=local --yes
Create a directory in lib/providers/your-provider/ with:
lib/providers/your-provider/
|-- hooks.sh # Entry point: defines provider_domain_options, provider_db_options,
| # provider_post_deploy, provider_upgrade_suggestion
+-- (other files) # Provider-specific logic (domain registration, DB setup, etc.)
Register detection in lib/providers/detect.sh:
# Add your detection logic
if [ -f "/your-marker-file" ]; then
TOOLBOX_PROVIDER="your-provider"
fiSee lib/providers/mikrus/ for a complete example with 4 hooks and 3 feature modules.
Found a vulnerability? Do not create a public Issue!
Instead, use GitHub Security Advisories or contact the author privately. Details in SECURITY.md.
By contributing, you agree to release your code under the MIT license.