---
title: "DAEMON Backend — Plan d'installation VPS complet"
type: project
created: 2026-04-16
updated: 2026-04-16
owner: jerem
agent: DAEMON
status: active
priority: p0
tags:
  - projet/daemon
  - infra
  - vps
related:
  - "[[_adn/routing-llm]]"
  - "[[_adn/soul]]"
---

# DAEMON Backend — Plan d'installation VPS

> Objectif : monter DAEMON sur un VPS dédié Hostinger pour qu'il tourne 24/7. Vault synchro, agents autonomes, accès sécurisé.

---

## Infos serveur

| Élément | Valeur |
|---|---|
| **Hébergeur** | Hostinger — VPS dédié |
| **OS** | Ubuntu 22.04 LTS |
| **IP** | `76.13.42.203` |
| **SSH** | Port 22 → sera changé en 2222 |
| **Domaine** | `jeremunlimited.com` (DNS géré sur OVH) |
| **Sous-domaine** | `deamon.jeremunlimited.com` → `76.13.42.203` ✅ |
| **Clé SSH Mac** | `~/.ssh/id_ed25519.pub` (ed25519, jerem@daemon) |

---

## Prérequis

- [x] Commander le VPS dédié Hostinger
- [x] Générer clé SSH ed25519 sur Mac
- [x] Créer un compte Doppler (doppler.com)
- [x] Installer le plugin Git dans Obsidian
- [x] Ajouter un DNS A record sur OVH : `deamon.jeremunlimited.com` → `76.13.42.203`
- [ ] Décider : déplacer le vault hors d'iCloud vers `~/Documents/DAEMON` (recommandé quand Git sync actif)

---

## Phase 1 — Sécurisation serveur

```bash
# 1.1 — Connexion root initiale
ssh root@76.13.42.203

# 1.2 — Mise à jour système
apt update && apt upgrade -y

# 1.3 — Créer utilisateur non-root
adduser daemon
usermod -aG sudo daemon

# 1.4 — Copier la clé SSH pour le nouvel utilisateur
mkdir -p /home/daemon/.ssh
cp ~/.ssh/authorized_keys /home/daemon/.ssh/authorized_keys
chown -R daemon:daemon /home/daemon/.ssh
chmod 700 /home/daemon/.ssh && chmod 600 /home/daemon/.ssh/authorized_keys

# 1.5 — Durcir SSH (port custom + pas de root + pas de password)
sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/#Port 22/Port 2222/' /etc/ssh/sshd_config
sed -i 's/^Port 22$/Port 2222/' /etc/ssh/sshd_config
systemctl restart sshd

# 1.6 — Firewall UFW
ufw default deny incoming
ufw default allow outgoing
ufw allow 2222/tcp comment 'SSH custom'
ufw allow 80/tcp comment 'HTTP'
ufw allow 443/tcp comment 'HTTPS'
ufw allow 51820/udp comment 'WireGuard VPN'
ufw --force enable

# 1.7 — fail2ban (anti-bruteforce)
apt install -y fail2ban
systemctl enable fail2ban && systemctl start fail2ban

# 1.8 — Mises à jour auto sécurité
apt install -y unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades
```

**Vérification** : `ssh daemon@76.13.42.203 -p 2222` depuis le Mac.

---

## Phase 2 — Docker

```bash
# 2.1 — Installer Docker (officiel, pas celui de Hostinger)
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker daemon

# 2.2 — Se reconnecter pour activer le groupe docker
exit
# ssh daemon@76.13.42.203 -p 2222

# 2.3 — Vérifier
docker --version
docker compose version

# 2.4 — Empêcher Docker de bypass le firewall
sudo tee /etc/docker/daemon.json << 'EOF'
{
  "iptables": false
}
EOF
sudo systemctl restart docker
```

---

## Phase 3 — Gitea (Git privé)

