Comment migrer une application d'analyse vers un serveur d'analyse sur Ubuntu 14.04

De Get Docs
Aller à :navigation, rechercher

Introduction

Parse est une plateforme Mobile Backend as a Service, détenue par Facebook depuis 2013. En janvier 2016, Parse a annoncé que ses services hébergés fermeraient complètement le 28 janvier 2017.

Heureusement, Parse a également publié un serveur API open source, compatible avec l'API du service hébergé, appelé Parse Server. Parse Server est en cours de développement et semble susceptible d'attirer une large communauté de développeurs. Il peut être déployé dans une gamme d'environnements exécutant Node.js et MongoDB.

Ce guide se concentre sur la migration d'une application Parse préexistante vers une instance autonome de Parse Server exécutée sur Ubuntu 14.04. Il utilise le cryptage TLS/SSL pour toutes les connexions, en utilisant un certificat fourni par Let's Encrypt, une nouvelle autorité de certification qui propose des certificats gratuits. Il inclut quelques détails spécifiques à DigitalOcean et Ubuntu 14.04, mais devrait être largement applicable aux systèmes exécutant des distributions GNU/Linux récentes dérivées de Debian.

Avertissement : Il est fortement recommandé de tester d'abord cette procédure avec une version de développement ou de test de l'application avant de la tenter avec une application de production destinée à l'utilisateur. Il est également fortement recommandé de lire ce guide conjointement avec la documentation officielle de migration.


Conditions préalables

Ce guide s'appuie sur Comment exécuter Parse Server sur Ubuntu 14.04. Cela nécessite les éléments suivants :

  • Un serveur Ubuntu 14.04, configuré avec un utilisateur non root sudo
  • Node.js 5.6.x
  • MongoDB 3.0.x
  • Un nom de domaine pointant vers le serveur
  • Une application d'analyse à migrer
  • Nginx installé et configuré avec SSL à l'aide de certificats Let's Encrypt. Comment sécuriser Nginx avec Let's Encrypt sur Ubuntu 14.04 vous guidera tout au long du processus.

Le serveur cible doit disposer de suffisamment d'espace de stockage pour gérer toutes les données de votre application. Étant donné que Parse compresse les données de leur côté, ils recommandent officiellement de fournir au moins 10 fois plus d'espace de stockage que celui utilisé par votre application hébergée.

Étape 1 - Configurer MongoDB pour la migration

Parse fournit un outil de migration pour les applications existantes. Pour l'utiliser, nous devons ouvrir MongoDB aux connexions externes et le sécuriser avec une copie du certificat TLS/SSL de Let's Encrypt. Commencez par combiner fullchain1.pem et privkey1.pem dans un nouveau fichier dans /etc/ssl :

sudo cat /etc/letsencrypt/archive/domain_name/{fullchain1.pem,privkey1.pem} | sudo tee /etc/ssl/mongo.pem

Vous devrez répéter la commande ci-dessus après avoir renouvelé votre certificat Let's Encrypt. Si vous configurez le renouvellement automatique du certificat Let's Encrypt, pensez à inclure cette opération.


Assurez-vous que mongo.pem appartient à l'utilisateur mongodb et ne peut être lu que par son propriétaire :

sudo chown mongodb:mongodb /etc/ssl/mongo.pem
sudo chmod 600 /etc/ssl/mongo.pem

