Some checks failed
🧪 CI (QA) / 🧪 Quality Assurance (push) Failing after 1m3s
- Restructure to pnpm monorepo (site moved to apps/web) - Integrate @mintel/tsconfig, @mintel/eslint-config, @mintel/husky-config - Implement Docker service architecture (Varnish, Directus, Gatekeeper) - Setup environment-aware Gitea Actions deployment
4.9 KiB
4.9 KiB
🚀 Hetzner Deployment - Complete Plan
✅ What's Ready
1. Docker Setup
- ✅ Multi-stage Dockerfile (optimized build)
- ✅ Nginx config with caching & security headers
- ✅ Caddy reverse proxy with automatic SSL
- ✅ Redis container for caching
- ✅ Docker Compose for local & production
2. CI/CD Pipeline
- ✅ Woodpecker
.woodpecker.ymlconfig - ✅ Automatic testing, building, deployment
- ✅ Slack notifications (optional)
- ✅ Gitea integration ready
3. Cache Architecture (Professional DI)
src/utils/cache/
├── interfaces.ts # Contracts
├── memory-adapter.ts # In-memory implementation
├── redis-adapter.ts # Redis implementation
└── index.ts # Service + Factory
Usage:
// Choose your adapter at construction
const cache = new CacheService(new RedisCacheAdapter(config));
// or
const cache = new CacheService(new MemoryCacheAdapter(config));
// Use it
await cache.wrap('key', asyncFn, ttl);
4. Clean Analytics Architecture (Constructor DI)
src/utils/analytics/
├── interfaces.ts # Contracts
├── plausible-adapter.ts # Plausible implementation
└── index.ts # Service + Factory
Usage:
// Choose adapter at construction
const analytics = new AnalyticsService(new PlausibleAdapter(config));
// Track events
await analytics.trackEvent('Page Load', { loadTime: 123 });
await analytics.trackOutboundLink(url, text);
await analytics.trackSearch(query, path);
Astro Component:
---
import { createPlausibleAnalytics } from '../utils/analytics';
const analytics = createPlausibleAnalytics({ domain, scriptUrl });
const adapter = analytics.getAdapter();
const scriptTag = adapter.getScriptTag?.();
---
{scriptTag && <Fragment set:html={scriptTag} />}
5. Deployment Scripts
- ✅
deploy.sh- Manual deployment - ✅
docker-compose.yml- Container orchestration - ✅
DEPLOYMENT.md- Complete documentation
🎯 Simple Deployment Flow
Option A: Manual (5 minutes)
# On Hetzner VM
git clone your-repo /opt/mintel
cd /opt/mintel
echo "DOMAIN=mintel.me" > .env
echo "ADMIN_EMAIL=admin@mintel.me" >> .env
./deploy.sh
Option B: CI/CD (Zero touch)
# On your machine
git push origin main
# Woodpecker handles everything
📊 Performance Features
| Feature | Implementation | Benefit |
|---|---|---|
| Static Caching | Nginx 1-year cache | Instant asset loading |
| Redis Cache | CacheService wrapper | Fast data retrieval |
| Gzip/Brotli | Nginx compression | ~70% smaller transfers |
| HTTP/2 | Caddy reverse proxy | Multiplexed requests |
| Auto-SSL | Let's Encrypt via Caddy | Zero config HTTPS |
🔒 Security
- ✅ HSTS headers
- ✅ XSS protection
- ✅ Clickjacking prevention
- ✅ Server header hiding
- ✅ Automatic SSL renewal
🏗️ Architecture (Clean & Decoupled)
Cache Pattern:
Your Code → CacheService → [Redis | Memory]Adapter
↓
CacheAdapter Interface
Analytics Pattern:
Your Code → AnalyticsService → [Plausible]Adapter
↓
AnalyticsAdapter Interface
Constructor Injection:
// Cache - Production
const cache = new CacheService(new RedisCacheAdapter(config));
// Cache - Development/Testing
const cache = new CacheService(new MemoryCacheAdapter(config));
// Analytics
const analytics = new AnalyticsService(new PlausibleAdapter(config));
📁 Files Created
mintel.me/
├── docker/
│ ├── Dockerfile
│ ├── nginx.conf
│ └── Caddyfile
├── docker-compose.yml
├── .woodpecker.yml
├── deploy.sh
├── DEPLOYMENT.md
├── DEPLOYMENT_SUMMARY.md
├── src/
│ ├── utils/cache/
│ │ ├── interfaces.ts
│ │ ├── memory-adapter.ts
│ │ ├── redis-adapter.ts
│ │ └── index.ts
│ ├── utils/analytics/
│ │ ├── interfaces.ts
│ │ ├── plausible-adapter.ts
│ │ └── index.ts
│ ├── components/
│ │ └── Analytics.astro (clean DI pattern)
│ └── layouts/
│ └── BaseLayout.astro (includes analytics)
└── package.json (ioredis added)
🎯 Next Steps
- Configure environment variables
- Test locally:
docker-compose up - Setup Woodpecker secrets in Gitea
- Deploy to Hetzner
- Monitor with Plausible
🚀 Result
- Fast: Redis + Nginx caching
- Secure: Auto SSL + security headers
- Simple: One command deployment
- Clean: Proper DI architecture
- Smart: CI/CD automation
- Private: Self-hosted analytics
Total setup time: ~15 minutes
Maintenance: Near zero
Performance: Excellent
Security: Production-ready
Ready to deploy! 🎉