```bash
# 3.1 — Créer la structure
mkdir -p ~/daemon-infra/{gitea,nginx,openclaw,scripts}
cd ~/daemon-infra

# 3.2 — Docker Compose : Gitea + PostgreSQL
cat > docker-compose.yml << 'EOF'
version: "3.9"
services:
  gitea:
    image: gitea/gitea:1.22
    container_name: gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=postgres
      - GITEA__database__HOST=db:5432
      - GITEA__database__NAME=gitea
      - GITEA__database__USER=gitea
      - GITEA__database__PASSWD=${GITEA_DB_PASS}
      - GITEA__server__ROOT_URL=${GITEA_URL}
      - GITEA__server__SSH_PORT=222
    volumes:
      - ./gitea/data:/data
    ports:
      - "127.0.0.1:3000:3000"
      - "222:22"
    depends_on:
      - db
    restart: always
  db:
    image: postgres:16-alpine
    container_name: gitea-db
    environment:
      - POSTGRES_USER=gitea
      - POSTGRES_PASSWORD=${GITEA_DB_PASS}
      - POSTGRES_DB=gitea
    volumes:
      - ./gitea/postgres:/var/lib/postgresql/data
    restart: always
EOF

# 3.3 — Générer mot de passe DB + .env
GITEA_DB_PASS=$(openssl rand -base64 24)
echo "GITEA_DB_PASS=$GITEA_DB_PASS" > .env
echo "GITEA_URL=http://76.13.42.203:3000/" >> .env
# Note : GITEA_URL sera changé quand on aura le domaine + HTTPS

# 3.4 — Lancer
docker compose up -d

# 3.5 — Vérifier
docker ps
curl http://127.0.0.1:3000
```

**Post-install** : aller sur `http://76.13.42.203:3000` pour finaliser le setup Gitea (créer admin, premier repo `daemon-vault`).

---

## Phase 4 — Coolify (reverse proxy + HTTPS + gestion containers)