Maintenant, ouvrez /etc/mongod.conf dans nano (ou l'éditeur de texte de votre choix) :

sudo nano /etc/mongod.conf

Ici, nous allons apporter plusieurs modifications importantes.

Tout d'abord, recherchez la ligne bindIp dans la section net: et dites à MongoDB d'écouter sur toutes les adresses en remplaçant 127.0.0.1 par 0.0.0.0. En dessous, ajoutez la configuration SSL à la même section :

/etc/mongod.conf

# network interfaces
net:
  port: 27017
  bindIp: 0.0.0.0
  ssl:
    mode: requireSSL
    PEMKeyFile: /etc/ssl/mongo.pem

Ensuite, sous # security, activez l'autorisation client :

/etc/mongod.conf

# security
security:
  authorization: enabled

Enfin, l'outil de migration nous oblige à définir le paramètre failIndexKeyTooLong sur false :

/etc/mongod.conf

setParameter:
  failIndexKeyTooLong: false

Remarque : Les espaces blancs sont importants dans les fichiers de configuration MongoDB, qui sont basés sur YAML. Lors de la copie des valeurs de configuration, veillez à conserver l'indentation.


Quittez et enregistrez le fichier.

Avant de redémarrer le service mongod, nous devons ajouter un utilisateur avec le rôle admin. Connectez-vous à l'instance MongoDB en cours d'exécution :

mongo --port 27017

Créez un utilisateur administrateur et quittez. Assurez-vous de remplacer sammy par le nom d'utilisateur souhaité et le mot de passe par un mot de passe fort.

use admin
db.createUser({
  user: "sammy",
  pwd: "password",
  roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
})
exit

Redémarrez le service mongod :

sudo service mongod restart

Étape 2 - Migrer les données d'application à partir de l'analyse

Maintenant que vous disposez d'une instance MongoDB accessible à distance, vous pouvez utiliser l'outil de migration Parse pour transférer les données de votre application vers votre serveur.

Configurer les informations d'identification MongoDB pour l'outil de migration

Nous allons commencer par nous connecter localement avec notre nouvel utilisateur administrateur :

mongo --port 27017 --ssl --sslAllowInvalidCertificates --authenticationDatabase admin --username sammy --password

Vous devriez être invité à entrer le mot de passe que vous avez défini précédemment.

Une fois connecté, choisissez un nom pour la base de données pour stocker les données de votre application. Par exemple, si vous migrez une application appelée Todo, vous pouvez utiliser todo. Vous devrez également choisir un autre mot de passe fort pour un utilisateur appelé parse.

À partir du shell mongo, accordez à cet utilisateur l'accès à database_name :

use database_name
db.createUser({ user: "parse", pwd: "password", roles: [ "readWrite", "dbAdmin" ] })

Lancer le processus de migration des données

Dans une fenêtre de navigateur, connectez-vous à Parse et ouvrez les paramètres de votre application. Sous Général, localisez le bouton Migrate et cliquez dessus :

Vous serez invité à entrer une chaîne de connexion MongoDB. Utilisez le format suivant :

mongodb://parse:[email protected]_domain_name:27017/database_name?ssl=true

Par exemple, si vous utilisez le domaine example.com, avec l'utilisateur parse, le mot de passe foo et une base de données appelée todo, votre chaîne de connexion ressemble à ca:

mongodb://parse:[email protected]:27017/todo?ssl=true

N'oubliez pas ?ssl=true à la fin, sinon la connexion échouera. Entrez la chaîne de connexion dans la boîte de dialogue comme ceci :

Cliquez sur Commencer la migration. Vous devriez voir des boîtes de dialogue de progression pour copier un instantané de votre base de données hébergée Parse sur votre serveur, puis pour synchroniser les nouvelles données depuis la prise de l'instantané. La durée de ce processus dépendra de la quantité de données à transférer et peut être substantielle.

Vérifier la migration des données

Une fois terminé, le processus de migration entrera dans une étape de vérification. Ne finalisez pas encore la migration. Vous devez d'abord vous assurer que les données ont bien été transférées et tester une instance locale de Parse Server.

Revenez à votre shell mongo et examinez votre base de données locale. Commencez par accéder à database_name et examinez les collections qu'il contient :

use database_name
show collections
Sample Output for Todo AppTodo
_Index
_SCHEMA
_Session
_User
_dummy
system.indexes

Vous pouvez examiner le contenu d'une collection spécifique avec la méthode .find() :

db.ApplicationName.find()
Sample Output for Todo App> db.Todo.find()
{ "_id" : "hhbrhmBrs0", "order" : NumberLong(1), "_p_user" : "_User$dceklyR50A", "done" : false, "_acl" : { "dceklyR50A" : { "r" : true, "w" : true } }, "_rperm" : [ "dceklyR50A" ], "content" : "Migrate this app to my own server.", "_updated_at" : ISODate("2016-02-08T20:44:26.157Z"), "_wperm" : [ "dceklyR50A" ], "_created_at" : ISODate("2016-02-08T20:44:26.157Z") }

Votre sortie spécifique sera différente, mais vous devriez voir les données de votre application. Une fois satisfait, quittez mongo et revenez au shell :

exit

Étape 3 - Installer et configurer Parse Server et PM2

Avec vos données d'application dans MongoDB, nous pouvons passer à l'installation de Parse Server lui-même et à l'intégration avec le reste du système. Nous donnerons à Parse Server un utilisateur dédié et utiliserons un utilitaire appelé PM2 pour le configurer et nous assurer qu'il est toujours en cours d'exécution.

Installer Parse Server et PM2 globalement

Utilisez npm pour installer l'utilitaire parse-server, le gestionnaire de processus pm2 et leurs dépendances, globalement :

sudo npm install -g parse-server pm2

Créer un utilisateur Parse dédié et un répertoire personnel

Au lieu d'exécuter parse-server en tant que root ou votre utilisateur sudo, nous allons créer un utilisateur système appelé parse :

sudo useradd --create-home --system parse

Définissez maintenant un mot de passe pour parse :

sudo passwd parse

Vous serez invité à entrer un mot de passe deux fois.

Maintenant, utilisez la commande su pour devenir l'utilisateur parse :

sudo su parse

Accédez au répertoire personnel de parse :

cd ~

Écrire ou migrer un fichier de code cloud

Créez un répertoire de code cloud :

mkdir -p ~/cloud

Modifier /home/parse/cloud/main.js :

nano ~/cloud/main.js

À des fins de test, vous pouvez coller les éléments suivants :

/home/parse/cloud/main.js

Parse.Cloud.define('hello', function(req, res) {
  res.success('Hi');
});

Vous pouvez également migrer n'importe quel code cloud défini pour votre application en le copiant depuis la section Cloud Code des paramètres de votre application sur le tableau de bord Parse.

Quittez et sauvegardez.

Récupérer les clés et écrire /home/parse/ecosystem.json

PM2 est un gestionnaire de processus riche en fonctionnalités, populaire auprès des développeurs Node.js. Nous utiliserons l'utilitaire pm2 pour configurer notre instance parse-server et la faire fonctionner à long terme.

Vous devrez récupérer certaines des clés de votre application. Dans le tableau de bord Parse, cliquez sur Paramètres de l'application suivi par Sécurité et clés :

Parmi ceux-ci, seuls Application ID et Master Key sont requis. D'autres (clés client, JavaScript, .NET et API REST) peuvent être nécessaires pour prendre en charge les versions client plus anciennes, mais, si elles sont définies, elles seront requises dans toutes les demandes. Sauf si vous avez des raisons de croire le contraire, vous devez commencer par utiliser uniquement l'ID d'application et la clé principale.

Avec ces clés à portée de main, éditez un nouveau fichier appelé /home/parse/ecosystem.json :

nano ecosystem.json

Collez les valeurs de configuration suivantes en modifiant les valeurs de votre chaîne de connexion MongoDB, de votre ID d'application et de votre clé principale :

{
  "apps" : [{
    "name"        : "parse-wrapper",
    "script"      : "/usr/bin/parse-server",
    "watch"       : true,
    "merge_logs"  : true,
    "cwd"         : "/home/parse",
    "env": {
      "PARSE_SERVER_CLOUD_CODE_MAIN": "/home/parse/cloud/main.js",
      "PARSE_SERVER_DATABASE_URI": "mongodb://parse:[email protected]_domain_name:27017/database_name?ssl=true",
      "PARSE_SERVER_APPLICATION_ID": "your_application_id",
      "PARSE_SERVER_MASTER_KEY": "your_master_key",
    }
  }]
}

L'objet env est utilisé pour définir des variables d'environnement. Si vous devez configurer des clés supplémentaires, parse-server reconnaît également les variables suivantes :

  • PARSE_SERVER_COLLECTION_PREFIX
  • PARSE_SERVER_CLIENT_KEY
  • PARSE_SERVER_REST_API_KEY
  • PARSE_SERVER_DOTNET_KEY
  • PARSE_SERVER_JAVASCRIPT_KEY
  • PARSE_SERVER_DOTNET_KEY
  • PARSE_SERVER_FILE_KEY
  • PARSE_SERVER_FACEBOOK_APP_IDS

Quittez et enregistrez ecosystem.json.

Maintenant, exécutez le script avec pm2 :

pm2 start ecosystem.json
Sample Output...
[PM2] Spawning PM2 daemon
[PM2] PM2 Successfully daemonized
[PM2] Process launched
┌───────────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────────────┬──────────┐
│ App name      │ id │ mode │ pid  │ status │ restart │ uptime │ memory      │ watching │
├───────────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────────────┼──────────┤
│ parse-wrapper │ 0  │ fork │ 3499 │ online │ 0       │ 0s     │ 13.680 MB   │  enabled │
└───────────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────────────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app

Dites maintenant à pm2 d'enregistrer cette liste de processus :

pm2 save
Sample Output[PM2] Dumping processes

La liste des processus pm2 en cours d'exécution pour l'utilisateur parse doit maintenant être stockée dans /home/parse/.pm2.

Nous devons maintenant nous assurer que le processus parse-wrapper que nous avons défini précédemment dans ecosystem.json est restauré à chaque redémarrage du serveur. Heureusement, pm2 peut générer et installer un script par lui-même.

Revenez à votre utilisateur habituel sudo :

exit

Dites à pm2 d'installer les scripts d'initialisation pour Ubuntu, à exécuter en tant qu'utilisateur parse, en utilisant /home/parse comme répertoire personnel :

sudo pm2 startup ubuntu -u parse --hp /home/parse/

Production

[PM2] Spawning PM2 daemon
[PM2] PM2 Successfully daemonized
[PM2] Generating system init script in /etc/init.d/pm2-init.sh
[PM2] Making script booting at startup...
[PM2] -ubuntu- Using the command:
      su -c "chmod +x /etc/init.d/pm2-init.sh && update-rc.d pm2-init.sh defaults"
 System start/stop links for /etc/init.d/pm2-init.sh already exist.
[PM2] Done.

Étape 4 - Installer et configurer Nginx

Nous utiliserons le serveur Web Nginx pour fournir un proxy inverse à parse-server, afin que nous puissions servir l'API Parse en toute sécurité via TLS/SSL.

Dans les prérequis, vous configurez le serveur default pour répondre à votre nom de domaine, avec SSL fourni par les certificats Let's Encrypt. Nous mettrons à jour ce fichier de configuration avec nos informations de proxy.

Ouvrez /etc/nginx/sites-enabled/default dans nano (ou l'éditeur de votre choix) :

sudo nano /etc/nginx/sites-enabled/default

Dans le bloc principal server (il devrait déjà contenir un bloc location /), ajoutez un autre bloc location pour gérer le proxy des URL /parse/ :

/etc/nginx/sites-enabled/default

. . .
        # Pass requests for /parse/ to Parse Server instance at localhost:1337
        location /parse/ {
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-NginX-Proxy true;
                proxy_pass http://localhost:1337/;
                proxy_ssl_session_reuse off;
                proxy_set_header Host $http_host;
                proxy_redirect off;
        }

Quittez l'éditeur et enregistrez le fichier. Redémarrez Nginx pour que les modifications prennent effet :

sudo service nginx restart
Output * Restarting nginx nginx
   ...done.

Étape 5 - Tester le serveur d'analyse

A ce stade, vous devriez avoir les éléments suivants :

  • Un certificat TLS/SSL, fourni par Let's Encrypt
  • MongoDB, sécurisé avec le certificat Let's Encrypt
  • parse-server exécuté sous l'utilisateur parse sur le port 1337, configuré avec les clés attendues par votre application
  • pm2 gérant le processus parse-server sous l'utilisateur parse, et un script de démarrage pour redémarrer pm2 au démarrage
  • nginx, sécurisé avec le certificat Let's Encrypt et configuré pour les connexions proxy à https://your_domain_name/parse vers l'instance parse-server

Il devrait maintenant être possible de tester les lectures, les écritures et l'exécution de code cloud à l'aide de curl.

Remarque : Les commandes curl de cette section doivent être inoffensives lorsqu'elles sont utilisées avec une application de test ou de développement. Soyez prudent lorsque vous écrivez des données dans une application de production.


Écrire des données avec un POST

Vous devrez donner à curl plusieurs options importantes :

Option La description
-X POST Définit le type de demande, qui serait autrement par défaut à GET
-H "X-Parse-Application-Id: your_application_id" Envoie un en-tête qui identifie votre application à parse-server
-H "Content-Type: application/json" Envoie un en-tête qui permet à parse-server de savoir s'attendre à des données au format JSON
-d '{json_data} Envoie les données elles-mêmes

En mettant tout cela ensemble, nous obtenons :

curl -X POST \
  -H "X-Parse-Application-Id: your_application_id" \
  -H "Content-Type: application/json" \
  -d '{"score":1337,"playerName":"Sammy","cheatMode":false}' \
  https://your_domain_name/parse/classes/GameScore

Exemple de sortie

{"objectId":"YpxFdzox3u","createdAt":"2016-02-18T18:03:43.188Z"}

Lire des données avec un GET

Étant donné que curl envoie des requêtes GET par défaut et que nous ne fournissons aucune donnée, il vous suffit d'envoyer l'ID d'application pour lire certains exemples de données :

curl -H "X-Parse-Application-Id: your_application_id" https://your_domain_name/parse/classes/GameScore

Exemple de sortie

{"results":[{"objectId":"BNGLzgF6KB","score":1337,"playerName":"Sammy","cheatMode":false,"updatedAt":"2016-02-17T20:53:59.947Z","createdAt":"2016-02-17T20:53:59.947Z"},{"objectId":"0l1yE3ivB6","score":1337,"playerName":"Sean Plott","cheatMode":false,"updatedAt":"2016-02-18T03:57:00.932Z","createdAt":"2016-02-18T03:57:00.932Z"},{"objectId":"aKgvFqDkXh","score":1337,"playerName":"Sean Plott","cheatMode":false,"updatedAt":"2016-02-18T04:44:01.275Z","createdAt":"2016-02-18T04:44:01.275Z"},{"objectId":"zCKTgKzCRH","score":1337,"playerName":"Sean Plott","cheatMode":false,"updatedAt":"2016-02-18T16:56:51.245Z","createdAt":"2016-02-18T16:56:51.245Z"},{"objectId":"YpxFdzox3u","score":1337,"playerName":"Sean Plott","cheatMode":false,"updatedAt":"2016-02-18T18:03:43.188Z","createdAt":"2016-02-18T18:03:43.188Z"}]}

Exécution d'un exemple de code cloud

Un POST simple sans données réelles vers https://your_domain_name/parse/functions/hello exécutera la fonction hello() définie dans /home/parse/cloud/main.js :

curl -X POST \
  -H "X-Parse-Application-Id: your_application_id" \
  -H "Content-Type: application/json" \
  -d '{}' \
  https://your_domain_name/parse/functions/hello

Exemple de sortie

{"result":"Hi"}

Si vous avez plutôt migré votre propre code cloud personnalisé, vous pouvez tester avec une fonction connue de main.js.

Étape 6 - Configurez votre application pour Parse Server et finalisez la migration

Votre prochaine étape consistera à modifier votre application client elle-même pour utiliser le point de terminaison de l'API Parse Server. Consultez la documentation officielle sur l'utilisation des SDK Parse avec Parse Server. Vous aurez besoin de la dernière version du SDK pour votre plateforme. Comme pour les tests basés sur curl ci-dessus, utilisez cette chaîne pour l'URL du serveur :

https://your_domain_name/parse

Revenez au tableau de bord Parse de votre navigateur et à l'onglet Migration :

Cliquez sur le bouton Finaliser :

Votre application devrait maintenant être migrée.

Conclusion et prochaines étapes

Ce guide offre un point de départ fonctionnel pour la migration d'une application hébergée par Parse vers une installation Parse Server sur un seul système Ubuntu, tel qu'un droplet DigitalOcean. La configuration que nous avons décrite devrait être adéquate pour une application à faible trafic avec une base d'utilisateurs modeste. L'hébergement d'une application plus grande peut nécessiter plusieurs systèmes pour fournir un stockage de données redondant et un équilibrage de charge entre les points de terminaison de l'API. Même les petits projets sont susceptibles d'impliquer des considérations d'infrastructure que nous n'avons pas directement abordées.

En plus de lire la documentation officielle de Parse Server et de suivre les problèmes GitHub pour le projet lors du dépannage, vous souhaiterez peut-être explorer les sujets suivants :