Zentrale Verwaltung aller Hetzner-Cloud-Ressourcen direkt im mittwald Control Panel.
Die mittwald–Hetzner Cloud Extension ermöglicht Agenturen, die sowohl mittwald-Produkte als auch Hetzner Cloud-Infrastruktur nutzen, eine vollständig integrierte Verwaltung ihrer Systeme aus einer Oberfläche. Statt zwischen verschiedenen Dashboards zu wechseln, erhalten Agenturen eine einheitliche Sicht auf Projekte, Server und Infrastrukturzustände – direkt im vertrauten mittwald-Ökosystem.
- ✅ Ressourcenübersicht: Alle Hetzner-Cloud-Ressourcen (Server, Volumes, IPs, Snapshots) im mittwald-Panel anzeigen
- ✅ Detailansicht eines Servers: Status, Region, Typ, Kosten, IPs, OS, Backups
- ✅ Kostenübersicht: Geschätzte monatliche Kosten der Hetzner-Ressourcen
- ✅ Manuelle Zuordnung: Hetzner-Server mittwald-Kunden oder Projekten zuordnen
- ✅ Tagging-Funktionen: Eigene Tags oder Labels für Server vergeben
- ✅ Live-Status: Aktueller Status und Erreichbarkeit eines Hetzner-Servers
- ✅ Ereignis-/Activity-Log: Hetzner-Events (Reboots, Scaling, Firewall Changes) einsehen
- ✅ Server Neustarten: Server neu starten können
- ✅ Ein-/Ausschalten: Server abschalten oder hochfahren können
- ✅ Firewall-Zustand anzeigen: Firewall-Regeln einsehen (View only)
- ✅ Notizfunktion: Notizen pro Server hinterlegen
- ✅ API-Token-Verknüpfung: Hetzner-Konto mit dem mittwald-Panel verbinden
- ✅ Rollen & Berechtigungen: Zugriffskontrolle über mittwald Extension System
- Node.js v20.11.1 or higher
- pnpm v10.4.1 or higher
- PostgreSQL database (non-pooling connection)
- Hetzner Cloud API Token (Generate here)
-
Install dependencies:
pnpm install
-
Set up your environment variables:
cp .env.example .env # Edit .env with your actual valuesRequired environment variables:
DATABASE_URL- PostgreSQL connection stringPRISMA_FIELD_ENCRYPTION_KEY- Encryption key for sensitive fieldsEXTENSION_ID- Your mittwald extension IDEXTENSION_SECRET- Your mittwald extension secret
-
Generate Prisma client and run migrations:
pnpm db:generate pnpm db:migrate:dev
-
Start the development server:
pnpm dev
Your extension will be available at http://localhost:5173
HETZNER_API_TOKEN- Hetzner Cloud API token (optional, for local development/testing only)⚠️ Note: In production, tokens should be stored in the database via the Settings page, not environment variables- This variable is only used if no token is found in the database
-
Remove Debug Logging: The codebase contains
console.logstatements for debugging. Consider:- Removing debug logs or wrapping them in conditional checks (
if (process.env.NODE_ENV === 'development')) - Using a proper logging library (e.g.,
pino,winston) with log levels
- Removing debug logs or wrapping them in conditional checks (
-
Environment Variables: Set all required environment variables in your hosting platform:
DATABASE_URL- Use SSL connection string in productionPRISMA_FIELD_ENCRYPTION_KEY- Generate a secure random key (32+ characters)EXTENSION_ID- Your mittwald extension IDEXTENSION_SECRET- Your mittwald extension secretNODE_ENV=production
-
Database Setup:
pnpm db:generate pnpm db:migrate:deploy
-
Build and Start:
pnpm build pnpm start
A render.yaml blueprint is included for easy deployment on Render. See DEPLOYMENT.md for detailed instructions.
Quick Start:
- Push your code to a Git repository
- Create a new Render Blueprint
- Connect your repository
- Render will automatically:
- Create a PostgreSQL database
- Set up the web service
- Run migrations during build
- Configure environment variables (including automatic PORT configuration)
Important: The render.yaml uses automatic port configuration via fromService. The vite.config.ts already reads process.env.PORT automatically.
- Verify HTTPS is enabled
- Test API token configuration via Settings page
- Verify database migrations completed successfully
- Check that debug logging is disabled/removed
- Test webhook endpoints are accessible
- Verify extension appears in mittwald Studio
- Test server actions (power on/off, reboot)
- Monitor error logs for any issues
-
Configure Hetzner API Token:
- Navigate to Settings (
/settings) - Enter your Hetzner Cloud API Token
- The token will be validated and stored encrypted
- Navigate to Settings (
-
View Resources:
- Dashboard (
/) shows overview of all resources - Servers list (
/servers) shows all Hetzner servers - Click on a server to see details (
/servers/:serverId)
- Dashboard (
- View Server Details: Click on any server to see full information
- Power Actions: Power on/off, reboot, or shutdown servers
- Assign to Projects: Link servers to mittwald projects or customers
- Add Notes: Document important information about servers
- View Status: Real-time server status and network information
- Assign Hetzner resources to mittwald projects or customers
- Add custom tags for better organization
- View assignments in resource lists
src/
├── components/ # React components
│ ├── ErrorMessage.tsx # Error display component
│ ├── Loader.tsx # Loading state component
│ └── NotFound.tsx # 404 page
├── lib/ # Utility libraries
│ └── hetzner-api.ts # Hetzner Cloud API client
├── middlewares/ # TanStack middleware
│ └── verify-access-to-instance.ts # Access verification
├── routes/ # TanStack Router routes
│ ├── api/ # API endpoints
│ │ └── webhooks.mittwald.ts # mittwald webhook handler
│ ├── index.tsx # Dashboard
│ ├── servers.tsx # Servers list
│ ├── servers/$serverId.tsx # Server details
│ └── settings.tsx # Settings page
├── server/ # Server functions
│ └── functions/ # Server-side functions
│ └── hetzner/ # Hetzner-specific functions
│ ├── getApiToken.ts
│ ├── setApiToken.ts
│ ├── deleteApiToken.ts
│ ├── listServers.ts
│ ├── getServer.ts
│ ├── listResources.ts
│ ├── serverActions.ts
│ ├── assignResource.ts
│ ├── unassignResource.ts
│ └── resourceNotes.ts
├── client.tsx # Client entry point
├── db.ts # Prisma client configuration
├── env.ts # Environment validation
├── global-middleware.ts # Global middleware
└── router.tsx # Router configuration
The extension uses the following Prisma models:
ExtensionInstance- Extension instance informationHetznerApiToken- Encrypted Hetzner API tokensHetznerResourceAssignment- Resource-to-project/customer mappingsHetznerResourceNote- Notes for resources
pnpm dev- Start development serverpnpm build- Build for productionpnpm start- Start production serverpnpm check- Run Biome checkspnpm lint- Lint codepnpm format- Format codepnpm test- Run testspnpm db:generate- Generate Prisma clientpnpm db:migrate:dev- Run migrations in developmentpnpm db:migrate:deploy- Deploy migrationspnpm db:studio- Open Prisma Studio
- Configure Webhooks: Set your webhook URL in mStudio Contributor UI
- Set Scopes: Configure required scopes and extension context
- Configure Anchors: Point anchors to
http://localhost:5173 - Install Extension: Perform first installation via API
- Start Development: Run
pnpm devand open your extension
The extension uses the Hetzner Cloud API to:
- List and manage servers
- View volumes and floating IPs
- Perform server actions (power on/off, reboot, shutdown)
- Retrieve pricing information
The extension integrates with mittwald using:
- Extension Bridge for authentication
- Webhooks for lifecycle events
- Context-based access control
- mittwald API Documentation
- Extension Development Guide
- Frontend Fragment Anchors
- Hetzner Cloud API Reference
- Flow UI Components
- Framework: TanStack Start (React-based full-stack framework)
- Database: PostgreSQL with Prisma ORM
- UI Components: mittwald Flow Remote React Components
- Authentication: mittwald Extension Bridge
- Webhooks: mitthooks library
- Code Quality: Biome (linting & formatting)
- Testing: Vitest
- API Client: Custom Hetzner Cloud API client with Zod validation
- Input Validation:
@tanstack/zod-adapterfor POST requests with middleware
inputValidator to ensure the request body is parsed before middleware runs. See DEVELOPER.md (local file, not in git) for detailed documentation on this known issue and solution.
- Encrypted Storage: API tokens are encrypted at rest using Prisma field encryption (
@encrypteddirective) - Server-Side Only: All Hetzner API calls are performed server-side - tokens never exposed to client
- Access Control: Authentication and authorization handled via mittwald Extension Bridge
- Context Isolation: Resources are isolated per extension instance using
extensionInstanceId - Token Validation: API tokens are validated before storage by making a test API call
- No Token Exposure: Token endpoints only return metadata (
hasToken,configuredAt), never the actual token
- Never commit
.envfiles - They are already in.gitignore - Use secure secrets management in production (e.g., Render secrets, AWS Secrets Manager)
- Rotate secrets regularly - Especially
PRISMA_FIELD_ENCRYPTION_KEYandEXTENSION_SECRET - Limit
HETZNER_API_TOKENusage - Only use for local development/testing, prefer database storage in production
- Remove debug logging - The codebase contains
console.logstatements for debugging that should be removed or conditionally disabled in production - Use HTTPS only - Ensure all connections use HTTPS in production
- Set secure headers - Configure Content Security Policy (CSP) and other security headers
- Monitor API usage - Implement rate limiting if needed to prevent abuse
- Regular security updates - Keep dependencies up to date (
pnpm update)
- Use non-pooling PostgreSQL connection - Required for Prisma field encryption
- Encrypt database connections - Use SSL/TLS for database connections in production
- Backup encryption keys - Store
PRISMA_FIELD_ENCRYPTION_KEYsecurely (losing it means losing access to encrypted data) - Principle of least privilege - Database user should only have necessary permissions
- Use read-only tokens when possible - Hetzner API tokens can be scoped to specific permissions
- Rotate tokens periodically - Generate new tokens and update them in settings
- Revoke unused tokens - Remove tokens from Hetzner console when no longer needed
- Monitor token usage - Check Hetzner API logs for suspicious activity
- Debug logging statements (
console.log) are present throughout the codebase for development purposes - These should be removed or conditionally disabled in production to avoid exposing sensitive information
- Consider using a logging library with log levels (e.g.,
pino,winston) for production
If you discover a security vulnerability, please report it responsibly. Do not create public GitHub issues for security vulnerabilities.
This project was generated with mittvibes CLI by mittwald.
For issues with the CLI tool itself, please report them at the mittvibes repository.
This extension is part of the mittwald ecosystem and follows mittwald's extension guidelines.