diff --git a/app/models/account.rb b/app/models/account.rb
index 5b0d2d65c6364cc4d33db5dc111af93b836a2abc..918d5b0f1c4faaa713489b9fd3520d783b74c0a2 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -56,7 +56,7 @@ class Account < ApplicationRecord
 
   # Local user validations
   with_options if: :local? do
-    validates :username, format: { with: /\A[a-z0-9_]+\z/i }, uniqueness: { scope: :domain, case_sensitive: false }, length: { maximum: 30 }
+    validates :username, format: { with: /\A[a-z0-9_]+\z/i }, uniqueness: { scope: :domain, case_sensitive: false }, length: { maximum: 30 }, unreserved: true
     validates :display_name, length: { maximum: 30 }
     validates :note, length: { maximum: 160 }
   end
diff --git a/app/validators/unreserved_validator.rb b/app/validators/unreserved_validator.rb
new file mode 100644
index 0000000000000000000000000000000000000000..4e5b9dafc3c54a7304b7f3c6ecabbb63e15236e2
--- /dev/null
+++ b/app/validators/unreserved_validator.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class UnreservedValidator < ActiveModel::EachValidator
+  def validate_each(record, attribute, value)
+    return if value.nil?
+    record.errors.add(attribute, I18n.t('accounts.reserved_username')) if reserved_username?(value)
+  end
+
+  private
+
+  def reserved_username?(value)
+    return false unless Setting.reserved_usernames
+    Setting.reserved_usernames.include?(value.downcase)
+  end
+end
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 2ff2f7eec6fdcb386e8625c82d3812b8fb47bbbb..965bfbe477e748bd8dca43975664ef8327ea95b9 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -40,6 +40,7 @@ en:
     posts: Posts
     remote_follow: Remote follow
     unfollow: Unfollow
+    reserved_username: The username is reserved
   activitypub:
     activity:
       announce:
diff --git a/config/settings.yml b/config/settings.yml
index 4811213cbdc5c6d0f4c261f075b55f06abbb7ac2..bffb7052acbfa0d37873d7f1bc433670a9bb06b4 100644
--- a/config/settings.yml
+++ b/config/settings.yml
@@ -7,7 +7,7 @@
 # For more information, see docs/Running-Mastodon/Administration-guide.md
 #
 defaults: &defaults
-  site_title: 'Mastodon'
+  site_title: Mastodon
   site_description: ''
   site_extended_description: ''
   site_contact_username: ''
@@ -27,6 +27,13 @@ defaults: &defaults
   interactions:
     must_be_follower: false
     must_be_following: false
+  reserved_usernames:
+    - admin
+    - support
+    - help
+    - root
+    - webmaster
+    - administrator
 
 development:
   <<: *defaults
diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb
index ebec463e12542a5e5f71f503d44d6342074e1d0b..ab4de9aa12afd742330b4a38f529ea6e5e927d23 100644
--- a/spec/models/account_spec.rb
+++ b/spec/models/account_spec.rb
@@ -381,6 +381,12 @@ RSpec.describe Account, type: :model do
       expect(account_2).to model_have_error_on_field(:username)
     end
 
+    it 'is invalid if the username is reserved' do
+      account = Fabricate.build(:account, username: 'support')
+      account.valid?
+      expect(account).to model_have_error_on_field(:username)
+    end
+
     context 'when is local' do
       it 'is invalid if the username doesn\'t only contains letters, numbers and underscores' do
         account = Fabricate.build(:account, username: 'the-doctor')