diff --git a/Changelog.md b/Changelog.md
index c47aa2c344a198d20f01c510b68adace061448bb..7b622618a23f83e6df11b658c9001df146b9df79 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -33,6 +33,8 @@
 
 ## Features
 
+* Add support for Nodeinfo 2.0 [#7447](https://github.com/diaspora/diaspora/pull/7447)
+
 # 0.6.5.0
 
 ## Refactor
diff --git a/app/presenters/node_info_presenter.rb b/app/presenters/node_info_presenter.rb
index a52668b7f7e4ccd6dd28356c773f54c53387abb3..1167ab5eacc727e163018502b38cda6450ef0b3b 100644
--- a/app/presenters/node_info_presenter.rb
+++ b/app/presenters/node_info_presenter.rb
@@ -17,17 +17,17 @@ class NodeInfoPresenter
   end
 
   def add_configuration(doc)
-    doc.software.version     = version
-    doc.services.outbound    = available_services
-    doc.open_registrations   = open_registrations?
-    doc.metadata["nodeName"] = name
-    doc.metadata["xmppChat"] = chat_enabled?
+    doc.software.version         = version
+    doc.services.outbound        = available_services
+    doc.open_registrations       = open_registrations?
+    doc.metadata["nodeName"]     = name
+    doc.metadata["xmppChat"]     = chat_enabled?
+    doc.metadata["adminAccount"] = admin_account
   end
 
   def add_static_data(doc)
     doc.software.name = "diaspora"
-    doc.protocols.inbound << "diaspora"
-    doc.protocols.outbound << "diaspora"
+    doc.protocols.protocols << "diaspora"
   end
 
   def add_user_counts(doc)
@@ -71,6 +71,10 @@ class NodeInfoPresenter
     AppConfig.chat.enabled?
   end
 
+  def admin_account
+    AppConfig.admins.account if AppConfig.admins.account?
+  end
+
   def available_services
     Configuration::KNOWN_SERVICES.select {|service|
       AppConfig.show_service?(service, nil)
diff --git a/lib/node_info.rb b/lib/node_info.rb
index eb012f98e389267d00577c8c9e83995668f418cf..789bdd64dd75d252cfac78afc72b7cddf98c75d0 100644
--- a/lib/node_info.rb
+++ b/lib/node_info.rb
@@ -2,7 +2,7 @@ require "pathname"
 require "json-schema"
 
 module NodeInfo
-  VERSIONS = %w(1.0)
+  VERSIONS = %w(1.0 2.0).freeze
   SCHEMAS = {}
   private_constant :VERSIONS, :SCHEMAS
 
@@ -21,17 +21,21 @@ module NodeInfo
       end
     end
 
-    Protocols = Struct.new(:inbound, :outbound) do
-      def initialize(inbound=[], outbound=[])
-        super(inbound, outbound)
+    Protocols = Struct.new(:protocols) do
+      def initialize(protocols=[])
+        super(protocols)
       end
 
       def version_10_hash
         {
-          "inbound"  => inbound,
-          "outbound" => outbound
+          "inbound"  => protocols,
+          "outbound" => protocols
         }
       end
+
+      def version_20_array
+        protocols
+      end
     end
 
     Services = Struct.new(:inbound, :outbound) do
@@ -90,6 +94,8 @@ module NodeInfo
       case version
       when "1.0"
         version_10_hash
+      when "2.0"
+        version_20_hash
       end
     end
 
@@ -124,6 +130,18 @@ module NodeInfo
       )
     end
 
+    def version_20_hash
+      deep_compact(
+        "version"           => "2.0",
+        "software"          => software.version_10_hash,
+        "protocols"         => protocols.version_20_array,
+        "services"          => services.version_10_hash,
+        "openRegistrations" => open_registrations,
+        "usage"             => usage.version_10_hash,
+        "metadata"          => metadata
+      )
+    end
+
     def deep_compact(hash)
       hash.tap do |hash|
         hash.reject! {|_, value|
diff --git a/spec/controllers/node_info_controller_spec.rb b/spec/controllers/node_info_controller_spec.rb
index ec7969581f7c7cd1ddec2523c72c6918fb61c32d..907f1183aff68320c807d8f690ec6ddb44b09ce5 100644
--- a/spec/controllers/node_info_controller_spec.rb
+++ b/spec/controllers/node_info_controller_spec.rb
@@ -15,6 +15,9 @@ describe NodeInfoController do
       expect(jrd).to include "links" => [{
         "rel"  => "http://nodeinfo.diaspora.software/ns/schema/1.0",
         "href" => node_info_url("1.0")
+      }, {
+        "rel"  => "http://nodeinfo.diaspora.software/ns/schema/2.0",
+        "href" => node_info_url("2.0")
       }]
     end
   end
@@ -28,24 +31,27 @@ describe NodeInfoController do
       end
     end
 
-    context "version 1.0" do
-      it "responds to JSON" do
-        get :document, version: "1.0", format: :json
+    %w(1.0 2.0).each do |version|
+      context "version #{version}" do
+        it "responds to JSON" do
+          get :document, version: version, format: :json
 
-        expect(response).to be_success
-      end
+          expect(response).to be_success
+        end
 
-      it "calls NodeInfoPresenter" do
-        expect(NodeInfoPresenter).to receive(:new).with("1.0")
-          .and_return(double(as_json: {}, content_type: "application/json"))
+        it "calls NodeInfoPresenter" do
+          expect(NodeInfoPresenter).to receive(:new).with(version)
+            .and_return(double(as_json: {}, content_type: "application/json"))
 
-        get :document, version: "1.0", format: :json
-      end
+          get :document, version: version, format: :json
+        end
 
-      it "notes the schema in the content type" do
-        get :document, version: "1.0", format: :json
+        it "notes the schema in the content type" do
+          get :document, version: version, format: :json
 
-        expect(response.content_type).to eq "application/json; profile=http://nodeinfo.diaspora.software/ns/schema/1.0#"
+          expect(response.content_type)
+            .to eq("application/json; profile=http://nodeinfo.diaspora.software/ns/schema/#{version}#")
+        end
       end
     end
   end
diff --git a/spec/lib/connection_tester_spec.rb b/spec/lib/connection_tester_spec.rb
index 85dd5d0a2a27496fc8dc41c1b17a18bcd262777d..6f2fcaaf58cbd9673b25c3488f31dab1ce0bcd59 100644
--- a/spec/lib/connection_tester_spec.rb
+++ b/spec/lib/connection_tester_spec.rb
@@ -116,8 +116,7 @@ describe ConnectionTester do
       ni_document = NodeInfo.build do |doc|
         doc.version = "1.0"
         doc.open_registrations = true
-        doc.protocols.inbound << "diaspora"
-        doc.protocols.outbound << "diaspora"
+        doc.protocols.protocols << "diaspora"
         doc.software.name = "diaspora"
         doc.software.version = "a.b.c.d"
       end
diff --git a/spec/presenters/node_info_presenter_spec.rb b/spec/presenters/node_info_presenter_spec.rb
index 6c168a8e62a9d4ab120f346854c86877471f006f..737ee07f75f7a4df7aedce52fa38103d51fcc0e2 100644
--- a/spec/presenters/node_info_presenter_spec.rb
+++ b/spec/presenters/node_info_presenter_spec.rb
@@ -128,5 +128,40 @@ describe NodeInfoPresenter do
         expect(hash).to include "metadata" => include("xmppChat" => true)
       end
     end
+
+    context "when admin account is set" do
+      before do
+        AppConfig.admins.account = "podmin"
+      end
+
+      it "adds the admin account username" do
+        expect(hash).to include "metadata" => include("adminAccount" => "podmin")
+      end
+    end
+
+    context "version 2.0" do
+      it "provides generic pod data in json" do
+        expect(NodeInfoPresenter.new("2.0").as_json.as_json).to eq(
+          "version"           => "2.0",
+          "software"          => {
+            "name"    => "diaspora",
+            "version" => AppConfig.version_string
+          },
+          "protocols"         => ["diaspora"],
+          "services"          => {
+            "inbound"  => [],
+            "outbound" => AppConfig.configured_services.map(&:to_s)
+          },
+          "openRegistrations" => AppConfig.settings.enable_registrations?,
+          "usage"             => {
+            "users" => {}
+          },
+          "metadata"          => {
+            "nodeName" => AppConfig.settings.pod_name,
+            "xmppChat" => AppConfig.chat.enabled?
+          }
+        )
+      end
+    end
   end
 end
diff --git a/vendor/nodeinfo/schemas/2.0.json b/vendor/nodeinfo/schemas/2.0.json
new file mode 100644
index 0000000000000000000000000000000000000000..ddaca625e5f6d6fcde4d38f616ecc131b30981bc
--- /dev/null
+++ b/vendor/nodeinfo/schemas/2.0.json
@@ -0,0 +1,182 @@
+
+
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "id": "http://nodeinfo.diaspora.software/ns/schema/2.0#",
+  "description": "NodeInfo schema version 2.0.",
+  "type": "object",
+  "additionalProperties": false,
+  "required": [
+    "version",
+    "software",
+    "protocols",
+    "services",
+    "openRegistrations",
+    "usage",
+    "metadata"
+  ],
+  "properties": {
+    "version": {
+      "description": "The schema version, must be 2.0.",
+      "enum": [
+        "2.0"
+      ]
+    },
+    "software": {
+      "description": "Metadata about server software in use.",
+      "type": "object",
+      "additionalProperties": false,
+      "required": [
+        "name",
+        "version"
+      ],
+      "properties": {
+        "name": {
+          "description": "The canonical name of this server software.",
+          "type": "string",
+          "pattern": "^[a-z0-9-]+$"
+        },
+        "version": {
+          "description": "The version of this server software.",
+          "type": "string"
+        }
+      }
+    },
+    "protocols": {
+      "description": "The protocols supported on this server.",
+      "type": "array",
+      "minItems": 1,
+      "items": {
+        "enum": [
+          "activitypub",
+          "buddycloud",
+          "dfrn",
+          "diaspora",
+          "libertree",
+          "ostatus",
+          "pumpio",
+          "tent",
+          "xmpp",
+          "zot"
+        ]
+      }
+    },
+    "services": {
+      "description": "The third party sites this server can connect to via their application API.",
+      "type": "object",
+      "additionalProperties": false,
+      "required": [
+        "inbound",
+        "outbound"
+      ],
+      "properties": {
+        "inbound": {
+          "description": "The third party sites this server can retrieve messages from for combined display with regular traffic.",
+          "type": "array",
+          "minItems": 0,
+          "items": {
+            "enum": [
+              "atom1.0",
+              "gnusocial",
+              "imap",
+              "pnut",
+              "pop3",
+              "pumpio",
+              "rss2.0",
+              "twitter"
+            ]
+          }
+        },
+        "outbound": {
+          "description": "The third party sites this server can publish messages to on the behalf of a user.",
+          "type": "array",
+          "minItems": 0,
+          "items": {
+            "enum": [
+              "atom1.0",
+              "blogger",
+              "buddycloud",
+              "diaspora",
+              "dreamwidth",
+              "drupal",
+              "facebook",
+              "friendica",
+              "gnusocial",
+              "google",
+              "insanejournal",
+              "libertree",
+              "linkedin",
+              "livejournal",
+              "mediagoblin",
+              "myspace",
+              "pinterest",
+              "pnut",
+              "posterous",
+              "pumpio",
+              "redmatrix",
+              "rss2.0",
+              "smtp",
+              "tent",
+              "tumblr",
+              "twitter",
+              "wordpress",
+              "xmpp"
+            ]
+          }
+        }
+      }
+    },
+    "openRegistrations": {
+      "description": "Whether this server allows open self-registration.",
+      "type": "boolean"
+    },
+    "usage": {
+      "description": "Usage statistics for this server.",
+      "type": "object",
+      "additionalProperties": false,
+      "required": [
+        "users"
+      ],
+      "properties": {
+        "users": {
+          "description": "statistics about the users of this server.",
+          "type": "object",
+          "additionalProperties": false,
+          "properties": {
+            "total": {
+              "description": "The total amount of on this server registered users.",
+              "type": "integer",
+              "minimum": 0
+            },
+            "activeHalfyear": {
+              "description": "The amount of users that signed in at least once in the last 180 days.",
+              "type": "integer",
+              "minimum": 0
+            },
+            "activeMonth": {
+              "description": "The amount of users that signed in at least once in the last 30 days.",
+              "type": "integer",
+              "minimum": 0
+            }
+          }
+        },
+        "localPosts": {
+          "description": "The amount of posts that were made by users that are registered on this server.",
+          "type": "integer",
+          "minimum": 0
+        },
+        "localComments": {
+          "description": "The amount of comments that were made by users that are registered on this server.",
+          "type": "integer",
+          "minimum": 0
+        }
+      }
+    },
+    "metadata": {
+      "description": "Free form key value pairs for software specific values. Clients should not rely on any specific key present.",
+      "type": "object",
+      "minProperties": 0,
+      "additionalProperties": true
+    }
+  }
+}