Aiuto ripristino - sistema bloccato a mezzanotte

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?

Ciao,
dopo aver ricreato il nuovo server da app.yml, hai avuto accesso ai backup nella sezione https://your.domain/admin/backups?

No, dopo aver ricreato da app.yml mi ha solo fornito una nuova configurazione pulita senza nulla. Ho scaricato l’ultimo backup da S3 e l’ho caricato manualmente su Discourse localmente e ho premuto ripristina.

Inizia a ripristinarlo, vedo tutte le impostazioni (incluse S3, le credenziali, tutto dalla pagina Impostazioni) tornare, vedo tutte le categorie apparire e i post apparire e tutto. Poi improvvisamente dopo pochi minuti ricevo un messaggio di logout e tutte le categorie, gli argomenti scompaiono e i log mostrano quell’errore (Sembra che torni indietro).

:thinking: quindi la configurazione s3 non è in app.yml (come descritto qui Configure an S3 compatible object storage provider for uploads )? Ma configurata come in Set up file and image uploads to S3

1 Mi Piace

No, non vedo questo in app.yml

Tutte le impostazioni S3 sono state definite nelle pagine Admin → Impostazioni e ha funzionato bene per un anno finché non ho dovuto ripristinarlo quando il server è andato in crash la scorsa notte.

Corretto, questo è ciò che ho usato per configurare i backup e i caricamenti S3.

Penso che proverei a modificare app.yml con le tue impostazioni e da lì credo (spero?) che dovresti vedere i tuoi backup nella sezione admin e ripristinare da lì, senza l’importazione manuale e i caricamenti, che non dovresti dover ripristinare, ma sembrano essere inclusi nei backup. Non so perché stia fallendo però…

1 Mi Piace

Credo che ciò possa essere dovuto al fatto che il tuo backup contenga un mix di caricamenti S3 e locali. Temo che non sia nel mio campo di competenza, ma c’è una discussione e una soluzione in questo argomento che ti permette di aggirare il problema. Tuttavia, era per un numero molto inferiore di errori, quindi potresti voler tenere conto di ciò:

2 Mi Piace

Grazie, purtroppo il mio sito è andato in crash, quindi mi rimangono solo i caricamenti e i backup su S3. Presumo che non ci sia modo per me di migrare eventuali file locali rimanenti su S3 ora.

Quindi mi chiedo quali siano le mie opzioni al momento? C’è un modo per ripristinare dai backup S3 e ignorare i file locali? Ho trovato un modo per ignorare il caricamento su S3, ma poi quasi tutti i post hanno collegamenti/immagini interrotti (il 90%+ è probabilmente su S3 perché ho impostato il caricamento su S3 molti, molti anni fa).

Quindi un aggiornamento per coloro che potrebbero avere lo stesso problema (in pratica non riesco a ripristinare da un backup e il server è andato in crash a causa di un aggiornamento di sistema difettoso).

Per quanto ne so, la causa principale del problema è che ci sono caricamenti locali E caricamenti S3, quindi quando lo strumento di ripristino sta cercando di ripristinare, si blocca perché non sa come gestire contemporaneamente ripristini locali e S3 (forse è ora che Discourse riveda backup/ripristini).

Grazie a @RGJ per questo suggerimento, ha suggerito di forzare Discourse a ignorare il caricamento S3 durante il ripristino:

  1. Aggiungi una riga al tuo app.yml DISCOURSE_ENABLE_S3_UPLOADS=false
  2. Ricostruisci Discourse ./launcher rebuild app
  3. Tenta un ripristino (dalla pagina Backup della GUI o utilizzando la CLI)
  4. Quindi, dopo il ripristino, rimuovi quella riga da app.yml e ricostruisci ancora una volta

Sebbene questo abbia funzionato, è importante notare che il forum era gravemente danneggiato, le categorie, le impostazioni e i post sono stati ripristinati, tuttavia tutte le immagini, i collegamenti, i documenti incorporati, ecc. erano danneggiati e hanno generato errori.

La soluzione disperata:
Sono riuscito a recuperare il vecchio server ed estratto la directory /var/discourse (tar/gz) e l’ho copiata sul nuovo server ed eseguito ./launcher rebuild app. Questo ha completamente ripristinato il funzionamento del forum, tuttavia il problema fondamentale rimane: i backup NON funzioneranno perché hanno un mix di caricamenti locali e S3.

Quindi ho davvero bisogno di consigli sul modo migliore per risolvere questo problema una volta per tutte. È meglio/più facile spostare tutti i caricamenti da locale a S3 o da S3 a locale e come si fa? L’intero scopo di un backup è aiutare in situazioni come questa, ma mi ha deluso, quindi ho bisogno che tu lo risolva.

1 Mi Piace

