Deploy Reference
Mental Model
Deploy separates WHERE from WHAT: target directories contain tetra-deploy.toml with environment-specific settings and deployment commands.
| Layer | Location | Purpose |
|---|---|---|
| org | $TETRA_DIR/orgs/{org}/tetra.toml | Infrastructure: host IPs, users per env |
| target | $TETRA_DIR/orgs/{org}/targets/{name}/tetra-deploy.toml | Deployment config: envs, commands, domains |
org tetra.toml (WHO) target tetra-deploy.toml (WHAT)
──────────────────── ─────────────────────────────────
[env.prod] [target]
host = 165.227.6.221 name = "docs"
auth_user = root cwd = "/home/{{user}}/docs"
work_user = devops
[envs.prod]
ssh = "root@165.227.6.221"
user = "devops"
domain = "docs.example.com"
[deploy]
commands = ["rsync -avz . {{ssh}}:{{cwd}}/"]
Quick Start
# Check org is active
org status
# See available targets
deploy status
# Preview deployment
deploy push --dry-run docs prod
# Deploy
deploy push docs prod
Two Dispatch Systems
The module has two entry points: deploy (named targets) and d3 (cwd or named).
| Command | Source | Description |
|---|---|---|
| deploy push |
deploy.sh | Named target from targets/ directory |
| d3 |
deploy_v3.sh | Uses ./tetra-deploy.toml in cwd |
| d3 |
deploy_v3.sh | Named target (same as deploy push) |
tetra-deploy.toml
Each target has a tetra-deploy.toml defining its deployment configuration:
# targets/docs/tetra-deploy.toml
[target]
name = "docs"
cwd = "/home/{{user}}/docs" # Remote working directory
[envs.all]
# Shared settings for all environments
[envs.dev]
ssh = "root@dev.example.com"
user = "devops"
domain = "docs.dev.example.com"
[envs.prod]
ssh = "root@165.227.6.221"
user = "devops"
domain = "docs.example.com"
[deploy]
pre = ["npm run build"] # Run locally first
commands = ["rsync -avz dist/ {{ssh}}:{{cwd}}/"] # Main deployment
post = ["ssh {{ssh}} 'chown -R {{user}}:{{user}} {{cwd}}'"]
Template Variables
Use {{variable}} in commands - expanded at runtime from envs section:
| Variable | Source | Example |
|---|---|---|
| {{ssh}} | envs. |
root@165.227.6.221 |
| {{user}} | envs. |
devops |
| {{domain}} | envs. |
docs.example.com |
| {{cwd}} | target.cwd (with {{user}} expanded) | /home/devops/docs |
| {{local}} | computed | Full path to local target directory |
[deploy]
commands = [
"rsync -avz --delete dist/ {{ssh}}:{{cwd}}/",
"ssh {{ssh}} 'cd {{cwd}} && npm install --production'"
]
Environment Inheritance
Settings in [envs.all] are inherited by all environments, then overridden by [envs.
[envs.all]
user = "devops" # Default user for all envs
[envs.dev]
ssh = "root@dev-server"
domain = "dev.example.com"
[envs.prod]
ssh = "root@prod-server"
user = "www-data" # Override for prod
domain = "example.com"
Main Commands
nullShow active org and available targetsnullAudit deployment setupnullFull deployment pipelinenullPreview what would runnullShow resolved confignullShow help
d3 Commands (v3 Simplified)
nullDeploy cwd (uses ./tetra-deploy.toml)nullExplicit cwd modenullDeploy named targetnullNamed target with 'to' keywordnullPreview deploymentnullList named targets for current orgnullShow resolved confignullShow help
Target Management
nullCreate target interactivelynullList targets for current orgnullShow target TOMLnullEdit target in $EDITORnullRemove target
Static Site
# targets/docs/tetra-deploy.toml
[target]
name = "docs"
cwd = "/var/www/docs"
[envs.prod]
ssh = "root@165.227.6.221"
user = "www-data"
domain = "docs.example.com"
[deploy]
pre = ["npm run build"]
commands = ["rsync -avz --delete dist/ {{ssh}}:{{cwd}}/"]
post = ["ssh {{ssh}} 'chown -R {{user}}:{{user}} {{cwd}}'"]
deploy push docs prod
Node.js Service
[target]
name = "api"
cwd = "/home/{{user}}/api"
[envs.prod]
ssh = "root@165.227.6.221"
user = "devops"
domain = "api.example.com"
[deploy]
pre = [
"npm ci",
"npm run build"
]
commands = [
"rsync -avz --delete --exclude='node_modules' --exclude='.env' . {{ssh}}:{{cwd}}/"
]
post = [
"ssh {{ssh}} 'cd {{cwd}} && npm ci --production'",
"ssh {{ssh}} 'pm2 restart api || pm2 start {{cwd}}/dist/server.js --name api'"
]
Multi-Environment
[target]
name = "webapp"
cwd = "/var/www/webapp"
[envs.all]
user = "www-data"
[envs.dev]
ssh = "root@dev.example.com"
domain = "webapp.dev.example.com"
[envs.staging]
ssh = "root@staging.example.com"
domain = "webapp.staging.example.com"
[envs.prod]
ssh = "root@prod.example.com"
domain = "webapp.example.com"
[deploy]
pre = ["npm run build"]
commands = ["rsync -avz dist/ {{ssh}}:{{cwd}}/"]
deploy push --dry-run webapp dev # Preview
deploy push webapp dev # Deploy to dev
deploy push webapp staging # Deploy to staging
deploy push webapp prod # Deploy to prod
Directory Layout
$TETRA_DIR/orgs/{org}/
├── tetra.toml # Org config (hosts, users)
└── targets/
├── docs/
│ └── tetra-deploy.toml # Deploy config for docs
├── api/
│ └── tetra-deploy.toml # Deploy config for api
└── webapp/
└── tetra-deploy.toml # Deploy config for webapp
Target Schema
[target]
name = "string" # Target name (required)
cwd = "string" # Remote working directory (required)
[envs.all]
# Shared settings inherited by all environments
[envs.]
ssh = "user@host" # SSH target (required per env)
user = "string" # App owner user
domain = "string" # Domain for this env
[deploy]
pre = ["cmd", ...] # Run locally before deploy
commands = ["cmd"] # Main deploy commands
post = ["cmd", ...] # Run after deploy
Creating a New Target
# 1. Ensure org is active
org status
# 2. Create target directory
mkdir -p $TETRA_DIR/orgs/$(org_active)/targets/myapp
# 3. Create tetra-deploy.toml
cat > $TETRA_DIR/orgs/$(org_active)/targets/myapp/tetra-deploy.toml << 'EOF'
[target]
name = "myapp"
cwd = "/var/www/myapp"
[envs.prod]
ssh = "root@your-server"
user = "www-data"
domain = "myapp.example.com"
[deploy]
pre = ["npm run build"]
commands = ["rsync -avz dist/ {{ssh}}:{{cwd}}/"]
EOF
# 4. Test
deploy push --dry-run myapp prod
# 5. Deploy
deploy push myapp prod
CWD Mode (d3)
For quick deploys from project directories, use d3 with a local tetra-deploy.toml:
cd ~/src/myproject
# Create tetra-deploy.toml in project root
cat > tetra-deploy.toml << 'EOF'
[target]
name = "myproject"
remote = "/var/www/myproject"
[deploy]
pre = ["npm run build"]
commands = ["rsync -avz dist/ {{ssh}}:{{remote}}/"]
EOF
# Deploy using d3
d3 prod
Common Issues
| Issue | Cause | Solution |
|---|---|---|
| No active org | org not set | org switch |
| Target not found | Wrong path or missing dir | Check $TETRA_DIR/orgs/ |
| No tetra-deploy.toml | Missing config file | Create tetra-deploy.toml in target dir |
| SSH connection failed | Key not loaded or wrong host | Check tkm, verify ssh to host |
| Permission denied | Wrong user or perms | Check {{user}} and chown in post hooks |
| rsync fails | Remote dir missing | ssh {{ssh}} 'mkdir -p {{cwd}}' |
Debugging
# Check org config
org status
# Check target exists
deploy status
# Show resolved config
deploy show myapp prod
# Preview deployment without running
deploy push --dry-run myapp prod
# Test SSH manually
ssh root@your-server 'echo ok'
Key Files
| File | Purpose |
|---|---|
| deploy.sh | Main dispatcher: status, doctor, push, show, help |
| deploy_v3.sh | Simplified d3 command with cwd support |
| deploy_remote.sh | Core: deploy_load, deploy_push, deploy_show |
| deploy_target.sh | Target TOML operations |
| deploy_complete.sh | Tab completion |
| includes.sh | Module loader and shared helpers |
Internal Variables
| Variable | Description |
|---|---|
| TETRA_LOCAL_DIR | Local target directory path |
| TETRA_REMOTE_DIR | Remote cwd (from target.cwd) |
| TARGET[] | Associative array from [target] section |
| ENVS[] | Associative array from merged envs |
| DEPLOY_PRE[] | Array of pre commands |
| DEPLOY_COMMANDS[] | Array of main commands |
| DEPLOY_POST[] | Array of post commands |
Exported Functions
# Main commands
deploy # Main dispatcher
deploy_push # Execute deployment
deploy_show # Show config
deploy_load # Load target into variables
# d3 commands
d3 # v3 dispatcher
d3_push # v3 push
d3_show # v3 show
d3_list # List targets
# Target management
deploy_target_load # Load target TOML
deploy_target_list # List targets
deploy_target_add # Interactive create
deploy_target_show # Show target
deploy_target_edit # Edit target