Aide à la restauration - le système s'est bloqué à minuit

Okay this was bound to happen, things were just too good for too long. Years of running on cruise control, the system would automatically update itself and I would update Discourse every few weeks. At midnight last night, Amazon showed the system was unresponsive, discourse was down and the CPU was pegged at 100% until it ran out of AWS CPU resources. Couldn’t login to the system, the one time after several reboots I was able to login momentarily, I saw this in htoptaking up a lot of CPU

snap lxd activate

If anyone has seen this can can throw some light as to why this may happened by itself, it would be much appreciated for future reference.

Coming the pressing issue at hand, I proceeded to rebuild a new server on AWS using Ubuntu 20LTS, Discourse setup was exceedingly easy. I had a copy of the app.yml file which I used to recreate the discourse forum. The old server was using S3 for the backups AND for the content (images etc).

After creating the server, I downloaded the latest discourse backup file from S3, manually uploaded it to the discourse server and hit the Restore buttons. After a few minutes I get this error.

[2022-06-09 09:01:56] ALTER TABLE
[2022-06-09 09:01:56] ALTER TABLE
[2022-06-09 09:01:56] Migrating the database...
[2022-06-09 09:02:11] == 20220308201942 CreateUploadReferences: migrating ===========================
-- create_table(:upload_references, {})
   -> 0.0486s
-- add_index(:upload_references, [:upload_id, :target_type, :target_id], {:unique=>true, :name=>"index_upload_references_on_upload_and_target"})
   -> 0.0030s
== 20220308201942 CreateUploadReferences: migrated (0.0580s) ==================

== 20220309132719 CopyPostUploadsToUploadReferences: migrating ================
-- execute("INSERT INTO upload_references(upload_id, target_type, target_id, created_at, updated_at)\nSELECT post_uploads.upload_id, 'Post', post_uploads.post_id, uploads.created_at, uploads.updated_at\nFROM post_uploads\nJOIN uploads ON uploads.id = post_uploads.upload_id\nON CONFLICT DO NOTHING\n")
   -> 0.0595s
== 20220309132719 CopyPostUploadsToUploadReferences: migrated (0.0602s) =======

== 20220309132720 CopyPostUploadsToUploadReferencesForSync: migrating =========
-- execute("INSERT INTO upload_references(upload_id, target_type, target_id, created_at, updated_at)\nSELECT upload_id, 'Post', post_id, NOW(), NOW()\nFROM post_uploads\nON CONFLICT DO NOTHING\n")
   -> 0.0076s
== 20220309132720 CopyPostUploadsToUploadReferencesForSync: migrated (0.0080s) 

== 20220330160747 CopySiteSettingsUploadsToUploadReferences: migrating ========
-- execute("WITH site_settings_uploads AS (\n  SELECT id, unnest(string_to_array(value, '|'))::integer upload_id\n  FROM site_settings\n  WHERE data_type = 17\n  UNION\n  SELECT id, value::integer\n  FROM site_settings\n  WHERE data_type = 18 AND value != ''\n)\nINSERT INTO upload_references(upload_id, target_type, target_id, created_at, updated_at)\nSELECT site_settings_uploads.upload_id, 'SiteSetting', site_settings_uploads.id, uploads.created_at, uploads.updated_at\nFROM site_settings_uploads\nJOIN uploads ON uploads.id = site_settings_uploads.upload_id\nON CONFLICT DO NOTHING\n")
   -> 0.0034s
== 20220330160747 CopySiteSettingsUploadsToUploadReferences: migrated (0.0038s) 

== 20220330160751 CopyBadgesUploadsToUploadReferences: migrating ==============
-- execute("INSERT INTO upload_references(upload_id, target_type, target_id, created_at, updated_at)\nSELECT badges.image_upload_id, 'Badge', badges.id, uploads.created_at, uploads.updated_at\nFROM badges\nJOIN uploads ON uploads.id = badges.image_upload_id\nWHERE badges.image_upload_id IS NOT NULL\nON CONFLICT DO NOTHING\n")
   -> 0.0006s
