diff --git a/config.yml b/config.yml
--- a/config.yml
+++ b/config.yml
@@ -35,3 +35,4 @@
     - "src/assets/js/app.js"
     - "src/assets/js/docker-registry.js"
     - "src/assets/js/servers-log.js"
+    - "src/assets/js/salt-config.js"
diff --git a/src/assets/js/salt-config.js b/src/assets/js/salt-config.js
new file mode 100644
--- /dev/null
+++ b/src/assets/js/salt-config.js
@@ -0,0 +1,378 @@
+/*  -------------------------------------------------------------
+    Nasqueron infrastructure
+    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+    Project:        Nasqueron
+    Author:         Sébastien Santoro aka Dereckson
+    Dependencies:   jQuery
+    Filename:       salt-config.js
+    Licence:        CC-BY 4.0, MIT, BSD-2-Clause (multi-licensing)
+    -------------------------------------------------------------    */
+
+/*  -------------------------------------------------------------
+    Table of contents
+    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ :: Servers list
+ :: States
+ :: Code to run when document is ready
+
+ */
+
+const ServersConfig = function (container) {
+
+    /*  -------------------------------------------------------------
+        States
+        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -    */
+
+    const States = function (container, serverName, serverHost) {
+        const states = {
+
+            ///
+            /// Constants
+            ///
+
+            SALT_BASE_URL: "https://devcentral.nasqueron.org/source/operations/browse/main/",
+            SALT_STAGING_URL: "https://devcentral.nasqueron.org/source/staging/browse/master/",
+
+            SALT_DOC_STATES_URL: "https://docs.saltproject.io/en/latest/ref/states/all/",
+
+            ///
+            /// Private properties
+            ///
+
+            /**
+             * A JQuery selector expression to a DOM element to publish to.
+             *
+             * @var string
+             */
+            container: "",
+
+            server: "",
+
+            ///
+            /// Constructor
+            ///
+
+            /**
+             * Initializes an instance of this object.
+             *
+             * @param container The DOM element JQuery selector where to write
+             * @param serverName The name of the server, to display it
+             * @param serverHost The FQDN of the server, to fetch config data
+             */
+            load: function (container, serverName, serverHost) {
+                this.container = container;
+                this.server = serverName;
+                this.refreshData(serverHost);
+            },
+
+            ///
+            /// Main methods
+            ///
+
+            refreshData: function (serverHost) {
+                let url = "https://" + serverHost + "/datasources/infra/all-states.json";
+                $.getJSON(url, function (configurationStates) {
+                    states.refreshUI(configurationStates);
+                });
+            },
+
+            refreshUI: function (configurationStates) {
+                $(this.container).html(this.formatConfig(configurationStates));
+
+                $("#config-back-to-server-list").on("click", function () {
+                    console.log("Back to servers list");
+                    new ServersList(container)
+                })
+            },
+
+            formatConfig: function (states) {
+                return `
+<button id="config-back-to-server-list" class="button extra-action">« Back to servers list</button>
+<h2 class="config-server">${this.server}</h2>
+${this.formatStates(states)}`
+            },
+
+            formatState: function (name, state) {
+                let output = '<div class="state">'
+                output += '<div class="state-name">' + name + "</div>"
+
+                for (const [key, properties] of Object.entries(state)) {
+                    if (key.startsWith("__")) {
+                        continue
+                    }
+                    output += `<div class="state-module">
+                        ${this.resolveSaltModuleMethod(key, properties)}
+                    </div>`
+
+                    output += '<div class="state-properties">'
+                    for (const property of properties) {
+                        if (typeof property === "string") {
+                            // Method is already parsed by extractMethod
+                            continue
+                        }
+
+                        if (property.order !== undefined) {
+                            // We're lucky we already receive the states in the
+                            // sorted order, so we can ignore this.
+                            continue
+                        }
+
+                        output += this.dump(property)
+                    }
+                    output += "</div>"
+                }
+
+                output += "</div>"
+
+                return output
+            },
+
+            formatStates: function (server_states) {
+                let current_unit = ""
+                let output = '<div class="states">'
+
+                let roles_output = ""
+                let roles = []
+
+                for (const [role, role_states] of Object.entries(server_states)) {
+                    roles.push(role)
+
+                    roles_output += `<div class="config-role">
+<h3 id="${this.makeId(role)}" class="config-role-title">${role}</h3>
+<div class="config-role-content">`
+
+                    if ($.isEmptyObject(role_states)) {
+                        roles_output += '<p class="config-error">No information gathered for this role. There is probably an error in Salt configuration.</p>';
+                    }
+
+                    for (const [name, individual_state] of Object.entries(role_states)) {
+                        // Gets unit from the state source SLS to generate units headings
+                        let unit = individual_state["__sls__"].replace(role + ".", "")
+                        if (unit !== current_unit) {
+                            roles_output += `<h4 class="config-unit">${unit}</h4>`
+                            current_unit = unit
+                        }
+
+                        roles_output += this.formatState(name, individual_state)
+                    }
+
+                    roles_output += "</div></div>";
+                }
+
+                roles_output += '</div>';
+
+                output += `
+<div class="config-summary-roles">
+<h3 class="config-summary-roles-heading">Roles assigned</h3>
+<ul class="config-summary-roles-list">
+`
+                for (const role of roles) {
+                    output += `
+<li class="config-summary-role">
+    <a href="#${this.makeId(role)}">${role}</a>
+</li>
+                    `
+                }
+                output += "</ul></div>"
+
+                output += roles_output;
+
+                return output;
+            },
+
+            makeId: function (expression) {
+                return expression.replace("/", ".")
+            },
+
+            resolveSaltModuleMethod: function (module, properties) {
+                const method = this.extractMethod(properties);
+                const link = `${this.SALT_DOC_STATES_URL}salt.states.${module}.html#salt.states.${module}.${method}`
+
+                return `<a class="salt-link" href="${link}">${module}.${method}</a>`
+            },
+
+            extractMethod: function (properties) {
+                for (const property of properties) {
+                    if (typeof property === "string") {
+                        return property
+                    }
+                }
+            },
+
+            isInStagingRepo: url => url.startsWith("salt://software/") || url.startsWith("salt://wwwroot/"),
+
+            resolveSaltLink: function (url) {
+                const base = this.isInStagingRepo(url)
+                    ? this.SALT_STAGING_URL
+                    : this.SALT_BASE_URL
+
+                const link = base + url.replace("salt://", "")
+                return `<a class="salt-link" href="${link}">${url}</a>`
+            },
+            // roles/core/rc/files/periodic.conf
+
+            dump: function (data) {
+                if (typeof data === "string" && data.startsWith("salt://")) {
+                    return this.resolveSaltLink(data)
+                }
+
+                if (this.isScalar(data)) {
+                    return data
+                }
+                if (typeof data === "object") {
+                    if (data.constructor.name === "Array") {
+                        return this.dumpArray(data);
+                    }
+
+                    return this.dumpObject(data);
+                }
+            },
+
+            dumpArray: function (values) {
+                let dumped = '<ul class="state-list">'
+
+                for (const value of values) {
+                    dumped += `<li class="state-list-item">${this.dump(value)}</li>`
+                }
+
+                dumped += '</ul>'
+
+                return dumped
+            },
+
+            dumpObject: function (data) {
+                let dumped = ""
+
+                for (const [key, value] of Object.entries(data)) {
+                    dumped += `
+    <div class="state-property">
+        <span class="key">${key}</span>
+        <span class="value">${this.dump(value)}</span>
+    </div>
+    `
+                }
+
+                return dumped
+            },
+
+            isScalar: value => typeof value === "boolean"
+                || typeof value === "number"
+                || typeof value === "string"
+        };
+
+        states.load(container, serverName, serverHost)
+
+        return states;
+    };
+
+    /*  -------------------------------------------------------------
+        Servers list
+        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -    */
+
+    const ServersList = function (container) {
+        const serversList = {
+
+            ///
+            /// Constants
+            ///
+
+            SERVERS_API_URL: "https://api.nasqueron.org/infra/servers.json",
+
+            ///
+            /// Private properties
+            ///
+
+            /**
+             * A JQuery selector expression to a DOM element to publish to.
+             *
+             * @var string
+             */
+            container: "",
+
+            servers: undefined,
+
+            ///
+            /// Constructor
+            ///
+
+            /**
+             * Initializes an instance of this object.
+             *
+             * @param container The DOM element JQuery selector where to write
+             */
+            load: function (container) {
+                this.container = container;
+                this.refreshData();
+            },
+
+            ///
+            /// Data model
+            ///
+
+            fetchServers: function () {
+                let that = this
+                $.getJSON(this.SERVERS_API_URL, function (servers) {
+                    that.servers = servers
+                    that.refreshUI()
+                })
+            },
+
+            refreshData: function () {
+                this.fetchServers();
+            },
+
+            ///
+            /// UI representation
+            ///
+
+            refreshUI: function () {
+                $(this.container).html(this.formatData())
+
+                for (const server of $(".server")) {
+                    $(server).on("click", function () {
+                        new States(container, server.id, server.dataset.hostname)
+                    })
+                }
+            },
+
+            formatData: function () {
+                let output = '<h2>Servers</h2><ul class="servers">';
+                for (const [server, properties] of Object.entries(this.servers)) {
+                    if (properties.configurator !== "salt") {
+                        continue;
+                    }
+
+                    output += `
+    <li class="server" id="${server}" data-hostname="${properties.hostname}">
+        <span class="server-property server-name">${properties.name}</span>
+        <span class="server-property server-description">${properties.description}</span>
+    </li>
+    `
+                }
+                output += "</ul>"
+
+                return output;
+            }
+
+        };
+
+        serversList.load(container);
+
+        return serversList;
+    };
+
+    /*  -------------------------------------------------------------
+        Initialization
+        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -    */
+
+    new ServersList(container)
+}
+
+/*  -------------------------------------------------------------
+    Code to run when document is ready
+    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -    */
+
+$(document).ready(function() {
+    new ServersConfig("#config");
+});
diff --git a/src/assets/scss/app.scss b/src/assets/scss/app.scss
--- a/src/assets/scss/app.scss
+++ b/src/assets/scss/app.scss
@@ -52,3 +52,4 @@
 @import 'components/layout';
 @import 'components/footer';
 @import 'components/utilities-classes';