Se si configura come descritto in Utilizzo dello storage di oggetti per i caricamenti (S3 e cloni) si dovrebbe essere in grado di

 rake uploads:migrate_to_s3

Se si desidera smettere di usare s3, allora si può entrare nella console rails e impostare

  SiteSetting.include_s3_uploads_in_backups=true

Quindi eseguire un backup, assicurarsi di non avere s3 configurato nel proprio file app.yml e ripristinare il backup. Penso che questo ripristinerà i backup in locale.

Ma in entrambi i casi, consiglierei comunque di impostare le chiavi e il bucket di backup nelle variabili ENV nel proprio file app.yml e quindi verificare che sia possibile ripristinarlo in un nuovo sito.

2 Mi Piace

Ok, penso di essermi un po’ confuso qui.

Penso che la cosa ideale da fare sarebbe avere tutti gli upload locali e salvare i backup (zip) su S3. In questo modo il backup è disponibile su S3 qualora succedesse qualcosa al server, ma il backup stesso è autonomo, senza dipendenze, quindi dovrebbe essere facile ripristinarlo su un nuovo server.

Quindi, se ho capito bene, dovrei seguire queste istruzioni:

If you want to stop using s3, then you can enter the rails console and set

  SiteSetting.include_s3_uploads_in_backups=true
Then take a backup, make sure that you do not have s3 configured in your app.yml and restore the backup. I think that this will restore backups to local.

e poi

  1. disabilitare l’opzione enable upload to S3 in Admin → Settings → Files
  2. abilitare l’opzione di backup su S3 nella pagina Admin → Settings → Backups

È corretto?

Questa è la parte che mi ha confuso, perché dovrei voler mettere la configurazione S3 nel file app.yml?

In modo da avere accesso ai tuoi backup tramite un ripristino da riga di comando prima di ripristinare il tuo backup. Altrimenti, devi configurare un account amministratore e quindi configurare S3 e quindi ripristinare. Allo stesso modo, tutte le impostazioni che inserisci nel tuo database vengono sovrascritte quando ripristini il database.

Penso che la best practice sia configurare S3 solo tramite variabili ENV nel file app.yml. Probabilmente avrebbe senso renderle impostazioni nascoste, se non per le centinaia di persone che sarebbero sorprese dalla loro scomparsa.

1 Mi Piace

Perché altrimenti avrai problemi a ripristinare.

2 Mi Piace

Come si ripristina un backup da S3 utilizzando la riga di comando? Secondo le istruzioni qui: Restore a backup from the command line
Dice che puoi inserire il file di backup nella cartella /var/discourse/shared/standalone/backups/default e quindi avviare un ripristino dalla CLI. Questo è ciò che avevo fatto con il tuo suggerimento in precedenza (che alla fine ha portato a collegamenti interrotti, sfortunatamente), ma funziona.

Come si ripristina direttamente da S3 utilizzando la CLI?

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

Stamperà i backup disponibili che potrai quindi copiare/incollare quello che desideri ripristinare.

2 Mi Piace

Grazie, quindi leggerà i backup S3 e li elencherà come opzione.

Jay, per dare seguito a un tuo suggerimento di spostare gli asset in locale:

Penso che tu possa impostare un’impostazione nascosta include_s3_uploads_in_backups su true e poi fare un backup e ripristinarlo quando S3 è disattivato per smettere di usare S3.

Avere backup S3 con essi configurati in app.yml significa che puoi fare un ripristino da riga di comando con solo il file app.yml (dopo aver clonato discourse e installato docker).

Per il primo passaggio dovrei eseguire il backup dei bucket S3 o si tratta di un’operazione sicura per i bucket?

Beh, almeno ho capito perché il mio server è andato in crash la scorsa notte (e di nuovo oggi dopo una ricostruzione completa :frowning: , vedi questo argomento per i dettagli: Ubuntu 20.04 kernel update with docker causing a crash on EC2 and Lightsail

2 Mi Piace

Per farlo funzionare da un backup, ho dovuto:

  1. disabilitare Impostazioni → Fileabilita caricamenti s3
  2. Impostazioni → Backupposizione di backupS3
  3. abilitare Impostazioni → Backupbackup con caricamenti

Poi ho eseguito un backup e sono stato in grado di ripristinarlo con successo. Tuttavia, una cosa si è rotta: tutti gli allegati (file) ora hanno collegamenti non validi. Le immagini vanno tutte bene, ma i collegamenti degli allegati come https://domain.com/uploads/short-url/phu1HOLvkE8LWpkKYfnMPSWsvHh.zip ora mi danno un errore

Oops! That page doesn’t exist or is private.

C’è un modo per correggere questi collegamenti short-url?

Potresti provare a eseguire una ricostruzione HTML (o rebake) su uno di quegli argomenti per vedere se risolve il problema.

Grazie. Esiste una guida su come emettere il comando per eseguire il bake di argomenti specifici?