diff --git a/client/src/app/+about/about-instance/about-instance.component.html b/client/src/app/+about/about-instance/about-instance.component.html
index 7c27ec760..0fd3626b7 100644
--- a/client/src/app/+about/about-instance/about-instance.component.html
+++ b/client/src/app/+about/about-instance/about-instance.component.html
@@ -1,7 +1,8 @@
 <div class="row">
   <div class="col-md-12 col-xl-6">
+
     <div class="about-instance-title">
-      <div i18n>About {{ instanceName }} instance</div>
+      <div i18n class="title">About {{ instanceName }} instance</div>
 
       <div *ngIf="isContactFormEnabled" (click)="openContactModal()" i18n role="button" class="contact-admin">Contact administrator</div>
     </div>
@@ -12,16 +13,58 @@
       <div *ngIf="isNSFW" class="dedicated-to-nsfw">This instance is dedicated to sensitive/NSFW content.</div>
     </div>
 
-    <div class="description">
-      <div i18n class="section-title">Description</div>
-
-      <div [innerHTML]="descriptionHTML"></div>
+    <div class="middle-title" *ngIf="html.administrator || maintenanceLifetime || businessModel">
+      Administrators & sustainability
     </div>
 
-    <div class="terms" id="terms-section">
+    <div class="block administrator" *ngIf="html.administrator">
+      <div i18n class="section-title">Instance administrators</div>
+
+      <div [innerHTML]="html.administrator"></div>
+    </div>
+
+    <div class="block maintenance-lifetime" *ngIf="maintenanceLifetime">
+      <div i18n class="section-title">Maintenance lifetime</div>
+
+      <p>{{ maintenanceLifetime }}</p>
+    </div>
+
+    <div class="block business-model" *ngIf="businessModel">
+      <div i18n class="section-title">Business model</div>
+
+      <p>{{ businessModel }}</p>
+    </div>
+
+    <div class="middle-title" *ngIf="html.description">
+      Information
+    </div>
+
+    <div class="block description">
+      <div i18n class="section-title">Description</div>
+
+      <div [innerHTML]="html.description"></div>
+    </div>
+
+    <div class="middle-title" *ngIf="html.moderationInformation || html.codeOfConduct || html.terms">
+      Moderation
+    </div>
+
+    <div class="block moderation-information" *ngIf="html.moderationInformation">
+      <div i18n class="section-title">Moderation information</div>
+
+      <div [innerHTML]="html.moderationInformation"></div>
+    </div>
+
+    <div class="block code-of-conduct" *ngIf="html.codeOfConduct">
+      <div i18n class="section-title">Code of conduct</div>
+
+      <div [innerHTML]="html.codeOfConduct"></div>
+    </div>
+
+    <div class="block terms" id="terms-section">
       <div i18n class="section-title">Terms</div>
 
-      <div [innerHTML]="termsHTML"></div>
+      <div [innerHTML]="html.terms"></div>
     </div>
   </div>
 
diff --git a/client/src/app/+about/about-instance/about-instance.component.scss b/client/src/app/+about/about-instance/about-instance.component.scss
index 0296ae8e9..0585ad5f3 100644
--- a/client/src/app/+about/about-instance/about-instance.component.scss
+++ b/client/src/app/+about/about-instance/about-instance.component.scss
@@ -5,13 +5,13 @@
   display: flex;
   justify-content: space-between;
 