+@import 'components/salt-config';
diff --git a/src/assets/scss/components/_salt-config.scss b/src/assets/scss/components/_salt-config.scss
new file mode 100644
--- /dev/null
+++ b/src/assets/scss/components/_salt-config.scss
@@ -0,0 +1,139 @@
+/*  -------------------------------------------------------------
+General elements
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -    */
+
+.extra-action {
+  float: right;
+}
+
+/*  -------------------------------------------------------------
+Servers list
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -    */
+
+.servers {
+  li {
+    list-style-type: none;
+    padding: 1em;
+    border: solid 2px $primary-color;
+    width: 16em;
+    float: left;
+    margin-right: 1em;
+    margin-bottom: 1em;
+
+    .server-property {
+      display: block;
+    }
+
+    .server-name {
+      color: $secondary-color;
+      font-weight: bold;
+    }
+  }
+
+  li:hover {
+    background-color: lighten($body-background, 10%);
+
+    //background-color: #474747;
+    cursor: zoom-in;
+  }
+}
+
+/*  -------------------------------------------------------------
+Salt configuration
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -    */
+
+$config-margin: 1em;
+$icon-width: 3.5rem;
+$config-block-margin-height: 2.5em;
+
+.config-server::before {
+  content: "🖥️ ";
+  display: inline-block;
+  width: $icon-width;
+}
+
+.config-summary-roles {
+  margin-bottom: $config-block-margin-height;
+}
+
+.config-summary-roles-heading::before {
+  content: "📖 ";
+  display: inline-block;
+  width: $icon-width;
+}
+
+.config-role {
+  margin-bottom: $config-block-margin-height;
+  line-height: 1.5em;
+
+  .config-role-title::before {
+    content: "📦 ";
+    display: inline-block;
+    width: $icon-width;
+  }
+
+  .config-role-content {
+
+    a {
+      color: #b5c9c7;
+    }
+
+    a:hover {
+      color: white;
+    }
+
+    .state {
+      margin-bottom: 1.25em;
+
+      .state-name {
+        color: #c4e3e9;
+        font-weight: bold;
+      }
+
+      .state-module {
+        margin-left: $config-margin;
+      }
+
+      .state-properties {
+        margin-left: 2 * $config-margin;
+
+        .state-property {
+          .key {
+            color: #d2eaee;
+          }
+
+          .key::after {
+            content: ": "
+          }
+
+          .value .state-property {
+            padding-left: $config-margin;
+          }
+        }
+
+        ul.state-list {
+          margin-bottom: 0;
+        }
+
+        .state-list-item {
+          margin-left: $config-margin / 2;
+
+          .state-property {
+            padding-left: 0 !important;
+          }
+        }
+      }
+    }
+
+  }
+
+  .config-error {
+    color: $warning-color;
+    font-weight: bold;
+  }
+
+  .config-error::before {
+    content: "🔥 ";
+  }
+
+}
diff --git a/src/pages/config/index.html b/src/pages/config/index.html
new file mode 100644
--- /dev/null
+++ b/src/pages/config/index.html
@@ -0,0 +1,18 @@
+---
+title: Servers configuration
+app: salt-config
+---
+
+<section class="row">
+    <div class="large-12 columns">
+        {{> config-intro}}
+    </div>
+</section>
+
+<div class="row">
+    <div class="large-9 columns" id="config">
+    </div>
+    <div class="large-3 columns">
+        {{> config-help}}
+    </div>
+</div>
diff --git a/src/partials/config/config-help.html b/src/partials/config/config-help.html
new file mode 100644
--- /dev/null
+++ b/src/partials/config/config-help.html
@@ -0,0 +1,18 @@
+<div class="callout primary">
+    <h3>Source</h3>
+    <p>These entries are compiled from the <a href="https://devcentral.nasqueron.org/source/operations/">Nasqueron Operations repository</a>.</p>
+    <p>They describe the state of the server, as known by Salt.</p>
+</div>
+<div class="callout primary">
+    <h3>Change config</h3>
+    <p>
+        To amend the server configuration, you need to commit it to <a href="https://devcentral.nasqueron.org/source/operations/">rOPS</a>.
+    </p>
+    <p>The <a href="https://agora.nasqueron.org/Operations_grimoire">operations grimoire</a> contains help how to do so.</p>
+</div>
+<div class="callout primary">
+    <h3>License</h3>
+    <p>Individual entries are too short to be original, and so are in the public domain.</p>
+    <p>When original enough, content is available under <a rel="license" href="https://creativecommons.org/licenses/by/4.0/">CC-BY 4.0</a> licence.</p>
+    <p>This configuration, as a database, is made available under the <a rel="license" href="https://www.opendatacommons.org/licenses/pddl/1.0/">Public Domain Dedication and License v1.0</a>.</p>
+</div>
diff --git a/src/partials/config/config-intro.html b/src/partials/config/config-intro.html
new file mode 100644
--- /dev/null
+++ b/src/partials/config/config-intro.html
@@ -0,0 +1,4 @@
+<div class="callout">
+    <p><strong>Nasqueron infrastructure servers</strong> support our budding community of creative people, writers, developers and thinkers.</p>
+    <p>According our transparency principle, our <strong>servers configuration</strong> is open and auditable.</p>
+</div>
diff --git a/src/partials/default-layout/footer.html b/src/partials/default-layout/footer.html
--- a/src/partials/default-layout/footer.html
+++ b/src/partials/default-layout/footer.html
@@ -11,7 +11,8 @@
             <div class="large-3 columns">
                 <dl>
                     <dt>Ops repositories</dt>
-                    <dd><a href="https://devcentral.nasqueron.org/source/operations/">Operations</a></dd>
+                    <dd><a href="https://devcentral.nasqueron.org/source/operations/">Operations</a> →
+                        <a href="/config">Config</a></dd>
                     <dd><a href="https://devcentral.nasqueron.org/diffusion/query/NelStiRVmgP0/">Docker images</a></dd>
 
                     <dt>Site repositories</dt>