== 20220330160751 CopyBadgesUploadsToUploadReferences: migrated (0.0010s) =====

== 20220330160754 CopyGroupsUploadsToUploadReferences: migrating ==============
-- execute("INSERT INTO upload_references(upload_id, target_type, target_id, created_at, updated_at)\nSELECT groups.flair_upload_id, 'Group', groups.id, uploads.created_at, uploads.updated_at\nFROM groups\nJOIN uploads ON uploads.id = groups.flair_upload_id\nWHERE groups.flair_upload_id IS NOT NULL\nON CONFLICT DO NOTHING\n")
   -> 0.0050s
== 20220330160754 CopyGroupsUploadsToUploadReferences: migrated (0.0055s) =====

== 20220330160757 CopyUserExportsUploadsToUploadReferences: migrating =========
-- execute("INSERT INTO upload_references(upload_id, target_type, target_id, created_at, updated_at)\nSELECT user_exports.upload_id, 'UserExport', user_exports.id, uploads.created_at, uploads.updated_at\nFROM user_exports\nJOIN uploads ON uploads.id = user_exports.upload_id\nON CONFLICT DO NOTHING\n")
   -> 0.0013s
== 20220330160757 CopyUserExportsUploadsToUploadReferences: migrated (0.0041s) 

== 20220330164740 CopyThemeFieldsUploadsToUploadReferences: migrating =========
-- execute("INSERT INTO upload_references(upload_id, target_type, target_id, created_at, updated_at)\nSELECT theme_fields.upload_id, 'ThemeField', theme_fields.id, uploads.created_at, uploads.updated_at\nFROM theme_fields\nJOIN uploads ON uploads.id = theme_fields.upload_id\nWHERE type_id = 2\nON CONFLICT DO NOTHING\n")
   -> 0.0006s
== 20220330164740 CopyThemeFieldsUploadsToUploadReferences: migrated (0.0010s) 

== 20220404195635 CopyCategoriesUploadsToUploadReferences: migrating ==========
-- execute("INSERT INTO upload_references(upload_id, target_type, target_id, created_at, updated_at)\nSELECT categories.uploaded_logo_id, 'Category', categories.id, uploads.created_at, uploads.updated_at\nFROM categories\nJOIN uploads ON uploads.id = categories.uploaded_logo_id\nWHERE categories.uploaded_logo_id IS NOT NULL\nON CONFLICT DO NOTHING\n")
   -> 0.0095s
-- execute("INSERT INTO upload_references(upload_id, target_type, target_id, created_at, updated_at)\nSELECT categories.uploaded_background_id, 'Category', categories.id, uploads.created_at, uploads.updated_at\nFROM categories\nJOIN uploads ON uploads.id = categories.uploaded_background_id\nWHERE categories.uploaded_background_id IS NOT NULL\nON CONFLICT DO NOTHING\n")
   -> 0.0004s
== 20220404195635 CopyCategoriesUploadsToUploadReferences: migrated (0.0103s) =

== 20220404201949 CopyCustomEmojisUploadsToUploadReferences: migrating ========
-- execute("INSERT INTO upload_references(upload_id, target_type, target_id, created_at, updated_at)\nSELECT custom_emojis.upload_id, 'CustomEmoji', custom_emojis.id, uploads.created_at, uploads.updated_at\nFROM custom_emojis\nJOIN uploads ON uploads.id = custom_emojis.upload_id\nWHERE custom_emojis.upload_id IS NOT NULL\nON CONFLICT DO NOTHING\n")
   -> 0.0032s
== 20220404201949 CopyCustomEmojisUploadsToUploadReferences: migrated (0.0036s) 

== 20220404203356 CopyUserProfilesUploadsToUploadReferences: migrating ========
-- execute("INSERT INTO upload_references(upload_id, target_type, target_id, created_at, updated_at)\nSELECT user_profiles.profile_background_upload_id, 'UserProfile', user_profiles.user_id, uploads.created_at, uploads.updated_at\nFROM user_profiles\nJOIN uploads ON uploads.id = user_profiles.profile_background_upload_id\nWHERE user_profiles.profile_background_upload_id IS NOT NULL\nON CONFLICT DO NOTHING\n")
   -> 0.0017s