-  & > div {
+  .title {
     font-size: 20px;
-    font-weight: bold;
     margin-bottom: 15px;
+    font-weight: $font-semibold;
   }
 
-  & > .contact-admin {
+  .contact-admin {
     @include peertube-button;
     @include orange-button;
 
@@ -21,11 +21,20 @@
 
 .section-title {
   font-weight: $font-semibold;
-  font-size: 20px;
+  font-size: 16px;
   margin-bottom: 5px;
+  display: flex;
+  align-items: center;
 }
 
-.short-description, .description, .terms, .signup {
+.middle-title {
+  @include in-content-small-title;
+
+  margin-top: 45px;
+  margin-bottom: 25px;
+}
+
+.block {
   margin-bottom: 30px;
 }
 
diff --git a/client/src/app/+about/about-instance/about-instance.component.ts b/client/src/app/+about/about-instance/about-instance.component.ts
index a5204de27..b85a6be94 100644
--- a/client/src/app/+about/about-instance/about-instance.component.ts
+++ b/client/src/app/+about/about-instance/about-instance.component.ts
@@ -14,8 +14,20 @@ export class AboutInstanceComponent implements OnInit {
   @ViewChild('contactAdminModal', { static: true }) contactAdminModal: ContactAdminModalComponent
 
   shortDescription = ''
-  descriptionHTML = ''
-  termsHTML = ''
+
+  html = {
+    description: '',
+    terms: '',
+    codeOfConduct: '',
+    moderationInformation: '',
+    administrator: ''
+  }
+
+  maintenanceLifetime = ''
+  businessModel = ''
+
+  languages: string[] = []
+  categories: number[] = []
 
   constructor (
     private notifier: Notifier,
@@ -43,8 +55,15 @@ export class AboutInstanceComponent implements OnInit {
         async res => {
           this.shortDescription = res.instance.shortDescription
 
-          this.descriptionHTML = await this.markdownService.textMarkdownToHTML(res.instance.description)
-          this.termsHTML = await this.markdownService.textMarkdownToHTML(res.instance.terms)
+          this.maintenanceLifetime = res.instance.maintenanceLifetime
+          this.businessModel = res.instance.businessModel
+
+          for (const key of [ 'description', 'terms', 'codeOfConduct', 'moderationInformation', 'administrator' ]) {
+            this.html[key] = await this.markdownService.textMarkdownToHTML(res.instance[key])
+          }
+
+          this.languages = res.instance.languages
+          this.categories = res.instance.categories
         },
 
         () => this.notifier.error(this.i18n('Cannot get about information from server'))
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
index ec6f879d7..50df8a8ac 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
+++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html
@@ -2,12 +2,13 @@
 
   <ngb-tabset class="root-tabset bootstrap">
 
-    <ngb-tab i18n-title title="Basic configuration">
+    <ngb-tab i18n-title title="Instance information">
       <ng-template ngbTabContent>
 
-        <div i18n class="inner-form-title">Instance</div>
-
         <ng-container formGroupName="instance">
+
+          <div i18n class="inner-form-title">Instance</div>
+
           <div class="form-group">
             <label i18n for="instanceName">Name</label>
             <input
@@ -36,36 +37,40 @@
           </div>
 
           <div class="form-group">
-            <label i18n for="instanceTerms">Terms</label><my-help helpType="markdownText"></my-help>
-            <my-markdown-textarea
-              id="instanceTerms" formControlName="terms" textareaWidth="500px" [previewColumn]="true"
-              [ngClass]="{ 'input-error': formErrors['instance.terms'] }"
-            ></my-markdown-textarea>
-            <div *ngIf="formErrors.instance.terms" class="form-error">{{ formErrors.instance.terms }}</div>
+            <label i18n for="instanceCategories">Main instance categories</label>
+
+            <div>
+              <p-multiSelect
+                inputId="instanceCategories" [options]="categoryItems" formControlName="categories" showToggleAll="false"
+                [defaultLabel]="getDefaultCategoryLabel()" [selectedItemsLabel]="getSelectedCategoryLabel()"
+                emptyFilterMessage="No results found" i18n-emptyFilterMessage
+              ></p-multiSelect>
+            </div>
           </div>
 
+          <div class="form-group">
+            <label i18n for="instanceLanguages">Main languages you/your moderators speak</label>
+
+            <div>
+              <p-multiSelect
+                inputId="instanceLanguages" [options]="languageItems" formControlName="languages" showToggleAll="false"
+                [defaultLabel]="getDefaultLanguageLabel()" [selectedItemsLabel]="getSelectedLanguageLabel()"
+                emptyFilterMessage="No results found" i18n-emptyFilterMessage
+              ></p-multiSelect>
+            </div>
+          </div>
+
+          <div i18n class="inner-form-title">Moderation & NSFW</div>
+
           <div class="form-group">
             <my-peertube-checkbox
               inputName="instanceIsNSFW" formControlName="isNSFW"
-              i18n-labelText labelText="Dedicated to sensitive or NSFW content"
+              i18n-labelText labelText="This instance is dedicated to sensitive or NSFW content"
               i18n-helpHtml helpHtml="Enabling it will allow other administrators to know that you are mainly federating sensitive content.<br /><br />
               Moreover, the NSFW checkbox on video upload will be automatically checked by default."
             ></my-peertube-checkbox>
           </div>
 
-          <div class="form-group">
-            <label i18n for="instanceDefaultClientRoute">Default client route</label>
-            <div class="peertube-select-container">
-              <select id="instanceDefaultClientRoute" formControlName="defaultClientRoute">
-                <option i18n value="/videos/overview">Videos Overview</option>
-                <option i18n value="/videos/trending">Videos Trending</option>
-                <option i18n value="/videos/recently-added">Videos Recently Added</option>
-                <option i18n value="/videos/local">Local videos</option>
-              </select>
-            </div>
-            <div *ngIf="formErrors.instance.defaultClientRoute" class="form-error">{{ formErrors.instance.defaultClientRoute }}</div>
-          </div>
-
           <div class="form-group">
             <label i18n for="instanceDefaultNSFWPolicy">Policy on videos containing sensitive content</label>
             <my-help
@@ -82,10 +87,79 @@
             </div>
             <div *ngIf="formErrors.instance.defaultNSFWPolicy" class="form-error">{{ formErrors.instance.defaultNSFWPolicy }}</div>
           </div>
+
+          <div class="form-group">
+            <label i18n for="instanceTerms">Terms</label><my-help helpType="markdownText"></my-help>
+            <my-markdown-textarea
+              id="instanceTerms" formControlName="terms" textareaWidth="500px" [previewColumn]="true"
+              [ngClass]="{ 'input-error': formErrors['instance.terms'] }"
+            ></my-markdown-textarea>
+            <div *ngIf="formErrors.instance.terms" class="form-error">{{ formErrors.instance.terms }}</div>
+          </div>
+
+          <div class="form-group">
+            <label i18n for="instanceCodeOfConduct">Code of conduct</label><my-help helpType="markdownText"></my-help>
+            <my-markdown-textarea
+              id="instanceCodeOfConduct" formControlName="codeOfConduct" textareaWidth="500px" [previewColumn]="true"
+              [ngClass]="{ 'input-error': formErrors['instance.codeOfConduct'] }"
+            ></my-markdown-textarea>
+            <div *ngIf="formErrors.instance.codeOfConduct" class="form-error">{{ formErrors.instance.codeOfConduct }}</div>
+          </div>
+
+          <div class="form-group">
+            <label i18n for="instanceModerationInformation">Moderation information</label><my-help helpType="markdownText"></my-help>
+            <div class="label-small-info">Who moderates the instance? What is the policy regarding NSFW videos? Political videos? etc</div>
+
+            <my-markdown-textarea
+              id="instanceModerationInformation" formControlName="moderationInformation" textareaWidth="500px" [previewColumn]="true"
+              [ngClass]="{ 'input-error': formErrors['instance.moderationInformation'] }"
+            ></my-markdown-textarea>
+            <div *ngIf="formErrors.instance.moderationInformation" class="form-error">{{ formErrors.instance.moderationInformation }}</div>
+          </div>
+
+          <div i18n class="inner-form-title">You and your instance</div>
+
+          <div class="form-group">
+            <label i18n for="instanceAdministrator">Who is behind the instance? </label>
+            <div class="label-small-info">A single person? A non profit? A company?</div>
+
+            <textarea
+              id="instanceAdministrator" formControlName="administrator"
+              [ngClass]="{ 'input-error': formErrors['instance.administrator'] }"
+            ></textarea>
+            <div *ngIf="formErrors.instance.administrator" class="form-error">{{ formErrors.instance.administrator }}</div>
+          </div>
+
+          <div class="form-group">
+            <label i18n for="instanceMaintenanceLifetime">How long do you plan to maintain this instance?</label>
+            <div class="label-small-info">It's important to know for users who want to register on your instance</div>
+
+            <textarea
+              id="instanceMaintenanceLifetime" formControlName="maintenanceLifetime"
+              [ngClass]="{ 'input-error': formErrors['instance.maintenanceLifetime'] }"
+            ></textarea>
+            <div *ngIf="formErrors.instance.maintenanceLifetime" class="form-error">{{ formErrors.instance.maintenanceLifetime }}</div>
+          </div>
+
+          <div class="form-group">
+            <label i18n for="instanceBusinessModel">How will you pay the PeerTube instance server?</label>
+            <div class="label-small-info">With you own funds? With users donations? Advertising?</div>
+
+            <textarea
+              id="instanceBusinessModel" formControlName="businessModel"
+              [ngClass]="{ 'input-error': formErrors['instance.businessModel'] }"
+            ></textarea>
+            <div *ngIf="formErrors.instance.businessModel" class="form-error">{{ formErrors.instance.businessModel }}</div>
+          </div>
+
         </ng-container>
+      </ng-template>
+    </ngb-tab>
 
+    <ngb-tab i18n-title title="Basic configuration">
+      <ng-template ngbTabContent>
 
-        <div i18n class="inner-form-title">Theme</div>
+        <div i18n class="inner-form-title">Theme & Default route</div>
 
         <ng-container formGroupName="theme">
           <div class="form-group">
@@ -102,6 +176,19 @@
         </ng-container>
 
 
+        <div class="form-group" formGroupName="instance">
+          <label i18n for="instanceDefaultClientRoute">Default client route</label>
+          <div class="peertube-select-container">
+            <select id="instanceDefaultClientRoute" formControlName="defaultClientRoute">
+              <option i18n value="/videos/overview">Videos Discover</option>
+              <option i18n value="/videos/trending">Videos Trending</option>
+              <option i18n value="/videos/recently-added">Videos Recently Added</option>
+              <option i18n value="/videos/local">Local videos</option>
+            </select>
+          </div>
+          <div *ngIf="formErrors.instance.defaultClientRoute" class="form-error">{{ formErrors.instance.defaultClientRoute }}</div>
+        </div>
+
         <div i18n class="inner-form-title">Signup</div>
 
         <ng-container formGroupName="signup">
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss
index c90bd5141..68f1b01b7 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss
+++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss
@@ -1,6 +1,10 @@
 @import '_variables';
 @import '_mixins';
 
+.form-group {
+  margin-bottom: 25px;
+}
+
 input[type=text] {
   @include peertube-input-text(340px);
   display: block;
@@ -44,3 +48,8 @@ textarea {
     height: 100px;
   }
 }
+
+.label-small-info {
+  font-style: italic;
+  margin-bottom: 10px;
+}
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
index d51104569..3119ab040 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
+++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts
@@ -6,6 +6,9 @@ import { Notifier } from '@app/core'
 import { CustomConfig } from '../../../../../../shared/models/server/custom-config.model'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
+import { SelectItem } from 'primeng/api'
+import { forkJoin } from 'rxjs'
+import { first } from 'rxjs/operators'
 
 @Component({
   selector: 'my-edit-custom-config',
@@ -18,6 +21,9 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
   resolutions: { id: string, label: string }[] = []
   transcodingThreadOptions: { label: string, value: number }[] = []
 
+  languageItems: SelectItem[] = []
+  categoryItems: SelectItem[] = []
+
   constructor (
     protected formValidatorService: FormValidatorService,
     private customConfigValidatorsService: CustomConfigValidatorsService,
@@ -88,10 +94,22 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
         name: this.customConfigValidatorsService.INSTANCE_NAME,
         shortDescription: this.customConfigValidatorsService.INSTANCE_SHORT_DESCRIPTION,
         description: null,
-        terms: null,
-        defaultClientRoute: null,
+
         isNSFW: false,
         defaultNSFWPolicy: null,
+
+        terms: null,
+        codeOfConduct: null,
+        moderationInformation: null,
+        administrator: null,
+        maintenanceLifetime: null,
+        businessModel: null,
+
+        categories: null,
+        languages: null,
+
+        defaultClientRoute: null,
+
         customizations: {
           javascript: null,
           css: null
@@ -184,18 +202,27 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
 
     this.buildForm(formGroupData)
 
-    this.configService.getCustomConfig()
-      .subscribe(
-        res => {
-          this.customConfig = res
+    forkJoin([
+      this.configService.getCustomConfig(),
+      this.serverService.videoLanguagesLoaded.pipe(first()), // First so the observable completes
+      this.serverService.videoCategoriesLoaded.pipe(first())
+    ]).subscribe(
+      ([ config ]) => {
+        this.customConfig = config
 
-          this.updateForm()
-          // Force form validation
-          this.forceCheck()
-        },
+        const languages = this.serverService.getVideoLanguages()
+        this.languageItems = languages.map(l => ({ label: l.label, value: l.id }))
 
-        err => this.notifier.error(err.message)
-      )
+        const categories = this.serverService.getVideoCategories()
+        this.categoryItems = categories.map(l => ({ label: l.label, value: l.id }))
+
+        this.updateForm()
+        // Force form validation
+        this.forceCheck()
+      },
+
+      err => this.notifier.error(err.message)
+    )
   }
 
   isTranscodingEnabled () {
@@ -224,8 +251,23 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
       )
   }
 
+  getSelectedLanguageLabel () {
+    return this.i18n('{{\'{0} languages selected')
+  }
+
+  getDefaultLanguageLabel () {
+    return this.i18n('No language')
+  }
+
+  getSelectedCategoryLabel () {
+    return this.i18n('{{\'{0} categories selected')
+  }
+
+  getDefaultCategoryLabel () {
+    return this.i18n('No category')
+  }
+
   private updateForm () {
     this.form.patchValue(this.customConfig)
   }
-
 }
diff --git a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
index 2796dd2db..caa032149 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
+++ b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
@@ -23,7 +23,7 @@
 
     <div>
       <p-multiSelect
-        [options]="languageItems" formControlName="videoLanguages" showToggleAll="true"
+        inputId="videoLanguages" [options]="languageItems" formControlName="videoLanguages" showToggleAll="true"
         [defaultLabel]="getDefaultVideoLanguageLabel()" [selectedItemsLabel]="getSelectedVideoLanguageLabel()"
         emptyFilterMessage="No results found" i18n-emptyFilterMessage
       ></p-multiSelect>
diff --git a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts
index 77febf179..4fb828082 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts
+++ b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts
@@ -5,9 +5,9 @@ import { AuthService } from '../../../core'
 import { FormReactive, User, UserService } from '../../../shared'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
-import { Subject } from 'rxjs'
+import { forkJoin, Subject } from 'rxjs'
 import { SelectItem } from 'primeng/api'
-import { switchMap } from 'rxjs/operators'
+import { first } from 'rxjs/operators'
 
 @Component({
   selector: 'my-account-video-settings',
@@ -39,30 +39,31 @@ export class MyAccountVideoSettingsComponent extends FormReactive implements OnI
       videoLanguages: null
     })
 
-    this.serverService.videoLanguagesLoaded
-        .pipe(switchMap(() => this.userInformationLoaded))
-        .subscribe(() => {
-          const languages = this.serverService.getVideoLanguages()
+    forkJoin([
+      this.serverService.videoLanguagesLoaded.pipe(first()),
+      this.userInformationLoaded.pipe(first())
+    ]).subscribe(() => {
+      const languages = this.serverService.getVideoLanguages()
 
-          this.languageItems = [ { label: this.i18n('Unknown language'), value: '_unknown' } ]
-          this.languageItems = this.languageItems
-                                   .concat(languages.map(l => ({ label: l.label, value: l.id })))
+      this.languageItems = [ { label: this.i18n('Unknown language'), value: '_unknown' } ]
+      this.languageItems = this.languageItems
+                               .concat(languages.map(l => ({ label: l.label, value: l.id })))
 
-          const videoLanguages = this.user.videoLanguages
-            ? this.user.videoLanguages
-            : this.languageItems.map(l => l.value)
+      const videoLanguages = this.user.videoLanguages
+        ? this.user.videoLanguages
+        : this.languageItems.map(l => l.value)
 
-          this.form.patchValue({
-            nsfwPolicy: this.user.nsfwPolicy,
-            webTorrentEnabled: this.user.webTorrentEnabled,
-            autoPlayVideo: this.user.autoPlayVideo === true,
-            videoLanguages
-          })
-        })
+      this.form.patchValue({
+        nsfwPolicy: this.user.nsfwPolicy,
+        webTorrentEnabled: this.user.webTorrentEnabled,
+        autoPlayVideo: this.user.autoPlayVideo === true,
+        videoLanguages
+      })
+    })
   }
 
   updateDetails () {
-    const nsfwPolicy = this.form.value['nsfwPolicy']
+    const nsfwPolicy = this.form.value[ 'nsfwPolicy' ]
     const webTorrentEnabled = this.form.value['webTorrentEnabled']
     const autoPlayVideo = this.form.value['autoPlayVideo']
 
diff --git a/client/src/app/+my-account/my-account.module.ts b/client/src/app/+my-account/my-account.module.ts
index 571f46de9..6cf1499d3 100644
--- a/client/src/app/+my-account/my-account.module.ts
+++ b/client/src/app/+my-account/my-account.module.ts
@@ -37,7 +37,6 @@ import {
 } from '@app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component'
 import { DragDropModule } from '@angular/cdk/drag-drop'
 import { MyAccountChangeEmailComponent } from '@app/+my-account/my-account-settings/my-account-change-email'
-import { MultiSelectModule } from 'primeng/multiselect'
 import { MyAccountInterfaceSettingsComponent } from '@app/+my-account/my-account-settings/my-account-interface'
 
 @NgModule({
@@ -48,8 +47,7 @@ import { MyAccountInterfaceSettingsComponent } from '@app/+my-account/my-account
     SharedModule,
     TableModule,
     InputSwitchModule,
-    DragDropModule,
-    MultiSelectModule
+    DragDropModule
   ],
 
   declarations: [
diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts
index eb57a2fff..d71f6357b 100644
--- a/client/src/app/shared/shared.module.ts
+++ b/client/src/app/shared/shared.module.ts
@@ -6,10 +6,8 @@ import { RouterModule } from '@angular/router'
 import { MarkdownTextareaComponent } from '@app/shared/forms/markdown-textarea.component'
 import { HelpComponent } from '@app/shared/misc/help.component'
 import { InfiniteScrollerDirective } from '@app/shared/video/infinite-scroller.directive'
-
 import { BytesPipe, KeysPipe, NgPipesModule } from 'ngx-pipes'
 import { SharedModule as PrimeSharedModule } from 'primeng/components/common/shared'
-
 import { AUTH_INTERCEPTOR_PROVIDER } from './auth'
 import { ButtonComponent } from './buttons/button.component'
 import { DeleteButtonComponent } from './buttons/delete-button.component'
@@ -93,6 +91,7 @@ import { VideoDownloadComponent } from '@app/shared/video/modals/video-download.
 import { VideoReportComponent } from '@app/shared/video/modals/video-report.component'
 import { ClipboardModule } from 'ngx-clipboard'
 import { FollowService } from '@app/shared/instance/follow.service'
+import { MultiSelectModule } from 'primeng/multiselect'
 
 @NgModule({
   imports: [
@@ -113,7 +112,8 @@ import { FollowService } from '@app/shared/instance/follow.service'
 
     PrimeSharedModule,
     InputMaskModule,
-    NgPipesModule
+    NgPipesModule,
+    MultiSelectModule
   ],
 
   declarations: [
@@ -186,6 +186,7 @@ import { FollowService } from '@app/shared/instance/follow.service'
     InputMaskModule,
     BytesPipe,
     KeysPipe,
+    MultiSelectModule,
 
     LoaderComponent,
     SmallLoaderComponent,
diff --git a/config/default.yaml b/config/default.yaml
index 5a935fede..f84ecfcf9 100644
--- a/config/default.yaml
+++ b/config/default.yaml
@@ -238,7 +238,53 @@ instance:
   short_description: 'PeerTube, a federated (ActivityPub) video streaming platform using P2P (BitTorrent) directly in the web browser with WebTorrent and Angular.'
   description: 'Welcome to this PeerTube instance!' # Support markdown
   terms: 'No terms for now.' # Support markdown
+  code_of_conduct: '' # Supports markdown
+
+  # Who moderates the instance? What is the policy regarding NSFW videos? Political videos? etc
+  moderation_information: '' # Supports markdown
+
+  # Who is behind the instance? A single person? A non profit?
+  administrator: ''
+
+  # How long do you plan to maintain this instance?
+  maintenance_lifetime: ''
+
+  # How will you pay the PeerTube instance server? With you own funds? With users donations? Advertising?
+  business_model: ''
+
+  # What are the main languages of your instance? To interact with your users for example
+  # Uncomment or add the languages you want
+  # List of supported languages: https://peertube.cpy.re/api/v1/videos/languages
+  languages:
+#    - en
+#    - es
+#    - fr
+
+  # You can specify the main categories of your instance (dedicated to music, gaming or politics etc)
+  # Uncomment or add the category ids you want
+  # List of supported categories: https://peertube.cpy.re/api/v1/videos/categories
+  categories:
+#    - 1  # Music
+#    - 2  # Films
+#    - 3  # Vehicles
+#    - 4  # Art
+#    - 5  # Sports
+#    - 6  # Travels
+#    - 7  # Gaming
+#    - 8  # People
+#    - 9  # Comedy
+#    - 10 # Entertainment
+#    - 11 # News & Politics
+#    - 12 # How To
+#    - 13 # Education
+#    - 14 # Activism
+#    - 15 # Science & Technology
+#    - 16 # Animals
+#    - 17 # Kids
+#    - 18 # Food
+
   default_client_route: '/videos/trending'
+
   # Whether or not the instance is dedicated to NSFW content
   # Enabling it will allow other administrators to know that you are mainly federating sensitive content
   # Moreover, the NSFW checkbox on video upload will be automatically checked by default
@@ -246,6 +292,7 @@ instance:
   # By default, "do_not_list" or "blur" or "display" NSFW videos
   # Could be overridden per user with a setting
   default_nsfw_policy: 'do_not_list'
+
   customizations:
     javascript: '' # Directly your JavaScript code (without <script> tags). Will be eval at runtime
     css: '' # Directly your CSS code (without <style> tags). Will be injected at runtime
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts
index 0c52bfa7a..b5244756d 100644
--- a/server/controllers/api/config.ts
+++ b/server/controllers/api/config.ts
@@ -158,7 +158,16 @@ function getAbout (req: express.Request, res: express.Response) {
       name: CONFIG.INSTANCE.NAME,
       shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION,
       description: CONFIG.INSTANCE.DESCRIPTION,
-      terms: CONFIG.INSTANCE.TERMS
+      terms: CONFIG.INSTANCE.TERMS,
+      codeOfConduct: CONFIG.INSTANCE.CODE_OF_CONDUCT,
+
+      moderationInformation: CONFIG.INSTANCE.MODERATION_INFORMATION,
+      administrator: CONFIG.INSTANCE.ADMINISTRATOR,
+      maintenanceLifetime: CONFIG.INSTANCE.MAINTENANCE_LIFETIME,
+      businessModel: CONFIG.INSTANCE.BUSINESS_MODEL,
+
+      languages: CONFIG.INSTANCE.LANGUAGES,
+      categories: CONFIG.INSTANCE.CATEGORIES
     }
   }
 
@@ -221,6 +230,16 @@ function customConfig (): CustomConfig {
       shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION,
       description: CONFIG.INSTANCE.DESCRIPTION,
       terms: CONFIG.INSTANCE.TERMS,
+      codeOfConduct: CONFIG.INSTANCE.CODE_OF_CONDUCT,
+
+      moderationInformation: CONFIG.INSTANCE.MODERATION_INFORMATION,
+      administrator: CONFIG.INSTANCE.ADMINISTRATOR,
+      maintenanceLifetime: CONFIG.INSTANCE.MAINTENANCE_LIFETIME,
+      businessModel: CONFIG.INSTANCE.BUSINESS_MODEL,
+
+      languages: CONFIG.INSTANCE.LANGUAGES,
+      categories: CONFIG.INSTANCE.CATEGORIES,
+
       isNSFW: CONFIG.INSTANCE.IS_NSFW,
       defaultClientRoute: CONFIG.INSTANCE.DEFAULT_CLIENT_ROUTE,
       defaultNSFWPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY,
diff --git a/server/initializers/config.ts b/server/initializers/config.ts
index 599f3f5ac..4e2b07e64 100644
--- a/server/initializers/config.ts
+++ b/server/initializers/config.ts
@@ -209,6 +209,16 @@ const CONFIG = {
     get SHORT_DESCRIPTION () { return config.get<string>('instance.short_description') },
     get DESCRIPTION () { return config.get<string>('instance.description') },
     get TERMS () { return config.get<string>('instance.terms') },
+    get CODE_OF_CONDUCT () { return config.get<string>('instance.code_of_conduct') },
+
+    get MODERATION_INFORMATION () { return config.get<string>('instance.moderation_information') },
+    get ADMINISTRATOR () { return config.get<string>('instance.administrator') },
+    get MAINTENANCE_LIFETIME () { return config.get<string>('instance.maintenance_lifetime') },
+    get BUSINESS_MODEL () { return config.get<string>('instance.business_model') },
+
+    get LANGUAGES () { return config.get<string[]>('instance.languages') || [] },
+    get CATEGORIES () { return config.get<number[]>('instance.categories') || [] },
+
     get IS_NSFW () { return config.get<boolean>('instance.is_nsfw') },
     get DEFAULT_CLIENT_ROUTE () { return config.get<string>('instance.default_client_route') },
     get DEFAULT_NSFW_POLICY () { return config.get<NSFWPolicyType>('instance.default_nsfw_policy') },
diff --git a/server/tests/api/check-params/config.ts b/server/tests/api/check-params/config.ts
index 1221735c5..f716dc673 100644
--- a/server/tests/api/check-params/config.ts
+++ b/server/tests/api/check-params/config.ts
@@ -27,6 +27,16 @@ describe('Test config API validators', function () {
       shortDescription: 'my short description',
       description: 'my super description',
       terms: 'my super terms',
+      codeOfConduct: 'my super coc',
+
+      moderationInformation: 'my super moderation information',
+      administrator: 'Kuja',
+      maintenanceLifetime: 'forever',
+      businessModel: 'my super business model',
+
+      languages: [ 'en', 'es' ],
+      categories: [ 1, 2 ],
+
       isNSFW: true,
       defaultClientRoute: '/videos/recently-added',
       defaultNSFWPolicy: 'blur',
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts
index b2f1933d1..da75495a5 100644
--- a/server/tests/api/server/config.ts
+++ b/server/tests/api/server/config.ts
@@ -28,7 +28,17 @@ function checkInitialConfig (server: ServerInfo, data: CustomConfig) {
     'with WebTorrent and Angular.'
   )
   expect(data.instance.description).to.equal('Welcome to this PeerTube instance!')
+
   expect(data.instance.terms).to.equal('No terms for now.')
+  expect(data.instance.codeOfConduct).to.be.empty
+  expect(data.instance.moderationInformation).to.be.empty
+  expect(data.instance.administrator).to.be.empty
+  expect(data.instance.maintenanceLifetime).to.be.empty
+  expect(data.instance.businessModel).to.be.empty
+
+  expect(data.instance.languages).to.have.lengthOf(0)
+  expect(data.instance.categories).to.have.lengthOf(0)
+
   expect(data.instance.defaultClientRoute).to.equal('/videos/trending')
   expect(data.instance.isNSFW).to.be.false
   expect(data.instance.defaultNSFWPolicy).to.equal('display')
@@ -78,7 +88,17 @@ function checkUpdatedConfig (data: CustomConfig) {
   expect(data.instance.name).to.equal('PeerTube updated')
   expect(data.instance.shortDescription).to.equal('my short description')
   expect(data.instance.description).to.equal('my super description')
+
   expect(data.instance.terms).to.equal('my super terms')
+  expect(data.instance.codeOfConduct).to.equal('my super coc')
+  expect(data.instance.moderationInformation).to.equal('my super moderation information')
+  expect(data.instance.administrator).to.equal('Kuja')
+  expect(data.instance.maintenanceLifetime).to.equal('forever')
+  expect(data.instance.businessModel).to.equal('my super business model')
+
+  expect(data.instance.languages).to.deep.equal([ 'en', 'es' ])
+  expect(data.instance.categories).to.deep.equal([ 1, 2 ])
+
   expect(data.instance.defaultClientRoute).to.equal('/videos/recently-added')
   expect(data.instance.isNSFW).to.be.true
   expect(data.instance.defaultNSFWPolicy).to.equal('blur')
@@ -190,6 +210,16 @@ describe('Test config', function () {
         shortDescription: 'my short description',
         description: 'my super description',
         terms: 'my super terms',
+        codeOfConduct: 'my super coc',
+
+        moderationInformation: 'my super moderation information',
+        administrator: 'Kuja',
+        maintenanceLifetime: 'forever',
+        businessModel: 'my super business model',
+
+        languages: [ 'en', 'es' ],
+        categories: [ 1, 2 ],
+
         defaultClientRoute: '/videos/recently-added',
         isNSFW: true,
         defaultNSFWPolicy: 'blur' as 'blur',
diff --git a/shared/extra-utils/server/config.ts b/shared/extra-utils/server/config.ts
index d784af9a9..785421c98 100644
--- a/shared/extra-utils/server/config.ts
+++ b/shared/extra-utils/server/config.ts
@@ -53,6 +53,16 @@ function updateCustomSubConfig (url: string, token: string, newConfig: DeepParti
       shortDescription: 'my short description',
       description: 'my super description',
       terms: 'my super terms',
+      codeOfConduct: 'my super coc',
+
+      moderationInformation: 'my super moderation information',
+      administrator: 'Kuja',
+      maintenanceLifetime: 'forever',
+      businessModel: 'my super business model',
+
+      languages: [ 'en', 'es' ],
+      categories: [ 1, 2 ],
+
       defaultClientRoute: '/videos/recently-added',
       isNSFW: true,
       defaultNSFWPolicy: 'blur',
diff --git a/shared/models/server/about.model.ts b/shared/models/server/about.model.ts
index 10dff8b8f..e32ed26ee 100644
--- a/shared/models/server/about.model.ts
+++ b/shared/models/server/about.model.ts
@@ -4,5 +4,15 @@ export interface About {
     shortDescription: string
     description: string
     terms: string
+
+    codeOfConduct: string
+
+    moderationInformation: string
+    administrator: string
+    maintenanceLifetime: string
+    businessModel: string
+
+    languages: string[]
+    categories: number[]
   }
 }
diff --git a/shared/models/server/custom-config.model.ts b/shared/models/server/custom-config.model.ts
index 1073ba32c..0c331a820 100644
--- a/shared/models/server/custom-config.model.ts
+++ b/shared/models/server/custom-config.model.ts
@@ -6,6 +6,16 @@ export interface CustomConfig {
     shortDescription: string
     description: string
     terms: string
+    codeOfConduct: string
+
+    moderationInformation: string
+    administrator: string
+    maintenanceLifetime: string
+    businessModel: string
+
+    languages: string[]
+    categories: number[]
+
     isNSFW: boolean
     defaultClientRoute: string
     defaultNSFWPolicy: NSFWPolicyType