# 03 — Setup Hetzner Cloud

---

## Création du compte et du projet

### 1. Créer le compte Hetzner

1. Rendez-vous sur https://console.hetzner.cloud
2. Créez votre compte (email + CB requis)
3. Activez la vérification 2FA (obligatoire en production)
4. Créez un **nouveau projet** : `xpeditis-prod`

### 2. Générer le token API

1. Dans le projet `xpeditis-prod` → **Security** → **API Tokens**
2. **Generate API Token**
   - Name: `hetzner-k3s-deploy`
   - Permissions: **Read & Write**
3. Copiez le token immédiatement (affiché une seule fois)

```bash
# Configurez hcloud avec ce token
hcloud context create xpeditis-prod
# → Entrez votre token

# Vérification
hcloud server list
# Output: ID   NAME   STATUS   IPV4   IPV6   DATACENTER
# (liste vide si première fois)
```

### 3. Ajouter la clé SSH

```bash
# Via CLI hcloud
hcloud ssh-key create \
  --name xpeditis-deploy \
  --public-key-from-file ~/.ssh/xpeditis_hetzner.pub

# Vérification
hcloud ssh-key list
# ID        NAME              FINGERPRINT
# 1234567   xpeditis-deploy   xx:xx:xx:...
```

---

## Réseau privé (obligatoire pour la sécurité inter-nœuds)

Le réseau privé permet aux nœuds de communiquer entre eux sans passer par internet.

```bash
# Créer le réseau privé
hcloud network create \
  --name xpeditis-network \
  --ip-range 10.0.0.0/16

# Récupérer l'ID du réseau (nécessaire pour la config k3s)
hcloud network list
# ID      NAME               IP RANGE      SERVERS
# 12345   xpeditis-network   10.0.0.0/16   0 servers

export HETZNER_NETWORK_ID=12345  # Remplacer par votre ID

# Créer un sous-réseau pour les nœuds du cluster
hcloud network add-subnet xpeditis-network \
  --type cloud \
  --network-zone eu-central \
  --ip-range 10.0.1.0/24
```

---

## Firewall (règles de sécurité)

Créez un firewall strict. Les workers ne doivent être accessibles que via le Load Balancer et depuis votre IP pour SSH.

```bash
# Créer le firewall
hcloud firewall create --name xpeditis-firewall

# Règle 1 : SSH depuis votre IP uniquement
hcloud firewall add-rule xpeditis-firewall \
  --direction in \
  --protocol tcp \
  --port 22 \
  --source-ips "$(curl -s https://api.ipify.org)/32" \
  --description "SSH depuis mon IP"

# Règle 2 : HTTP/HTTPS depuis partout (via LB → workers)
hcloud firewall add-rule xpeditis-firewall \
  --direction in \
  --protocol tcp \
  --port 80 \
  --source-ips 0.0.0.0/0 \
  --description "HTTP public"

hcloud firewall add-rule xpeditis-firewall \
  --direction in \
  --protocol tcp \
  --port 443 \
  --source-ips 0.0.0.0/0 \
  --description "HTTPS public"

# Règle 3 : Kubernetes API (votre IP + réseau privé Hetzner)
hcloud firewall add-rule xpeditis-firewall \
  --direction in \
  --protocol tcp \
  --port 6443 \
  --source-ips "$(curl -s https://api.ipify.org)/32" \
  --description "kube-apiserver depuis mon IP"

hcloud firewall add-rule xpeditis-firewall \
  --direction in \
  --protocol tcp \
  --port 6443 \
  --source-ips 10.0.0.0/16 \
  --description "kube-apiserver depuis réseau privé"

# Règle 4 : Communication inter-nœuds (réseau privé uniquement)
hcloud firewall add-rule xpeditis-firewall \
  --direction in \
  --protocol tcp \
  --port 1-65535 \
  --source-ips 10.0.0.0/16 \
  --description "Trafic interne cluster"

hcloud firewall add-rule xpeditis-firewall \
  --direction in \
  --protocol udp \
  --port 1-65535 \
  --source-ips 10.0.0.0/16 \
  --description "Trafic UDP interne cluster"

# Règle 5 : ICMP (ping) pour monitoring
hcloud firewall add-rule xpeditis-firewall \
  --direction in \
  --protocol icmp \
  --source-ips 0.0.0.0/0 \
  --description "ICMP ping"

# Vérification
hcloud firewall describe xpeditis-firewall
```

---

## Object Storage — Setup du bucket S3

### Créer le bucket

