diff --git a/.env.production.sample b/.env.production.sample
index bd81b8fcaa0df45c4fa84bab0de63faa87d2ff79..a7f9eb4bf85c8629c3d027b2d8d9abf387488ec4 100644
--- a/.env.production.sample
+++ b/.env.production.sample
@@ -22,6 +22,8 @@ OTP_SECRET=
 # SINGLE_USER_MODE=true
 # Prevent registrations with following e-mail domains
 # EMAIL_DOMAIN_BLACKLIST=example1.com|example2.de|etc
+# Only allow registrations with the following e-mail domains
+# EMAIL_DOMAIN_WHITELIST=example1.com|example2.de|etc
 
 # E-mail configuration
 SMTP_SERVER=smtp.mailgun.org
diff --git a/app/assets/javascripts/components/locales/fi.jsx b/app/assets/javascripts/components/locales/fi.jsx
index 5bef999231f8e35f2ff097669e14ac749179ee68..7b151d6f83532b6d5decbef79673ec10e07fb1d1 100644
--- a/app/assets/javascripts/components/locales/fi.jsx
+++ b/app/assets/javascripts/components/locales/fi.jsx
@@ -22,10 +22,10 @@ const fi = {
   "account.followers": "Seuraajia",
   "account.follows_you": "Seuraa sinua",
   "account.requested": "Odottaa hyväksyntää",
-  "getting_started.heading": "Päästä alkuun",
+  "getting_started.heading": "Aloitus",
   "getting_started.about_addressing": "Voit seurata ihmisiä jos tiedät heidän käyttäjänimensä ja domainin missä he ovat syöttämällä e-mail-esque osoitteen Etsi kenttään.",
   "getting_started.about_shortcuts": "Jos etsimäsi henkilö on samassa domainissa kuin sinä, pelkkä käyttäjänimi kelpaa. Sama pätee kun mainitset ihmisiä statuksessasi",
-  "getting_started.open_source_notice": "Mastodon Mastodon on avoimen lähdekoodin ohjelma. Voit avustaa tai raportoida ongelmia githubissa {github}. {apps}.",
+  "getting_started.open_source_notice": "Mastodon Mastodon on avoimen lähdekoodin ohjelma. Voit avustaa tai raportoida ongelmia GitHub palvelussa {github}. {apps}.",
   "column.home": "Koti",
   "column.community": "Paikallinen aikajana",
   "column.public": "Yhdistetty aikajana",
diff --git a/app/assets/stylesheets/accounts.scss b/app/assets/stylesheets/accounts.scss
index 25e24a95a61df2ea0c75f4957a522662b4e07a31..b3ae33500edb9454f4ee6c1e3045e5a432248507 100644
--- a/app/assets/stylesheets/accounts.scss
+++ b/app/assets/stylesheets/accounts.scss
@@ -34,6 +34,7 @@
     text-align: center;
     position: relative;
     z-index: 2;
+    text-shadow: 0 0 2px $color8;
 
     small {
       display: block;
@@ -128,6 +129,7 @@
       text-transform: uppercase;
       display: block;
       margin-bottom: 5px;
+      text-shadow: 0 0 2px $color8;
     }
 
     .counter-number {
@@ -385,5 +387,6 @@
   .account__header__content {
     font-size: 14px;
     color: $color1;
+    text-shadow: 0 0 2px $color8;
   }
 }
diff --git a/app/controllers/remote_follow_controller.rb b/app/controllers/remote_follow_controller.rb
index 7d4bfe6ceeb2afd59cf8f4a8e8e0ecdd7ca26de3..1e3f786ec8bcecd2ed33c7f5d94ea9cd78c81eeb 100644
--- a/app/controllers/remote_follow_controller.rb
+++ b/app/controllers/remote_follow_controller.rb
@@ -8,6 +8,7 @@ class RemoteFollowController < ApplicationController
 
   def new
     @remote_follow = RemoteFollow.new
+    @remote_follow.acct = session[:remote_follow] if session.key?(:remote_follow)
   end
 
   def create
@@ -22,6 +23,8 @@ class RemoteFollowController < ApplicationController
         render(:new) && return
       end
 
+      session[:remote_follow] = @remote_follow.acct
+
       redirect_to Addressable::Template.new(redirect_url_link.template).expand(uri: "#{@account.username}@#{Rails.configuration.x.local_domain}").to_s
     else
       render :new
diff --git a/app/lib/email_validator.rb b/app/lib/email_validator.rb
index 856b8b1f7be970c50d84d8edd021077dc198e8a5..06e9375f60d080fe12ab9c21afd8e4bdb32ab218 100644
--- a/app/lib/email_validator.rb
+++ b/app/lib/email_validator.rb
@@ -2,17 +2,30 @@
 
 class EmailValidator < ActiveModel::EachValidator
   def validate_each(record, attribute, value)
-    return if Rails.configuration.x.email_domains_blacklist.empty?
-
     record.errors.add(attribute, I18n.t('users.invalid_email')) if blocked_email?(value)
   end
 
   private
 
   def blocked_email?(value)
+    on_blacklist?(value) || not_on_whitelist?(value)
+  end
+
+  def on_blacklist?(value)
+    return false if Rails.configuration.x.email_domains_blacklist.blank?
+
     domains = Rails.configuration.x.email_domains_blacklist.gsub('.', '\.')
     regexp  = Regexp.new("@(.+\\.)?(#{domains})", true)
 
     value =~ regexp
   end
+
+  def not_on_whitelist?(value)
+    return false if Rails.configuration.x.email_domains_whitelist.blank?
+
+    domains = Rails.configuration.x.email_domains_whitelist.gsub('.', '\.')
+    regexp  = Regexp.new("@(.+\\.)?(#{domains})", true)
+
+    value !~ regexp
+  end
 end
diff --git a/app/lib/feed_manager.rb b/app/lib/feed_manager.rb
index 28e7127049783e9f3733357e578e7eaa566ea77f..2cca1cefe4f7a6a71fbb89e36edc2a748e8ff891 100644
--- a/app/lib/feed_manager.rb
+++ b/app/lib/feed_manager.rb
@@ -118,7 +118,7 @@ class FeedManager
 
   def filter_from_mentions?(status, receiver_id)
     check_for_blocks = [status.account_id]
-    check_for_blocks.concat(status.mentions.select('account_id').map(&:account_id))
+    check_for_blocks.concat(status.mentions.pluck(:account_id))
     check_for_blocks.concat([status.in_reply_to_account]) if status.reply? && !status.in_reply_to_account_id.nil?
 
     should_filter   = receiver_id == status.account_id                                                                                   # Filter if I'm mentioning myself
diff --git a/app/workers/pubsubhubbub/delivery_worker.rb b/app/workers/pubsubhubbub/delivery_worker.rb
index 15005bc80200a02a88edd32eefd719fad29d5458..466def3a85f2f7ba65544b97922cde79bb2fe2d3 100644
--- a/app/workers/pubsubhubbub/delivery_worker.rb
+++ b/app/workers/pubsubhubbub/delivery_worker.rb
@@ -22,6 +22,7 @@ class Pubsubhubbub::DeliveryWorker
                    .headers(headers)
                    .post(subscription.callback_url, body: payload)
 
+    return subscription.destroy! if response.code > 299 && response.code < 500 && response.code != 429 # HTTP 4xx means error is not temporary, except for 429 (throttling)
     raise "Delivery failed for #{subscription.callback_url}: HTTP #{response.code}" unless response.code > 199 && response.code < 300
 
     subscription.touch(:last_successful_delivery_at)
diff --git a/config/initializers/blacklists.rb b/config/initializers/blacklists.rb
index 52646e64d66c75a79ecbbb60b00e64574fd375b3..6db7be7dc553ffc2dd13a20fb5a22f2bf1bf4725 100644
--- a/config/initializers/blacklists.rb
+++ b/config/initializers/blacklists.rb
@@ -2,4 +2,5 @@
 
 Rails.application.configure do
   config.x.email_domains_blacklist = ENV.fetch('EMAIL_DOMAIN_BLACKLIST') { 'mvrht.com' }
+  config.x.email_domains_whitelist = ENV.fetch('EMAIL_DOMAIN_WHITELIST') { '' }  
 end
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 320bd3144f4e9268ba86d7a489931c13167e05e9..d44845c6bc78c5e2b3e9cd67d5c9bf519d0512ea 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -1,14 +1,14 @@
 ---
 de:
   about:
-    about_mastodon: Mastodon ist ein <em>freier, quelloffener</em> soziales Netzwerkserver. Eine <em>dezentralisierte</em> Alternative zu kommerziellen Plattformen, verhindert es die Risiken, die entstehen, wenn eine einzelne Firma deine Kommunikation monopolisiert. Jeder kann Mastodon verwenden und ganz einfach am <em>sozialen Netzwerk</em> teilnehmen.
+    about_mastodon: Mastodon ist ein <em>freier, quelloffener</em> soziales Netzwerkserver. Als <em>dezentralisierte</em> Alternative zu kommerziellen Plattformen verhindert es die Risiken, die entstehen, wenn eine einzelne Firma deine Kommunikation monopolisiert. Jeder kann Mastodon verwenden und ganz einfach am <em>sozialen Netzwerk</em> teilnehmen.
     get_started: Erste Schritte
     source_code: Quellcode
     terms: AGB
   accounts:
     follow: Folgen
-    followers: Folger
-    following: Folgt
+    followers: Follower
+    following: Gefolgt
     nothing_here: Hier gibt es nichts!
     people_followed_by: Nutzer, denen %{name} folgt
     people_who_follow: Nutzer, die %{name} folgen
@@ -27,7 +27,7 @@ de:
     reset_password: Passwort zurücksetzen
     set_new_password: Neues Passwort setzen
   authorize_follow:
-    error: Das entfernte Profil konnte nicht geladen werden
+    error: Das Profil konnte nicht geladen werden
     follow: Folgen
     prompt_html: 'Du (<strong>%{self}</strong>) möchtest dieser Person folgen:'
     title: "%{acct} folgen"
@@ -55,25 +55,25 @@ de:
   notification_mailer:
     favourite:
       body: 'Dein Beitrag wurde von %{name} favorisiert:'
-      subject: "%{name} hat deinen Beitrag favorisiert"
+      subject: "%{name} hat deinen Beitrag favorisiert."
     follow:
       body: "%{name} folgt dir jetzt!"
-      subject: "%{name} folgt dir nun"
+      subject: "%{name} folgt dir jetzt."
     follow_request:
       body: "%{name} möchte dir folgen:"
-      subject: "%{name} möchte dir folgen"
+      subject: "%{name} möchte dir folgen."
     mention:
       body: "%{name} hat dich erwähnt:"
-      subject: "%{name} hat dich erwähnt"
+      subject: "%{name} hat dich erwähnt."
     reblog:
       body: 'Dein Beitrag wurde von %{name} geteilt:'
-      subject: "%{name} teilte deinen Beitrag"
+      subject: "%{name} teilte deinen Beitrag."
   pagination:
     next: Vorwärts
     prev: Zurück
   remote_follow:
-    acct: Dein Nutzername@Domain, von dem du dieser Person folgen möchtest
-    missing_resource: Die erforderliche Weiterleitungs-URL konnte leider in deinem Profil nicht gefunden werden
+    acct: Dein Nutzername@Domain, von dem aus du dieser Person folgen möchtest.
+    missing_resource: Die erforderliche Weiterleitungs-URL konnte leider in deinem Profil nicht gefunden werden.
     proceed: Weiter
     prompt: 'Du wirst dieser Person folgen:'
   settings:
diff --git a/config/locales/devise.de.yml b/config/locales/devise.de.yml
index 181502f9c48de23fa79c915f63c2d9bbd827866c..58bfaa3d685a19117199264f967f0f0baabf049f 100644
--- a/config/locales/devise.de.yml
+++ b/config/locales/devise.de.yml
@@ -2,59 +2,59 @@
 de:
   devise:
     confirmations:
-      confirmed: "Vielen Dank für Deine Registrierung. Bitte melde dich jetzt an."
-      send_instructions: "Du erhältst in wenigen Minuten eine E-Mail, mit der Du Deine Registrierung bestätigen kannst."
-      send_paranoid_instructions: "Falls Deine E-Mail-Adresse in unserer Datenbank existiert erhältst Du in wenigen Minuten eine E-Mail mit der Du Deine Registrierung bestätigen kannst."
+      confirmed: "Vielen Dank für deine Registrierung. Bitte melde dich jetzt an."
+      send_instructions: "Du erhältst in wenigen Minuten eine E-Mail, mit der du deine Registrierung bestätigen kannst."
+      send_paranoid_instructions: "Falls Deine E-Mail-Adresse in unserer Datenbank existiert, erhältst Du in wenigen Minuten eine E-Mail mit der du deine Registrierung bestätigen kannst."
     failure:
       already_authenticated: "Du bist bereits angemeldet."
       inactive: "Dein Account ist nicht aktiv."
       invalid: "Ungültige Anmeldedaten."
-      last_attempt: "Du hast noch einen Versuch bevor dein Account gesperrt wird"
+      last_attempt: "Du hast noch einen Versuch bevor dein Account gesperrt wird."
       locked: "Dein Account ist gesperrt."
       not_found_in_database: "E-Mail-Adresse oder Passwort ungültig."
-      timeout: "Deine Sitzung ist abgelaufen, bitte melde Dich erneut an."
-      unauthenticated: "Du musst Dich anmelden oder registrieren, bevor Du fortfahren kannst."
-      unconfirmed: "Du musst Deinen Account bestätigen, bevor Du fortfahren kannst."
+      timeout: "Deine Sitzung ist abgelaufen, bitte melde dich erneut an."
+      unauthenticated: "Du musst Dich anmelden oder registrieren, bevor du fortfahren kannst."
+      unconfirmed: "Du musst deinen Account bestätigen, bevor du fortfahren kannst."
     mailer:
       confirmation_instructions:
-        subject: "Mastodon: Anleitung zur Bestätigung Deines Accounts"
+        subject: "Mastodon: Anleitung zur Bestätigung deines Accounts"
       password_change:
         subject: 'Mastodon: Passwort wurde geändert'
       reset_password_instructions:
-        subject: "Mastodon: Anleitung um Dein Passwort zurückzusetzen"
+        subject: "Mastodon: Anleitung um dein Passwort zurückzusetzen"
       unlock_instructions:
-        subject: "Mastodon: Anleitung um Deinen Account freizuschalten"
+        subject: "Mastodon: Anleitung um deinen Account freizuschalten"
     omniauth_callbacks:
-      failure: "Du konntest nicht Deinem %{kind}-Account angemeldet werden, weil '%{reason}'."
-      success: "Du hast Dich erfolgreich mit Deinem %{kind}-Account angemeldet."
+      failure: "Du konntest nicht mit deinem %{kind}-Account angemeldet werden, weil '%{reason}'."
+      success: "Du hast dich erfolgreich mit Deinem %{kind}-Account angemeldet."
     passwords:
-      no_token: "Du kannst diese Seite nur von dem Link aus einer E-Mail zum Passwort-Zurücksetzen aufrufen. Wenn du einen solchen Link aufgerufen hast stelle bitte sicher, dass du die vollständige Adresse aufrufst."
-      send_instructions: "Du erhältst in wenigen Minuten eine E-Mail mit der Anleitung, wie Du Dein Passwort zurücksetzen kannst."
-      send_paranoid_instructions: "Falls Deine E-Mail-Adresse in unserer Datenbank existiert erhältst Du in wenigen Minuten eine E-Mail mit der Anleitung, wie Du Dein Passwort zurücksetzen können."
+      no_token: "Du kannst diese Seite nur über den Link aus der E-Mail zum Passwort-Zurücksetzen aufrufen. Wenn du einen solchen Link aufgerufen hast, stelle bitte sicher, dass du die vollständige Adresse aufrufst."
+      send_instructions: "Du erhältst in wenigen Minuten eine E-Mail mit der Anleitung, wie du dein Passwort zurücksetzen kannst."
+      send_paranoid_instructions: "Falls deine E-Mail-Adresse in unserer Datenbank existiert erhältst du in wenigen Minuten eine E-Mail mit der Anleitung, wie du dein Passwort zurücksetzen kannst."
       updated: "Dein Passwort wurde geändert. Du bist jetzt angemeldet."
       updated_not_active: "Dein Passwort wurde geändert."
     registrations:
       destroyed: "Dein Account wurde gelöscht."
       signed_up: "Du hast dich erfolgreich registriert."
-      signed_up_but_inactive: "Du hast dich erfolgreich registriert. Wir konnten Dich noch nicht anmelden, da Dein Account inaktiv ist."
-      signed_up_but_locked: "Du hast dich erfolgreich registriert. Wir konnten Dich noch nicht anmelden, da Dein Account gesperrt ist."
-      signed_up_but_unconfirmed: "Du hast Dich erfolgreich registriert. Wir konnten Dich noch nicht anmelden, da Dein Account noch nicht bestätigt ist. Du erhältst in Kürze eine E-Mail mit der Anleitung, wie Du Deinen Account freischalten kannst."
-      update_needs_confirmation: "Deine Daten wurden aktualisiert, aber Du musst Deine neue E-Mail-Adresse bestätigen. Du erhälst in wenigen Minuten eine E-Mail, mit der Du die Änderung Deiner E-Mail-Adresse abschließen kannst."
+      signed_up_but_inactive: "Du hast dich erfolgreich registriert. Wir konnten dich noch nicht anmelden, da dein Account inaktiv ist."
+      signed_up_but_locked: "Du hast dich erfolgreich registriert. Wir konnten dich noch nicht anmelden, da dein Account gesperrt ist."
+      signed_up_but_unconfirmed: "Du hast Dich erfolgreich registriert. Wir konnten dich noch nicht anmelden, da dein Account noch nicht bestätigt ist. Du erhältst in Kürze eine E-Mail mit der Anleitung, wie Du Deinen Account freischalten kannst."
+      update_needs_confirmation: "Deine Daten wurden aktualisiert, aber du musst deine neue E-Mail-Adresse bestätigen. Du erhälst in wenigen Minuten eine E-Mail, mit der du die Änderung deiner E-Mail-Adresse abschließen kannst."
       updated: "Deine Daten wurden aktualisiert."
     sessions:
       already_signed_out: "Erfolgreich abgemeldet."
       signed_in: "Erfolgreich angemeldet."
       signed_out: "Erfolgreich abgemeldet."
     unlocks:
-      send_instructions: "Du erhältst in wenigen Minuten eine E-Mail mit der Anleitung, wie Du Deinen Account entsperren können."
-      send_paranoid_instructions: "Falls Deine E-Mail-Adresse in unserer Datenbank existiert erhältst Du in wenigen Minuten eine E-Mail mit der Anleitung, wie Du Deinen Account entsperren kannst."
+      send_instructions: "Du erhältst in wenigen Minuten eine E-Mail mit der Anleitung, wie du deinen Account entsperren können."
+      send_paranoid_instructions: "Falls deine E-Mail-Adresse in unserer Datenbank existiert erhältst du in wenigen Minuten eine E-Mail mit der Anleitung, wie du deinen Account entsperren kannst."
       unlocked: "Dein Account wurde entsperrt. Du bist jetzt angemeldet."
   errors:
     messages:
-      already_confirmed: "wurde bereits bestätigt"
-      confirmation_period_expired: "muss innerhalb %{period} bestätigt werden, bitte fordere einen neuen Link an"
-      expired: "ist abgelaufen, bitte neu anfordern"
-      not_found: "nicht gefunden"
+      already_confirmed: "wurde bereits bestätigt."
+      confirmation_period_expired: "muss innerhalb %{period} bestätigt werden, bitte fordere einen neuen Link an."
+      expired: "ist abgelaufen, bitte neu anfordern."
+      not_found: "wurde nicht gefunden."
       not_locked: "ist nicht gesperrt"
       not_saved:
         one: "Konnte %{resource} nicht speichern: ein Fehler."
diff --git a/config/locales/doorkeeper.fr.yml b/config/locales/doorkeeper.fr.yml
index c94e5c095b22c3fb98e90fdf8d74923b48e6437a..be109df9cc5ede42d711802d8cf30436267dd53d 100644
--- a/config/locales/doorkeeper.fr.yml
+++ b/config/locales/doorkeeper.fr.yml
@@ -62,7 +62,7 @@ fr:
       buttons:
         revoke: Annuler
       confirmations:
-        revoke: Êtes-vous certain?
+        revoke: Êtes-vous certain ?
       index:
         application: Application
         created_at: Créé le
@@ -72,19 +72,19 @@ fr:
     errors:
       messages:
         access_denied: Le propriétaire de la ressource ou le serveur d'autorisation a refusé la demande.
-        credential_flow_not_configured: Le flux des identifiants du mot de passe du propriétaire de la ressource a échoué en raison de Doorkeeper.configure.resource_owner_from_credentials n'est pas configuré.
+        credential_flow_not_configured: Le flux des identifiants du mot de passe du propriétaire de la ressource a échoué car Doorkeeper.configure.resource_owner_from_credentials n'est pas configuré.
         invalid_client: L'authentification du client a échoué à cause d'un client inconnu, d'aucune authentification de client incluse, ou d'une méthode d'authentification non prise en charge.
         invalid_grant: Le consentement d'autorisation accordé n'est pas valide, a expiré, est annulé, ne concorde pas avec l'URL de redirection utilisée dans la demande d'autorisation, ou a été émis à un autre client.
         invalid_redirect_uri: L'URL de redirection n'est pas valide.
         invalid_request: La demande manque un paramètre requis, inclut une valeur de paramètre non prise en charge, ou est autrement mal formée.
-        invalid_resource_owner: Les identifiants fournis du propriétaire de la ressource ne sont pas valides, ou le propriétaire de la ressource ne peut être trouvé
+        invalid_resource_owner: Les identifiants fournis par le propriétaire de la ressource ne sont pas valides, ou le propriétaire de la ressource ne peut être trouvé
         invalid_scope: La portée demandée n'est pas valide, est inconnue, ou est mal formée.
         invalid_token:
           expired: Le jeton d'accès a expiré
           revoked: Le jeton d'accès a été révoqué
           unknown: Le jeton d'accès n'est pas valide
-        resource_owner_authenticator_not_configured: La recherche du propriétaire de la ressource a échoué en raison de Doorkeeper.configure.resource_owner_authenticator n'est pas configuré.
-        server_error: Le serveur d'autorisation a rencontré une condition inattendue qui l'a empêché de remplir la demande.
+        resource_owner_authenticator_not_configured: La recherche du propriétaire de la ressource a échoué car Doorkeeper.configure.resource_owner_authenticator n'est pas configuré.
+        server_error: Le serveur d'autorisation a rencontré une condition inattendue l'empêchant de remplir la demande.
         temporarily_unavailable: Le serveur d'autorisation est actuellement incapable de traiter la demande à cause d'une surcharge ou d'un entretien temporaire du serveur.
         unauthorized_client: Le client n'est pas autorisé à effectuer cette demande à l'aide de cette méthode.
         unsupported_grant_type: Le type de consentement d'autorisation n'est pas pris en charge par le serveur d'autorisation.
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 7585014034907f514dc63b373a804fcc534ed6f0..e9989e3835d3ff0ff085126e3cd000698b301640 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -5,6 +5,7 @@ fr:
     about_this: À propos de cette instance
     apps: Applications
     business_email: E-mail professionnel
+    closed_registrations: Les inscriptions sont actuellement fermées sur cette instance. . 
     description_headline: Qu'est-ce que %{domain} ?
     domain_count_after: autres instances
     domain_count_before: Connectés à
diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml
index df4f6ca00797e7588ccc1fd64e401ff7c5789bd1..dfc67fdfd2bbc7ff5eec6cea1eaee46a5b66123b 100644
--- a/config/locales/simple_form.en.yml
+++ b/config/locales/simple_form.en.yml
@@ -38,7 +38,7 @@ en:
         follow: Send e-mail when someone follows you
         follow_request: Send e-mail when someone requests to follow you
         mention: Send e-mail when someone mentions you
-        reblog: Send e-mail when someone reblogs your status
+        reblog: Send e-mail when someone boosts your status
     'no': 'No'
     required:
       mark: "*"
diff --git a/config/locales/simple_form.fi.yml b/config/locales/simple_form.fi.yml
index 02c11752f90be62bc01bcf9e8be54ee486478eeb..02943cea306522746dc963d2381ac04bac5cee66 100644
--- a/config/locales/simple_form.fi.yml
+++ b/config/locales/simple_form.fi.yml
@@ -6,7 +6,7 @@ fi:
         avatar: PNG, GIF tai JPG. Korkeintaan 2MB. Skaalataan kokoon 120x120px
         display_name: Korkeintaan 30 merkkiä
         header: PNG, GIF tai JPG. Korkeintaan 2MB. Skaalataan kokoon 700x335px
-        locked: Vaatii sinun manuaalisesti hyväksymään seuraajat ja asettaa julkaisun yksityisyyden vain seuraajille
+        locked: Vaatii sinun manuaalisesti hyväksymään seuraajat ja asettaa julkaisujen yksityisyyden vain seuraajille
         note: Korkeintaan 160 merkkiä
       imports:
         data: CSV tiedosto tuotu toiselta Mastodon palvelimelta
diff --git a/docs/Running-Mastodon/Administration-guide.md b/docs/Running-Mastodon/Administration-guide.md
index af78f62355bc63e60807b6bed14afb9b89750d50..dd69eb303041fcd39eca4479b6b1beef33034c0d 100644
--- a/docs/Running-Mastodon/Administration-guide.md
+++ b/docs/Running-Mastodon/Administration-guide.md
@@ -7,7 +7,7 @@ So, you have a working Mastodon instance... now what?
 
 The following rake task:
 
-    rails mastodon:make_admin USERNAME=alice
+    rake mastodon:make_admin USERNAME=alice
 
 Would turn the local user "alice" into an admin.
 
diff --git a/docs/Running-Mastodon/Heroku-guide.md b/docs/Running-Mastodon/Heroku-guide.md
index b66e56200158d9cef30d6b9ce3a9d2b9eafe5696..0de26230c74beb8204dcc3834bc9b9f31e48b082 100644
--- a/docs/Running-Mastodon/Heroku-guide.md
+++ b/docs/Running-Mastodon/Heroku-guide.md
@@ -11,3 +11,5 @@ Mastodon can theoretically run indefinitely on a free [Heroku](https://heroku.co
   * You will want Amazon S3 for file storage. The only exception is for development purposes, where you may not care if files are not saved. Follow a guide online for creating a free Amazon S3 bucket and Access Key, then enter the details.
   * If you want your Mastodon to be able to send emails, configure SMTP settings here (or later). Consider using [Mailgun](https://mailgun.com) or similar, who offer free plans that should suit your interests.
 3. Deploy! The app should be set up, with a working web interface and database. You can change settings and manage versions from the Heroku dashboard.
+
+You may need to use the `heroku` CLI application to run `USERNAME=yourUsername rails mastodon:make_admin` to make yourself an admin.
diff --git a/docs/Running-Mastodon/Production-guide.md b/docs/Running-Mastodon/Production-guide.md
index 469fefa94355568d3dc0268deebeb50c7de09034..b1f7bd35b99b685fa1992aaac7adc3116555cad8 100644
--- a/docs/Running-Mastodon/Production-guide.md
+++ b/docs/Running-Mastodon/Production-guide.md
@@ -76,7 +76,7 @@ It is recommended to create a special user for mastodon on the server (you could
 ## General dependencies
 
     curl -sL https://deb.nodesource.com/setup_4.x | sudo bash -
-    sudo apt-get install imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev nodejs
+    sudo apt-get install imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev nodejs file
     sudo npm install -g yarn
 
 ## Redis
@@ -112,7 +112,7 @@ Then once `rbenv` is ready, run `rbenv install 2.3.1` to install the Ruby versio
 You need the `git-core` package installed on your system. If it is so, from the `mastodon` user:
 
     cd ~
-    git clone https://github.com/Gargron/mastodon.git live
+    git clone https://github.com/tootsuite/mastodon.git live
     cd live
 
 Then you can proceed to install project dependencies:
@@ -132,7 +132,7 @@ Fill in the important data, like host/port of the redis database, host/port/user
 
     rake secret
 
-To get a random string. If you are setting up on one single server (most likely), then REDIS_HOST is localhost and `DB_HOST` is `/var/run/postgresql`, `DB_USER` is `mastodon` and `DB_NAME` is `mastodon_production` while `DB_PASS` is empty because this setup will use the ident authentication method (system user "mastodon" maps to postgres user "mastodon").
+To get a random string. If you are setting up on one single server (most likely), then `REDIS_HOST` is localhost and `DB_HOST` is `/var/run/postgresql`, `DB_USER` is `mastodon` and `DB_NAME` is `mastodon_production` while `DB_PASS` is empty because this setup will use the ident authentication method (system user "mastodon" maps to postgres user "mastodon").
 
 ## Setup
 
@@ -221,7 +221,7 @@ I recommend creating a couple cronjobs for the following tasks:
 
 You may want to run `which bundle` first and copypaste that full path instead of simply `bundle` in the above commands because cronjobs usually don't have all the paths set. The time and intervals of when to run these jobs are up to you, but once every day should be enough for all.
 
-You can edit the cronjob file for the `mastodon` user by running `sudo crontab -e mastodon` (outside of the mastodon user).
+You can edit the cronjob file for the `mastodon` user by running `sudo crontab -e -u mastodon` (outside of the mastodon user).
 
 ## Things to look out for when upgrading Mastodon
 
diff --git a/docs/Using-Mastodon/List-of-Mastodon-instances.md b/docs/Using-Mastodon/List-of-Mastodon-instances.md
index 677ec7e560d63e84ed009b4a8c5cd8d924d2a500..0cd3f18d670b65b940e98aaff05f8ccd04341ee4 100644
--- a/docs/Using-Mastodon/List-of-Mastodon-instances.md
+++ b/docs/Using-Mastodon/List-of-Mastodon-instances.md
@@ -7,25 +7,25 @@ There is also a list at [instances.mastodon.xyz](https://instances.mastodon.xyz)
 | -------------|-------------|---|---|
 | [mastodon.social](https://mastodon.social) |Flagship, quick updates|Yes|No|
 | [awoo.space](https://awoo.space) |Intentionally moderated, only federates with mastodon.social|Yes|No|
-| [social.tchncs.de](https://social.tchncs.de)|N/A|Yes|No|
 | [animalliberation.social](https://animalliberation.social) |Animal Rights|Yes|No|
 | [socially.constructed.space](https://socially.constructed.space) |Single user|No|No|
 | [epiktistes.com](https://epiktistes.com) |N/A|Yes|No|
 | [fern.surgeplay.com](https://fern.surgeplay.com) |Federates everywhere, Minecraft-focused|Yes|No
-| [gay.crime.team](https://gay.crime.team) |the place for doin' gay crime online (please don't actually do crime here)|Yes|No|
+| [gay.crime.team](https://gay.crime.team) |the place for doin' gay crime online (please don't actually do crime here)|No|No|
 | [icosahedron.website](https://icosahedron.website/) |Icosahedron-themed (well, visually), open registration.|Yes|No|
 | [memetastic.space](https://memetastic.space) |Memes|Yes|No|
-| [social.diskseven.com](https://social.diskseven.com) |Single user|No|No (DNS entry but no response)|
+| [social.diskseven.com](https://social.diskseven.com) |Single user|No|Yes|
 | [social.gestaltzerfall.net](https://social.gestaltzerfall.net) |Single user|No|No|
 | [mastodon.xyz](https://mastodon.xyz) |N/A|Yes|Yes|
 | [social.targaryen.house](https://social.targaryen.house) |Federates everywhere, quick updates.|Yes|Yes|
-| [social.mashek.net](https://social.mashek.net) |Themed and customised for Mashekstein Labs community. Selectively federates.|Yes|No|
 | [masto.themimitoof.fr](https://masto.themimitoof.fr) |N/A|Yes|Yes|
 | [social.imirhil.fr](https://social.imirhil.fr) |N/A|No|Yes|
 | [social.wxcafe.net](https://social.wxcafe.net) |Open registrations, federates everywhere, no moderation yet|Yes|Yes|
 | [octodon.social](https://octodon.social) |Open registrations, federates everywhere, cutest instance yet|Yes|Yes|
+| [mastodon.club](https://mastodon.club)|Open Registration, Open Federation, Mostly Canadians|Yes|No|
 | [hostux.social](https://hostux.social) |N/A|Yes|Yes|
 | [social.alex73630.xyz](https://social.alex73630.xyz) |Francophones|Yes|Yes|
+| [oc.todon.fr](https://oc.todon.fr) |Modérée et principalement francophone, pas de tolérances pour misogynie/LGBTphobies/validisme/etc.|Yes|Yes|
 | [maly.io](https://maly.io) |N/A|Yes|No|
 | [social.lou.lt](https://social.lou.lt) |N/A|Yes|No|
 | [mastodon.ninetailed.uk](https://mastodon.ninetailed.uk) |N/A|Yes|No|
@@ -36,6 +36,9 @@ There is also a list at [instances.mastodon.xyz](https://instances.mastodon.xyz)
 | [share.elouworld.org](https://share.elouworld.org)|N/A|No|No|
 | [social.lkw.tf](https://social.lkw.tf)|N/A|No|No|
 | [manowar.social](https://manowar.social)|N/A|No|No|
-| [social.ballpointcarrot.net](https://social.ballpointcarrot.net)|Down at time of entry|No|No|
+| [social.ballpointcarrot.net](https://social.ballpointcarrot.net)|N/A|No|No|
+| [social.nasqueron.org](https://social.nasqueron.org) |Dreamers, open source developers, free culture|Yes|Yes|
+| [status.dissidence.ovh](https://status.dissidence.ovh)|N/A|Yes|Yes|
+| [mastodon.cc](https://mastodon.cc)|Art|Yes|No|
 
 Let me know if you start running one so I can add it to the list! (Alternatively, add it yourself as a pull request).
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 1a32541850895a260da5b1195b79d7d973555845..5575ba107b8435b36b728ec7abc83e09a5d95041 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -45,5 +45,43 @@ RSpec.describe User, type: :model do
         expect(User.confirmed).to match_array([user_2])
       end
     end
+
+  let(:account) { Fabricate(:account, username: 'alice') }  
+  let(:password) { 'abcd1234' }
+
+  describe 'blacklist' do
+    it 'should allow a non-blacklisted user to be created' do
+      user = User.new(email: 'foo@example.com', account: account, password: password)
+
+      expect(user.valid?).to be_truthy
+    end
+    
+    it 'should not allow a blacklisted user to be created' do
+      user = User.new(email: 'foo@mvrht.com', account: account, password: password)
+
+      expect(user.valid?).to be_falsey
+    end
+  end
+
+  describe 'whitelist' do
+    around(:each) do |example|
+      old_whitelist = Rails.configuration.x.email_whitelist
+
+      Rails.configuration.x.email_domains_whitelist = 'mastodon.space'
+
+      example.run
+
+      Rails.configuration.x.email_domains_whitelist = old_whitelist
+    end
+
+    it 'should not allow a user to be created unless they are whitelisted' do
+      user = User.new(email: 'foo@example.com', account: account, password: password)
+      expect(user.valid?).to be_falsey
+    end
+
+    it 'should allow a user to be created if they are whitelisted' do
+      user = User.new(email: 'foo@mastodon.space', account: account, password: password)
+      expect(user.valid?).to be_truthy
+    end
   end
 end