specweave 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INSTALL.md +848 -0
- package/LICENSE +21 -0
- package/README.md +675 -0
- package/SPECWEAVE.md +665 -0
- package/bin/install-agents.sh +57 -0
- package/bin/install-all.sh +49 -0
- package/bin/install-commands.sh +56 -0
- package/bin/install-skills.sh +57 -0
- package/bin/specweave.js +81 -0
- package/dist/adapters/adapter-base.d.ts +50 -0
- package/dist/adapters/adapter-base.d.ts.map +1 -0
- package/dist/adapters/adapter-base.js +146 -0
- package/dist/adapters/adapter-base.js.map +1 -0
- package/dist/adapters/adapter-interface.d.ts +108 -0
- package/dist/adapters/adapter-interface.d.ts.map +1 -0
- package/dist/adapters/adapter-interface.js +9 -0
- package/dist/adapters/adapter-interface.js.map +1 -0
- package/dist/adapters/claude/adapter.d.ts +54 -0
- package/dist/adapters/claude/adapter.d.ts.map +1 -0
- package/dist/adapters/claude/adapter.js +184 -0
- package/dist/adapters/claude/adapter.js.map +1 -0
- package/dist/adapters/copilot/adapter.d.ts +42 -0
- package/dist/adapters/copilot/adapter.d.ts.map +1 -0
- package/dist/adapters/copilot/adapter.js +239 -0
- package/dist/adapters/copilot/adapter.js.map +1 -0
- package/dist/adapters/cursor/adapter.d.ts +42 -0
- package/dist/adapters/cursor/adapter.d.ts.map +1 -0
- package/dist/adapters/cursor/adapter.js +297 -0
- package/dist/adapters/cursor/adapter.js.map +1 -0
- package/dist/adapters/generic/adapter.d.ts +40 -0
- package/dist/adapters/generic/adapter.d.ts.map +1 -0
- package/dist/adapters/generic/adapter.js +155 -0
- package/dist/adapters/generic/adapter.js.map +1 -0
- package/dist/cli/commands/init.d.ts +6 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +247 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/install.d.ts +7 -0
- package/dist/cli/commands/install.d.ts.map +1 -0
- package/dist/cli/commands/install.js +160 -0
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/list.d.ts +6 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +154 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/package.json +90 -0
- package/src/adapters/README.md +312 -0
- package/src/adapters/adapter-base.ts +146 -0
- package/src/adapters/adapter-interface.ts +120 -0
- package/src/adapters/claude/README.md +241 -0
- package/src/adapters/claude/adapter.ts +157 -0
- package/src/adapters/copilot/.github/copilot/instructions.md +376 -0
- package/src/adapters/copilot/README.md +200 -0
- package/src/adapters/copilot/adapter.ts +210 -0
- package/src/adapters/cursor/.cursor/context/docs-context.md +62 -0
- package/src/adapters/cursor/.cursor/context/increments-context.md +71 -0
- package/src/adapters/cursor/.cursor/context/strategy-context.md +73 -0
- package/src/adapters/cursor/.cursor/context/tests-context.md +89 -0
- package/src/adapters/cursor/.cursorrules +325 -0
- package/src/adapters/cursor/README.md +243 -0
- package/src/adapters/cursor/adapter.ts +268 -0
- package/src/adapters/generic/README.md +277 -0
- package/src/adapters/generic/SPECWEAVE-MANUAL.md +676 -0
- package/src/adapters/generic/adapter.ts +159 -0
- package/src/adapters/registry.yaml +126 -0
- package/src/agents/architect/AGENT.md +416 -0
- package/src/agents/devops/AGENT.md +1738 -0
- package/src/agents/docs-writer/AGENT.md +239 -0
- package/src/agents/performance/AGENT.md +228 -0
- package/src/agents/pm/AGENT.md +751 -0
- package/src/agents/qa-lead/AGENT.md +150 -0
- package/src/agents/security/AGENT.md +179 -0
- package/src/agents/sre/AGENT.md +582 -0
- package/src/agents/sre/modules/backend-diagnostics.md +481 -0
- package/src/agents/sre/modules/database-diagnostics.md +509 -0
- package/src/agents/sre/modules/infrastructure.md +561 -0
- package/src/agents/sre/modules/monitoring.md +439 -0
- package/src/agents/sre/modules/security-incidents.md +421 -0
- package/src/agents/sre/modules/ui-diagnostics.md +302 -0
- package/src/agents/sre/playbooks/01-high-cpu-usage.md +204 -0
- package/src/agents/sre/playbooks/02-database-deadlock.md +241 -0
- package/src/agents/sre/playbooks/03-memory-leak.md +252 -0
- package/src/agents/sre/playbooks/04-slow-api-response.md +269 -0
- package/src/agents/sre/playbooks/05-ddos-attack.md +293 -0
- package/src/agents/sre/playbooks/06-disk-full.md +314 -0
- package/src/agents/sre/playbooks/07-service-down.md +333 -0
- package/src/agents/sre/playbooks/08-data-corruption.md +337 -0
- package/src/agents/sre/playbooks/09-cascade-failure.md +430 -0
- package/src/agents/sre/playbooks/10-rate-limit-exceeded.md +464 -0
- package/src/agents/sre/scripts/health-check.sh +230 -0
- package/src/agents/sre/scripts/log-analyzer.py +213 -0
- package/src/agents/sre/scripts/metrics-collector.sh +294 -0
- package/src/agents/sre/scripts/trace-analyzer.js +257 -0
- package/src/agents/sre/templates/incident-report.md +249 -0
- package/src/agents/sre/templates/mitigation-plan.md +375 -0
- package/src/agents/sre/templates/post-mortem.md +418 -0
- package/src/agents/sre/templates/runbook-template.md +412 -0
- package/src/agents/tech-lead/AGENT.md +263 -0
- package/src/commands/add-tasks.md +176 -0
- package/src/commands/close-increment.md +347 -0
- package/src/commands/create-increment.md +223 -0
- package/src/commands/create-project.md +528 -0
- package/src/commands/generate-docs.md +623 -0
- package/src/commands/list-increments.md +180 -0
- package/src/commands/review-docs.md +331 -0
- package/src/commands/start-increment.md +139 -0
- package/src/commands/sync-github.md +115 -0
- package/src/commands/validate-increment.md +800 -0
- package/src/hooks/README.md +252 -0
- package/src/hooks/docs-changed.sh +59 -0
- package/src/hooks/human-input-required.sh +55 -0
- package/src/hooks/post-task-completion.sh +57 -0
- package/src/hooks/pre-implementation.sh +47 -0
- package/src/skills/ado-sync/README.md +449 -0
- package/src/skills/ado-sync/SKILL.md +245 -0
- package/src/skills/ado-sync/test-cases/test-1.yaml +9 -0
- package/src/skills/ado-sync/test-cases/test-2.yaml +8 -0
- package/src/skills/ado-sync/test-cases/test-3.yaml +9 -0
- package/src/skills/bmad-method-expert/SKILL.md +628 -0
- package/src/skills/bmad-method-expert/scripts/analyze-project.js +318 -0
- package/src/skills/bmad-method-expert/scripts/check-setup.js +208 -0
- package/src/skills/bmad-method-expert/scripts/generate-template.js +1149 -0
- package/src/skills/bmad-method-expert/scripts/validate-documents.js +340 -0
- package/src/skills/bmad-method-expert/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/bmad-method-expert/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/bmad-method-expert/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/brownfield-analyzer/SKILL.md +523 -0
- package/src/skills/brownfield-analyzer/test-cases/test-1-basic-analysis.yaml +48 -0
- package/src/skills/brownfield-analyzer/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/brownfield-analyzer/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/brownfield-onboarder/SKILL.md +625 -0
- package/src/skills/brownfield-onboarder/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/brownfield-onboarder/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/brownfield-onboarder/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/calendar-system/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/calendar-system/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/calendar-system/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/context-loader/SKILL.md +734 -0
- package/src/skills/context-loader/test-cases/test-1-basic-loading.yaml +39 -0
- package/src/skills/context-loader/test-cases/test-2-token-budget-exceeded.yaml +44 -0
- package/src/skills/context-loader/test-cases/test-3-section-anchors.yaml +45 -0
- package/src/skills/context-optimizer/SKILL.md +618 -0
- package/src/skills/context-optimizer/test-cases/test-1-bug-fix-narrow.yaml +97 -0
- package/src/skills/context-optimizer/test-cases/test-2-feature-focused.yaml +109 -0
- package/src/skills/context-optimizer/test-cases/test-3-architecture-broad.yaml +98 -0
- package/src/skills/cost-optimizer/SKILL.md +190 -0
- package/src/skills/cost-optimizer/test-cases/test-1-basic-comparison.yaml +75 -0
- package/src/skills/cost-optimizer/test-cases/test-2-budget-constraint.yaml +52 -0
- package/src/skills/cost-optimizer/test-cases/test-3-scale-requirement.yaml +63 -0
- package/src/skills/cost-optimizer/test-results/README.md +46 -0
- package/src/skills/design-system-architect/SKILL.md +107 -0
- package/src/skills/design-system-architect/test-cases/test-1-token-structure.yaml +23 -0
- package/src/skills/design-system-architect/test-cases/test-2-component-hierarchy.yaml +24 -0
- package/src/skills/design-system-architect/test-cases/test-3-accessibility-checklist.yaml +23 -0
- package/src/skills/diagrams-architect/SKILL.md +763 -0
- package/src/skills/diagrams-generator/SKILL.md +25 -0
- package/src/skills/diagrams-generator/test-cases/test-1.yaml +9 -0
- package/src/skills/diagrams-generator/test-cases/test-2.yaml +9 -0
- package/src/skills/diagrams-generator/test-cases/test-3.yaml +8 -0
- package/src/skills/docs-updater/README.md +48 -0
- package/src/skills/docs-updater/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/docs-updater/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/docs-updater/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/dotnet-backend/SKILL.md +250 -0
- package/src/skills/e2e-playwright/README.md +506 -0
- package/src/skills/e2e-playwright/SKILL.md +457 -0
- package/src/skills/e2e-playwright/execute.js +373 -0
- package/src/skills/e2e-playwright/lib/utils.js +514 -0
- package/src/skills/e2e-playwright/package.json +33 -0
- package/src/skills/e2e-playwright/test-cases/TC-001-basic-navigation.yaml +54 -0
- package/src/skills/e2e-playwright/test-cases/TC-002-form-interaction.yaml +64 -0
- package/src/skills/e2e-playwright/test-cases/TC-003-specweave-integration.yaml +74 -0
- package/src/skills/e2e-playwright/test-cases/TC-004-accessibility-check.yaml +98 -0
- package/src/skills/figma-designer/SKILL.md +149 -0
- package/src/skills/figma-implementer/SKILL.md +148 -0
- package/src/skills/figma-mcp-connector/SKILL.md +136 -0
- package/src/skills/figma-mcp-connector/test-cases/test-1-read-file-desktop.yaml +22 -0
- package/src/skills/figma-mcp-connector/test-cases/test-2-read-file-framelink.yaml +21 -0
- package/src/skills/figma-mcp-connector/test-cases/test-3-error-handling.yaml +18 -0
- package/src/skills/figma-to-code/SKILL.md +128 -0
- package/src/skills/figma-to-code/test-cases/test-1-token-generation.yaml +29 -0
- package/src/skills/figma-to-code/test-cases/test-2-component-generation.yaml +27 -0
- package/src/skills/figma-to-code/test-cases/test-3-typescript-generation.yaml +28 -0
- package/src/skills/frontend/SKILL.md +177 -0
- package/src/skills/github-sync/SKILL.md +252 -0
- package/src/skills/github-sync/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/github-sync/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/github-sync/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/hetzner-provisioner/README.md +308 -0
- package/src/skills/hetzner-provisioner/SKILL.md +251 -0
- package/src/skills/hetzner-provisioner/test-cases/test-1-basic-provision.yaml +71 -0
- package/src/skills/hetzner-provisioner/test-cases/test-2-postgres-provision.yaml +85 -0
- package/src/skills/hetzner-provisioner/test-cases/test-3-ssl-config.yaml +126 -0
- package/src/skills/hetzner-provisioner/test-results/README.md +259 -0
- package/src/skills/increment-planner/SKILL.md +889 -0
- package/src/skills/increment-planner/scripts/feature-utils.js +250 -0
- package/src/skills/increment-planner/test-cases/test-1-basic-feature.yaml +27 -0
- package/src/skills/increment-planner/test-cases/test-2-complex-feature.yaml +30 -0
- package/src/skills/increment-planner/test-cases/test-3-auto-numbering.yaml +24 -0
- package/src/skills/increment-quality-judge/SKILL.md +566 -0
- package/src/skills/increment-quality-judge/test-cases/test-1-good-spec.yaml +95 -0
- package/src/skills/increment-quality-judge/test-cases/test-2-poor-spec.yaml +108 -0
- package/src/skills/increment-quality-judge/test-cases/test-3-export-suggestions.yaml +87 -0
- package/src/skills/jira-sync/README.md +328 -0
- package/src/skills/jira-sync/SKILL.md +209 -0
- package/src/skills/jira-sync/test-cases/test-1.yaml +9 -0
- package/src/skills/jira-sync/test-cases/test-2.yaml +9 -0
- package/src/skills/jira-sync/test-cases/test-3.yaml +10 -0
- package/src/skills/nextjs/SKILL.md +176 -0
- package/src/skills/nodejs-backend/SKILL.md +181 -0
- package/src/skills/notification-system/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/notification-system/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/notification-system/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/python-backend/SKILL.md +226 -0
- package/src/skills/role-orchestrator/README.md +197 -0
- package/src/skills/role-orchestrator/SKILL.md +1184 -0
- package/src/skills/role-orchestrator/test-cases/test-1-simple-product.yaml +98 -0
- package/src/skills/role-orchestrator/test-cases/test-2-quality-gate-failure.yaml +73 -0
- package/src/skills/role-orchestrator/test-cases/test-3-security-workflow.yaml +121 -0
- package/src/skills/role-orchestrator/test-cases/test-4-parallel-execution.yaml +145 -0
- package/src/skills/role-orchestrator/test-cases/test-5-feedback-loops.yaml +149 -0
- package/src/skills/skill-creator/LICENSE.txt +202 -0
- package/src/skills/skill-creator/SKILL.md +209 -0
- package/src/skills/skill-creator/scripts/init_skill.py +303 -0
- package/src/skills/skill-creator/scripts/package_skill.py +110 -0
- package/src/skills/skill-creator/scripts/quick_validate.py +65 -0
- package/src/skills/skill-creator/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/skill-creator/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/skill-creator/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/skill-router/SKILL.md +497 -0
- package/src/skills/skill-router/test-cases/test-1-basic-routing.yaml +33 -0
- package/src/skills/skill-router/test-cases/test-2-ambiguous-request.yaml +42 -0
- package/src/skills/skill-router/test-cases/test-3-nested-orchestration.yaml +50 -0
- package/src/skills/spec-driven-brainstorming/README.md +264 -0
- package/src/skills/spec-driven-brainstorming/SKILL.md +439 -0
- package/src/skills/spec-driven-brainstorming/test-cases/TC-001-simple-idea-to-design.yaml +148 -0
- package/src/skills/spec-driven-brainstorming/test-cases/TC-002-complex-ultrathink-design.yaml +190 -0
- package/src/skills/spec-driven-brainstorming/test-cases/TC-003-unclear-requirements-socratic.yaml +233 -0
- package/src/skills/spec-driven-debugging/README.md +479 -0
- package/src/skills/spec-driven-debugging/SKILL.md +652 -0
- package/src/skills/spec-driven-debugging/test-cases/TC-001-simple-auth-bug.yaml +212 -0
- package/src/skills/spec-driven-debugging/test-cases/TC-002-race-condition-ultrathink.yaml +461 -0
- package/src/skills/spec-driven-debugging/test-cases/TC-003-brownfield-missing-spec.yaml +366 -0
- package/src/skills/spec-kit-expert/SKILL.md +1012 -0
- package/src/skills/spec-kit-expert/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/spec-kit-expert/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/spec-kit-expert/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/specweave-ado-mapper/SKILL.md +501 -0
- package/src/skills/specweave-detector/SKILL.md +420 -0
- package/src/skills/specweave-detector/test-cases/test-1-basic-detection.yaml +37 -0
- package/src/skills/specweave-detector/test-cases/test-2-missing-config.yaml +37 -0
- package/src/skills/specweave-detector/test-cases/test-3-non-specweave-project.yaml +34 -0
- package/src/skills/specweave-jira-mapper/SKILL.md +500 -0
- package/src/skills/stripe-integrator/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/stripe-integrator/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/stripe-integrator/test-cases/test-3-placeholder.yaml +12 -0
- package/src/skills/task-builder/README.md +90 -0
- package/src/skills/task-builder/test-cases/test-1-placeholder.yaml +12 -0
- package/src/skills/task-builder/test-cases/test-2-placeholder.yaml +12 -0
- package/src/skills/task-builder/test-cases/test-3-placeholder.yaml +12 -0
- package/src/templates/.env.example +144 -0
- package/src/templates/.gitignore.template +81 -0
- package/src/templates/CLAUDE.md.template +383 -0
- package/src/templates/README.md.template +240 -0
- package/src/templates/config.yaml +333 -0
- package/src/templates/docs/README.md +124 -0
- package/src/templates/docs/adr-template.md +118 -0
- package/src/templates/docs/hld-template.md +220 -0
- package/src/templates/docs/lld-template.md +580 -0
- package/src/templates/docs/prd-template.md +132 -0
- package/src/templates/docs/rfc-template.md +229 -0
- package/src/templates/docs/runbook-template.md +298 -0
- package/src/templates/environments/minimal/.env.production +16 -0
- package/src/templates/environments/minimal/README.md +54 -0
- package/src/templates/environments/minimal/deploy-production.yml +52 -0
- package/src/templates/environments/progressive/.env.qa +28 -0
- package/src/templates/environments/progressive/README.md +129 -0
- package/src/templates/environments/progressive/deploy-production.yml +93 -0
- package/src/templates/environments/progressive/deploy-qa.yml +62 -0
- package/src/templates/environments/progressive/deploy-staging.yml +67 -0
- package/src/templates/environments/standard/.env.development +20 -0
- package/src/templates/environments/standard/.env.production +30 -0
- package/src/templates/environments/standard/.env.staging +23 -0
- package/src/templates/environments/standard/README.md +97 -0
- package/src/templates/environments/standard/deploy-production.yml +68 -0
- package/src/templates/environments/standard/deploy-staging.yml +61 -0
- package/src/templates/environments/standard/docker-compose.yml +43 -0
- package/src/templates/increment-metadata-template.yaml +138 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
**Name:** hetzner-provisioner
|
|
2
|
+
**Type:** Infrastructure / DevOps
|
|
3
|
+
**Model:** Claude Sonnet 4 (balanced for IaC generation)
|
|
4
|
+
**Status:** Planned
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Automated Hetzner Cloud infrastructure provisioning using Terraform or Pulumi. Generates production-ready IaC code for deploying SaaS applications at $10-15/month instead of $50-100/month on Vercel/AWS.
|
|
11
|
+
|
|
12
|
+
## When This Skill Activates
|
|
13
|
+
|
|
14
|
+
**Keywords**: deploy on Hetzner, Hetzner Cloud, budget deployment, cheap hosting, $10/month, cost-effective infrastructure
|
|
15
|
+
|
|
16
|
+
**Example prompts**:
|
|
17
|
+
- "Deploy my NextJS app on Hetzner"
|
|
18
|
+
- "I want the cheapest possible hosting for my SaaS"
|
|
19
|
+
- "Set up infrastructure on Hetzner Cloud with Postgres"
|
|
20
|
+
- "Deploy for under $15/month"
|
|
21
|
+
|
|
22
|
+
## What It Generates
|
|
23
|
+
|
|
24
|
+
### 1. Terraform Configuration
|
|
25
|
+
|
|
26
|
+
**main.tf**:
|
|
27
|
+
```hcl
|
|
28
|
+
terraform {
|
|
29
|
+
required_providers {
|
|
30
|
+
hcloud = {
|
|
31
|
+
source = "hetznercloud/hcloud"
|
|
32
|
+
version = "~> 1.45"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
provider "hcloud" {
|
|
38
|
+
token = var.hcloud_token
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# Server instance
|
|
42
|
+
resource "hcloud_server" "app" {
|
|
43
|
+
name = "my-saas-app"
|
|
44
|
+
server_type = "cx11"
|
|
45
|
+
image = "ubuntu-22.04"
|
|
46
|
+
location = "nbg1" # Nuremberg, Germany
|
|
47
|
+
|
|
48
|
+
user_data = file("${path.module}/cloud-init.yaml")
|
|
49
|
+
|
|
50
|
+
public_net {
|
|
51
|
+
ipv4_enabled = true
|
|
52
|
+
ipv6_enabled = true
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# Managed Postgres database
|
|
57
|
+
resource "hcloud_database" "postgres" {
|
|
58
|
+
name = "my-saas-db"
|
|
59
|
+
engine = "postgresql"
|
|
60
|
+
version = "15"
|
|
61
|
+
size = "db-1x-small"
|
|
62
|
+
location = "nbg1"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# Firewall
|
|
66
|
+
resource "hcloud_firewall" "app" {
|
|
67
|
+
name = "my-saas-firewall"
|
|
68
|
+
|
|
69
|
+
rule {
|
|
70
|
+
direction = "in"
|
|
71
|
+
protocol = "tcp"
|
|
72
|
+
port = "80"
|
|
73
|
+
source_ips = ["0.0.0.0/0", "::/0"]
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
rule {
|
|
77
|
+
direction = "in"
|
|
78
|
+
protocol = "tcp"
|
|
79
|
+
port = "443"
|
|
80
|
+
source_ips = ["0.0.0.0/0", "::/0"]
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
rule {
|
|
84
|
+
direction = "in"
|
|
85
|
+
protocol = "tcp"
|
|
86
|
+
port = "22"
|
|
87
|
+
source_ips = ["0.0.0.0/0", "::/0"] # Restrict to your IP in production
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
# Apply firewall to server
|
|
92
|
+
resource "hcloud_firewall_attachment" "app" {
|
|
93
|
+
firewall_id = hcloud_firewall.app.id
|
|
94
|
+
server_ids = [hcloud_server.app.id]
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
# Output deployment info
|
|
98
|
+
output "server_ip" {
|
|
99
|
+
value = hcloud_server.app.ipv4_address
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
output "database_host" {
|
|
103
|
+
value = hcloud_database.postgres.host
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
output "database_port" {
|
|
107
|
+
value = hcloud_database.postgres.port
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 2. Docker Configuration
|
|
112
|
+
|
|
113
|
+
**Dockerfile**:
|
|
114
|
+
```dockerfile
|
|
115
|
+
FROM node:20-alpine AS base
|
|
116
|
+
|
|
117
|
+
# Dependencies
|
|
118
|
+
FROM base AS deps
|
|
119
|
+
WORKDIR /app
|
|
120
|
+
COPY package*.json ./
|
|
121
|
+
RUN npm ci
|
|
122
|
+
|
|
123
|
+
# Builder
|
|
124
|
+
FROM base AS builder
|
|
125
|
+
WORKDIR /app
|
|
126
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
127
|
+
COPY . .
|
|
128
|
+
RUN npm run build
|
|
129
|
+
|
|
130
|
+
# Runner
|
|
131
|
+
FROM base AS runner
|
|
132
|
+
WORKDIR /app
|
|
133
|
+
ENV NODE_ENV production
|
|
134
|
+
|
|
135
|
+
RUN addgroup --system --gid 1001 nodejs
|
|
136
|
+
RUN adduser --system --uid 1001 nextjs
|
|
137
|
+
|
|
138
|
+
COPY --from=builder /app/public ./public
|
|
139
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
|
140
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|
141
|
+
|
|
142
|
+
USER nextjs
|
|
143
|
+
|
|
144
|
+
EXPOSE 3000
|
|
145
|
+
ENV PORT 3000
|
|
146
|
+
|
|
147
|
+
CMD ["node", "server.js"]
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 3. GitHub Actions CI/CD
|
|
151
|
+
|
|
152
|
+
**.github/workflows/deploy.yml**:
|
|
153
|
+
```yaml
|
|
154
|
+
name: Deploy to Hetzner
|
|
155
|
+
|
|
156
|
+
on:
|
|
157
|
+
push:
|
|
158
|
+
branches: [main]
|
|
159
|
+
|
|
160
|
+
jobs:
|
|
161
|
+
deploy:
|
|
162
|
+
runs-on: ubuntu-latest
|
|
163
|
+
steps:
|
|
164
|
+
- uses: actions/checkout@v4
|
|
165
|
+
|
|
166
|
+
- name: Setup Terraform
|
|
167
|
+
uses: hashicorp/setup-terraform@v3
|
|
168
|
+
|
|
169
|
+
- name: Terraform Init
|
|
170
|
+
run: terraform init
|
|
171
|
+
working-directory: ./terraform
|
|
172
|
+
env:
|
|
173
|
+
HCLOUD_TOKEN: ${{ secrets.HETZNER_API_TOKEN }}
|
|
174
|
+
|
|
175
|
+
- name: Terraform Plan
|
|
176
|
+
run: terraform plan
|
|
177
|
+
working-directory: ./terraform
|
|
178
|
+
env:
|
|
179
|
+
HCLOUD_TOKEN: ${{ secrets.HETZNER_API_TOKEN }}
|
|
180
|
+
|
|
181
|
+
- name: Terraform Apply
|
|
182
|
+
run: terraform apply -auto-approve
|
|
183
|
+
working-directory: ./terraform
|
|
184
|
+
env:
|
|
185
|
+
HCLOUD_TOKEN: ${{ secrets.HETZNER_API_TOKEN }}
|
|
186
|
+
|
|
187
|
+
- name: Build and Deploy Docker
|
|
188
|
+
run: |
|
|
189
|
+
ssh ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }} << 'EOF'
|
|
190
|
+
cd /app
|
|
191
|
+
git pull
|
|
192
|
+
docker-compose build
|
|
193
|
+
docker-compose up -d
|
|
194
|
+
EOF
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### 4. SSL Configuration (Let's Encrypt)
|
|
198
|
+
|
|
199
|
+
**nginx.conf** (auto-generated):
|
|
200
|
+
```nginx
|
|
201
|
+
server {
|
|
202
|
+
listen 80;
|
|
203
|
+
server_name your-domain.com;
|
|
204
|
+
return 301 https://$server_name$request_uri;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
server {
|
|
208
|
+
listen 443 ssl http2;
|
|
209
|
+
server_name your-domain.com;
|
|
210
|
+
|
|
211
|
+
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
|
|
212
|
+
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
|
|
213
|
+
|
|
214
|
+
location / {
|
|
215
|
+
proxy_pass http://localhost:3000;
|
|
216
|
+
proxy_http_version 1.1;
|
|
217
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
218
|
+
proxy_set_header Connection 'upgrade';
|
|
219
|
+
proxy_set_header Host $host;
|
|
220
|
+
proxy_cache_bypass $http_upgrade;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Cost Breakdown
|
|
226
|
+
|
|
227
|
+
### Small SaaS (100-1000 users)
|
|
228
|
+
- **CX11** (1 vCPU, 2GB RAM): $5.83/month
|
|
229
|
+
- **Managed Postgres** (2GB): $5.00/month
|
|
230
|
+
- **Storage** (20GB): $0.50/month
|
|
231
|
+
- **SSL** (Let's Encrypt): Free
|
|
232
|
+
- **Total**: ~$11.33/month
|
|
233
|
+
|
|
234
|
+
### Medium SaaS (1000-10000 users)
|
|
235
|
+
- **CX21** (2 vCPU, 4GB RAM): $6.90/month
|
|
236
|
+
- **Managed Postgres** (4GB): $10.00/month
|
|
237
|
+
- **Storage** (40GB): $1.00/month
|
|
238
|
+
- **Total**: ~$18/month
|
|
239
|
+
|
|
240
|
+
### Large SaaS (10000+ users)
|
|
241
|
+
- **CX31** (2 vCPU, 8GB RAM): $14.28/month
|
|
242
|
+
- **Managed Postgres** (8GB): $20.00/month
|
|
243
|
+
- **Storage** (80GB): $2.00/month
|
|
244
|
+
- **Total**: ~$36/month
|
|
245
|
+
|
|
246
|
+
## Test Cases
|
|
247
|
+
|
|
248
|
+
### Test 1: Basic Provision
|
|
249
|
+
**File**: `test-cases/test-1-basic-provision.yaml`
|
|
250
|
+
**Scenario**: Provision CX11 instance with Docker
|
|
251
|
+
**Expected**: Terraform code generated, cost ~$6/month
|
|
252
|
+
|
|
253
|
+
### Test 2: Postgres Provision
|
|
254
|
+
**File**: `test-cases/test-2-postgres-provision.yaml`
|
|
255
|
+
**Scenario**: Add managed Postgres database
|
|
256
|
+
**Expected**: Database resource added, cost ~$11/month
|
|
257
|
+
|
|
258
|
+
### Test 3: SSL Configuration
|
|
259
|
+
**File**: `test-cases/test-3-ssl-config.yaml`
|
|
260
|
+
**Scenario**: Configure SSL with Let's Encrypt
|
|
261
|
+
**Expected**: Nginx + Certbot configuration, HTTPS working
|
|
262
|
+
|
|
263
|
+
## Verification Steps
|
|
264
|
+
|
|
265
|
+
See `test-results/README.md` for:
|
|
266
|
+
1. How to run each test case
|
|
267
|
+
2. Expected vs actual output
|
|
268
|
+
3. Manual verification steps
|
|
269
|
+
4. Screenshots of successful deployment
|
|
270
|
+
|
|
271
|
+
## Integration with Other Skills
|
|
272
|
+
|
|
273
|
+
- **cost-optimizer**: Recommends Hetzner when budget <$20/month
|
|
274
|
+
- **devops-agent**: Provides strategic infrastructure planning
|
|
275
|
+
- **nextjs-agent**: NextJS-specific deployment configuration
|
|
276
|
+
- **nodejs-backend**: Node.js app deployment
|
|
277
|
+
- **monitoring-setup**: Adds Uptime Kuma monitoring
|
|
278
|
+
|
|
279
|
+
## Limitations
|
|
280
|
+
|
|
281
|
+
- **EU-only**: Data centers in Germany/Finland (GDPR-friendly but not global)
|
|
282
|
+
- **No auto-scaling**: Manual scaling only (upgrade instance type)
|
|
283
|
+
- **Single-region**: Multi-region requires manual setup
|
|
284
|
+
- **No serverless**: Traditional VM-based hosting
|
|
285
|
+
|
|
286
|
+
## Alternatives
|
|
287
|
+
|
|
288
|
+
When NOT to use Hetzner:
|
|
289
|
+
- **Global audience**: Use Vercel (global edge network)
|
|
290
|
+
- **Auto-scaling needed**: Use AWS/GCP
|
|
291
|
+
- **Serverless preferred**: Use Vercel/Netlify
|
|
292
|
+
- **Enterprise SLA required**: Use AWS/Azure with support plans
|
|
293
|
+
|
|
294
|
+
## Future Enhancements
|
|
295
|
+
|
|
296
|
+
- [ ] Kubernetes (k3s) cluster setup
|
|
297
|
+
- [ ] Load balancer configuration
|
|
298
|
+
- [ ] Multi-region deployment
|
|
299
|
+
- [ ] Auto-scaling with Hetzner Cloud API
|
|
300
|
+
- [ ] Monitoring integration (Grafana + Prometheus)
|
|
301
|
+
- [ ] Disaster recovery automation
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
**Status**: Planned (Increment 003)
|
|
306
|
+
**Priority**: P1
|
|
307
|
+
**Tests**: 3+ test cases required
|
|
308
|
+
**Documentation**: `.specweave/docs/guides/hetzner-deployment.md`
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hetzner-provisioner
|
|
3
|
+
description: Provisions infrastructure on Hetzner Cloud with Terraform/Pulumi. Generates IaC code for CX11/CX21/CX31 instances, managed Postgres, SSL configuration, Docker deployment. Activates for deploy on Hetzner, Hetzner Cloud, budget deployment, cheap hosting, $10/month hosting.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Hetzner Cloud Provisioner
|
|
7
|
+
|
|
8
|
+
Automated infrastructure provisioning for Hetzner Cloud - the budget-friendly alternative to Vercel and AWS.
|
|
9
|
+
|
|
10
|
+
## Purpose
|
|
11
|
+
|
|
12
|
+
Generate and deploy infrastructure-as-code (Terraform/Pulumi) for Hetzner Cloud, enabling $10-15/month SaaS deployments instead of $50-100/month on other platforms.
|
|
13
|
+
|
|
14
|
+
## When to Use
|
|
15
|
+
|
|
16
|
+
Activates when user mentions:
|
|
17
|
+
- "deploy on Hetzner"
|
|
18
|
+
- "Hetzner Cloud"
|
|
19
|
+
- "budget deployment"
|
|
20
|
+
- "cheap hosting"
|
|
21
|
+
- "deploy for $10/month"
|
|
22
|
+
- "cost-effective infrastructure"
|
|
23
|
+
|
|
24
|
+
## What It Does
|
|
25
|
+
|
|
26
|
+
1. **Analyzes requirements**:
|
|
27
|
+
- Application type (NextJS, Node.js, Python, etc.)
|
|
28
|
+
- Database needs (Postgres, MySQL, Redis)
|
|
29
|
+
- Expected traffic/users
|
|
30
|
+
- Budget constraints
|
|
31
|
+
|
|
32
|
+
2. **Generates Infrastructure-as-Code**:
|
|
33
|
+
- Terraform configuration for Hetzner Cloud
|
|
34
|
+
- Alternative: Pulumi for TypeScript-native IaC
|
|
35
|
+
- Server instances (CX11, CX21, CX31)
|
|
36
|
+
- Managed databases (Postgres, MySQL)
|
|
37
|
+
- Object storage (if needed)
|
|
38
|
+
- Networking (firewall rules, floating IPs)
|
|
39
|
+
|
|
40
|
+
3. **Configures Production Setup**:
|
|
41
|
+
- Docker containerization
|
|
42
|
+
- SSL certificates (Let's Encrypt)
|
|
43
|
+
- DNS configuration (Cloudflare or Hetzner DNS)
|
|
44
|
+
- GitHub Actions CI/CD pipeline
|
|
45
|
+
- Monitoring (Uptime Kuma, self-hosted)
|
|
46
|
+
- Automated backups
|
|
47
|
+
|
|
48
|
+
4. **Outputs Deployment Guide**:
|
|
49
|
+
- Step-by-step deployment instructions
|
|
50
|
+
- Cost breakdown
|
|
51
|
+
- Monitoring URLs
|
|
52
|
+
- Troubleshooting guide
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## ⚠️ CRITICAL: Secrets Required (MANDATORY CHECK)
|
|
57
|
+
|
|
58
|
+
**BEFORE generating Terraform/Pulumi code, CHECK for Hetzner API token.**
|
|
59
|
+
|
|
60
|
+
### Step 1: Check If Token Exists
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Check .env file
|
|
64
|
+
if [ -f .env ] && grep -q "HETZNER_API_TOKEN" .env; then
|
|
65
|
+
echo "✅ Hetzner API token found"
|
|
66
|
+
else
|
|
67
|
+
# Token NOT found - STOP and prompt user
|
|
68
|
+
fi
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Step 2: If Token Missing, STOP and Show This Message
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
🔐 **Hetzner API Token Required**
|
|
75
|
+
|
|
76
|
+
I need your Hetzner API token to provision infrastructure.
|
|
77
|
+
|
|
78
|
+
**How to get it**:
|
|
79
|
+
1. Go to: https://console.hetzner.cloud/
|
|
80
|
+
2. Click on your project (or create one)
|
|
81
|
+
3. Navigate to: Security → API Tokens
|
|
82
|
+
4. Click "Generate API Token"
|
|
83
|
+
5. Give it a name (e.g., "specweave-deployment")
|
|
84
|
+
6. Permissions: **Read & Write**
|
|
85
|
+
7. Click "Generate"
|
|
86
|
+
8. **Copy the token immediately** (you can't see it again!)
|
|
87
|
+
|
|
88
|
+
**Where I'll save it**:
|
|
89
|
+
- File: `.env` (gitignored, secure)
|
|
90
|
+
- Format: `HETZNER_API_TOKEN=your-token-here`
|
|
91
|
+
|
|
92
|
+
**Security**:
|
|
93
|
+
✅ .env is in .gitignore (never committed to git)
|
|
94
|
+
✅ Token is 64 characters, alphanumeric
|
|
95
|
+
✅ Stored locally only (not in source code)
|
|
96
|
+
|
|
97
|
+
Please paste your Hetzner API token:
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Step 3: Validate Token Format
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# Hetzner tokens are 64 alphanumeric characters
|
|
104
|
+
if [[ ! "$HETZNER_API_TOKEN" =~ ^[a-zA-Z0-9]{64}$ ]]; then
|
|
105
|
+
echo "⚠️ Warning: Token format unexpected"
|
|
106
|
+
echo "Expected: 64 alphanumeric characters"
|
|
107
|
+
echo "Got: ${#HETZNER_API_TOKEN} characters"
|
|
108
|
+
echo ""
|
|
109
|
+
echo "This might not be a valid Hetzner API token."
|
|
110
|
+
echo "Continue anyway? (yes/no)"
|
|
111
|
+
fi
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Step 4: Save Token Securely
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# Save to .env
|
|
118
|
+
echo "HETZNER_API_TOKEN=$HETZNER_API_TOKEN" >> .env
|
|
119
|
+
|
|
120
|
+
# Ensure .env is gitignored
|
|
121
|
+
if ! grep -q "^\.env$" .gitignore; then
|
|
122
|
+
echo ".env" >> .gitignore
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
# Create .env.example for team
|
|
126
|
+
cat > .env.example << 'EOF'
|
|
127
|
+
# Hetzner Cloud API Token
|
|
128
|
+
# Get from: https://console.hetzner.cloud/ → Security → API Tokens
|
|
129
|
+
HETZNER_API_TOKEN=your-hetzner-token-here
|
|
130
|
+
EOF
|
|
131
|
+
|
|
132
|
+
echo "✅ Token saved to .env (gitignored)"
|
|
133
|
+
echo "✅ Created .env.example for team (commit this)"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Step 5: Use Token in Terraform
|
|
137
|
+
|
|
138
|
+
```hcl
|
|
139
|
+
# terraform/variables.tf
|
|
140
|
+
variable "hetzner_token" {
|
|
141
|
+
description = "Hetzner Cloud API Token"
|
|
142
|
+
type = string
|
|
143
|
+
sensitive = true
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
# terraform/provider.tf
|
|
147
|
+
provider "hcloud" {
|
|
148
|
+
token = var.hetzner_token
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
# Run Terraform
|
|
152
|
+
# export TF_VAR_hetzner_token=$HETZNER_API_TOKEN
|
|
153
|
+
# terraform apply
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Example Usage
|
|
159
|
+
|
|
160
|
+
**User**: "Deploy my NextJS app on Hetzner with Postgres, as cheaply as possible"
|
|
161
|
+
|
|
162
|
+
**hetzner-provisioner**:
|
|
163
|
+
```markdown
|
|
164
|
+
I'll provision your NextJS app on Hetzner Cloud for ~$12/month.
|
|
165
|
+
|
|
166
|
+
Infrastructure:
|
|
167
|
+
- CX11 instance (2 vCPU, 2GB RAM): $5.83/month
|
|
168
|
+
- Managed Postgres (2GB): $5.00/month
|
|
169
|
+
- 20GB storage: $0.50/month
|
|
170
|
+
- SSL (Let's Encrypt): Free
|
|
171
|
+
- Total: ~$11.33/month
|
|
172
|
+
|
|
173
|
+
Creating Terraform configuration...
|
|
174
|
+
|
|
175
|
+
✅ Generated files:
|
|
176
|
+
- terraform/main.tf
|
|
177
|
+
- terraform/variables.tf
|
|
178
|
+
- terraform/outputs.tf
|
|
179
|
+
- .github/workflows/deploy.yml
|
|
180
|
+
|
|
181
|
+
Next steps:
|
|
182
|
+
1. Set HETZNER_API_TOKEN in GitHub secrets
|
|
183
|
+
2. Push to GitHub
|
|
184
|
+
3. GitHub Actions will deploy automatically
|
|
185
|
+
|
|
186
|
+
Deployment URL: https://your-app.yourdomain.com (after DNS configured)
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Configuration
|
|
190
|
+
|
|
191
|
+
Supports multiple instance types:
|
|
192
|
+
- **CX11** (1 vCPU, 2GB RAM): $5.83/month - Small apps, 100-1000 users
|
|
193
|
+
- **CX21** (2 vCPU, 4GB RAM): $6.90/month - Medium apps, 1000-10000 users
|
|
194
|
+
- **CX31** (2 vCPU, 8GB RAM): $14.28/month - Larger apps, 10000+ users
|
|
195
|
+
|
|
196
|
+
Database options:
|
|
197
|
+
- Managed Postgres (2GB): $5/month
|
|
198
|
+
- Managed MySQL (2GB): $5/month
|
|
199
|
+
- Self-hosted (included in instance cost)
|
|
200
|
+
|
|
201
|
+
## Test Cases
|
|
202
|
+
|
|
203
|
+
See `test-cases/` for validation scenarios:
|
|
204
|
+
1. **test-1-basic-provision.yaml** - Basic CX11 instance
|
|
205
|
+
2. **test-2-postgres-provision.yaml** - Add managed Postgres
|
|
206
|
+
3. **test-3-ssl-config.yaml** - SSL and DNS configuration
|
|
207
|
+
|
|
208
|
+
## Cost Comparison
|
|
209
|
+
|
|
210
|
+
| Platform | Small App | Medium App | Large App |
|
|
211
|
+
|----------|-----------|------------|-----------|
|
|
212
|
+
| **Hetzner** | $12/mo | $15/mo | $25/mo |
|
|
213
|
+
| Vercel | $60/mo | $120/mo | $240/mo |
|
|
214
|
+
| AWS | $25/mo | $80/mo | $200/mo |
|
|
215
|
+
| Railway | $20/mo | $50/mo | $100/mo |
|
|
216
|
+
|
|
217
|
+
**Savings**: 50-80% vs alternatives
|
|
218
|
+
|
|
219
|
+
## Technical Details
|
|
220
|
+
|
|
221
|
+
**Terraform Provider**: `hetznercloud/hcloud`
|
|
222
|
+
**API**: Hetzner Cloud API v1
|
|
223
|
+
**Regions**: Nuremberg, Falkenstein, Helsinki (Germany/Finland)
|
|
224
|
+
**Deployment**: Docker + GitHub Actions
|
|
225
|
+
**Monitoring**: Uptime Kuma (self-hosted, free)
|
|
226
|
+
|
|
227
|
+
## Integration
|
|
228
|
+
|
|
229
|
+
Works with:
|
|
230
|
+
- `cost-optimizer` - Recommends Hetzner when budget-conscious
|
|
231
|
+
- `devops-agent` - Strategic infrastructure planning
|
|
232
|
+
- `nextjs-agent` - NextJS-specific deployment
|
|
233
|
+
- Any backend framework (Node.js, Python, Go, etc.)
|
|
234
|
+
|
|
235
|
+
## Limitations
|
|
236
|
+
|
|
237
|
+
- EU-only data centers (GDPR-friendly)
|
|
238
|
+
- Requires Hetzner Cloud account
|
|
239
|
+
- Manual DNS configuration needed
|
|
240
|
+
- Not suitable for multi-region deployments (use AWS/GCP for that)
|
|
241
|
+
|
|
242
|
+
## Future Enhancements
|
|
243
|
+
|
|
244
|
+
- Kubernetes support (k3s on Hetzner)
|
|
245
|
+
- Load balancer configuration
|
|
246
|
+
- Multi-region deployment
|
|
247
|
+
- Disaster recovery setup
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
**For detailed usage**, see `README.md` and test cases in `test-cases/`
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Basic Hetzner CX11 Provisioning"
|
|
3
|
+
description: "Provision a basic CX11 instance with Docker for NextJS app deployment"
|
|
4
|
+
skill: hetzner-provisioner
|
|
5
|
+
priority: P1
|
|
6
|
+
estimated_time: "5-10 minutes"
|
|
7
|
+
|
|
8
|
+
input:
|
|
9
|
+
prompt: "Deploy my NextJS app on Hetzner as cheaply as possible"
|
|
10
|
+
requirements:
|
|
11
|
+
app_type: nextjs
|
|
12
|
+
instance_type: cx11
|
|
13
|
+
database: none
|
|
14
|
+
ssl: false
|
|
15
|
+
budget: "$10/month"
|
|
16
|
+
|
|
17
|
+
expected_output:
|
|
18
|
+
terraform_files_generated:
|
|
19
|
+
- main.tf
|
|
20
|
+
- variables.tf
|
|
21
|
+
- outputs.tf
|
|
22
|
+
- cloud-init.yaml
|
|
23
|
+
|
|
24
|
+
terraform_resources:
|
|
25
|
+
- type: hcloud_server
|
|
26
|
+
name: app
|
|
27
|
+
server_type: cx11
|
|
28
|
+
image: ubuntu-22.04
|
|
29
|
+
location: nbg1
|
|
30
|
+
|
|
31
|
+
- type: hcloud_firewall
|
|
32
|
+
name: app
|
|
33
|
+
rules:
|
|
34
|
+
- port: 80
|
|
35
|
+
- port: 443
|
|
36
|
+
- port: 22
|
|
37
|
+
|
|
38
|
+
dockerfile_generated: true
|
|
39
|
+
|
|
40
|
+
github_actions_workflow: true
|
|
41
|
+
|
|
42
|
+
cost_estimate:
|
|
43
|
+
monthly: "$5.83"
|
|
44
|
+
breakdown:
|
|
45
|
+
- "CX11 instance: $5.83/month"
|
|
46
|
+
- "Storage (20GB): $0.50/month"
|
|
47
|
+
total: "$6.33/month"
|
|
48
|
+
within_budget: true
|
|
49
|
+
|
|
50
|
+
deployment_guide:
|
|
51
|
+
steps:
|
|
52
|
+
- "Set HETZNER_API_TOKEN in GitHub secrets"
|
|
53
|
+
- "Push code to GitHub"
|
|
54
|
+
- "GitHub Actions will deploy automatically"
|
|
55
|
+
- "Access app at http://[SERVER_IP]:3000"
|
|
56
|
+
|
|
57
|
+
validation:
|
|
58
|
+
- "terraform validate passes without errors"
|
|
59
|
+
- "main.tf contains hcloud_server resource"
|
|
60
|
+
- "Dockerfile exists and is valid"
|
|
61
|
+
- "Cost estimate under $10/month"
|
|
62
|
+
- "GitHub Actions workflow file exists"
|
|
63
|
+
|
|
64
|
+
expected_errors: []
|
|
65
|
+
|
|
66
|
+
success_criteria:
|
|
67
|
+
- "All Terraform files generated"
|
|
68
|
+
- "Cost within budget"
|
|
69
|
+
- "Deployment guide provided"
|
|
70
|
+
- "No validation errors"
|
|
71
|
+
---
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Hetzner Provisioning with Managed Postgres"
|
|
3
|
+
description: "Provision CX11 instance + managed Postgres database for full-stack app"
|
|
4
|
+
skill: hetzner-provisioner
|
|
5
|
+
priority: P1
|
|
6
|
+
estimated_time: "10-15 minutes"
|
|
7
|
+
|
|
8
|
+
input:
|
|
9
|
+
prompt: "Deploy my NextJS app on Hetzner with Postgres database"
|
|
10
|
+
requirements:
|
|
11
|
+
app_type: nextjs
|
|
12
|
+
instance_type: cx11
|
|
13
|
+
database: postgres
|
|
14
|
+
database_size: "2GB"
|
|
15
|
+
ssl: false
|
|
16
|
+
budget: "$15/month"
|
|
17
|
+
|
|
18
|
+
expected_output:
|
|
19
|
+
terraform_files_generated:
|
|
20
|
+
- main.tf
|
|
21
|
+
- variables.tf
|
|
22
|
+
- outputs.tf
|
|
23
|
+
- cloud-init.yaml
|
|
24
|
+
- database.tf
|
|
25
|
+
|
|
26
|
+
terraform_resources:
|
|
27
|
+
- type: hcloud_server
|
|
28
|
+
name: app
|
|
29
|
+
server_type: cx11
|
|
30
|
+
|
|
31
|
+
- type: hcloud_database
|
|
32
|
+
name: postgres
|
|
33
|
+
engine: postgresql
|
|
34
|
+
version: "15"
|
|
35
|
+
size: db-1x-small
|
|
36
|
+
|
|
37
|
+
- type: hcloud_firewall
|
|
38
|
+
name: app
|
|
39
|
+
|
|
40
|
+
environment_variables:
|
|
41
|
+
- DATABASE_URL: "postgresql://user:pass@[DB_HOST]:5432/dbname"
|
|
42
|
+
- POSTGRES_HOST: "[DB_HOST from terraform output]"
|
|
43
|
+
- POSTGRES_PORT: "5432"
|
|
44
|
+
- POSTGRES_DB: "my_saas_db"
|
|
45
|
+
|
|
46
|
+
dockerfile_generated: true
|
|
47
|
+
|
|
48
|
+
docker_compose_generated: true
|
|
49
|
+
docker_compose_services:
|
|
50
|
+
- app
|
|
51
|
+
- (database managed separately by Hetzner)
|
|
52
|
+
|
|
53
|
+
cost_estimate:
|
|
54
|
+
monthly: "$10.83"
|
|
55
|
+
breakdown:
|
|
56
|
+
- "CX11 instance: $5.83/month"
|
|
57
|
+
- "Managed Postgres (2GB): $5.00/month"
|
|
58
|
+
- "Storage (20GB): $0.50/month"
|
|
59
|
+
total: "$11.33/month"
|
|
60
|
+
within_budget: true
|
|
61
|
+
|
|
62
|
+
deployment_guide:
|
|
63
|
+
steps:
|
|
64
|
+
- "Set HETZNER_API_TOKEN in GitHub secrets"
|
|
65
|
+
- "Set database credentials in environment variables"
|
|
66
|
+
- "Run terraform apply to provision infrastructure"
|
|
67
|
+
- "Database will be accessible at terraform output"
|
|
68
|
+
- "Configure app DATABASE_URL"
|
|
69
|
+
- "Deploy app with GitHub Actions"
|
|
70
|
+
|
|
71
|
+
validation:
|
|
72
|
+
- "terraform validate passes"
|
|
73
|
+
- "hcloud_database resource exists in main.tf or database.tf"
|
|
74
|
+
- "Database connection string in outputs.tf"
|
|
75
|
+
- "Environment variables documented"
|
|
76
|
+
- "Cost under $15/month"
|
|
77
|
+
|
|
78
|
+
expected_errors: []
|
|
79
|
+
|
|
80
|
+
success_criteria:
|
|
81
|
+
- "Managed Postgres provisioned"
|
|
82
|
+
- "Connection string outputted"
|
|
83
|
+
- "Cost within budget"
|
|
84
|
+
- "App can connect to database"
|
|
85
|
+
---
|