1. Dans la console Hetzner → votre projet → **Object Storage**
2. Cliquez **Create Bucket**
   - Location: **Falkenstein (fsn1)** (même région que vos serveurs)
   - Bucket name: `xpeditis-prod`
   - Visibility: **Private** (obligatoire)
3. Cliquez **Create**

### Créer les credentials S3

1. Dans Object Storage → **Access Keys**
2. **Generate Access Key**
   - Name: `xpeditis-backend`
3. Notez bien les deux valeurs (affichées une seule fois) :
   - **Access Key** (commence par `htz...`)
   - **Secret Key** (longue chaîne)

### Vérifier avec AWS CLI

```bash
# Configurer AWS CLI pour Hetzner Object Storage
aws configure --profile hetzner
# AWS Access Key ID: <votre_access_key>
# AWS Secret Access Key: <votre_secret_key>
# Default region name: eu-central-1
# Default output format: json

# Tester la connexion
aws s3 ls --profile hetzner \
  --endpoint-url https://fsn1.your-objectstorage.com

# Créer un dossier de test
aws s3 cp /dev/null s3://xpeditis-prod/test/.gitkeep \
  --profile hetzner \
  --endpoint-url https://fsn1.your-objectstorage.com

# Vérifier
aws s3 ls s3://xpeditis-prod/ \
  --profile hetzner \
  --endpoint-url https://fsn1.your-objectstorage.com
```

### Structure du bucket recommandée

```
xpeditis-prod/
├── documents/          # Documents carrier (PDF, XLS, images)
│   └── {orgId}/
│       └── {bookingId}/
│           └── {filename}
├── pdfs/               # PDFs de confirmation booking
│   └── {year}/
│       └── {month}/
│           └── {bookingNumber}.pdf
├── exports/            # Exports CSV/Excel des bookings
│   └── {orgId}/
│       └── {timestamp}-bookings.xlsx
├── logos/              # Logos des organisations
│   └── {orgId}/
│       └── logo.{ext}
└── backups/            # Backups PostgreSQL (voir doc 13)
    └── {date}/
        └── xpeditis-{timestamp}.sql.gz
```

---

## Volumes Hetzner (si PostgreSQL self-hosted)

Si vous choisissez d'héberger PostgreSQL sur Hetzner (voir doc 07), créez un volume dédié :

```bash
# Créer un volume de 50 GB pour PostgreSQL
hcloud volume create \
  --name xpeditis-postgres-data \
  --size 50 \
  --location fsn1 \
  --format ext4

# L'ID sera utilisé dans la config k3s pour le PersistentVolume
hcloud volume list
# ID      NAME                     SIZE   SERVER   LOCATION
# 67890   xpeditis-postgres-data   50 GB  -        fsn1
```

---

## Placement Groups (haute disponibilité)

Les placement groups garantissent que vos workers sont sur des hôtes physiques différents :

```bash
# Créer un placement group "spread" (workers sur différents hôtes physiques)
hcloud placement-group create \
  --name xpeditis-workers \
  --type spread

# Noter l'ID pour la config hetzner-k3s
hcloud placement-group list
# ID    NAME               TYPE    SERVERS
# 111   xpeditis-workers   spread  0
```

---

## Récapitulatif des IDs à noter

Après cette étape, vous devez avoir :

```bash
# À sauvegarder dans ~/.xpeditis-deploy.env
export HCLOUD_TOKEN="<votre_token>"
export HCLOUD_NETWORK_ID="12345"        # ID du réseau privé
export HCLOUD_SSH_KEY_NAME="xpeditis-deploy"
export HCLOUD_FIREWALL_NAME="xpeditis-firewall"
export HCLOUD_PLACEMENT_GROUP_NAME="xpeditis-workers"

# Object Storage
export HETZNER_S3_ENDPOINT="https://fsn1.your-objectstorage.com"
export HETZNER_S3_BUCKET="xpeditis-prod"
export HETZNER_S3_ACCESS_KEY="<access_key>"
export HETZNER_S3_SECRET_KEY="<secret_key>"
```

---

## Vérification globale

```bash
# Tout doit être en place avant de continuer vers le doc 04/05
echo "=== Network ===" && hcloud network list
echo "=== SSH Keys ===" && hcloud ssh-key list
echo "=== Firewalls ===" && hcloud firewall list
echo "=== Volumes ===" && hcloud volume list
echo "=== Placement Groups ===" && hcloud placement-group list
echo "=== Object Storage ===" && aws s3 ls s3://xpeditis-prod/ \
  --profile hetzner \
  --endpoint-url https://fsn1.your-objectstorage.com 2>/dev/null && echo "✅ Bucket accessible" || echo "❌ Bucket inaccessible"
```