-- execute("INSERT INTO upload_references(upload_id, target_type, target_id, created_at, updated_at)\nSELECT user_profiles.card_background_upload_id, 'UserProfile', user_profiles.user_id, uploads.created_at, uploads.updated_at\nFROM user_profiles\nJOIN uploads ON uploads.id = user_profiles.card_background_upload_id\nWHERE user_profiles.card_background_upload_id IS NOT NULL\nON CONFLICT DO NOTHING\n")
   -> 0.0011s
== 20220404203356 CopyUserProfilesUploadsToUploadReferences: migrated (0.0033s) 

== 20220404204439 CopyUserAvatarsUploadsToUploadReferences: migrating =========
-- execute("INSERT INTO upload_references(upload_id, target_type, target_id, created_at, updated_at)\nSELECT user_avatars.custom_upload_id, 'UserAvatar', user_avatars.id, uploads.created_at, uploads.updated_at\nFROM user_avatars\nJOIN uploads ON uploads.id = user_avatars.custom_upload_id\nWHERE user_avatars.custom_upload_id IS NOT NULL\nON CONFLICT DO NOTHING\n")
   -> 0.0200s
-- execute("INSERT INTO upload_references(upload_id, target_type, target_id, created_at, updated_at)\nSELECT user_avatars.gravatar_upload_id, 'UserAvatar', user_avatars.id, uploads.created_at, uploads.updated_at\nFROM user_avatars\nJOIN uploads ON uploads.id = user_avatars.gravatar_upload_id\nWHERE user_avatars.gravatar_upload_id IS NOT NULL\nON CONFLICT DO NOTHING\n")
   -> 0.0069s
== 20220404204439 CopyUserAvatarsUploadsToUploadReferences: migrated (0.0276s) 

== 20220404212716 CopyThemeSettingsUploadsToUploadReferences: migrating =======
-- execute("INSERT INTO upload_references(upload_id, target_type, target_id, created_at, updated_at)\nSELECT theme_settings.value::int, 'ThemeSetting', theme_settings.id, uploads.created_at, uploads.updated_at\nFROM theme_settings\nJOIN uploads ON uploads.id = theme_settings.value::int\nWHERE data_type = 6 AND theme_settings.value IS NOT NULL AND theme_settings.value != ''\nON CONFLICT DO NOTHING\n")
   -> 0.0025s
== 20220404212716 CopyThemeSettingsUploadsToUploadReferences: migrated (0.0030s) 

== 20220526203356 CopyUserUploadsToUploadReferences: migrating ================
-- execute("INSERT INTO upload_references(upload_id, target_type, target_id, created_at, updated_at)\nSELECT users.uploaded_avatar_id, 'User', users.id, uploads.created_at, uploads.updated_at\nFROM users\nJOIN uploads ON uploads.id = users.uploaded_avatar_id\nWHERE users.uploaded_avatar_id IS NOT NULL\nON CONFLICT DO NOTHING\n")
   -> 0.0227s
== 20220526203356 CopyUserUploadsToUploadReferences: migrated (0.0234s) =======


