# Le manifeste arkya.json

> Décrire la machine, la puissance et les prérequis d'une application, et laisser ark tenir la promesse.

`arkya.json` décrit **l'état voulu** de ton application : où elle tourne, quelle
puissance elle a, de quoi elle a besoin pour démarrer. `ark plan` dit ce qui manque
pour y arriver, `ark deploy` l'applique puis déploie.

```json arkya.json
{
  "app": "mon-api",
  "dockerfile": "Dockerfile",
  "context": ".",

  "node": "gra-01",
  "project": "Production",
  "size": { "cpu": 2, "ram": 2, "disk": 20 },

  "services": {
    "db": {
      "type": "postgres-16",
      "size": { "cpu": 1, "ram": 2, "disk": 20 },
      "env": { "POSTGRES_DB": "boutique" }
    },
    "cache": {
      "type": "redis-7"
    }
  },

  "env": {
    "DATABASE_URL": "${db.url}",
    "REDIS_HOST": "${cache.host}",
    "LOG_LEVEL": "info"
  }
}
```

## L'application

| Champ | Ce qu'il fait | Défaut |
| --- | --- | --- |
| `app` | Le nom de l'application. Minuscules, chiffres et tirets. | obligatoire |
| `dockerfile` | Le fichier à construire. | `Dockerfile` |
| `context` | Le contexte de construction. | `.` |
| `node` | Le nœud qui l'héberge, par son libellé ou son identifiant. | Arkya choisit |
| `project` | Le projet de rattachement. Créé s'il n'existe pas. | le projet par défaut |
| `size` | `{ "cpu": 2, "ram": 2, "disk": 20 }` — vCPU, Go de mémoire, Go de disque. | le plancher du nœud |
| `start` | La commande lancée dans le conteneur au démarrage. | celle de l'image |

<Note>
  Sans `size`, le service prend **le minimum qu'accepte le nœud** — 1 vCPU, 1 Go, et le
  disque plancher de la machine, souvent 10 Go. C'est la plus petite taille qui démarre
  vraiment, pas une valeur théorique.
</Note>

<Note>
  `size` vaut aussi bien à la création qu'ensuite : si tu montes `ram` de 2 à 4,
  `ark deploy` retaille l'application avant de déployer. Le disque ne se réduit pas.
</Note>

## La commande de démarrage

`start` remplace le `CMD` de ton image. C'est là que va un script de migration, par
exemple :

```json
{
  "app": "mon-api",
  "start": "./scripts/migrate-then-start.sh"
}
```

Elle s'applique au prochain démarrage — donc à la mise en service que `ark deploy`
enchaîne juste après. Chaque image du manifeste a la sienne.

```bash
ark command mon-api            # lire celle qui tourne
ark command mon-api --restore  # revenir à celle de l'image
```

## Les prérequis

Chaque entrée de `services` est un service qu'Arkya doit tenir prêt. La clé est
**l'alias** : c'est par lui que tu y fais référence dans `env`.

| Champ | Ce qu'il fait | Défaut |
| --- | --- | --- |
| `type` | L'édition voulue : `postgres-16`, `mysql-8`, `redis-7`… | obligatoire |
| `size` | La taille du service. | le plancher du nœud |
| `env` | Les variables posées à sa création — mot de passe, nom de base… | aucune |
| `name` | Son nom chez Arkya. | `<app>-<alias>` |
| `product` | Le produit du catalogue, quand le type ne suffit pas à le deviner. | déduit |

Les éditions disponibles se lisent dans le catalogue :

```bash
curl -s https://api.arkya.gg/catalog/products/bases-de-donnees | jq '.variants[].slug'
```

```
"postgres-16"
"mysql-8"
"redis-7"
```

## Les références

Dans `env`, `${alias.clé}` est remplacé par la vraie valeur du service, au moment du
déploiement.

| Clé | Ce qu'elle vaut |
| --- | --- |
| `host` | L'alias interne du service dans le projet. |
| `port` | Son port interne. |
| `user` | L'utilisateur de la base. |
| `password` | Son mot de passe. |
| `name` | Le nom de la base. |
| `url` | L'URL complète : `postgres://user:mot-de-passe@host:port/base`. |

```json
"env": {
  "DATABASE_URL": "${db.url}",
  "DATABASE_HOST": "${db.host}",
  "DATABASE_PORT": "${db.port}",
  "REDIS_URL": "${cache.url}"
}
```

