Files
mintel.me/apps/web/DEPLOYMENT_SUMMARY.md
Marc Mintel 103d71851c
Some checks failed
🧪 CI (QA) / 🧪 Quality Assurance (push) Failing after 1m3s
chore: overhaul infrastructure and integrate @mintel packages
- 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
2026-02-05 14:18:51 +01:00

192 lines
4.9 KiB
Markdown

# 🚀 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.yml` config
- ✅ 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:**
```typescript
// 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:**
```typescript
// 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:**
```astro
---
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)
```bash
# 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)
```bash
# 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:**
```typescript
// 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
1. **Configure** environment variables
2. **Test locally**: `docker-compose up`
3. **Setup Woodpecker secrets** in Gitea
4. **Deploy** to Hetzner
5. **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!** 🎉