[2022-06-09 09:02:11] Reconnecting to the database...
[2022-06-09 09:02:12] Reloading site settings...
[2022-06-09 09:02:12] Disabling outgoing emails for non-staff users...
[2022-06-09 09:02:14] Disabling readonly mode...
[2022-06-09 09:02:14] Clearing category cache...
[2022-06-09 09:02:14] Reloading translations...
[2022-06-09 09:02:14] Remapping uploads...
[2022-06-09 09:02:14] Restoring uploads, this may take a while...
[2022-06-09 09:03:05] EXCEPTION: 509 of 1823 uploads are not migrated to S3. S3 migration failed for db 'default'.
[2022-06-09 09:03:05] /var/www/discourse/lib/file_store/to_s3_migration.rb:132:in `raise_or_log'
/var/www/discourse/lib/file_store/to_s3_migration.rb:79:in `migration_successful?'
/var/www/discourse/lib/file_store/to_s3_migration.rb:373:in `migrate_to_s3'
/var/www/discourse/lib/file_store/to_s3_migration.rb:66:in `migrate'
/var/www/discourse/lib/file_store/s3_store.rb:328:in `copy_from'
/var/www/discourse/lib/backup_restore/uploads_restorer.rb:62:in `restore_uploads'
/var/www/discourse/lib/backup_restore/uploads_restorer.rb:44:in `restore'
/var/www/discourse/lib/backup_restore/restorer.rb:61:in `run'
/var/www/discourse/script/spawn_backup_restore.rb:23:in `restore'
/var/www/discourse/script/spawn_backup_restore.rb:36:in `block in <main>'
/var/www/discourse/script/spawn_backup_restore.rb:4:in `fork'
/var/www/discourse/script/spawn_backup_restore.rb:4:in `<main>'

Can anyone advise on what’s the problem and how I can restore the server from the Amazon S3 server backups?

Salut,
après avoir recréé le nouveau serveur à partir du fichier app.yml, avez-vous eu accès aux sauvegardes dans la section https://your.domain/admin/backups ?

Non, après l’avoir recréé à partir de app.yml, cela m’a juste donné une nouvelle configuration propre sans rien. J’ai téléchargé la dernière sauvegarde depuis S3 et l’ai téléchargée manuellement sur Discourse localement, puis j’ai cliqué sur restaurer.

Je commence à la restaurer, je vois tous les paramètres (y compris S3, les identifiants, tout depuis la page Paramètres) revenir, je vois toutes les catégories apparaître, les messages s’afficher et tout. Puis soudainement, après quelques minutes, j’obtiens un message de déconnexion et toutes les catégories, les sujets disparaissent et les logs montrent cette erreur (Il semble qu’il y ait un retour en arrière).

:thinking: la configuration s3 ne se trouve donc pas dans app.yml (comme décrit ici Configure an S3 compatible object storage provider for uploads ) ? Mais configurée comme dans Set up file and image uploads to S3

1 « J'aime »

Non, je ne vois pas cela dans mon app.yml

Tous les paramètres S3 étaient définis dans les pages Admin → Paramètres et cela fonctionnait bien depuis un an jusqu’à ce que j’aie besoin de le restaurer lorsque le serveur est tombé hier soir.

Correct, c’est ce que j’ai utilisé pour configurer les sauvegardes et les téléchargements S3.

Je pense que j’essaierais de modifier le fichier app.yml avec vos paramètres et à partir de là, je pense (j’espère ?) que vous devriez voir vos sauvegardes dans la section d’administration et restaurer à partir de là, sans l’importation manuelle et les téléchargements, qui ne devraient pas avoir besoin d’être restaurés, mais semblent être inclus dans les sauvegardes. Je ne sais pas pourquoi cela échoue cependant…

1 « J'aime »

Je pense que cela peut être dû au fait que votre sauvegarde contient un mélange de téléchargements S3 et locaux. Je crains que ce ne soit pas mon domaine d’expertise, mais il y a une discussion et une solution dans ce sujet qui vous permet de contourner l’échec. Cependant, c’était pour un nombre beaucoup plus restreint d’erreurs, vous voudrez donc peut-être en tenir compte :

2 « J'aime »

Merci, mon site a malheureusement planté, il ne me reste donc que les téléchargements et les sauvegardes S3. Je suppose qu’il n’y a aucun moyen pour moi de migrer les fichiers locaux restants vers S3 maintenant.

Je me demande donc quelles sont mes options actuelles ? Existe-t-il un moyen de restaurer à partir des sauvegardes S3 et d’ignorer les fichiers locaux ? J’ai trouvé un moyen de faire en sorte qu’il ignore le téléchargement S3, mais alors pratiquement tous les articles ont des liens/images cassés (90 % ou plus sont probablement dans S3 car j’ai configuré le téléchargement S3 il y a de très nombreuses années).