> Coolify remplace Nginx + certbot. Il gère le reverse proxy (Traefik intégré), les certificats HTTPS automatiques (Let's Encrypt), et offre une interface web pour gérer tous les services.

```bash
# 4.1 — Installer Coolify (script officiel)
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash

# Coolify sera accessible sur http://76.13.42.203:8000
# Après config VPN → accessible uniquement via http://10.0.0.1:8000

# 4.2 — Post-install (dans le navigateur)
# - Créer le compte admin
# - Ajouter le serveur local
# - Configurer le domaine deamon.jeremunlimited.com
# - Activer HTTPS automatique (Let's Encrypt intégré)
# - Déployer Gitea, n8n, Uptime Kuma via l'interface Coolify
```

---

## Phase 5 — WireGuard VPN (gratuit, open source)

```bash
# 5.1 — Installer WireGuard sur le VPS
sudo apt install -y wireguard

# 5.2 — Générer les clés serveur
wg genkey | sudo tee /etc/wireguard/server_private.key | wg pubkey | sudo tee /etc/wireguard/server_public.key
sudo chmod 600 /etc/wireguard/server_private.key

# 5.3 — Config serveur
SERVER_PRIVKEY=$(sudo cat /etc/wireguard/server_private.key)
sudo tee /etc/wireguard/wg0.conf << EOF
[Interface]
PrivateKey = $SERVER_PRIVKEY
Address = 10.0.0.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
# Mac de Jerem
PublicKey = <MAC_PUBLIC_KEY>
AllowedIPs = 10.0.0.2/32
EOF

# 5.4 — Activer
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

# 5.5 — Générer la config client (Mac)
wg genkey | tee ~/mac_private.key | wg pubkey > ~/mac_public.key
MAC_PRIVKEY=$(cat ~/mac_private.key)
MAC_PUBKEY=$(cat ~/mac_public.key)
SERVER_PUBKEY=$(sudo cat /etc/wireguard/server_public.key)

# Mettre à jour la config serveur avec la clé publique du Mac
sudo sed -i "s|<MAC_PUBLIC_KEY>|$MAC_PUBKEY|" /etc/wireguard/wg0.conf
sudo systemctl restart wg-quick@wg0

# Générer le fichier config pour le Mac
cat > ~/mac-wireguard.conf << EOF
[Interface]
PrivateKey = $MAC_PRIVKEY
Address = 10.0.0.2/24
DNS = 1.1.1.1

[Peer]
PublicKey = $SERVER_PUBKEY
AllowedIPs = 10.0.0.0/24
Endpoint = 76.13.42.203:51820
PersistentKeepalive = 25
EOF

echo "=== Copier ce fichier sur le Mac ==="
cat ~/mac-wireguard.conf
```

**Côté Mac** : installer WireGuard (App Store gratuit), importer `mac-wireguard.conf`.

---

## Phase 6 — Node.js + Python

```bash
# 6.1 — Node.js via nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
source ~/.bashrc
nvm install 22 && nvm alias default 22
npm install -g pnpm

# 6.2 — Python
sudo apt install -y python3 python3-venv python3-pip
```

---

## Phase 7 — Doppler (secrets)

```bash
# 7.1 — Installer Doppler CLI
curl -sLf --retry 3 --tlsv1.2 --proto "=https" \
  'https://packages.doppler.com/public/cli/gpg.DE2A7741A397C129.key' | \
  sudo gpg --dearmor -o /usr/share/keyrings/doppler-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/doppler-archive-keyring.gpg] \
  https://packages.doppler.com/public/cli/deb/debian any-version main" | \
  sudo tee /etc/apt/sources.list.d/doppler-cli.list
sudo apt update && sudo apt install -y doppler

# 7.2 — Login + setup
doppler login
doppler setup --project daemon --config prd

# 7.3 — Secrets à ajouter (via dashboard ou CLI) :
# doppler secrets set ANTHROPIC_API_KEY="sk-ant-..."
# doppler secrets set NOTION_API_KEY="ntn_..."
# doppler secrets set OBSIDIAN_API_KEY="..."
# doppler secrets set GITEA_DB_PASS="<valeur générée en phase 3>"
# doppler secrets set PERPLEXITY_API_KEY="..."
# doppler secrets set XAI_API_KEY="..."
# doppler secrets set GOOGLE_AI_KEY="..."
```

---

## Phase 8 — Whisper (transcription audio)

```bash
# 8.1 — Deployer faster-whisper via Docker
cat >> ~/daemon-infra/docker-compose.yml << 'EOF'

  whisper:
    image: fedirz/faster-whisper-server:latest-cpu
    container_name: whisper
    ports:
      - "127.0.0.1:8100:8000"
    environment:
      - WHISPER__MODEL=Systran/faster-whisper-medium
      - WHISPER__DEVICE=cpu
    restart: always
EOF

cd ~/daemon-infra && docker compose up -d whisper

# 8.2 — Tester
curl -X POST http://127.0.0.1:8100/v1/audio/transcriptions \
  -F "file=@test.wav" -F "language=fr"
```

> Note : Groq Whisper API = option rapide + pas chère pour le quotidien. Whisper local = fallback gros fichiers / mode offline.

---

## Phase 9 — n8n (workflows / automatisation)

```bash
cat >> ~/daemon-infra/docker-compose.yml << 'EOF'

  n8n:
    image: n8nio/n8n:latest
    container_name: n8n
    ports:
      - "127.0.0.1:5678:5678"
    volumes:
      - ./n8n/data:/home/node/.n8n
    environment:
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER=jerem
      - N8N_BASIC_AUTH_PASSWORD=${N8N_PASSWORD}
    restart: always
EOF

N8N_PASSWORD=$(openssl rand -base64 16)
echo "N8N_PASSWORD=$N8N_PASSWORD" >> ~/daemon-infra/.env
cd ~/daemon-infra && docker compose up -d n8n
```

> Accessible uniquement via VPN (10.0.0.1:5678) ou SSH tunnel.

---

## Phase 10 — Uptime Kuma (monitoring)

```bash
cat >> ~/daemon-infra/docker-compose.yml << 'EOF'

  uptime-kuma:
    image: louislam/uptime-kuma:1
    container_name: uptime-kuma
    ports:
      - "127.0.0.1:3001:3001"
    volumes:
      - ./uptime-kuma/data:/app/data
    restart: always
EOF

cd ~/daemon-infra && docker compose up -d uptime-kuma
```

> Dashboard monitoring : vérifier que Gitea, OpenClaw, Whisper, n8n sont up. Alertes via webhook.

---

## Phase 11 — OpenClaw (le cerveau de DAEMON)

> OpenClaw = framework agent open-source, self-hosted. Multi-LLM (Claude, GPT, Gemini, local), multi-chat (WhatsApp, Slack, Telegram, Discord, Signal, iMessage), mémoire persistante, skills extensibles, accès système complet. Site : https://openclaw.ai — Repo : https://github.com/openclaw/openclaw

```bash
# 12.1 — Installer OpenClaw (méthode hackable, pour pouvoir modifier)
cd ~/daemon-infra
git clone https://github.com/openclaw/openclaw.git openclaw
cd openclaw
npm install

# 12.2 — Configurer le SOUL.md (personnalité DAEMON)
# Copier le soul.md du vault comme system prompt OpenClaw
cp /home/daemon/vault/_adn/soul.md ./soul.md

# 12.3 — Configurer les clés API (via Doppler ou .env)
# OpenClaw supporte : Anthropic Claude, OpenAI, Google Gemini, modèles locaux
# Les clés sont injectées via Doppler au runtime

# 12.4 — Connecter les MCP Servers
# Obsidian MCP : accès au vault
# Notion MCP : accès aux bases Notion
npm install @notionhq/notion-mcp-server

# 12.5 — Configurer les canaux de communication
# WhatsApp, Slack, Telegram — config dans openclaw selon la doc
# Priorité : Slack d'abord (le plus simple), WhatsApp ensuite

# 12.6 — Service systemd (tourne 24/7)
sudo tee /etc/systemd/system/openclaw.service << 'EOF'
[Unit]
Description=OpenClaw DAEMON
After=network.target docker.service
[Service]
Type=simple
User=daemon
WorkingDirectory=/home/daemon/daemon-infra/openclaw
ExecStart=/usr/bin/doppler run -- node server.js
Restart=always
RestartSec=5
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload && sudo systemctl enable openclaw
sudo systemctl start openclaw
```

---

## Phase 12 — Sync Vault Mac ↔ Gitea ↔ VPS

```bash
# 13.1 — Sur le VPS : cloner le vault depuis Gitea
cd /home/daemon
git clone http://127.0.0.1:3000/jerem/daemon-vault.git vault
cd vault
git config user.name "DAEMON"
git config user.email "daemon@jerem.dev"

# 13.2 — Script sync auto (cron toutes les 5 min)
cat > ~/daemon-infra/scripts/vault-sync.sh << 'SCRIPT'
#!/bin/bash
cd /home/daemon/vault
git pull --rebase origin main
git add -A
CHANGES=$(git status --porcelain)
if [ -n "$CHANGES" ]; then
    git commit -m "vault-sync: $(date '+%Y-%m-%d %H:%M')"
    git push origin main
fi
SCRIPT
chmod +x ~/daemon-infra/scripts/vault-sync.sh
(crontab -l 2>/dev/null; echo "*/5 * * * * ~/daemon-infra/scripts/vault-sync.sh >> ~/daemon-infra/scripts/sync.log 2>&1") | crontab -
```

**Côté Mac** : plugin Obsidian Git (auto-commit + auto-push toutes les 5 min, pull strategy: rebase).

```bash
# Initialisation unique sur le Mac
cd "/Users/jerems_mac/Library/Mobile Documents/iCloud~md~obsidian/Documents/DAEMON"
git init
git remote add origin http://76.13.42.203:3000/jerem/daemon-vault.git
git add -A && git commit -m "initial vault commit"
git push -u origin main
```

---

## Checklist post-installation

- [ ] Tester SSH avec user `daemon` sur port 2222
- [ ] Vérifier que root SSH est bloqué
- [ ] Tester VPN WireGuard depuis Mac
- [ ] Accéder à Gitea, créer repo `daemon-vault`
- [ ] Push initial du vault depuis Mac
- [ ] Vérifier sync auto (attendre 5 min, vérifier le log)
- [ ] Accéder à n8n via VPN
- [ ] Accéder à Uptime Kuma via VPN
- [ ] Accéder à Coolify via VPN
- [ ] Tester transcription Whisper
- [ ] Migrer les clés API dans Doppler
- [ ] Configurer les monitors Uptime Kuma (Gitea, OpenClaw, Whisper, n8n)

---

## ⚠️ Point d'attention : iCloud vs Git

Le vault est dans iCloud. iCloud + Git sur le même dossier = conflits possibles.

**Recommandation** : déplacer le vault vers `~/Documents/DAEMON` quand Git sync est stable. iCloud n'est plus nécessaire quand Gitea fait le job.

---

## Après installation — priorités

1. Corriger les 6 skills Obsidian (audit du 16 avril)
2. Déployer les agents Obsidian comme première charge de travail
3. Premier import Notion → Obsidian
4. Configurer les routines cron (organizer quotidien, dream hebdo)
5. Interface Jerem : Slack ou terminal pour parler à DAEMON