<Warning>
  Une référence vers un alias absent de `services` arrête le déploiement plutôt que de
  poser une variable vide. C'est volontaire : une application qui démarre avec une
  `DATABASE_URL` tronquée est plus difficile à diagnostiquer qu'un refus net.
</Warning>

## Voir avant de faire

```bash
ark plan
```

```
mon-api Production

À créer :
  mon-api-db  postgres-16 · 1 vCPU · 2 Go · 20 Go  4.20 €/mois

À modifier :
  mon-api     2 vCPU · 2 Go · 20 Go (au lieu de 1 vCPU · 1 Go · 10 Go)  3.24 €/mois  +2.18 €

Total après application  7.44 €/mois

Variables qui seront posées :
  DATABASE_URL  ••••••••••••
  LOG_LEVEL     info

`ark plan --apply` applique, `ark deploy` applique puis déploie.
```

Chaque ligne porte son tarif mensuel, y compris les services déjà en place — le total
est celui que tu paieras une fois le manifeste tenu, pas seulement le coût de ce qui
change. Une retaille montre en plus l'écart avec le tarif actuel.

Les valeurs qui contiennent un secret sont masquées à l'affichage — le mot de passe
part bien au service, il ne s'affiche simplement pas dans ton terminal.

## Appliquer

```bash
ark plan --apply     # met l'hébergement en conformité, sans déployer
ark deploy           # la même chose, puis construit, pousse et met en service
```

Les deux montrent le plan et **demandent confirmation avant de commander quoi que ce
soit** : déclarer une base dans un fichier, c'est engager une dépense. `--yes` saute la
question, pour l'intégration continue.

```bash
ark deploy --yes
```

## Plusieurs images dans un même dépôt

Un service de type `app` est une **seconde image**, construite depuis le même dépôt :
un worker, un cron, un consommateur de file.

```json
{
  "app": "mon-api",
  "dockerfile": "Dockerfile",

  "services": {
    "db": { "type": "postgres-16" },
    "worker": {
      "type": "app",
      "dockerfile": "Dockerfile.worker",
      "env": {
        "ROLE": "worker",
        "DATABASE_URL": "${db.url}"
      }
    }
  },

  "env": { "DATABASE_URL": "${db.url}" }
}
```

`ark deploy` construit, pousse et met en service **chaque image**, avec le même nom de
version — tu sais toujours quelle ligne de code tourne, des deux côtés.

```
mon-api
- construction de registry.arkya.gg/c-7f3a91c04d2e/mon-api:8f2c1d9a44e0
ok mon-api tourne en 8f2c1d9a44e0
  51.210.44.12:30013

mon-api-worker (worker)
- construction de registry.arkya.gg/c-7f3a91c04d2e/mon-api-worker:8f2c1d9a44e0
ok mon-api-worker tourne en 8f2c1d9a44e0
```

Chaque image a son propre bloc `env` : le worker ne reçoit pas les variables de l'API,
et inversement. `dockerfile` et `context` valent ceux de l'application quand ils ne sont
pas précisés.

## Venir de Railway

Un `railway.json` se traduit presque ligne pour ligne, à deux exceptions près :

| Railway | Chez nous |
| --- | --- |
| `build.dockerfilePath` | `dockerfile` |
| `deploy.startCommand` | `start` |
| `deploy.healthcheckPath` / `healthcheckTimeout` | pas d'équivalent |
| `deploy.restartPolicyType` / `restartPolicyMaxRetries` | pas de réglage |

```json arkya.json
{
  "app": "mon-api",
  "dockerfile": "Dockerfile",
  "start": "./scripts/migrate-then-start.sh",
  "services": { "db": { "type": "postgres-16" } },
  "env": { "DATABASE_URL": "${db.url}" }
}
```

<Note>
  **Sur le redémarrage :** le nœud relance tout seul un conteneur qui s'arrête en erreur,
  et cesse d'insister quand il replante dans la minute. Ce n'est pas réglable par
  application, et il n'y a pas de sonde de santé : un processus qui répond mal sans
  planter ne sera pas redémarré à ta place. `ark logs --follow` reste le moyen de voir
  ce qui se passe.
</Note>

## Ce que ça ne fait pas

- **Rien n'est supprimé.** Retirer un service du manifeste ne le détruit pas : il reste,
  simplement plus personne ne le réclame. La suppression passe par `ark rm`, à la main.
- **Le nœud ne change pas après coup.** `node` sert à la création ; déplacer un service
  d'un nœud à l'autre ne se fait pas depuis le CLI.