Voici une mise à jour pour ceux qui pourraient rencontrer le même problème (en gros, je ne parviens pas à restaurer à partir d’une sauvegarde et le serveur a planté suite à une mise à niveau du système défaillante).

D’après ce que je comprends, la cause première du problème est qu’il y a des téléchargements locaux ET des téléchargements S3, donc lorsque l’outil de restauration essaie de restaurer, il bugue car il ne sait pas comment gérer simultanément les restaurations locales et S3 (peut-être est-il temps que Discourse réexamine les sauvegardes/restaurations).

Merci à @RGJ pour cette astuce, il a suggéré de forcer Discourse à ignorer le téléchargement S3 lors de la restauration :

  1. Ajoutez une ligne à votre fichier app.yml : DISCOURSE_ENABLE_S3_UPLOADS=false
  2. Reconstruisez Discourse : ./launcher rebuild app
  3. Tentez une restauration (soit depuis la page de sauvegarde de l’interface graphique, soit en utilisant la ligne de commande)
  4. Ensuite, après la restauration, supprimez cette ligne de app.yml et reconstruisez une fois de plus.

Bien que cela ait fonctionné, il est à noter que le forum était gravement endommagé, les catégories, les paramètres et les publications ont été restaurés, mais toutes les images, liens, documents intégrés, etc. étaient cassés et généraient des erreurs.

La solution de dernier recours :
J’ai réussi à récupérer l’ancien serveur et j’ai extrait le répertoire /var/discourse (tar/gz) et je l’ai copié sur le nouveau serveur et j’ai exécuté ./launcher rebuild app. Cela a complètement restauré le fonctionnement du forum, cependant le problème fondamental demeure : les sauvegardes ne fonctionneront PAS car elles contiennent un mélange de téléchargements locaux et S3.

J’ai donc vraiment besoin de conseils sur la meilleure façon de résoudre ce problème une fois pour toutes. Est-il préférable/plus facile de déplacer tous les téléchargements du local vers S3 ou de S3 vers le local, et comment faire ? L’objectif même d’une sauvegarde est d’aider dans des situations comme celle-ci, mais elle m’a fait défaut, j’ai donc besoin de votre aide pour la remettre en état.

1 « J'aime »

Si vous configurez comme décrit dans Utilisation du stockage d’objets pour les téléchargements (S3 et clones), vous devriez pouvoir exécuter

 rake uploads:migrate_to_s3

Si vous souhaitez arrêter d’utiliser S3, vous pouvez entrer dans la console Rails et définir

  SiteSetting.include_s3_uploads_in_backups=true

Ensuite, effectuez une sauvegarde, assurez-vous de ne pas avoir configuré S3 dans votre app.yml et restaurez la sauvegarde. Je pense que cela restaurera les sauvegardes en local.

Mais dans les deux cas, je recommanderais toujours de définir vos clés et votre bucket de sauvegarde dans des variables d’environnement dans votre fichier app.yml, puis de vérifier que vous pouvez les restaurer sur un nouveau site.

2 « J'aime »

D’accord, je pense que je me suis un peu embrouillé ici.

Je pense que la meilleure chose à faire serait d’avoir tous les téléchargements en local et de sauvegarder les sauvegardes (zips) sur S3. De cette façon, la sauvegarde est disponible sur S3 en cas de problème avec le serveur, mais la sauvegarde elle-même est autonome, sans dépendances, il devrait donc être facile de la restaurer sur un nouveau serveur.

Donc, si j’ai bien compris, je devrais suivre ces instructions :

Si vous souhaitez arrêter d'utiliser S3, vous pouvez entrer dans la console Rails et définir
  SiteSetting.include_s3_uploads_in_backups=true
Ensuite, faites une sauvegarde, assurez-vous de ne pas avoir de S3 configuré dans votre app.yml et restaurez la sauvegarde. Je pense que cela restaurera les sauvegardes en local.

et ensuite

  1. désactiver l’option activer le téléchargement vers S3 dans Admin → Paramètres → Fichiers
  2. activer l’option de sauvegarde vers S3 sur la page Admin → Paramètres → Sauvegardes

Est-ce correct ?

C’est la partie qui m’a confondu, pourquoi voudrais-je mettre la configuration S3 dans le fichier app.yml ?

Pour que vous ayez accès à vos sauvegardes via une restauration en ligne de commande avant de restaurer votre sauvegarde. Sinon, vous devez configurer un compte administrateur, puis configurer S3, puis restaurer. De même, tous les paramètres que vous mettez dans votre base de données sont écrasés lorsque vous restaurez la base de données.

Je pense que la meilleure pratique est de configurer S3 uniquement via des variables d’environnement dans le fichier app.yml. Il serait probablement judicieux de les rendre cachées, sinon des centaines de personnes seraient surprises de les voir disparaître.

1 « J'aime »

Parce que vous aurez du mal à restaurer autrement.

2 « J'aime »

Comment restaurer une sauvegarde depuis S3 en utilisant la ligne de commande ? Selon les instructions ici : Restore a backup from the command line
Il est dit que vous pouvez déposer le fichier de sauvegarde dans le dossier /var/discourse/shared/standalone/backups/default puis démarrer une restauration depuis la ligne de commande. C’est ce que j’avais fait avec votre suggestion plus tôt (ce qui a finalement conduit à des liens brisés malheureusement), mais cela fonctionne.

Comment restaurer directement depuis S3 en utilisant la ligne de commande ?

cd /var/discourse
./launcher enter app
discourse restore

Cela imprimera les sauvegardes disponibles que vous pourrez ensuite copier/coller celle que vous souhaitez restaurer.

2 « J'aime »

Merci, donc il lira les sauvegardes S3 et les listera comme une option.

Jay, pour faire suite à une suggestion que vous aviez faite pour déplacer les actifs localement :

Je pense que vous pouvez définir un paramètre caché include_s3_uploads_in_backups sur true, puis faire une sauvegarde et la restaurer lorsque S3 est désactivé pour arrêter d’utiliser S3.

Avoir des sauvegardes S3 configurées dans app.yml signifie que vous pouvez effectuer une restauration en ligne de commande avec uniquement le fichier app.yml (après avoir cloné discourse et installé docker).

Pour la première étape, devrai-je sauvegarder les buckets S3 ou s’agit-il d’une opération sans risque pour les buckets ?

Eh bien, au moins j’ai compris pourquoi mon serveur s’est planté la nuit dernière (et encore aujourd’hui après une reconstruction complète :frowning: , voir ce sujet pour plus de détails : Ubuntu 20.04 kernel update with docker causing a crash on EC2 and Lightsail

2 « J'aime »

Pour le faire fonctionner à partir d’une sauvegarde, j’ai dû :

  1. désactiver Paramètres - Fichiers - activer les téléchargements s3
  2. Paramètres - Sauvegardes - emplacement de la sauvegarde - S3
  3. activer Paramètres - Sauvegardes - sauvegarde avec téléchargements

Ensuite, j’ai effectué une sauvegarde et j’ai pu la restaurer avec succès. Cependant, une chose a cassé, toutes les pièces jointes (fichiers) n’ont plus de liens invalides. Les images sont toutes bonnes, mais les liens des pièces jointes comme https://domain.com/uploads/short-url/phu1HOLvkE8LWpkKYfnMPSWsvHh.zip me donnent maintenant une erreur :

Oops ! Cette page n’existe pas ou est privée.

Existe-t-il un moyen de corriger ces liens d’URL courte ?

Vous pourriez essayer de reconstruire le HTML (également appelé rebake) sur l’un de ces sujets pour voir si cela résout le problème.

Merci. Existe-t-il un guide quelque part sur la façon d’émettre la commande pour cuire des sujets spécifiques ?