From 254d3579f5338f5fd775c17d15cdfc37078bcfb4 Mon Sep 17 00:00:00 2001
From: Chocobozzz <me@florianbigard.com>
Date: Fri, 16 Jul 2021 09:47:51 +0200
Subject: [PATCH] Use an object to represent a server

---
 scripts/benchmark.ts                          |   6 +-
 server/tests/api/activitypub/cleaner.ts       |   8 +-
 server/tests/api/activitypub/client.ts        |   8 +-
 server/tests/api/activitypub/fetch.ts         |   6 +-
 server/tests/api/activitypub/refresher.ts     |  11 +-
 server/tests/api/activitypub/security.ts      |  17 +-
 server/tests/api/check-params/abuses.ts       |  12 +-
 server/tests/api/check-params/accounts.ts     |   8 +-
 server/tests/api/check-params/blocklist.ts    |  10 +-
 server/tests/api/check-params/bulk.ts         |   8 +-
 server/tests/api/check-params/config.ts       |   8 +-
 server/tests/api/check-params/contact-form.ts |  10 +-
 server/tests/api/check-params/custom-pages.ts |   8 +-
 server/tests/api/check-params/debug.ts        |   8 +-
 server/tests/api/check-params/follows.ts      |   8 +-
 server/tests/api/check-params/jobs.ts         |   8 +-
 server/tests/api/check-params/live.ts         |   8 +-
 server/tests/api/check-params/logs.ts         |   8 +-
 server/tests/api/check-params/plugins.ts      |   8 +-
 server/tests/api/check-params/redundancy.ts   |   8 +-
 server/tests/api/check-params/search.ts       |  10 +-
 server/tests/api/check-params/services.ts     |  10 +-
 server/tests/api/check-params/upload-quota.ts |   8 +-
 .../api/check-params/user-notifications.ts    |   8 +-
 .../api/check-params/user-subscriptions.ts    |   8 +-
 server/tests/api/check-params/users.ts        |  15 +-
 .../tests/api/check-params/video-blacklist.ts |   8 +-
 .../tests/api/check-params/video-captions.ts  |   8 +-
 .../tests/api/check-params/video-channels.ts  |   8 +-
 .../tests/api/check-params/video-comments.ts  |   8 +-
 .../tests/api/check-params/video-imports.ts   |   8 +-
 .../tests/api/check-params/video-playlists.ts |   8 +-
 .../tests/api/check-params/videos-filter.ts   |  10 +-
 .../tests/api/check-params/videos-history.ts  |   8 +-
 .../api/check-params/videos-overviews.ts      |   6 +-
 server/tests/api/check-params/videos.ts       |   8 +-
 server/tests/api/live/live-constraints.ts     |   8 +-
 server/tests/api/live/live-permanent.ts       |   8 +-
 server/tests/api/live/live-save-replay.ts     |   8 +-
 server/tests/api/live/live-socket-messages.ts |   8 +-
 server/tests/api/live/live-views.ts           |   8 +-
 server/tests/api/live/live.ts                 |  11 +-
 server/tests/api/moderation/abuses.ts         |  12 +-
 .../api/moderation/blocklist-notification.ts  |   8 +-
 server/tests/api/moderation/blocklist.ts      |  16 +-
 .../tests/api/moderation/video-blacklist.ts   |  13 +-
 .../api/notifications/admin-notifications.ts  |   4 +-
 .../notifications/comments-notifications.ts   |   4 +-
 .../notifications/moderation-notifications.ts |   4 +-
 .../api/notifications/notifications-api.ts    |   4 +-
 .../api/notifications/user-notifications.ts   |   4 +-
 .../tests/api/redundancy/manage-redundancy.ts |   8 +-
 .../api/redundancy/redundancy-constraints.ts  |  19 +-
 server/tests/api/redundancy/redundancy.ts     |  33 +-
 .../search-activitypub-video-channels.ts      |   8 +-
 .../search-activitypub-video-playlists.ts     |   8 +-
 .../api/search/search-activitypub-videos.ts   |   8 +-
 server/tests/api/search/search-channels.ts    |   6 +-
 server/tests/api/search/search-index.ts       |   6 +-
 server/tests/api/search/search-playlists.ts   |   8 +-
 server/tests/api/search/search-videos.ts      |   8 +-
 server/tests/api/server/auto-follows.ts       |  14 +-
 server/tests/api/server/bulk.ts               |   8 +-
 server/tests/api/server/config.ts             |  15 +-
 server/tests/api/server/contact-form.ts       |  16 +-
 server/tests/api/server/email.ts              |   6 +-
 server/tests/api/server/follow-constraints.ts |   6 +-
 server/tests/api/server/follows-moderation.ts |  12 +-
 server/tests/api/server/follows.ts            |   8 +-
 server/tests/api/server/handle-down.ts        |  13 +-
 server/tests/api/server/homepage.ts           |  13 +-
 server/tests/api/server/jobs.ts               |   8 +-
 server/tests/api/server/logs.ts               |  11 +-
 server/tests/api/server/no-client.ts          |   8 +-
 server/tests/api/server/plugins.ts            |  13 +-
 server/tests/api/server/reverse-proxy.ts      |   6 +-
 server/tests/api/server/services.ts           |   6 +-
 server/tests/api/server/stats.ts              |   8 +-
 server/tests/api/server/tracker.ts            |  10 +-
 server/tests/api/users/user-subscriptions.ts  |   8 +-
 .../tests/api/users/users-multiple-servers.ts |   8 +-
 server/tests/api/users/users-verification.ts  |   6 +-
 server/tests/api/users/users.ts               |  13 +-
 server/tests/api/videos/audio-only.ts         |   6 +-
 server/tests/api/videos/multiple-servers.ts   |   8 +-
 server/tests/api/videos/resumable-upload.ts   |   8 +-
 server/tests/api/videos/single-server.ts      |   8 +-
 server/tests/api/videos/video-captions.ts     |   8 +-
 .../api/videos/video-change-ownership.ts      |  14 +-
 server/tests/api/videos/video-channels.ts     |  10 +-
 server/tests/api/videos/video-comments.ts     |   8 +-
 server/tests/api/videos/video-description.ts  |   6 +-
 server/tests/api/videos/video-hls.ts          |  10 +-
 server/tests/api/videos/video-imports.ts      |  12 +-
 server/tests/api/videos/video-nsfw.ts         |   6 +-
 .../api/videos/video-playlist-thumbnails.ts   |  12 +-
 server/tests/api/videos/video-playlists.ts    |  18 +-
 server/tests/api/videos/video-privacy.ts      |   8 +-
 .../tests/api/videos/video-schedule-update.ts |   8 +-
 server/tests/api/videos/video-transcoder.ts   |  10 +-
 server/tests/api/videos/videos-filter.ts      |  10 +-
 server/tests/api/videos/videos-history.ts     |  13 +-
 server/tests/api/videos/videos-overview.ts    |   6 +-
 .../tests/api/videos/videos-views-cleaner.ts  |  13 +-
 .../tests/cli/create-import-video-file-job.ts |   6 +-
 server/tests/cli/create-transcoding-job.ts    |   8 +-
 server/tests/cli/optimize-old-videos.ts       |   8 +-
 server/tests/cli/peertube.ts                  |  14 +-
 server/tests/cli/plugins.ts                   |  13 +-
 server/tests/cli/prune-storage.ts             |  14 +-
 server/tests/cli/regenerate-thumbnails.ts     |  10 +-
 server/tests/cli/reset-password.ts            |   6 +-
 server/tests/cli/update-host.ts               |  11 +-
 server/tests/client.ts                        |   8 +-
 server/tests/external-plugins/auth-ldap.ts    |   6 +-
 .../external-plugins/auto-block-videos.ts     |  13 +-
 server/tests/external-plugins/auto-mute.ts    |  11 +-
 server/tests/feeds/feeds.ts                   |  14 +-
 server/tests/misc-endpoints.ts                |   6 +-
 server/tests/plugins/action-hooks.ts          |  11 +-
 server/tests/plugins/external-auth.ts         |  10 +-
 server/tests/plugins/filter-hooks.ts          |   8 +-
 server/tests/plugins/html-injection.ts        |   8 +-
 server/tests/plugins/id-and-pass-auth.ts      |   6 +-
 server/tests/plugins/plugin-helpers.ts        |  10 +-
 server/tests/plugins/plugin-router.ts         |   8 +-
 server/tests/plugins/plugin-storage.ts        |  13 +-
 server/tests/plugins/plugin-transcoding.ts    |  12 +-
 server/tests/plugins/plugin-unloading.ts      |  13 +-
 server/tests/plugins/translations.ts          |   7 +-
 server/tests/plugins/video-constants.ts       |   6 +-
 server/tools/cli.ts                           |  15 +-
 server/tools/peertube-import-videos.ts        |   4 +-
 server/tools/test-live.ts                     |   8 +-
 shared/extra-utils/miscs/checks.ts            |   4 +-
 shared/extra-utils/miscs/webtorrent.ts        |   4 +-
 shared/extra-utils/server/directories.ts      |   6 +-
 shared/extra-utils/server/follows-command.ts  |   6 +-
 shared/extra-utils/server/follows.ts          |   4 +-
 shared/extra-utils/server/index.ts            |   1 +
 shared/extra-utils/server/jobs.ts             |  10 +-
 shared/extra-utils/server/plugins.ts          |   4 +-
 shared/extra-utils/server/server.ts           | 376 ++++++++++++++++
 shared/extra-utils/server/servers-command.ts  |   2 +-
 shared/extra-utils/server/servers.ts          | 404 +-----------------
 shared/extra-utils/shared/abstract-command.ts |   4 +-
 shared/extra-utils/users/accounts.ts          |   4 +-
 shared/extra-utils/users/login.ts             |   4 +-
 shared/extra-utils/users/notifications.ts     |   7 +-
 shared/extra-utils/videos/channels.ts         |   4 +-
 shared/extra-utils/videos/live.ts             |   6 +-
 .../extra-utils/videos/streaming-playlists.ts |   8 +-
 shared/extra-utils/videos/videos-command.ts   |   4 +-
 shared/extra-utils/videos/videos.ts           |  10 +-
 154 files changed, 1068 insertions(+), 1056 deletions(-)
 create mode 100644 shared/extra-utils/server/server.ts

diff --git a/scripts/benchmark.ts b/scripts/benchmark.ts
index 1d980063b..071c4dea7 100644
--- a/scripts/benchmark.ts
+++ b/scripts/benchmark.ts
@@ -1,12 +1,12 @@
 import * as autocannon from 'autocannon'
 import { writeJson } from 'fs-extra'
-import { flushAndRunServer, killallServers, ServerInfo, setAccessTokensToServers } from '@shared/extra-utils'
+import { createSingleServer, killallServers, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
 import { Video, VideoPrivacy } from '@shared/models'
 import { registerTSPaths } from '../server/helpers/register-ts-paths'
 
 registerTSPaths()
 
-let server: ServerInfo
+let server: PeerTubeServer
 let video: Video
 let threadId: number
 
@@ -188,7 +188,7 @@ function runBenchmark (options: {
 }
 
 async function prepare () {
-  server = await flushAndRunServer(1, {
+  server = await createSingleServer(1, {
     rates_limit: {
       api: {
         max: 5_000_000
diff --git a/server/tests/api/activitypub/cleaner.ts b/server/tests/api/activitypub/cleaner.ts
index 1421824da..a5ce449f3 100644
--- a/server/tests/api/activitypub/cleaner.ts
+++ b/server/tests/api/activitypub/cleaner.ts
@@ -5,8 +5,8 @@ import * as chai from 'chai'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   wait,
   waitJobs
@@ -15,7 +15,7 @@ import {
 const expect = chai.expect
 
 describe('Test AP cleaner', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let videoUUID1: string
   let videoUUID2: string
   let videoUUID3: string
@@ -30,7 +30,7 @@ describe('Test AP cleaner', function () {
         videos: { cleanup_remote_interactions: true }
       }
     }
-    servers = await flushAndRunMultipleServers(3, config)
+    servers = await createMultipleServers(3, config)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/activitypub/client.ts b/server/tests/api/activitypub/client.ts
index 5845045a3..720231f02 100644
--- a/server/tests/api/activitypub/client.ts
+++ b/server/tests/api/activitypub/client.ts
@@ -6,9 +6,9 @@ import { HttpStatusCode } from '@shared/core-utils'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   makeActivityPubGetRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel
 } from '@shared/extra-utils'
@@ -17,7 +17,7 @@ import { VideoPlaylistPrivacy } from '@shared/models'
 const expect = chai.expect
 
 describe('Test activitypub', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let video: { id: number, uuid: string, shortUUID: string }
   let playlist: { id: number, uuid: string, shortUUID: string }
 
@@ -62,7 +62,7 @@ describe('Test activitypub', function () {
   before(async function () {
     this.timeout(30000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     await setAccessTokensToServers(servers)
     await setDefaultVideoChannel(servers)
diff --git a/server/tests/api/activitypub/fetch.ts b/server/tests/api/activitypub/fetch.ts
index 34694a773..ddfe6cfe0 100644
--- a/server/tests/api/activitypub/fetch.ts
+++ b/server/tests/api/activitypub/fetch.ts
@@ -2,19 +2,19 @@
 
 import 'mocha'
 import * as chai from 'chai'
-import { cleanupTests, doubleFollow, flushAndRunMultipleServers, ServerInfo, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
+import { cleanupTests, doubleFollow, createMultipleServers, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
 
 const expect = chai.expect
 
 describe('Test ActivityPub fetcher', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
 
   // ---------------------------------------------------------------
 
   before(async function () {
     this.timeout(60000)
 
-    servers = await flushAndRunMultipleServers(3)
+    servers = await createMultipleServers(3)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/activitypub/refresher.ts b/server/tests/api/activitypub/refresher.ts
index d2f71e857..bbec0d309 100644
--- a/server/tests/api/activitypub/refresher.ts
+++ b/server/tests/api/activitypub/refresher.ts
@@ -5,10 +5,9 @@ import { HttpStatusCode } from '@shared/core-utils'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   killallServers,
-  reRunServer,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   wait,
@@ -17,7 +16,7 @@ import {
 import { VideoPlaylistPrivacy } from '@shared/models'
 
 describe('Test AP refresher', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let videoUUID1: string
   let videoUUID2: string
   let videoUUID3: string
@@ -27,7 +26,7 @@ describe('Test AP refresher', function () {
   before(async function () {
     this.timeout(60000)
 
-    servers = await flushAndRunMultipleServers(2, { transcoding: { enabled: false } })
+    servers = await createMultipleServers(2, { transcoding: { enabled: false } })
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
@@ -95,7 +94,7 @@ describe('Test AP refresher', function () {
       // The refresh should fail
       await waitJobs([ servers[0] ])
 
-      await reRunServer(servers[1])
+      await servers[1].run()
 
       await servers[0].videos.get({ id: videoUUID3 })
     })
diff --git a/server/tests/api/activitypub/security.ts b/server/tests/api/activitypub/security.ts
index ab0eb256e..c173648b3 100644
--- a/server/tests/api/activitypub/security.ts
+++ b/server/tests/api/activitypub/security.ts
@@ -7,10 +7,9 @@ import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-c
 import {
   buildAbsoluteFixturePath,
   cleanupTests,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   killallServers,
-  reRunServer,
-  ServerInfo,
+  PeerTubeServer,
   wait
 } from '../../../../shared/extra-utils'
 import { makeFollowRequest, makePOSTAPRequest } from '../../../../shared/extra-utils/requests/activitypub'
@@ -20,7 +19,7 @@ import { buildGlobalHeaders } from '../../../lib/job-queue/handlers/utils/activi
 
 const expect = chai.expect
 
-function setKeysOfServer (onServer: ServerInfo, ofServer: ServerInfo, publicKey: string, privateKey: string) {
+function setKeysOfServer (onServer: PeerTubeServer, ofServer: PeerTubeServer, publicKey: string, privateKey: string) {
   const url = 'http://localhost:' + ofServer.port + '/accounts/peertube'
 
   return Promise.all([
@@ -29,7 +28,7 @@ function setKeysOfServer (onServer: ServerInfo, ofServer: ServerInfo, publicKey:
   ])
 }
 
-function setUpdatedAtOfServer (onServer: ServerInfo, ofServer: ServerInfo, updatedAt: string) {
+function setUpdatedAtOfServer (onServer: PeerTubeServer, ofServer: PeerTubeServer, updatedAt: string) {
   const url = 'http://localhost:' + ofServer.port + '/accounts/peertube'
 
   return Promise.all([
@@ -38,7 +37,7 @@ function setUpdatedAtOfServer (onServer: ServerInfo, ofServer: ServerInfo, updat
   ])
 }
 
-function getAnnounceWithoutContext (server: ServerInfo) {
+function getAnnounceWithoutContext (server: PeerTubeServer) {
   const json = require(buildAbsoluteFixturePath('./ap-json/peertube/announce-without-context.json'))
   const result: typeof json = {}
 
@@ -54,7 +53,7 @@ function getAnnounceWithoutContext (server: ServerInfo) {
 }
 
 describe('Test ActivityPub security', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
   let url: string
 
   const keys = require(buildAbsoluteFixturePath('./ap-json/peertube/keys.json'))
@@ -72,7 +71,7 @@ describe('Test ActivityPub security', function () {
   before(async function () {
     this.timeout(60000)
 
-    servers = await flushAndRunMultipleServers(3)
+    servers = await createMultipleServers(3)
 
     url = servers[0].url + '/inbox'
 
@@ -172,7 +171,7 @@ describe('Test ActivityPub security', function () {
 
       // Invalid peertube actor cache
       await killallServers([ servers[1] ])
-      await reRunServer(servers[1])
+      await servers[1].run()
 
       const body = activityPubContextify(getAnnounceWithoutContext(servers[1]))
       const headers = buildGlobalHeaders(body)
diff --git a/server/tests/api/check-params/abuses.ts b/server/tests/api/check-params/abuses.ts
index 7a6790ba8..62811f932 100644
--- a/server/tests/api/check-params/abuses.ts
+++ b/server/tests/api/check-params/abuses.ts
@@ -9,10 +9,10 @@ import {
   checkBadStartPagination,
   cleanupTests,
   doubleFollow,
-  flushAndRunServer,
+  createSingleServer,
   makeGetRequest,
   makePostBodyRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs
 } from '@shared/extra-utils'
@@ -21,7 +21,7 @@ import { AbuseCreate, AbuseState } from '@shared/models'
 describe('Test abuses API validators', function () {
   const basePath = '/api/v1/abuses/'
 
-  let server: ServerInfo
+  let server: PeerTubeServer
 
   let userToken = ''
   let userToken2 = ''
@@ -35,7 +35,7 @@ describe('Test abuses API validators', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
@@ -404,12 +404,12 @@ describe('Test abuses API validators', function () {
 
   describe('When trying to manage messages of a remote abuse', function () {
     let remoteAbuseId: number
-    let anotherServer: ServerInfo
+    let anotherServer: PeerTubeServer
 
     before(async function () {
       this.timeout(50000)
 
-      anotherServer = await flushAndRunServer(2)
+      anotherServer = await createSingleServer(2)
       await setAccessTokensToServers([ anotherServer ])
 
       await doubleFollow(anotherServer, server)
diff --git a/server/tests/api/check-params/accounts.ts b/server/tests/api/check-params/accounts.ts
index 223322626..e866593db 100644
--- a/server/tests/api/check-params/accounts.ts
+++ b/server/tests/api/check-params/accounts.ts
@@ -7,20 +7,20 @@ import {
   checkBadSortPagination,
   checkBadStartPagination,
   cleanupTests,
-  flushAndRunServer,
-  ServerInfo
+  createSingleServer,
+  PeerTubeServer
 } from '@shared/extra-utils'
 
 describe('Test accounts API validators', function () {
   const path = '/api/v1/accounts/'
-  let server: ServerInfo
+  let server: PeerTubeServer
 
   // ---------------------------------------------------------------
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
   })
 
   describe('When listing accounts', function () {
diff --git a/server/tests/api/check-params/blocklist.ts b/server/tests/api/check-params/blocklist.ts
index 14e45e503..b2a1cc4e2 100644
--- a/server/tests/api/check-params/blocklist.ts
+++ b/server/tests/api/check-params/blocklist.ts
@@ -5,11 +5,11 @@ import 'mocha'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   makeDeleteRequest,
   makeGetRequest,
   makePostBodyRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '../../../../shared/extra-utils'
 import {
@@ -20,14 +20,14 @@ import {
 import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 describe('Test blocklist API validators', function () {
-  let servers: ServerInfo[]
-  let server: ServerInfo
+  let servers: PeerTubeServer[]
+  let server: PeerTubeServer
   let userAccessToken: string
 
   before(async function () {
     this.timeout(60000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
     await setAccessTokensToServers(servers)
 
     server = servers[0]
diff --git a/server/tests/api/check-params/bulk.ts b/server/tests/api/check-params/bulk.ts
index 69ff7dd96..a660c3d80 100644
--- a/server/tests/api/check-params/bulk.ts
+++ b/server/tests/api/check-params/bulk.ts
@@ -3,15 +3,15 @@
 import 'mocha'
 import {
   cleanupTests,
-  flushAndRunServer,
-  ServerInfo,
+  createSingleServer,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '../../../../shared/extra-utils'
 import { makePostBodyRequest } from '../../../../shared/extra-utils/requests/requests'
 import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 describe('Test bulk API validators', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userAccessToken: string
 
   // ---------------------------------------------------------------
@@ -19,7 +19,7 @@ describe('Test bulk API validators', function () {
   before(async function () {
     this.timeout(120000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
 
     const user = { username: 'user1', password: 'password' }
diff --git a/server/tests/api/check-params/config.ts b/server/tests/api/check-params/config.ts
index 6fd26864e..1756d58ee 100644
--- a/server/tests/api/check-params/config.ts
+++ b/server/tests/api/check-params/config.ts
@@ -5,18 +5,18 @@ import { omit } from 'lodash'
 import { HttpStatusCode } from '@shared/core-utils'
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   makeDeleteRequest,
   makeGetRequest,
   makePutBodyRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '@shared/extra-utils'
 import { CustomConfig } from '@shared/models'
 
 describe('Test config API validators', function () {
   const path = '/api/v1/config/custom'
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userAccessToken: string
   const updateParams: CustomConfig = {
     instance: {
@@ -197,7 +197,7 @@ describe('Test config API validators', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
diff --git a/server/tests/api/check-params/contact-form.ts b/server/tests/api/check-params/contact-form.ts
index d2541777f..8c2b2a84b 100644
--- a/server/tests/api/check-params/contact-form.ts
+++ b/server/tests/api/check-params/contact-form.ts
@@ -2,11 +2,11 @@
 
 import 'mocha'
 import { HttpStatusCode } from '@shared/core-utils'
-import { cleanupTests, flushAndRunServer, killallServers, MockSmtpServer, reRunServer, ServerInfo } from '@shared/extra-utils'
+import { cleanupTests, createSingleServer, killallServers, MockSmtpServer, PeerTubeServer } from '@shared/extra-utils'
 import { ContactFormCommand } from '@shared/extra-utils/server'
 
 describe('Test contact form API validators', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   const emails: object[] = []
   const defaultBody = {
     fromName: 'super name',
@@ -25,7 +25,7 @@ describe('Test contact form API validators', function () {
     emailPort = await MockSmtpServer.Instance.collectEmails(emails)
 
     // Email is disabled
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     command = server.contactForm
   })
 
@@ -39,7 +39,7 @@ describe('Test contact form API validators', function () {
     await killallServers([ server ])
 
     // Contact form is disabled
-    await reRunServer(server, { smtp: { hostname: 'localhost', port: emailPort }, contact_form: { enabled: false } })
+    await server.run({ smtp: { hostname: 'localhost', port: emailPort }, contact_form: { enabled: false } })
     await command.send({ ...defaultBody, expectedStatus: HttpStatusCode.CONFLICT_409 })
   })
 
@@ -49,7 +49,7 @@ describe('Test contact form API validators', function () {
     await killallServers([ server ])
 
     // Email & contact form enabled
-    await reRunServer(server, { smtp: { hostname: 'localhost', port: emailPort } })
+    await server.run({ smtp: { hostname: 'localhost', port: emailPort } })
 
     await command.send({ ...defaultBody, fromEmail: 'badEmail', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
     await command.send({ ...defaultBody, fromEmail: 'badEmail@', expectedStatus: HttpStatusCode.BAD_REQUEST_400 })
diff --git a/server/tests/api/check-params/custom-pages.ts b/server/tests/api/check-params/custom-pages.ts
index 3d84fb3e6..043505e32 100644
--- a/server/tests/api/check-params/custom-pages.ts
+++ b/server/tests/api/check-params/custom-pages.ts
@@ -4,8 +4,8 @@ import 'mocha'
 import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 import {
   cleanupTests,
-  flushAndRunServer,
-  ServerInfo,
+  createSingleServer,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '../../../../shared/extra-utils'
 import { makeGetRequest, makePutBodyRequest } from '../../../../shared/extra-utils/requests/requests'
@@ -13,7 +13,7 @@ import { makeGetRequest, makePutBodyRequest } from '../../../../shared/extra-uti
 describe('Test custom pages validators', function () {
   const path = '/api/v1/custom-pages/homepage/instance'
 
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userAccessToken: string
 
   // ---------------------------------------------------------------
@@ -21,7 +21,7 @@ describe('Test custom pages validators', function () {
   before(async function () {
     this.timeout(120000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
 
     const user = { username: 'user1', password: 'password' }
diff --git a/server/tests/api/check-params/debug.ts b/server/tests/api/check-params/debug.ts
index 609f9566e..9c13e9daf 100644
--- a/server/tests/api/check-params/debug.ts
+++ b/server/tests/api/check-params/debug.ts
@@ -4,8 +4,8 @@ import 'mocha'
 
 import {
   cleanupTests,
-  flushAndRunServer,
-  ServerInfo,
+  createSingleServer,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '../../../../shared/extra-utils'
 import { makeGetRequest } from '../../../../shared/extra-utils/requests/requests'
@@ -13,7 +13,7 @@ import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-c
 
 describe('Test debug API validators', function () {
   const path = '/api/v1/server/debug'
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userAccessToken = ''
 
   // ---------------------------------------------------------------
@@ -21,7 +21,7 @@ describe('Test debug API validators', function () {
   before(async function () {
     this.timeout(120000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
diff --git a/server/tests/api/check-params/follows.ts b/server/tests/api/check-params/follows.ts
index fae3712ce..0fd2b4925 100644
--- a/server/tests/api/check-params/follows.ts
+++ b/server/tests/api/check-params/follows.ts
@@ -4,10 +4,10 @@ import 'mocha'
 
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   makeDeleteRequest, makeGetRequest,
   makePostBodyRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '../../../../shared/extra-utils'
 import {
@@ -18,14 +18,14 @@ import {
 import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 describe('Test server follows API validators', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
 
   // ---------------------------------------------------------------
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
   })
diff --git a/server/tests/api/check-params/jobs.ts b/server/tests/api/check-params/jobs.ts
index 3786e8612..a370ec2d3 100644
--- a/server/tests/api/check-params/jobs.ts
+++ b/server/tests/api/check-params/jobs.ts
@@ -4,8 +4,8 @@ import 'mocha'
 
 import {
   cleanupTests,
-  flushAndRunServer,
-  ServerInfo,
+  createSingleServer,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '../../../../shared/extra-utils'
 import {
@@ -18,7 +18,7 @@ import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-c
 
 describe('Test jobs API validators', function () {
   const path = '/api/v1/jobs/failed'
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userAccessToken = ''
 
   // ---------------------------------------------------------------
@@ -26,7 +26,7 @@ describe('Test jobs API validators', function () {
   before(async function () {
     this.timeout(120000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
diff --git a/server/tests/api/check-params/live.ts b/server/tests/api/check-params/live.ts
index 20f27dd1d..eb5cdd1d8 100644
--- a/server/tests/api/check-params/live.ts
+++ b/server/tests/api/check-params/live.ts
@@ -6,12 +6,12 @@ import { HttpStatusCode } from '@shared/core-utils'
 import {
   buildAbsoluteFixturePath,
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   LiveCommand,
   makePostBodyRequest,
   makeUploadRequest,
   sendRTMPStream,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   stopFfmpeg
 } from '@shared/extra-utils'
@@ -19,7 +19,7 @@ import { VideoCreateResult, VideoPrivacy } from '@shared/models'
 
 describe('Test video lives API validator', function () {
   const path = '/api/v1/videos/live'
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userAccessToken = ''
   let channelId: number
   let video: VideoCreateResult
@@ -31,7 +31,7 @@ describe('Test video lives API validator', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
diff --git a/server/tests/api/check-params/logs.ts b/server/tests/api/check-params/logs.ts
index cf8f77959..2eb074007 100644
--- a/server/tests/api/check-params/logs.ts
+++ b/server/tests/api/check-params/logs.ts
@@ -4,8 +4,8 @@ import 'mocha'
 
 import {
   cleanupTests,
-  flushAndRunServer,
-  ServerInfo,
+  createSingleServer,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '../../../../shared/extra-utils'
 import { makeGetRequest } from '../../../../shared/extra-utils/requests/requests'
@@ -13,7 +13,7 @@ import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-c
 
 describe('Test logs API validators', function () {
   const path = '/api/v1/server/logs'
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userAccessToken = ''
 
   // ---------------------------------------------------------------
@@ -21,7 +21,7 @@ describe('Test logs API validators', function () {
   before(async function () {
     this.timeout(120000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
diff --git a/server/tests/api/check-params/plugins.ts b/server/tests/api/check-params/plugins.ts
index d4b72c0f4..2b471ee7d 100644
--- a/server/tests/api/check-params/plugins.ts
+++ b/server/tests/api/check-params/plugins.ts
@@ -7,17 +7,17 @@ import {
   checkBadSortPagination,
   checkBadStartPagination,
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   makeGetRequest,
   makePostBodyRequest,
   makePutBodyRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '@shared/extra-utils'
 import { PeerTubePlugin, PluginType } from '@shared/models'
 
 describe('Test server plugins API validators', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userAccessToken = null
 
   const npmPlugin = 'peertube-plugin-hello-world'
@@ -33,7 +33,7 @@ describe('Test server plugins API validators', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
diff --git a/server/tests/api/check-params/redundancy.ts b/server/tests/api/check-params/redundancy.ts
index fca92fde4..18b98a0f9 100644
--- a/server/tests/api/check-params/redundancy.ts
+++ b/server/tests/api/check-params/redundancy.ts
@@ -9,18 +9,18 @@ import {
   checkBadStartPagination,
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   makeDeleteRequest,
   makeGetRequest,
   makePostBodyRequest,
   makePutBodyRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs
 } from '../../../../shared/extra-utils'
 
 describe('Test server redundancy API validators', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
   let userAccessToken = null
   let videoIdLocal: number
   let videoRemote: VideoCreateResult
@@ -30,7 +30,7 @@ describe('Test server redundancy API validators', function () {
   before(async function () {
     this.timeout(80000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     await setAccessTokensToServers(servers)
     await doubleFollow(servers[0], servers[1])
diff --git a/server/tests/api/check-params/search.ts b/server/tests/api/check-params/search.ts
index 1acfa0922..43cd81af9 100644
--- a/server/tests/api/check-params/search.ts
+++ b/server/tests/api/check-params/search.ts
@@ -7,13 +7,13 @@ import {
   checkBadSortPagination,
   checkBadStartPagination,
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   makeGetRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '@shared/extra-utils'
 
-function updateSearchIndex (server: ServerInfo, enabled: boolean, disableLocalSearch = false) {
+function updateSearchIndex (server: PeerTubeServer, enabled: boolean, disableLocalSearch = false) {
   return server.config.updateCustomSubConfig({
     newConfig: {
       search: {
@@ -27,14 +27,14 @@ function updateSearchIndex (server: ServerInfo, enabled: boolean, disableLocalSe
 }
 
 describe('Test videos API validator', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
 
   // ---------------------------------------------------------------
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
   })
 
diff --git a/server/tests/api/check-params/services.ts b/server/tests/api/check-params/services.ts
index 83435c24a..c623240b7 100644
--- a/server/tests/api/check-params/services.ts
+++ b/server/tests/api/check-params/services.ts
@@ -4,16 +4,16 @@ import 'mocha'
 import { HttpStatusCode } from '@shared/core-utils'
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   makeGetRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel
 } from '@shared/extra-utils'
 import { VideoPlaylistPrivacy } from '@shared/models'
 
 describe('Test services API validators', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let playlistUUID: string
 
   // ---------------------------------------------------------------
@@ -21,7 +21,7 @@ describe('Test services API validators', function () {
   before(async function () {
     this.timeout(60000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
     await setDefaultVideoChannel([ server ])
 
@@ -120,7 +120,7 @@ describe('Test services API validators', function () {
   })
 })
 
-function checkParamEmbed (server: ServerInfo, embedUrl: string, statusCodeExpected = HttpStatusCode.BAD_REQUEST_400, query = {}) {
+function checkParamEmbed (server: PeerTubeServer, embedUrl: string, statusCodeExpected = HttpStatusCode.BAD_REQUEST_400, query = {}) {
   const path = '/services/oembed'
 
   return makeGetRequest({
diff --git a/server/tests/api/check-params/upload-quota.ts b/server/tests/api/check-params/upload-quota.ts
index 4ca544790..2c73e6a19 100644
--- a/server/tests/api/check-params/upload-quota.ts
+++ b/server/tests/api/check-params/upload-quota.ts
@@ -5,9 +5,9 @@ import { expect } from 'chai'
 import { HttpStatusCode, randomInt } from '@shared/core-utils'
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   ImportsCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   VideosCommand,
@@ -16,7 +16,7 @@ import {
 import { VideoImportState, VideoPrivacy } from '@shared/models'
 
 describe('Test upload quota', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let rootId: number
   let command: VideosCommand
 
@@ -25,7 +25,7 @@ describe('Test upload quota', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
     await setDefaultVideoChannel([ server ])
 
diff --git a/server/tests/api/check-params/user-notifications.ts b/server/tests/api/check-params/user-notifications.ts
index 913eca366..038c444b3 100644
--- a/server/tests/api/check-params/user-notifications.ts
+++ b/server/tests/api/check-params/user-notifications.ts
@@ -8,25 +8,25 @@ import {
   checkBadSortPagination,
   checkBadStartPagination,
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   makeGetRequest,
   makePostBodyRequest,
   makePutBodyRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   wait
 } from '@shared/extra-utils'
 import { UserNotificationSetting, UserNotificationSettingValue } from '@shared/models'
 
 describe('Test user notifications API validators', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
 
   // ---------------------------------------------------------------
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
   })
diff --git a/server/tests/api/check-params/user-subscriptions.ts b/server/tests/api/check-params/user-subscriptions.ts
index 885ad68e4..22cf130c2 100644
--- a/server/tests/api/check-params/user-subscriptions.ts
+++ b/server/tests/api/check-params/user-subscriptions.ts
@@ -4,11 +4,11 @@ import 'mocha'
 
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   makeDeleteRequest,
   makeGetRequest,
   makePostBodyRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '../../../../shared/extra-utils'
 
@@ -22,7 +22,7 @@ import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-c
 
 describe('Test user subscriptions API validators', function () {
   const path = '/api/v1/users/me/subscriptions'
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userAccessToken = ''
 
   // ---------------------------------------------------------------
@@ -30,7 +30,7 @@ describe('Test user subscriptions API validators', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
diff --git a/server/tests/api/check-params/users.ts b/server/tests/api/check-params/users.ts
index bce3f0774..c2c98f429 100644
--- a/server/tests/api/check-params/users.ts
+++ b/server/tests/api/check-params/users.ts
@@ -9,15 +9,14 @@ import {
   checkBadSortPagination,
   checkBadStartPagination,
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   killallServers,
   makeGetRequest,
   makePostBodyRequest,
   makePutBodyRequest,
   makeUploadRequest,
   MockSmtpServer,
-  reRunServer,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   UsersCommand
 } from '@shared/extra-utils'
@@ -29,8 +28,8 @@ describe('Test users API validators', function () {
   let rootId: number
   let moderatorId: number
   let video: VideoCreateResult
-  let server: ServerInfo
-  let serverWithRegistrationDisabled: ServerInfo
+  let server: PeerTubeServer
+  let serverWithRegistrationDisabled: PeerTubeServer
   let userToken = ''
   let moderatorToken = ''
   let emailPort: number
@@ -48,8 +47,8 @@ describe('Test users API validators', function () {
 
     {
       const res = await Promise.all([
-        flushAndRunServer(1, overrideConfig),
-        flushAndRunServer(2)
+        createSingleServer(1, overrideConfig),
+        createSingleServer(2)
       ])
 
       server = res[0]
@@ -196,7 +195,7 @@ describe('Test users API validators', function () {
           port: emailPort
         }
       }
-      await reRunServer(server, config)
+      await server.run(config)
 
       const fields = {
         ...baseCorrectParams,
diff --git a/server/tests/api/check-params/video-blacklist.ts b/server/tests/api/check-params/video-blacklist.ts
index 51609b982..b5d0e0778 100644
--- a/server/tests/api/check-params/video-blacklist.ts
+++ b/server/tests/api/check-params/video-blacklist.ts
@@ -10,17 +10,17 @@ import {
   checkBadStartPagination,
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   makePostBodyRequest,
   makePutBodyRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs
 } from '@shared/extra-utils'
 import { VideoBlacklistType } from '@shared/models'
 
 describe('Test video blacklist API validators', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
   let notBlacklistedVideoId: string
   let remoteVideoUUID: string
   let userAccessToken1 = ''
@@ -32,7 +32,7 @@ describe('Test video blacklist API validators', function () {
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     await setAccessTokensToServers(servers)
     await doubleFollow(servers[0], servers[1])
diff --git a/server/tests/api/check-params/video-captions.ts b/server/tests/api/check-params/video-captions.ts
index 913f894b9..26aab79e7 100644
--- a/server/tests/api/check-params/video-captions.ts
+++ b/server/tests/api/check-params/video-captions.ts
@@ -5,11 +5,11 @@ import { HttpStatusCode } from '@shared/core-utils'
 import {
   buildAbsoluteFixturePath,
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   makeDeleteRequest,
   makeGetRequest,
   makeUploadRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '@shared/extra-utils'
 import { VideoCreateResult } from '@shared/models'
@@ -17,7 +17,7 @@ import { VideoCreateResult } from '@shared/models'
 describe('Test video captions API validator', function () {
   const path = '/api/v1/videos/'
 
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userAccessToken: string
   let video: VideoCreateResult
 
@@ -26,7 +26,7 @@ describe('Test video captions API validator', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
diff --git a/server/tests/api/check-params/video-channels.ts b/server/tests/api/check-params/video-channels.ts
index 8e6e32f20..62b8fa4f6 100644
--- a/server/tests/api/check-params/video-channels.ts
+++ b/server/tests/api/check-params/video-channels.ts
@@ -11,12 +11,12 @@ import {
   checkBadSortPagination,
   checkBadStartPagination,
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   makeGetRequest,
   makePostBodyRequest,
   makePutBodyRequest,
   makeUploadRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '@shared/extra-utils'
 import { VideoChannelUpdate } from '@shared/models'
@@ -25,7 +25,7 @@ const expect = chai.expect
 
 describe('Test video channels API validator', function () {
   const videoChannelPath = '/api/v1/video-channels'
-  let server: ServerInfo
+  let server: PeerTubeServer
   let accessTokenUser: string
   let command: ChannelsCommand
 
@@ -34,7 +34,7 @@ describe('Test video channels API validator', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
diff --git a/server/tests/api/check-params/video-comments.ts b/server/tests/api/check-params/video-comments.ts
index 44af9d7e3..ea5340b40 100644
--- a/server/tests/api/check-params/video-comments.ts
+++ b/server/tests/api/check-params/video-comments.ts
@@ -8,11 +8,11 @@ import {
   checkBadSortPagination,
   checkBadStartPagination,
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   makeDeleteRequest,
   makeGetRequest,
   makePostBodyRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '@shared/extra-utils'
 import { VideoCreateResult } from '@shared/models'
@@ -22,7 +22,7 @@ const expect = chai.expect
 describe('Test video comments API validator', function () {
   let pathThread: string
   let pathComment: string
-  let server: ServerInfo
+  let server: PeerTubeServer
   let video: VideoCreateResult
   let userAccessToken: string
   let userAccessToken2: string
@@ -33,7 +33,7 @@ describe('Test video comments API validator', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
diff --git a/server/tests/api/check-params/video-imports.ts b/server/tests/api/check-params/video-imports.ts
index 1a6b6075f..627f0c7ad 100644
--- a/server/tests/api/check-params/video-imports.ts
+++ b/server/tests/api/check-params/video-imports.ts
@@ -9,19 +9,19 @@ import {
   checkBadSortPagination,
   checkBadStartPagination,
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   ImportsCommand,
   makeGetRequest,
   makePostBodyRequest,
   makeUploadRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '@shared/extra-utils'
 import { VideoPrivacy } from '@shared/models'
 
 describe('Test video imports API validator', function () {
   const path = '/api/v1/videos/imports'
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userAccessToken = ''
   let channelId: number
 
@@ -30,7 +30,7 @@ describe('Test video imports API validator', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
diff --git a/server/tests/api/check-params/video-playlists.ts b/server/tests/api/check-params/video-playlists.ts
index e0e42ebb0..9d054b176 100644
--- a/server/tests/api/check-params/video-playlists.ts
+++ b/server/tests/api/check-params/video-playlists.ts
@@ -7,10 +7,10 @@ import {
   checkBadSortPagination,
   checkBadStartPagination,
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   makeGetRequest,
   PlaylistsCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel
 } from '@shared/extra-utils'
@@ -25,7 +25,7 @@ import {
 } from '@shared/models'
 
 describe('Test video playlists API validator', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userAccessToken: string
 
   let playlist: VideoPlaylistCreateResult
@@ -42,7 +42,7 @@ describe('Test video playlists API validator', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
     await setDefaultVideoChannel([ server ])
diff --git a/server/tests/api/check-params/videos-filter.ts b/server/tests/api/check-params/videos-filter.ts
index cbfdef1db..e4e799cc7 100644
--- a/server/tests/api/check-params/videos-filter.ts
+++ b/server/tests/api/check-params/videos-filter.ts
@@ -3,16 +3,16 @@
 import 'mocha'
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   makeGetRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel
 } from '../../../../shared/extra-utils'
 import { UserRole } from '../../../../shared/models/users'
 import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
-async function testEndpoints (server: ServerInfo, token: string, filter: string, statusCodeExpected: HttpStatusCode) {
+async function testEndpoints (server: PeerTubeServer, token: string, filter: string, statusCodeExpected: HttpStatusCode) {
   const paths = [
     '/api/v1/video-channels/root_channel/videos',
     '/api/v1/accounts/root/videos',
@@ -34,7 +34,7 @@ async function testEndpoints (server: ServerInfo, token: string, filter: string,
 }
 
 describe('Test video filters validators', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userAccessToken: string
   let moderatorAccessToken: string
 
@@ -43,7 +43,7 @@ describe('Test video filters validators', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
     await setDefaultVideoChannel([ server ])
diff --git a/server/tests/api/check-params/videos-history.ts b/server/tests/api/check-params/videos-history.ts
index 549c9fa1f..3c1f479e4 100644
--- a/server/tests/api/check-params/videos-history.ts
+++ b/server/tests/api/check-params/videos-history.ts
@@ -6,11 +6,11 @@ import {
   checkBadCountPagination,
   checkBadStartPagination,
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   makeGetRequest,
   makePostBodyRequest,
   makePutBodyRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '@shared/extra-utils'
 
@@ -18,14 +18,14 @@ describe('Test videos history API validator', function () {
   const myHistoryPath = '/api/v1/users/me/history/videos'
   const myHistoryRemove = myHistoryPath + '/remove'
   let watchingPath: string
-  let server: ServerInfo
+  let server: PeerTubeServer
 
   // ---------------------------------------------------------------
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
diff --git a/server/tests/api/check-params/videos-overviews.ts b/server/tests/api/check-params/videos-overviews.ts
index 3597c81d3..c2139d74b 100644
--- a/server/tests/api/check-params/videos-overviews.ts
+++ b/server/tests/api/check-params/videos-overviews.ts
@@ -1,17 +1,17 @@
 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
 
 import 'mocha'
-import { cleanupTests, flushAndRunServer, ServerInfo } from '@shared/extra-utils'
+import { cleanupTests, createSingleServer, PeerTubeServer } from '@shared/extra-utils'
 
 describe('Test videos overview', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
 
   // ---------------------------------------------------------------
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
   })
 
   describe('When getting videos overview', function () {
diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts
index 69bdae7cf..c60de2640 100644
--- a/server/tests/api/check-params/videos.ts
+++ b/server/tests/api/check-params/videos.ts
@@ -11,13 +11,13 @@ import {
   checkBadStartPagination,
   checkUploadVideoParam,
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   makeDeleteRequest,
   makeGetRequest,
   makePutBodyRequest,
   makeUploadRequest,
   root,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '@shared/extra-utils'
 import { PeerTubeProblemDocument, VideoCreateResult, VideoPrivacy } from '@shared/models'
@@ -26,7 +26,7 @@ const expect = chai.expect
 
 describe('Test videos API validator', function () {
   const path = '/api/v1/videos/'
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userAccessToken = ''
   let accountName: string
   let channelId: number
@@ -38,7 +38,7 @@ describe('Test videos API validator', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
diff --git a/server/tests/api/live/live-constraints.ts b/server/tests/api/live/live-constraints.ts
index 1c380883c..a00833569 100644
--- a/server/tests/api/live/live-constraints.ts
+++ b/server/tests/api/live/live-constraints.ts
@@ -8,8 +8,8 @@ import {
   cleanupTests,
   ConfigCommand,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   wait,
@@ -19,7 +19,7 @@ import {
 const expect = chai.expect
 
 describe('Test live constraints', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let userId: number
   let userAccessToken: string
   let userChannelId: number
@@ -63,7 +63,7 @@ describe('Test live constraints', function () {
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/live/live-permanent.ts b/server/tests/api/live/live-permanent.ts
index 900bd6f5c..30d499e20 100644
--- a/server/tests/api/live/live-permanent.ts
+++ b/server/tests/api/live/live-permanent.ts
@@ -7,8 +7,8 @@ import {
   cleanupTests,
   ConfigCommand,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   stopFfmpeg,
@@ -19,7 +19,7 @@ import {
 const expect = chai.expect
 
 describe('Permanent live', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let videoUUID: string
 
   async function createLiveWrapper (permanentLive: boolean) {
@@ -45,7 +45,7 @@ describe('Permanent live', function () {
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/live/live-save-replay.ts b/server/tests/api/live/live-save-replay.ts
index 7a33df90a..d403f27bf 100644
--- a/server/tests/api/live/live-save-replay.ts
+++ b/server/tests/api/live/live-save-replay.ts
@@ -9,8 +9,8 @@ import {
   cleanupTests,
   ConfigCommand,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   stopFfmpeg,
@@ -23,7 +23,7 @@ import { LiveVideoCreate, VideoPrivacy, VideoState } from '@shared/models'
 const expect = chai.expect
 
 describe('Save replay setting', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let liveVideoUUID: string
   let ffmpegCommand: FfmpegCommand
 
@@ -82,7 +82,7 @@ describe('Save replay setting', function () {
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/live/live-socket-messages.ts b/server/tests/api/live/live-socket-messages.ts
index ad67d6285..3808964d1 100644
--- a/server/tests/api/live/live-socket-messages.ts
+++ b/server/tests/api/live/live-socket-messages.ts
@@ -6,8 +6,8 @@ import { VideoPrivacy, VideoState } from '@shared/models'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   stopFfmpeg,
@@ -19,12 +19,12 @@ import {
 const expect = chai.expect
 
 describe('Test live', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
 
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/live/live-views.ts b/server/tests/api/live/live-views.ts
index 43222f9c9..4a137b185 100644
--- a/server/tests/api/live/live-views.ts
+++ b/server/tests/api/live/live-views.ts
@@ -7,8 +7,8 @@ import { VideoPrivacy } from '@shared/models'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   stopFfmpeg,
@@ -20,12 +20,12 @@ import {
 const expect = chai.expect
 
 describe('Test live', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
 
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/live/live.ts b/server/tests/api/live/live.ts
index 2cce1f448..7cfac522c 100644
--- a/server/tests/api/live/live.ts
+++ b/server/tests/api/live/live.ts
@@ -11,13 +11,12 @@ import {
   checkResolutionsInMasterPlaylist,
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   killallServers,
   LiveCommand,
   makeRawRequest,
-  reRunServer,
   sendRTMPStream,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   stopFfmpeg,
@@ -32,13 +31,13 @@ import { LiveVideo, LiveVideoCreate, VideoDetails, VideoPrivacy, VideoState, Vid
 const expect = chai.expect
 
 describe('Test live', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let commands: LiveCommand[]
 
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
@@ -571,7 +570,7 @@ describe('Test live', function () {
       await commands[0].waitUntilSegmentGeneration({ videoUUID: liveVideoReplayId, resolution: 0, segment: 2 })
 
       await killallServers([ servers[0] ])
-      await reRunServer(servers[0])
+      await servers[0].run()
 
       await wait(5000)
     })
diff --git a/server/tests/api/moderation/abuses.ts b/server/tests/api/moderation/abuses.ts
index 97a0d95c4..360b9de35 100644
--- a/server/tests/api/moderation/abuses.ts
+++ b/server/tests/api/moderation/abuses.ts
@@ -6,8 +6,8 @@ import {
   AbusesCommand,
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs
 } from '@shared/extra-utils'
@@ -16,7 +16,7 @@ import { AbuseMessage, AbusePredefinedReasonsString, AbuseState, AdminAbuse, Use
 const expect = chai.expect
 
 describe('Test abuses', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let abuseServer1: AdminAbuse
   let abuseServer2: AdminAbuse
   let commands: AbusesCommand[]
@@ -25,7 +25,7 @@ describe('Test abuses', function () {
     this.timeout(50000)
 
     // Run servers
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
@@ -389,7 +389,7 @@ describe('Test abuses', function () {
 
   describe('Comment abuses', function () {
 
-    async function getComment (server: ServerInfo, videoIdArg: number | string) {
+    async function getComment (server: PeerTubeServer, videoIdArg: number | string) {
       const videoId = typeof videoIdArg === 'string'
         ? await server.videos.getId({ uuid: videoIdArg })
         : videoIdArg
@@ -591,7 +591,7 @@ describe('Test abuses', function () {
 
   describe('Account abuses', function () {
 
-    function getAccountFromServer (server: ServerInfo, targetName: string, targetServer: ServerInfo) {
+    function getAccountFromServer (server: PeerTubeServer, targetName: string, targetServer: PeerTubeServer) {
       return server.accounts.get({ accountName: targetName + '@' + targetServer.host })
     }
 
diff --git a/server/tests/api/moderation/blocklist-notification.ts b/server/tests/api/moderation/blocklist-notification.ts
index 6b56fdd65..fdfbcbced 100644
--- a/server/tests/api/moderation/blocklist-notification.ts
+++ b/server/tests/api/moderation/blocklist-notification.ts
@@ -2,12 +2,12 @@
 
 import 'mocha'
 import * as chai from 'chai'
-import { cleanupTests, doubleFollow, flushAndRunMultipleServers, ServerInfo, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
+import { cleanupTests, doubleFollow, createMultipleServers, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
 import { UserNotificationType } from '@shared/models'
 
 const expect = chai.expect
 
-async function checkNotifications (server: ServerInfo, token: string, expected: UserNotificationType[]) {
+async function checkNotifications (server: PeerTubeServer, token: string, expected: UserNotificationType[]) {
   const { data } = await server.notifications.list({ token, start: 0, count: 10, unread: true })
   expect(data).to.have.lengthOf(expected.length)
 
@@ -17,7 +17,7 @@ async function checkNotifications (server: ServerInfo, token: string, expected:
 }
 
 describe('Test blocklist', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
   let videoUUID: string
 
   let userToken1: string
@@ -62,7 +62,7 @@ describe('Test blocklist', function () {
   before(async function () {
     this.timeout(60000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
     await setAccessTokensToServers(servers)
 
     {
diff --git a/server/tests/api/moderation/blocklist.ts b/server/tests/api/moderation/blocklist.ts
index 9a4a3b3b9..593291e87 100644
--- a/server/tests/api/moderation/blocklist.ts
+++ b/server/tests/api/moderation/blocklist.ts
@@ -7,8 +7,8 @@ import {
   cleanupTests,
   CommentsCommand,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs
 } from '@shared/extra-utils'
@@ -16,7 +16,7 @@ import { UserNotificationType } from '@shared/models'
 
 const expect = chai.expect
 
-async function checkAllVideos (server: ServerInfo, token: string) {
+async function checkAllVideos (server: PeerTubeServer, token: string) {
   {
     const { data } = await server.videos.listWithToken({ token })
     expect(data).to.have.lengthOf(5)
@@ -28,7 +28,7 @@ async function checkAllVideos (server: ServerInfo, token: string) {
   }
 }
 
-async function checkAllComments (server: ServerInfo, token: string, videoUUID: string) {
+async function checkAllComments (server: PeerTubeServer, token: string, videoUUID: string) {
   const { data } = await server.comments.listThreads({ videoId: videoUUID, start: 0, count: 25, sort: '-createdAt', token })
 
   const threads = data.filter(t => t.isDeleted === false)
@@ -41,8 +41,8 @@ async function checkAllComments (server: ServerInfo, token: string, videoUUID: s
 }
 
 async function checkCommentNotification (
-  mainServer: ServerInfo,
-  comment: { server: ServerInfo, token: string, videoUUID: string, text: string },
+  mainServer: PeerTubeServer,
+  comment: { server: PeerTubeServer, token: string, videoUUID: string, text: string },
   check: 'presence' | 'absence'
 ) {
   const command = comment.server.comments
@@ -63,7 +63,7 @@ async function checkCommentNotification (
 }
 
 describe('Test blocklist', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
   let videoUUID1: string
   let videoUUID2: string
   let videoUUID3: string
@@ -77,7 +77,7 @@ describe('Test blocklist', function () {
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(3)
+    servers = await createMultipleServers(3)
     await setAccessTokensToServers(servers)
 
     command = servers[0].blocklist
diff --git a/server/tests/api/moderation/video-blacklist.ts b/server/tests/api/moderation/video-blacklist.ts
index d23d23bcb..62cbf2e07 100644
--- a/server/tests/api/moderation/video-blacklist.ts
+++ b/server/tests/api/moderation/video-blacklist.ts
@@ -7,11 +7,10 @@ import {
   BlacklistCommand,
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   ImportsCommand,
   killallServers,
-  reRunServer,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs
 } from '@shared/extra-utils'
@@ -20,11 +19,11 @@ import { UserAdminFlag, UserRole, VideoBlacklist, VideoBlacklistType } from '@sh
 const expect = chai.expect
 
 describe('Test video blacklist', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let videoId: number
   let command: BlacklistCommand
 
-  async function blacklistVideosOnServer (server: ServerInfo) {
+  async function blacklistVideosOnServer (server: PeerTubeServer) {
     const { data } = await server.videos.list()
 
     for (const video of data) {
@@ -36,7 +35,7 @@ describe('Test video blacklist', function () {
     this.timeout(50000)
 
     // Run servers
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
@@ -344,7 +343,7 @@ describe('Test video blacklist', function () {
           }
         }
       }
-      await reRunServer(servers[0], config)
+      await servers[0].run(config)
 
       {
         const user = { username: 'user_without_flag', password: 'password' }
diff --git a/server/tests/api/notifications/admin-notifications.ts b/server/tests/api/notifications/admin-notifications.ts
index 5a5bdb0c8..d65551f0a 100644
--- a/server/tests/api/notifications/admin-notifications.ts
+++ b/server/tests/api/notifications/admin-notifications.ts
@@ -10,13 +10,13 @@ import {
   MockJoinPeerTubeVersions,
   MockSmtpServer,
   prepareNotificationsTest,
-  ServerInfo,
+  PeerTubeServer,
   wait
 } from '@shared/extra-utils'
 import { PluginType, UserNotification, UserNotificationType } from '@shared/models'
 
 describe('Test admin notifications', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userNotifications: UserNotification[] = []
   let adminNotifications: UserNotification[] = []
   let emails: object[] = []
diff --git a/server/tests/api/notifications/comments-notifications.ts b/server/tests/api/notifications/comments-notifications.ts
index 133b6340f..d54819aaa 100644
--- a/server/tests/api/notifications/comments-notifications.ts
+++ b/server/tests/api/notifications/comments-notifications.ts
@@ -9,7 +9,7 @@ import {
   cleanupTests,
   MockSmtpServer,
   prepareNotificationsTest,
-  ServerInfo,
+  PeerTubeServer,
   waitJobs
 } from '@shared/extra-utils'
 import { UserNotification } from '@shared/models'
@@ -17,7 +17,7 @@ import { UserNotification } from '@shared/models'
 const expect = chai.expect
 
 describe('Test comments notifications', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let userToken: string
   let userNotifications: UserNotification[] = []
   let emails: object[] = []
diff --git a/server/tests/api/notifications/moderation-notifications.ts b/server/tests/api/notifications/moderation-notifications.ts
index e7c5badd2..3a294192b 100644
--- a/server/tests/api/notifications/moderation-notifications.ts
+++ b/server/tests/api/notifications/moderation-notifications.ts
@@ -20,14 +20,14 @@ import {
   MockInstancesIndex,
   MockSmtpServer,
   prepareNotificationsTest,
-  ServerInfo,
+  PeerTubeServer,
   wait,
   waitJobs
 } from '@shared/extra-utils'
 import { AbuseState, CustomConfig, UserNotification, VideoPrivacy } from '@shared/models'
 
 describe('Test moderation notifications', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let userAccessToken: string
   let userNotifications: UserNotification[] = []
   let adminNotifications: UserNotification[] = []
diff --git a/server/tests/api/notifications/notifications-api.ts b/server/tests/api/notifications/notifications-api.ts
index 647d783b5..178b20687 100644
--- a/server/tests/api/notifications/notifications-api.ts
+++ b/server/tests/api/notifications/notifications-api.ts
@@ -9,7 +9,7 @@ import {
   getAllNotificationsSettings,
   MockSmtpServer,
   prepareNotificationsTest,
-  ServerInfo,
+  PeerTubeServer,
   waitJobs
 } from '@shared/extra-utils'
 import { UserNotification, UserNotificationSettingValue } from '@shared/models'
@@ -17,7 +17,7 @@ import { UserNotification, UserNotificationSettingValue } from '@shared/models'
 const expect = chai.expect
 
 describe('Test notifications API', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userNotifications: UserNotification[] = []
   let userToken: string
   let emails: object[] = []
diff --git a/server/tests/api/notifications/user-notifications.ts b/server/tests/api/notifications/user-notifications.ts
index 53f8c7594..b7c22d118 100644
--- a/server/tests/api/notifications/user-notifications.ts
+++ b/server/tests/api/notifications/user-notifications.ts
@@ -13,7 +13,7 @@ import {
   ImportsCommand,
   MockSmtpServer,
   prepareNotificationsTest,
-  ServerInfo,
+  PeerTubeServer,
   uploadRandomVideoOnServers,
   wait,
   waitJobs
@@ -23,7 +23,7 @@ import { UserNotification, UserNotificationType, VideoPrivacy } from '@shared/mo
 const expect = chai.expect
 
 describe('Test user notifications', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let userAccessToken: string
   let userNotifications: UserNotification[] = []
   let adminNotifications: UserNotification[] = []
diff --git a/server/tests/api/redundancy/manage-redundancy.ts b/server/tests/api/redundancy/manage-redundancy.ts
index e193b968e..aff64e2eb 100644
--- a/server/tests/api/redundancy/manage-redundancy.ts
+++ b/server/tests/api/redundancy/manage-redundancy.ts
@@ -5,9 +5,9 @@ import * as chai from 'chai'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   RedundancyCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs
 } from '@shared/extra-utils'
@@ -18,7 +18,7 @@ const expect = chai.expect
 describe('Test manage videos redundancy', function () {
   const targets: VideoRedundanciesTarget[] = [ 'my-videos', 'remote-videos' ]
 
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
   let video1Server2UUID: string
   let video2Server2UUID: string
   let redundanciesToRemove: number[] = []
@@ -48,7 +48,7 @@ describe('Test manage videos redundancy', function () {
         }
       }
     }
-    servers = await flushAndRunMultipleServers(3, config)
+    servers = await createMultipleServers(3, config)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/redundancy/redundancy-constraints.ts b/server/tests/api/redundancy/redundancy-constraints.ts
index 0378cc122..217691fb6 100644
--- a/server/tests/api/redundancy/redundancy-constraints.ts
+++ b/server/tests/api/redundancy/redundancy-constraints.ts
@@ -4,19 +4,18 @@ import 'mocha'
 import { expect } from 'chai'
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   killallServers,
-  reRunServer,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs
 } from '@shared/extra-utils'
 import { VideoPrivacy } from '@shared/models'
 
 describe('Test redundancy constraints', function () {
-  let remoteServer: ServerInfo
-  let localServer: ServerInfo
-  let servers: ServerInfo[]
+  let remoteServer: PeerTubeServer
+  let localServer: PeerTubeServer
+  let servers: PeerTubeServer[]
 
   const remoteServerConfig = {
     redundancy: {
@@ -59,7 +58,7 @@ describe('Test redundancy constraints', function () {
     this.timeout(120000)
 
     {
-      remoteServer = await flushAndRunServer(1, remoteServerConfig)
+      remoteServer = await createSingleServer(1, remoteServerConfig)
     }
 
     {
@@ -70,7 +69,7 @@ describe('Test redundancy constraints', function () {
           }
         }
       }
-      localServer = await flushAndRunServer(2, config)
+      localServer = await createSingleServer(2, config)
     }
 
     servers = [ remoteServer, localServer ]
@@ -119,7 +118,7 @@ describe('Test redundancy constraints', function () {
       }
     }
     await await killallServers([ localServer ])
-    await reRunServer(localServer, config)
+    await localServer.run(config)
 
     await uploadWrapper('video 2 server 2')
 
@@ -148,7 +147,7 @@ describe('Test redundancy constraints', function () {
       }
     }
     await killallServers([ localServer ])
-    await reRunServer(localServer, config)
+    await localServer.run(config)
 
     await uploadWrapper('video 3 server 2')
 
diff --git a/server/tests/api/redundancy/redundancy.ts b/server/tests/api/redundancy/redundancy.ts
index 77ea2278e..9d5d96efd 100644
--- a/server/tests/api/redundancy/redundancy.ts
+++ b/server/tests/api/redundancy/redundancy.ts
@@ -11,12 +11,11 @@ import {
   checkVideoFilesWereRemoved,
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   killallServers,
   makeGetRequest,
-  reRunServer,
   root,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   wait,
   waitJobs
@@ -25,11 +24,11 @@ import { VideoPrivacy, VideoRedundancyStrategy, VideoRedundancyStrategyWithManua
 
 const expect = chai.expect
 
-let servers: ServerInfo[] = []
+let servers: PeerTubeServer[] = []
 let video1Server2UUID: string
 let video1Server2Id: number
 
-function checkMagnetWebseeds (file: { magnetUri: string, resolution: { id: number } }, baseWebseeds: string[], server: ServerInfo) {
+function checkMagnetWebseeds (file: { magnetUri: string, resolution: { id: number } }, baseWebseeds: string[], server: PeerTubeServer) {
   const parsed = magnetUtil.decode(file.magnetUri)
 
   for (const ws of baseWebseeds) {
@@ -40,7 +39,7 @@ function checkMagnetWebseeds (file: { magnetUri: string, resolution: { id: numbe
   expect(parsed.urlList).to.have.lengthOf(baseWebseeds.length)
 }
 
-async function flushAndRunServers (strategy: VideoRedundancyStrategy | null, additionalParams: any = {}, withWebtorrent = true) {
+async function createSingleServers (strategy: VideoRedundancyStrategy | null, additionalParams: any = {}, withWebtorrent = true) {
   const strategies: any[] = []
 
   if (strategy !== null) {
@@ -72,7 +71,7 @@ async function flushAndRunServers (strategy: VideoRedundancyStrategy | null, add
     }
   }
 
-  servers = await flushAndRunMultipleServers(3, config)
+  servers = await createMultipleServers(3, config)
 
   // Get the access tokens
   await setAccessTokensToServers(servers)
@@ -288,7 +287,7 @@ describe('Test videos redundancy', function () {
     before(function () {
       this.timeout(120000)
 
-      return flushAndRunServers(strategy)
+      return createSingleServers(strategy)
     })
 
     it('Should have 1 webseed on the first video', async function () {
@@ -338,7 +337,7 @@ describe('Test videos redundancy', function () {
     before(function () {
       this.timeout(120000)
 
-      return flushAndRunServers(strategy)
+      return createSingleServers(strategy)
     })
 
     it('Should have 1 webseed on the first video', async function () {
@@ -388,7 +387,7 @@ describe('Test videos redundancy', function () {
     before(function () {
       this.timeout(120000)
 
-      return flushAndRunServers(strategy, { min_views: 3 })
+      return createSingleServers(strategy, { min_views: 3 })
     })
 
     it('Should have 1 webseed on the first video', async function () {
@@ -458,7 +457,7 @@ describe('Test videos redundancy', function () {
     before(async function () {
       this.timeout(120000)
 
-      await flushAndRunServers(strategy, { min_views: 3 }, false)
+      await createSingleServers(strategy, { min_views: 3 }, false)
     })
 
     it('Should have 0 playlist redundancy on the first video', async function () {
@@ -519,7 +518,7 @@ describe('Test videos redundancy', function () {
     before(function () {
       this.timeout(120000)
 
-      return flushAndRunServers(null)
+      return createSingleServers(null)
     })
 
     it('Should have 1 webseed on the first video', async function () {
@@ -575,7 +574,7 @@ describe('Test videos redundancy', function () {
   describe('Test expiration', function () {
     const strategy = 'recently-added'
 
-    async function checkContains (servers: ServerInfo[], str: string) {
+    async function checkContains (servers: PeerTubeServer[], str: string) {
       for (const server of servers) {
         const video = await server.videos.get({ id: video1Server2UUID })
 
@@ -585,7 +584,7 @@ describe('Test videos redundancy', function () {
       }
     }
 
-    async function checkNotContains (servers: ServerInfo[], str: string) {
+    async function checkNotContains (servers: PeerTubeServer[], str: string) {
       for (const server of servers) {
         const video = await server.videos.get({ id: video1Server2UUID })
 
@@ -598,7 +597,7 @@ describe('Test videos redundancy', function () {
     before(async function () {
       this.timeout(120000)
 
-      await flushAndRunServers(strategy, { min_lifetime: '7 seconds', min_views: 0 })
+      await createSingleServers(strategy, { min_lifetime: '7 seconds', min_views: 0 })
 
       await enableRedundancyOnServer1()
     })
@@ -640,7 +639,7 @@ describe('Test videos redundancy', function () {
     before(async function () {
       this.timeout(120000)
 
-      await flushAndRunServers(strategy, { min_lifetime: '7 seconds', min_views: 0 })
+      await createSingleServers(strategy, { min_lifetime: '7 seconds', min_views: 0 })
 
       await enableRedundancyOnServer1()
 
@@ -691,7 +690,7 @@ describe('Test videos redundancy', function () {
       await waitJobs(servers)
 
       await killallServers([ servers[0] ])
-      await reRunServer(servers[0], {
+      await servers[0].run({
         redundancy: {
           videos: {
             check_interval: '1 second',
diff --git a/server/tests/api/search/search-activitypub-video-channels.ts b/server/tests/api/search/search-activitypub-video-channels.ts
index 71e9367e5..f5896ec25 100644
--- a/server/tests/api/search/search-activitypub-video-channels.ts
+++ b/server/tests/api/search/search-activitypub-video-channels.ts
@@ -4,9 +4,9 @@ import 'mocha'
 import * as chai from 'chai'
 import {
   cleanupTests,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   SearchCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   wait,
   waitJobs
@@ -16,7 +16,7 @@ import { VideoChannel } from '@shared/models'
 const expect = chai.expect
 
 describe('Test ActivityPub video channels search', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
   let userServer2Token: string
   let videoServer2UUID: string
   let channelIdServer2: number
@@ -25,7 +25,7 @@ describe('Test ActivityPub video channels search', function () {
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     await setAccessTokensToServers(servers)
 
diff --git a/server/tests/api/search/search-activitypub-video-playlists.ts b/server/tests/api/search/search-activitypub-video-playlists.ts
index 7c99b954b..ada2d3d6c 100644
--- a/server/tests/api/search/search-activitypub-video-playlists.ts
+++ b/server/tests/api/search/search-activitypub-video-playlists.ts
@@ -4,9 +4,9 @@ import 'mocha'
 import * as chai from 'chai'
 import {
   cleanupTests,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   SearchCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   wait,
@@ -17,7 +17,7 @@ import { VideoPlaylistPrivacy } from '@shared/models'
 const expect = chai.expect
 
 describe('Test ActivityPub playlists search', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
   let playlistServer1UUID: string
   let playlistServer2UUID: string
   let video2Server2: string
@@ -27,7 +27,7 @@ describe('Test ActivityPub playlists search', function () {
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     await setAccessTokensToServers(servers)
     await setDefaultVideoChannel(servers)
diff --git a/server/tests/api/search/search-activitypub-videos.ts b/server/tests/api/search/search-activitypub-videos.ts
index 0dfc63446..a015b72a7 100644
--- a/server/tests/api/search/search-activitypub-videos.ts
+++ b/server/tests/api/search/search-activitypub-videos.ts
@@ -4,9 +4,9 @@ import 'mocha'
 import * as chai from 'chai'
 import {
   cleanupTests,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   SearchCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   wait,
   waitJobs
@@ -16,7 +16,7 @@ import { VideoPrivacy } from '@shared/models'
 const expect = chai.expect
 
 describe('Test ActivityPub videos search', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
   let videoServer1UUID: string
   let videoServer2UUID: string
 
@@ -25,7 +25,7 @@ describe('Test ActivityPub videos search', function () {
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     await setAccessTokensToServers(servers)
 
diff --git a/server/tests/api/search/search-channels.ts b/server/tests/api/search/search-channels.ts
index 7035fbd62..07e00a214 100644
--- a/server/tests/api/search/search-channels.ts
+++ b/server/tests/api/search/search-channels.ts
@@ -2,19 +2,19 @@
 
 import 'mocha'
 import * as chai from 'chai'
-import { cleanupTests, flushAndRunServer, SearchCommand, ServerInfo, setAccessTokensToServers } from '@shared/extra-utils'
+import { cleanupTests, createSingleServer, SearchCommand, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
 import { VideoChannel } from '@shared/models'
 
 const expect = chai.expect
 
 describe('Test channels search', function () {
-  let server: ServerInfo = null
+  let server: PeerTubeServer = null
   let command: SearchCommand
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
diff --git a/server/tests/api/search/search-index.ts b/server/tests/api/search/search-index.ts
index b54c0da22..38edcf7c6 100644
--- a/server/tests/api/search/search-index.ts
+++ b/server/tests/api/search/search-index.ts
@@ -2,7 +2,7 @@
 
 import 'mocha'
 import * as chai from 'chai'
-import { cleanupTests, flushAndRunServer, SearchCommand, ServerInfo, setAccessTokensToServers } from '@shared/extra-utils'
+import { cleanupTests, createSingleServer, SearchCommand, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
 import { BooleanBothQuery, VideoPlaylistPrivacy, VideoPlaylistType, VideosSearchQuery } from '@shared/models'
 
 const expect = chai.expect
@@ -10,13 +10,13 @@ const expect = chai.expect
 describe('Test videos search', function () {
   const localVideoName = 'local video' + new Date().toISOString()
 
-  let server: ServerInfo = null
+  let server: PeerTubeServer = null
   let command: SearchCommand
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
diff --git a/server/tests/api/search/search-playlists.ts b/server/tests/api/search/search-playlists.ts
index e15128c8e..b29c2d127 100644
--- a/server/tests/api/search/search-playlists.ts
+++ b/server/tests/api/search/search-playlists.ts
@@ -4,9 +4,9 @@ import 'mocha'
 import * as chai from 'chai'
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   SearchCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel
 } from '@shared/extra-utils'
@@ -15,13 +15,13 @@ import { VideoPlaylistPrivacy } from '@shared/models'
 const expect = chai.expect
 
 describe('Test playlists search', function () {
-  let server: ServerInfo = null
+  let server: PeerTubeServer = null
   let command: SearchCommand
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
     await setDefaultVideoChannel([ server ])
diff --git a/server/tests/api/search/search-videos.ts b/server/tests/api/search/search-videos.ts
index 478ebafc9..a9b0a4fcd 100644
--- a/server/tests/api/search/search-videos.ts
+++ b/server/tests/api/search/search-videos.ts
@@ -4,9 +4,9 @@ import 'mocha'
 import * as chai from 'chai'
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   SearchCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   stopFfmpeg,
@@ -17,7 +17,7 @@ import { VideoPrivacy } from '@shared/models'
 const expect = chai.expect
 
 describe('Test videos search', function () {
-  let server: ServerInfo = null
+  let server: PeerTubeServer = null
   let startDate: string
   let videoUUID: string
 
@@ -26,7 +26,7 @@ describe('Test videos search', function () {
   before(async function () {
     this.timeout(60000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
     await setDefaultVideoChannel([ server ])
diff --git a/server/tests/api/server/auto-follows.ts b/server/tests/api/server/auto-follows.ts
index e9fb5b4b1..8dca2e5e5 100644
--- a/server/tests/api/server/auto-follows.ts
+++ b/server/tests/api/server/auto-follows.ts
@@ -4,9 +4,9 @@ import 'mocha'
 import * as chai from 'chai'
 import {
   cleanupTests,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   MockInstancesIndex,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   wait,
   waitJobs
@@ -14,7 +14,7 @@ import {
 
 const expect = chai.expect
 
-async function checkFollow (follower: ServerInfo, following: ServerInfo, exists: boolean) {
+async function checkFollow (follower: PeerTubeServer, following: PeerTubeServer, exists: boolean) {
   {
     const body = await following.follows.getFollowers({ start: 0, count: 5, sort: '-createdAt' })
     const follow = body.data.find(f => f.follower.host === follower.host && f.state === 'accepted')
@@ -32,13 +32,13 @@ async function checkFollow (follower: ServerInfo, following: ServerInfo, exists:
   }
 }
 
-async function server1Follows2 (servers: ServerInfo[]) {
+async function server1Follows2 (servers: PeerTubeServer[]) {
   await servers[0].follows.follow({ targets: [ servers[1].host ] })
 
   await waitJobs(servers)
 }
 
-async function resetFollows (servers: ServerInfo[]) {
+async function resetFollows (servers: PeerTubeServer[]) {
   try {
     await servers[0].follows.unfollow({ target: servers[1] })
     await servers[1].follows.unfollow({ target: servers[0] })
@@ -52,12 +52,12 @@ async function resetFollows (servers: ServerInfo[]) {
 }
 
 describe('Test auto follows', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
 
   before(async function () {
     this.timeout(30000)
 
-    servers = await flushAndRunMultipleServers(3)
+    servers = await createMultipleServers(3)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/server/bulk.ts b/server/tests/api/server/bulk.ts
index acc17092d..5d8c87983 100644
--- a/server/tests/api/server/bulk.ts
+++ b/server/tests/api/server/bulk.ts
@@ -6,8 +6,8 @@ import {
   BulkCommand,
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs
 } from '@shared/extra-utils'
@@ -17,7 +17,7 @@ const expect = chai.expect
 describe('Test bulk actions', function () {
   const commentsUser3: { videoId: number, commentId: number }[] = []
 
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let user1Token: string
   let user2Token: string
   let user3Token: string
@@ -27,7 +27,7 @@ describe('Test bulk actions', function () {
   before(async function () {
     this.timeout(30000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts
index 479e177a8..a7191c5ef 100644
--- a/server/tests/api/server/config.ts
+++ b/server/tests/api/server/config.ts
@@ -5,19 +5,18 @@ import * as chai from 'chai'
 import { HttpStatusCode } from '@shared/core-utils'
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   killallServers,
   makeGetRequest,
   parallelTests,
-  reRunServer,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '@shared/extra-utils'
 import { CustomConfig } from '@shared/models'
 
 const expect = chai.expect
 
-function checkInitialConfig (server: ServerInfo, data: CustomConfig) {
+function checkInitialConfig (server: PeerTubeServer, data: CustomConfig) {
   expect(data.instance.name).to.equal('PeerTube')
   expect(data.instance.shortDescription).to.equal(
     'PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.'
@@ -204,12 +203,12 @@ function checkUpdatedConfig (data: CustomConfig) {
 }
 
 describe('Test config', function () {
-  let server: ServerInfo = null
+  let server: PeerTubeServer = null
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
   })
 
@@ -456,7 +455,7 @@ describe('Test config', function () {
 
     await killallServers([ server ])
 
-    await reRunServer(server)
+    await server.run()
 
     const data = await server.config.getCustomConfig()
 
@@ -512,7 +511,7 @@ describe('Test config', function () {
         frameguard: { enabled: false }
       }
     }
-    server = await reRunServer(server, config)
+    await server.run(config)
 
     {
       const res = await makeGetRequest({
diff --git a/server/tests/api/server/contact-form.ts b/server/tests/api/server/contact-form.ts
index 353fed80a..f0905bb3b 100644
--- a/server/tests/api/server/contact-form.ts
+++ b/server/tests/api/server/contact-form.ts
@@ -3,13 +3,21 @@
 import 'mocha'
 import * as chai from 'chai'
 import { HttpStatusCode } from '@shared/core-utils'
-import { cleanupTests, flushAndRunServer, MockSmtpServer, ServerInfo, setAccessTokensToServers, wait, waitJobs } from '@shared/extra-utils'
-import { ContactFormCommand } from '@shared/extra-utils/server'
+import {
+  cleanupTests,
+  ContactFormCommand,
+  createSingleServer,
+  MockSmtpServer,
+  PeerTubeServer,
+  setAccessTokensToServers,
+  wait,
+  waitJobs
+} from '@shared/extra-utils'
 
 const expect = chai.expect
 
 describe('Test contact form', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   const emails: object[] = []
   let command: ContactFormCommand
 
@@ -24,7 +32,7 @@ describe('Test contact form', function () {
         port
       }
     }
-    server = await flushAndRunServer(1, overrideConfig)
+    server = await createSingleServer(1, overrideConfig)
     await setAccessTokensToServers([ server ])
 
     command = server.contactForm
diff --git a/server/tests/api/server/email.ts b/server/tests/api/server/email.ts
index 258e835e7..b202cf8a7 100644
--- a/server/tests/api/server/email.ts
+++ b/server/tests/api/server/email.ts
@@ -3,12 +3,12 @@
 import 'mocha'
 import * as chai from 'chai'
 import { HttpStatusCode } from '@shared/core-utils'
-import { cleanupTests, flushAndRunServer, MockSmtpServer, ServerInfo, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
+import { cleanupTests, createSingleServer, MockSmtpServer, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
 
 const expect = chai.expect
 
 describe('Test emails', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userId: number
   let userId2: number
   let userAccessToken: string
@@ -39,7 +39,7 @@ describe('Test emails', function () {
         port: emailPort
       }
     }
-    server = await flushAndRunServer(1, overrideConfig)
+    server = await createSingleServer(1, overrideConfig)
     await setAccessTokensToServers([ server ])
 
     {
diff --git a/server/tests/api/server/follow-constraints.ts b/server/tests/api/server/follow-constraints.ts
index 887e400e9..4ed593b76 100644
--- a/server/tests/api/server/follow-constraints.ts
+++ b/server/tests/api/server/follow-constraints.ts
@@ -3,13 +3,13 @@
 import 'mocha'
 import * as chai from 'chai'
 import { HttpStatusCode } from '@shared/core-utils'
-import { cleanupTests, doubleFollow, flushAndRunMultipleServers, ServerInfo, setAccessTokensToServers } from '@shared/extra-utils'
+import { cleanupTests, doubleFollow, createMultipleServers, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
 import { PeerTubeProblemDocument, ServerErrorCode } from '@shared/models'
 
 const expect = chai.expect
 
 describe('Test follow constraints', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let video1UUID: string
   let video2UUID: string
   let userToken: string
@@ -17,7 +17,7 @@ describe('Test follow constraints', function () {
   before(async function () {
     this.timeout(90000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/server/follows-moderation.ts b/server/tests/api/server/follows-moderation.ts
index 045024544..0aa328c5a 100644
--- a/server/tests/api/server/follows-moderation.ts
+++ b/server/tests/api/server/follows-moderation.ts
@@ -4,16 +4,16 @@ import 'mocha'
 import * as chai from 'chai'
 import {
   cleanupTests,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   FollowsCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs
 } from '@shared/extra-utils'
 
 const expect = chai.expect
 
-async function checkServer1And2HasFollowers (servers: ServerInfo[], state = 'accepted') {
+async function checkServer1And2HasFollowers (servers: PeerTubeServer[], state = 'accepted') {
   const fns = [
     servers[0].follows.getFollowings.bind(servers[0].follows),
     servers[1].follows.getFollowers.bind(servers[1].follows)
@@ -30,7 +30,7 @@ async function checkServer1And2HasFollowers (servers: ServerInfo[], state = 'acc
   }
 }
 
-async function checkNoFollowers (servers: ServerInfo[]) {
+async function checkNoFollowers (servers: PeerTubeServer[]) {
   const fns = [
     servers[0].follows.getFollowings.bind(servers[0].follows),
     servers[1].follows.getFollowers.bind(servers[1].follows)
@@ -43,13 +43,13 @@ async function checkNoFollowers (servers: ServerInfo[]) {
 }
 
 describe('Test follows moderation', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let commands: FollowsCommand[]
 
   before(async function () {
     this.timeout(30000)
 
-    servers = await flushAndRunMultipleServers(3)
+    servers = await createMultipleServers(3)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/server/follows.ts b/server/tests/api/server/follows.ts
index d43064689..8856177b8 100644
--- a/server/tests/api/server/follows.ts
+++ b/server/tests/api/server/follows.ts
@@ -7,9 +7,9 @@ import {
   completeVideoCheck,
   dateIsValid,
   expectAccountFollows,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   FollowsCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   testCaptionFile,
   waitJobs
@@ -19,13 +19,13 @@ import { Video, VideoPrivacy } from '@shared/models'
 const expect = chai.expect
 
 describe('Test follows', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let followsCommands: FollowsCommand[]
 
   before(async function () {
     this.timeout(30000)
 
-    servers = await flushAndRunMultipleServers(3)
+    servers = await createMultipleServers(3)
     followsCommands = servers.map(s => s.follows)
 
     // Get the access tokens
diff --git a/server/tests/api/server/handle-down.ts b/server/tests/api/server/handle-down.ts
index de3dee826..5f20b0093 100644
--- a/server/tests/api/server/handle-down.ts
+++ b/server/tests/api/server/handle-down.ts
@@ -7,10 +7,9 @@ import {
   cleanupTests,
   CommentsCommand,
   completeVideoCheck,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   killallServers,
-  reRunServer,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   wait,
   waitJobs
@@ -20,7 +19,7 @@ import { JobState, VideoCreateResult, VideoPrivacy } from '@shared/models'
 const expect = chai.expect
 
 describe('Test handle downs', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let threadIdServer1: number
   let threadIdServer2: number
   let commentIdServer1: number
@@ -54,7 +53,7 @@ describe('Test handle downs', function () {
   before(async function () {
     this.timeout(30000)
 
-    servers = await flushAndRunMultipleServers(3)
+    servers = await createMultipleServers(3)
     commentCommands = servers.map(s => s.comments)
 
     checkAttributes = {
@@ -176,8 +175,8 @@ describe('Test handle downs', function () {
   it('Should re-follow server 1', async function () {
     this.timeout(35000)
 
-    await reRunServer(servers[1])
-    await reRunServer(servers[2])
+    await servers[1].run()
+    await servers[2].run()
 
     await servers[1].follows.unfollow({ target: servers[0] })
     await waitJobs(servers)
diff --git a/server/tests/api/server/homepage.ts b/server/tests/api/server/homepage.ts
index aac075321..c291037f2 100644
--- a/server/tests/api/server/homepage.ts
+++ b/server/tests/api/server/homepage.ts
@@ -6,29 +6,28 @@ import { HttpStatusCode } from '@shared/core-utils'
 import {
   cleanupTests,
   CustomPagesCommand,
-  flushAndRunServer,
+  createSingleServer,
   killallServers,
-  reRunServer,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '../../../../shared/extra-utils/index'
 
 const expect = chai.expect
 
-async function getHomepageState (server: ServerInfo) {
+async function getHomepageState (server: PeerTubeServer) {
   const config = await server.config.getConfig()
 
   return config.homepage.enabled
 }
 
 describe('Test instance homepage actions', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let command: CustomPagesCommand
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
 
     command = server.customPage
@@ -56,7 +55,7 @@ describe('Test instance homepage actions', function () {
 
     await killallServers([ server ])
 
-    await reRunServer(server)
+    await server.run()
 
     const page = await command.getInstanceHomepage()
     expect(page.content).to.equal('<picsou-magazine></picsou-magazine>')
diff --git a/server/tests/api/server/jobs.ts b/server/tests/api/server/jobs.ts
index 0c44e4dad..376cd10d0 100644
--- a/server/tests/api/server/jobs.ts
+++ b/server/tests/api/server/jobs.ts
@@ -6,8 +6,8 @@ import {
   cleanupTests,
   dateIsValid,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs
 } from '@shared/extra-utils'
@@ -15,12 +15,12 @@ import {
 const expect = chai.expect
 
 describe('Test jobs', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
 
   before(async function () {
     this.timeout(30000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     await setAccessTokensToServers(servers)
 
diff --git a/server/tests/api/server/logs.ts b/server/tests/api/server/logs.ts
index 2d141fd8c..bcd94dda3 100644
--- a/server/tests/api/server/logs.ts
+++ b/server/tests/api/server/logs.ts
@@ -4,11 +4,10 @@ import 'mocha'
 import * as chai from 'chai'
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   killallServers,
   LogsCommand,
-  reRunServer,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs
 } from '@shared/extra-utils'
@@ -16,13 +15,13 @@ import {
 const expect = chai.expect
 
 describe('Test logs', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let logsCommand: LogsCommand
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
 
     logsCommand = server.logs
@@ -113,7 +112,7 @@ describe('Test logs', function () {
 
       await killallServers([ server ])
 
-      await reRunServer(server, { log: { log_ping_requests: false } })
+      await server.run({ log: { log_ping_requests: false } })
 
       const now = new Date()
 
diff --git a/server/tests/api/server/no-client.ts b/server/tests/api/server/no-client.ts
index d589f51f3..f45222f2f 100644
--- a/server/tests/api/server/no-client.ts
+++ b/server/tests/api/server/no-client.ts
@@ -1,16 +1,16 @@
 import 'mocha'
 import * as request from 'supertest'
-import { ServerInfo } from '../../../../shared/extra-utils'
-import { cleanupTests, flushAndRunServer } from '../../../../shared/extra-utils/server/servers'
+import { PeerTubeServer } from '../../../../shared/extra-utils'
+import { cleanupTests, createSingleServer } from '../../../../shared/extra-utils/server/servers'
 import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 describe('Start and stop server without web client routes', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1, {}, [ '--no-client' ])
+    server = await createSingleServer(1, {}, [ '--no-client' ])
   })
 
   it('Should fail getting the client', function () {
diff --git a/server/tests/api/server/plugins.ts b/server/tests/api/server/plugins.ts
index 45a22e48d..db03d026a 100644
--- a/server/tests/api/server/plugins.ts
+++ b/server/tests/api/server/plugins.ts
@@ -5,11 +5,10 @@ import * as chai from 'chai'
 import { HttpStatusCode } from '@shared/core-utils'
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   killallServers,
   PluginsCommand,
-  reRunServer,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   testHelloWorldRegisteredSettings,
   wait
@@ -19,7 +18,7 @@ import { PluginType } from '@shared/models'
 const expect = chai.expect
 
 describe('Test plugins', function () {
-  let server: ServerInfo = null
+  let server: PeerTubeServer = null
   let command: PluginsCommand
 
   before(async function () {
@@ -30,7 +29,7 @@ describe('Test plugins', function () {
         index: { check_latest_versions_interval: '5 seconds' }
       }
     }
-    server = await flushAndRunServer(1, configOverride)
+    server = await createSingleServer(1, configOverride)
     await setAccessTokensToServers([ server ])
 
     command = server.plugins
@@ -245,7 +244,7 @@ describe('Test plugins', function () {
 
     // Restart the server to take into account this change
     await killallServers([ server ])
-    await reRunServer(server)
+    await server.run()
 
     {
       const body = await command.list({ pluginType: PluginType.PLUGIN })
@@ -326,7 +325,7 @@ describe('Test plugins', function () {
     await check()
 
     await killallServers([ server ])
-    await reRunServer(server)
+    await server.run()
 
     await check()
   })
diff --git a/server/tests/api/server/reverse-proxy.ts b/server/tests/api/server/reverse-proxy.ts
index de3cf02f2..c20b7a5f0 100644
--- a/server/tests/api/server/reverse-proxy.ts
+++ b/server/tests/api/server/reverse-proxy.ts
@@ -2,10 +2,10 @@
 
 import { expect } from 'chai'
 import { HttpStatusCode } from '@shared/core-utils'
-import { cleanupTests, flushAndRunServer, ServerInfo, setAccessTokensToServers, wait } from '@shared/extra-utils'
+import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers, wait } from '@shared/extra-utils'
 
 describe('Test application behind a reverse proxy', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let videoId: string
 
   before(async function () {
@@ -30,7 +30,7 @@ describe('Test application behind a reverse proxy', function () {
       }
     }
 
-    server = await flushAndRunServer(1, config)
+    server = await createSingleServer(1, config)
     await setAccessTokensToServers([ server ])
 
     const { uuid } = await server.videos.upload()
diff --git a/server/tests/api/server/services.ts b/server/tests/api/server/services.ts
index 28f9ae3b6..69d030dbb 100644
--- a/server/tests/api/server/services.ts
+++ b/server/tests/api/server/services.ts
@@ -2,13 +2,13 @@
 
 import 'mocha'
 import * as chai from 'chai'
-import { cleanupTests, flushAndRunServer, ServerInfo, setAccessTokensToServers, setDefaultVideoChannel } from '@shared/extra-utils'
+import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers, setDefaultVideoChannel } from '@shared/extra-utils'
 import { Video, VideoPlaylistPrivacy } from '@shared/models'
 
 const expect = chai.expect
 
 describe('Test services', function () {
-  let server: ServerInfo = null
+  let server: PeerTubeServer = null
   let playlistUUID: string
   let playlistDisplayName: string
   let video: Video
@@ -16,7 +16,7 @@ describe('Test services', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
     await setDefaultVideoChannel([ server ])
diff --git a/server/tests/api/server/stats.ts b/server/tests/api/server/stats.ts
index be5abad52..f07d0fd39 100644
--- a/server/tests/api/server/stats.ts
+++ b/server/tests/api/server/stats.ts
@@ -5,8 +5,8 @@ import * as chai from 'chai'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   wait,
   waitJobs
@@ -16,7 +16,7 @@ import { ActivityType, VideoPlaylistPrivacy } from '@shared/models'
 const expect = chai.expect
 
 describe('Test stats (excluding redundancy)', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let channelId
   const user = {
     username: 'user1',
@@ -26,7 +26,7 @@ describe('Test stats (excluding redundancy)', function () {
   before(async function () {
     this.timeout(60000)
 
-    servers = await flushAndRunMultipleServers(3)
+    servers = await createMultipleServers(3)
 
     await setAccessTokensToServers(servers)
 
diff --git a/server/tests/api/server/tracker.ts b/server/tests/api/server/tracker.ts
index d80362fee..f597ac60c 100644
--- a/server/tests/api/server/tracker.ts
+++ b/server/tests/api/server/tracker.ts
@@ -3,16 +3,16 @@
 import 'mocha'
 import * as magnetUtil from 'magnet-uri'
 import * as WebTorrent from 'webtorrent'
-import { cleanupTests, flushAndRunServer, killallServers, reRunServer, ServerInfo, setAccessTokensToServers } from '@shared/extra-utils'
+import { cleanupTests, createSingleServer, killallServers, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
 
 describe('Test tracker', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let badMagnet: string
   let goodMagnet: string
 
   before(async function () {
     this.timeout(60000)
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
 
     {
@@ -48,7 +48,7 @@ describe('Test tracker', function () {
     const errCb = () => done(new Error('Tracker is enabled'))
 
     killallServers([ server ])
-      .then(() => reRunServer(server, { tracker: { enabled: false } }))
+      .then(() => server.run({ tracker: { enabled: false } }))
       .then(() => {
         const webtorrent = new WebTorrent()
 
@@ -72,7 +72,7 @@ describe('Test tracker', function () {
     this.timeout(20000)
 
     killallServers([ server ])
-      .then(() => reRunServer(server))
+      .then(() => server.run())
       .then(() => {
         const webtorrent = new WebTorrent()
 
diff --git a/server/tests/api/users/user-subscriptions.ts b/server/tests/api/users/user-subscriptions.ts
index 1b15a98dc..d2bb9c387 100644
--- a/server/tests/api/users/user-subscriptions.ts
+++ b/server/tests/api/users/user-subscriptions.ts
@@ -5,8 +5,8 @@ import * as chai from 'chai'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   SubscriptionsCommand,
   waitJobs
@@ -15,7 +15,7 @@ import {
 const expect = chai.expect
 
 describe('Test users subscriptions', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   const users: { accessToken: string }[] = []
   let video3UUID: string
 
@@ -24,7 +24,7 @@ describe('Test users subscriptions', function () {
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(3)
+    servers = await createMultipleServers(3)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/users/users-multiple-servers.ts b/server/tests/api/users/users-multiple-servers.ts
index f8d7ae88e..e629966bb 100644
--- a/server/tests/api/users/users-multiple-servers.ts
+++ b/server/tests/api/users/users-multiple-servers.ts
@@ -8,8 +8,8 @@ import {
   checkVideoFilesWereRemoved,
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   testImage,
   waitJobs
@@ -19,7 +19,7 @@ import { User } from '@shared/models'
 const expect = chai.expect
 
 describe('Test users with multiple servers', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let user: User
   let userId: number
   let videoUUID: string
@@ -29,7 +29,7 @@ describe('Test users with multiple servers', function () {
   before(async function () {
     this.timeout(120_000)
 
-    servers = await flushAndRunMultipleServers(3)
+    servers = await createMultipleServers(3)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/users/users-verification.ts b/server/tests/api/users/users-verification.ts
index c8c226fa8..5dbe2af59 100644
--- a/server/tests/api/users/users-verification.ts
+++ b/server/tests/api/users/users-verification.ts
@@ -3,12 +3,12 @@
 import 'mocha'
 import * as chai from 'chai'
 import { HttpStatusCode } from '@shared/core-utils'
-import { cleanupTests, flushAndRunServer, MockSmtpServer, ServerInfo, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
+import { cleanupTests, createSingleServer, MockSmtpServer, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
 
 const expect = chai.expect
 
 describe('Test users account verification', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userId: number
   let userAccessToken: string
   let verificationString: string
@@ -34,7 +34,7 @@ describe('Test users account verification', function () {
         port
       }
     }
-    server = await flushAndRunServer(1, overrideConfig)
+    server = await createSingleServer(1, overrideConfig)
 
     await setAccessTokensToServers([ server ])
   })
diff --git a/server/tests/api/users/users.ts b/server/tests/api/users/users.ts
index 310136a37..6ae5410b3 100644
--- a/server/tests/api/users/users.ts
+++ b/server/tests/api/users/users.ts
@@ -5,11 +5,10 @@ import * as chai from 'chai'
 import { HttpStatusCode } from '@shared/core-utils'
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   killallServers,
   makePutBodyRequest,
-  reRunServer,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   testImage,
   waitJobs
@@ -19,7 +18,7 @@ import { AbuseState, OAuth2ErrorCode, UserAdminFlag, UserRole, Video, VideoPlayl
 const expect = chai.expect
 
 describe('Test users', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let token: string
   let userToken: string
   let videoId: number
@@ -32,7 +31,7 @@ describe('Test users', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1, {
+    server = await createSingleServer(1, {
       rates_limit: {
         login: {
           max: 30
@@ -238,7 +237,7 @@ describe('Test users', function () {
       await server.sql.setTokenField(server.accessToken, 'refreshTokenExpiresAt', new Date().toISOString())
 
       await killallServers([ server ])
-      await reRunServer(server)
+      await server.run()
 
       await server.users.getMyInfo({ expectedStatus: HttpStatusCode.UNAUTHORIZED_401 })
     })
@@ -254,7 +253,7 @@ describe('Test users', function () {
       await server.sql.setTokenField(server.accessToken, 'refreshTokenExpiresAt', futureDate)
 
       await killallServers([ server ])
-      await reRunServer(server)
+      await server.run()
 
       const res = await server.login.refreshToken({ refreshToken: server.refreshToken })
       server.accessToken = res.body.access_token
diff --git a/server/tests/api/videos/audio-only.ts b/server/tests/api/videos/audio-only.ts
index b2952e38b..b9bf96650 100644
--- a/server/tests/api/videos/audio-only.ts
+++ b/server/tests/api/videos/audio-only.ts
@@ -4,12 +4,12 @@ import 'mocha'
 import * as chai from 'chai'
 import { join } from 'path'
 import { getAudioStream, getVideoStreamSize } from '@server/helpers/ffprobe-utils'
-import { cleanupTests, doubleFollow, flushAndRunMultipleServers, ServerInfo, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
+import { cleanupTests, doubleFollow, createMultipleServers, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
 
 const expect = chai.expect
 
 describe('Test audio only video transcoding', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let videoUUID: string
 
   before(async function () {
@@ -36,7 +36,7 @@ describe('Test audio only video transcoding', function () {
         }
       }
     }
-    servers = await flushAndRunMultipleServers(2, configOverride)
+    servers = await createMultipleServers(2, configOverride)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts
index 89d842307..562079a15 100644
--- a/server/tests/api/videos/multiple-servers.ts
+++ b/server/tests/api/videos/multiple-servers.ts
@@ -12,8 +12,8 @@ import {
   completeVideoCheck,
   dateIsValid,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   testImage,
   wait,
@@ -25,7 +25,7 @@ import { VideoCommentThreadTree, VideoPrivacy } from '@shared/models'
 const expect = chai.expect
 
 describe('Test multiple servers', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   const toRemove = []
   let videoUUID = ''
   let videoChannelId: number
@@ -33,7 +33,7 @@ describe('Test multiple servers', function () {
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(3)
+    servers = await createMultipleServers(3)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/videos/resumable-upload.ts b/server/tests/api/videos/resumable-upload.ts
index 2f1cf8a55..b4fc5ee09 100644
--- a/server/tests/api/videos/resumable-upload.ts
+++ b/server/tests/api/videos/resumable-upload.ts
@@ -8,8 +8,8 @@ import { HttpStatusCode } from '@shared/core-utils'
 import {
   buildAbsoluteFixturePath,
   cleanupTests,
-  flushAndRunServer,
-  ServerInfo,
+  createSingleServer,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel
 } from '@shared/extra-utils'
@@ -21,7 +21,7 @@ const expect = chai.expect
 
 describe('Test resumable upload', function () {
   const defaultFixture = 'video_short.mp4'
-  let server: ServerInfo
+  let server: PeerTubeServer
   let rootId: number
 
   async function buildSize (fixture: string, size?: number) {
@@ -99,7 +99,7 @@ describe('Test resumable upload', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
     await setDefaultVideoChannel([ server ])
 
diff --git a/server/tests/api/videos/single-server.ts b/server/tests/api/videos/single-server.ts
index 12c1f7b2f..c0535be09 100644
--- a/server/tests/api/videos/single-server.ts
+++ b/server/tests/api/videos/single-server.ts
@@ -6,8 +6,8 @@ import {
   checkVideoFilesWereRemoved,
   cleanupTests,
   completeVideoCheck,
-  flushAndRunServer,
-  ServerInfo,
+  createSingleServer,
+  PeerTubeServer,
   setAccessTokensToServers,
   testImage,
   wait
@@ -19,7 +19,7 @@ const expect = chai.expect
 describe('Test a single server', function () {
 
   function runSuite (mode: 'legacy' | 'resumable') {
-    let server: ServerInfo = null
+    let server: PeerTubeServer = null
     let videoId: number | string
     let videoId2: string
     let videoUUID = ''
@@ -94,7 +94,7 @@ describe('Test a single server', function () {
     before(async function () {
       this.timeout(30000)
 
-      server = await flushAndRunServer(1)
+      server = await createSingleServer(1)
 
       await setAccessTokensToServers([ server ])
     })
diff --git a/server/tests/api/videos/video-captions.ts b/server/tests/api/videos/video-captions.ts
index abc07194d..6caba6aa6 100644
--- a/server/tests/api/videos/video-captions.ts
+++ b/server/tests/api/videos/video-captions.ts
@@ -6,8 +6,8 @@ import {
   checkVideoFilesWereRemoved,
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   testCaptionFile,
   wait,
@@ -19,13 +19,13 @@ const expect = chai.expect
 describe('Test video captions', function () {
   const uuidRegex = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
 
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
   let videoUUID: string
 
   before(async function () {
     this.timeout(60000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     await setAccessTokensToServers(servers)
     await doubleFollow(servers[0], servers[1])
diff --git a/server/tests/api/videos/video-change-ownership.ts b/server/tests/api/videos/video-change-ownership.ts
index 352eb5ea3..cefddb68e 100644
--- a/server/tests/api/videos/video-change-ownership.ts
+++ b/server/tests/api/videos/video-change-ownership.ts
@@ -7,9 +7,9 @@ import {
   ChangeOwnershipCommand,
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
-  flushAndRunServer,
-  ServerInfo,
+  createMultipleServers,
+  createSingleServer,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   waitJobs
@@ -19,7 +19,7 @@ import { VideoPrivacy } from '@shared/models'
 const expect = chai.expect
 
 describe('Test video change ownership - nominal', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
 
   const firstUser = 'first'
   const secondUser = 'second'
@@ -39,7 +39,7 @@ describe('Test video change ownership - nominal', function () {
   before(async function () {
     this.timeout(50000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
     await setAccessTokensToServers(servers)
     await setDefaultVideoChannel(servers)
 
@@ -251,7 +251,7 @@ describe('Test video change ownership - nominal', function () {
 })
 
 describe('Test video change ownership - quota too small', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   const firstUser = 'first'
   const secondUser = 'second'
 
@@ -263,7 +263,7 @@ describe('Test video change ownership - quota too small', function () {
     this.timeout(50000)
 
     // Run one server
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
 
     await server.users.create({ username: secondUser, videoQuota: 10 })
diff --git a/server/tests/api/videos/video-channels.ts b/server/tests/api/videos/video-channels.ts
index 1efef932c..140fee7fe 100644
--- a/server/tests/api/videos/video-channels.ts
+++ b/server/tests/api/videos/video-channels.ts
@@ -7,8 +7,8 @@ import { ACTOR_IMAGES_SIZE } from '@server/initializers/constants'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   testFileExistsOrNot,
@@ -20,14 +20,14 @@ import { User, VideoChannel } from '@shared/models'
 
 const expect = chai.expect
 
-async function findChannel (server: ServerInfo, channelId: number) {
+async function findChannel (server: PeerTubeServer, channelId: number) {
   const body = await server.channels.list({ sort: '-name' })
 
   return body.data.find(c => c.id === channelId)
 }
 
 describe('Test video channels', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
   let userInfo: User
   let secondVideoChannelId: number
   let totoChannel: number
@@ -40,7 +40,7 @@ describe('Test video channels', function () {
   before(async function () {
     this.timeout(60000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     await setAccessTokensToServers(servers)
     await setDefaultVideoChannel(servers)
diff --git a/server/tests/api/videos/video-comments.ts b/server/tests/api/videos/video-comments.ts
index adb59bd74..9709e0628 100644
--- a/server/tests/api/videos/video-comments.ts
+++ b/server/tests/api/videos/video-comments.ts
@@ -6,8 +6,8 @@ import {
   cleanupTests,
   CommentsCommand,
   dateIsValid,
-  flushAndRunServer,
-  ServerInfo,
+  createSingleServer,
+  PeerTubeServer,
   setAccessTokensToServers,
   testImage
 } from '@shared/extra-utils'
@@ -15,7 +15,7 @@ import {
 const expect = chai.expect
 
 describe('Test video comments', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let videoId: number
   let videoUUID: string
   let threadId: number
@@ -28,7 +28,7 @@ describe('Test video comments', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
diff --git a/server/tests/api/videos/video-description.ts b/server/tests/api/videos/video-description.ts
index b89247288..ce45eac80 100644
--- a/server/tests/api/videos/video-description.ts
+++ b/server/tests/api/videos/video-description.ts
@@ -2,12 +2,12 @@
 
 import 'mocha'
 import * as chai from 'chai'
-import { cleanupTests, doubleFollow, flushAndRunMultipleServers, ServerInfo, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
+import { cleanupTests, doubleFollow, createMultipleServers, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
 
 const expect = chai.expect
 
 describe('Test video description', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let videoUUID = ''
   let videoId: number
   const longDescription = 'my super description for server 1'.repeat(50)
@@ -16,7 +16,7 @@ describe('Test video description', function () {
     this.timeout(40000)
 
     // Run servers
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/videos/video-hls.ts b/server/tests/api/videos/video-hls.ts
index 9d79f2683..4c4b18887 100644
--- a/server/tests/api/videos/video-hls.ts
+++ b/server/tests/api/videos/video-hls.ts
@@ -11,9 +11,9 @@ import {
   checkTmpIsEmpty,
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   makeRawRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs,
   webtorrentAdd
@@ -23,7 +23,7 @@ import { DEFAULT_AUDIO_RESOLUTION } from '../../../initializers/constants'
 
 const expect = chai.expect
 
-async function checkHlsPlaylist (servers: ServerInfo[], videoUUID: string, hlsOnly: boolean, resolutions = [ 240, 360, 480, 720 ]) {
+async function checkHlsPlaylist (servers: PeerTubeServer[], videoUUID: string, hlsOnly: boolean, resolutions = [ 240, 360, 480, 720 ]) {
   for (const server of servers) {
     const videoDetails = await server.videos.get({ id: videoUUID })
     const baseUrl = `http://${videoDetails.account.host}`
@@ -98,7 +98,7 @@ async function checkHlsPlaylist (servers: ServerInfo[], videoUUID: string, hlsOn
 }
 
 describe('Test HLS videos', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let videoUUID = ''
   let videoAudioUUID = ''
 
@@ -176,7 +176,7 @@ describe('Test HLS videos', function () {
         }
       }
     }
-    servers = await flushAndRunMultipleServers(2, configOverride)
+    servers = await createMultipleServers(2, configOverride)
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/videos/video-imports.ts b/server/tests/api/videos/video-imports.ts
index 8b6542aa4..4ef55c3af 100644
--- a/server/tests/api/videos/video-imports.ts
+++ b/server/tests/api/videos/video-imports.ts
@@ -6,9 +6,9 @@ import {
   areHttpImportTestsDisabled,
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   ImportsCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   testCaptionFile,
   testImage,
@@ -19,13 +19,13 @@ import { VideoPrivacy, VideoResolution } from '@shared/models'
 const expect = chai.expect
 
 describe('Test video imports', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let channelIdServer1: number
   let channelIdServer2: number
 
   if (areHttpImportTestsDisabled()) return
 
-  async function checkVideosServer1 (server: ServerInfo, idHttp: string, idMagnet: string, idTorrent: string) {
+  async function checkVideosServer1 (server: PeerTubeServer, idHttp: string, idMagnet: string, idTorrent: string) {
     const videoHttp = await server.videos.get({ id: idHttp })
 
     expect(videoHttp.name).to.equal('small video - youtube')
@@ -63,7 +63,7 @@ describe('Test video imports', function () {
     expect(bodyCaptions.total).to.equal(2)
   }
 
-  async function checkVideoServer2 (server: ServerInfo, id: number | string) {
+  async function checkVideoServer2 (server: PeerTubeServer, id: number | string) {
     const video = await server.videos.get({ id })
 
     expect(video.name).to.equal('my super name')
@@ -84,7 +84,7 @@ describe('Test video imports', function () {
     this.timeout(30_000)
 
     // Run servers
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     await setAccessTokensToServers(servers)
 
diff --git a/server/tests/api/videos/video-nsfw.ts b/server/tests/api/videos/video-nsfw.ts
index 95395a582..b25dcda20 100644
--- a/server/tests/api/videos/video-nsfw.ts
+++ b/server/tests/api/videos/video-nsfw.ts
@@ -2,7 +2,7 @@
 
 import 'mocha'
 import * as chai from 'chai'
-import { cleanupTests, flushAndRunServer, ServerInfo, setAccessTokensToServers } from '@shared/extra-utils'
+import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
 import { BooleanBothQuery, CustomConfig, ResultList, Video, VideosOverview } from '@shared/models'
 
 const expect = chai.expect
@@ -13,7 +13,7 @@ function createOverviewRes (overview: VideosOverview) {
 }
 
 describe('Test video NSFW policy', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userAccessToken: string
   let customConfig: CustomConfig
 
@@ -61,7 +61,7 @@ describe('Test video NSFW policy', function () {
 
   before(async function () {
     this.timeout(50000)
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     // Get the access tokens
     await setAccessTokensToServers([ server ])
diff --git a/server/tests/api/videos/video-playlist-thumbnails.ts b/server/tests/api/videos/video-playlist-thumbnails.ts
index 709f64c4d..9a682c12b 100644
--- a/server/tests/api/videos/video-playlist-thumbnails.ts
+++ b/server/tests/api/videos/video-playlist-thumbnails.ts
@@ -5,8 +5,8 @@ import * as chai from 'chai'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   testImage,
@@ -17,7 +17,7 @@ import { VideoPlaylistPrivacy } from '../../../../shared/models/videos/playlist/
 const expect = chai.expect
 
 describe('Playlist thumbnail', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
 
   let playlistWithoutThumbnailId: number
   let playlistWithThumbnailId: number
@@ -30,13 +30,13 @@ describe('Playlist thumbnail', function () {
   let video1: number
   let video2: number
 
-  async function getPlaylistWithoutThumbnail (server: ServerInfo) {
+  async function getPlaylistWithoutThumbnail (server: PeerTubeServer) {
     const body = await server.playlists.list({ start: 0, count: 10 })
 
     return body.data.find(p => p.displayName === 'playlist without thumbnail')
   }
 
-  async function getPlaylistWithThumbnail (server: ServerInfo) {
+  async function getPlaylistWithThumbnail (server: PeerTubeServer) {
     const body = await server.playlists.list({ start: 0, count: 10 })
 
     return body.data.find(p => p.displayName === 'playlist with thumbnail')
@@ -45,7 +45,7 @@ describe('Playlist thumbnail', function () {
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(2, { transcoding: { enabled: false } })
+    servers = await createMultipleServers(2, { transcoding: { enabled: false } })
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/videos/video-playlists.ts b/server/tests/api/videos/video-playlists.ts
index 0dc53d4c0..71ca3e63a 100644
--- a/server/tests/api/videos/video-playlists.ts
+++ b/server/tests/api/videos/video-playlists.ts
@@ -7,9 +7,9 @@ import {
   checkPlaylistFilesWereRemoved,
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   PlaylistsCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   testImage,
@@ -28,7 +28,7 @@ import {
 const expect = chai.expect
 
 async function checkPlaylistElementType (
-  servers: ServerInfo[],
+  servers: PeerTubeServer[],
   playlistId: string,
   type: VideoPlaylistElementType,
   position: number,
@@ -52,7 +52,7 @@ async function checkPlaylistElementType (
 }
 
 describe('Test video playlists', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
 
   let playlistServer2Id1: number
   let playlistServer2Id2: number
@@ -75,7 +75,7 @@ describe('Test video playlists', function () {
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(3, { transcoding: { enabled: false } })
+    servers = await createMultipleServers(3, { transcoding: { enabled: false } })
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
@@ -584,10 +584,10 @@ describe('Test video playlists', function () {
   })
 
   describe('Element type', function () {
-    let groupUser1: ServerInfo[]
-    let groupWithoutToken1: ServerInfo[]
-    let group1: ServerInfo[]
-    let group2: ServerInfo[]
+    let groupUser1: PeerTubeServer[]
+    let groupWithoutToken1: PeerTubeServer[]
+    let group1: PeerTubeServer[]
+    let group2: PeerTubeServer[]
 
     let video1: string
     let video2: string
diff --git a/server/tests/api/videos/video-privacy.ts b/server/tests/api/videos/video-privacy.ts
index de08a9e7b..5ec626155 100644
--- a/server/tests/api/videos/video-privacy.ts
+++ b/server/tests/api/videos/video-privacy.ts
@@ -3,13 +3,13 @@
 import 'mocha'
 import * as chai from 'chai'
 import { HttpStatusCode } from '@shared/core-utils'
-import { cleanupTests, doubleFollow, flushAndRunServer, ServerInfo, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
+import { cleanupTests, doubleFollow, createSingleServer, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
 import { VideoCreateResult, VideoPrivacy } from '@shared/models'
 
 const expect = chai.expect
 
 describe('Test video privacy', function () {
-  const servers: ServerInfo[] = []
+  const servers: PeerTubeServer[] = []
   let anotherUserToken: string
 
   let privateVideoId: number
@@ -35,8 +35,8 @@ describe('Test video privacy', function () {
     this.timeout(50000)
 
     // Run servers
-    servers.push(await flushAndRunServer(1, dontFederateUnlistedConfig))
-    servers.push(await flushAndRunServer(2))
+    servers.push(await createSingleServer(1, dontFederateUnlistedConfig))
+    servers.push(await createSingleServer(2))
 
     // Get the access tokens
     await setAccessTokensToServers(servers)
diff --git a/server/tests/api/videos/video-schedule-update.ts b/server/tests/api/videos/video-schedule-update.ts
index 3938b47c8..22b5cf1c2 100644
--- a/server/tests/api/videos/video-schedule-update.ts
+++ b/server/tests/api/videos/video-schedule-update.ts
@@ -5,8 +5,8 @@ import * as chai from 'chai'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   wait,
   waitJobs
@@ -23,14 +23,14 @@ function in10Seconds () {
 }
 
 describe('Test video update scheduler', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let video2UUID: string
 
   before(async function () {
     this.timeout(30000)
 
     // Run servers
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     await setAccessTokensToServers(servers)
 
diff --git a/server/tests/api/videos/video-transcoder.ts b/server/tests/api/videos/video-transcoder.ts
index 37450eeeb..2465d2d89 100644
--- a/server/tests/api/videos/video-transcoder.ts
+++ b/server/tests/api/videos/video-transcoder.ts
@@ -9,11 +9,11 @@ import {
   buildAbsoluteFixturePath,
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   generateHighBitrateVideo,
   generateVideoWithFramerate,
   makeGetRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs,
   webtorrentAdd
@@ -31,7 +31,7 @@ import {
 
 const expect = chai.expect
 
-function updateConfigForTranscoding (server: ServerInfo) {
+function updateConfigForTranscoding (server: PeerTubeServer) {
   return server.config.updateCustomSubConfig({
     newConfig: {
       transcoding: {
@@ -56,14 +56,14 @@ function updateConfigForTranscoding (server: ServerInfo) {
 }
 
 describe('Test video transcoding', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let video4k: string
 
   before(async function () {
     this.timeout(30_000)
 
     // Run servers
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     await setAccessTokensToServers(servers)
 
diff --git a/server/tests/api/videos/videos-filter.ts b/server/tests/api/videos/videos-filter.ts
index af1541dbd..db9150655 100644
--- a/server/tests/api/videos/videos-filter.ts
+++ b/server/tests/api/videos/videos-filter.ts
@@ -6,14 +6,14 @@ import { HttpStatusCode } from '@shared/core-utils'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   makeGetRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '@shared/extra-utils'
 import { UserRole, Video, VideoPrivacy } from '@shared/models'
 
-async function getVideosNames (server: ServerInfo, token: string, filter: string, statusCodeExpected = HttpStatusCode.OK_200) {
+async function getVideosNames (server: PeerTubeServer, token: string, filter: string, statusCodeExpected = HttpStatusCode.OK_200) {
   const paths = [
     '/api/v1/video-channels/root_channel/videos',
     '/api/v1/accounts/root/videos',
@@ -42,14 +42,14 @@ async function getVideosNames (server: ServerInfo, token: string, filter: string
 }
 
 describe('Test videos filter', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
 
   // ---------------------------------------------------------------
 
   before(async function () {
     this.timeout(160000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     await setAccessTokensToServers(servers)
 
diff --git a/server/tests/api/videos/videos-history.ts b/server/tests/api/videos/videos-history.ts
index 4b5e581d1..55e53cb94 100644
--- a/server/tests/api/videos/videos-history.ts
+++ b/server/tests/api/videos/videos-history.ts
@@ -5,11 +5,10 @@ import * as chai from 'chai'
 import { HttpStatusCode } from '@shared/core-utils'
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   HistoryCommand,
   killallServers,
-  reRunServer,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   wait
 } from '@shared/extra-utils'
@@ -18,7 +17,7 @@ import { Video } from '@shared/models'
 const expect = chai.expect
 
 describe('Test videos history', function () {
-  let server: ServerInfo = null
+  let server: PeerTubeServer = null
   let video1UUID: string
   let video2UUID: string
   let video3UUID: string
@@ -29,7 +28,7 @@ describe('Test videos history', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
 
@@ -191,7 +190,7 @@ describe('Test videos history', function () {
 
     await killallServers([ server ])
 
-    await reRunServer(server, { history: { videos: { max_age: '10 days' } } })
+    await server.run({ history: { videos: { max_age: '10 days' } } })
 
     await wait(6000)
 
@@ -206,7 +205,7 @@ describe('Test videos history', function () {
 
     await killallServers([ server ])
 
-    await reRunServer(server, { history: { videos: { max_age: '5 seconds' } } })
+    await server.run({ history: { videos: { max_age: '5 seconds' } } })
 
     await wait(6000)
 
diff --git a/server/tests/api/videos/videos-overview.ts b/server/tests/api/videos/videos-overview.ts
index f0657b334..70aa66549 100644
--- a/server/tests/api/videos/videos-overview.ts
+++ b/server/tests/api/videos/videos-overview.ts
@@ -2,13 +2,13 @@
 
 import 'mocha'
 import * as chai from 'chai'
-import { cleanupTests, flushAndRunServer, ServerInfo, setAccessTokensToServers, wait } from '@shared/extra-utils'
+import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers, wait } from '@shared/extra-utils'
 import { VideosOverview } from '@shared/models'
 
 const expect = chai.expect
 
 describe('Test a videos overview', function () {
-  let server: ServerInfo = null
+  let server: PeerTubeServer = null
 
   function testOverviewCount (overview: VideosOverview, expected: number) {
     expect(overview.tags).to.have.lengthOf(expected)
@@ -19,7 +19,7 @@ describe('Test a videos overview', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
 
     await setAccessTokensToServers([ server ])
   })
diff --git a/server/tests/api/videos/videos-views-cleaner.ts b/server/tests/api/videos/videos-views-cleaner.ts
index 238662cf3..0be03ddd2 100644
--- a/server/tests/api/videos/videos-views-cleaner.ts
+++ b/server/tests/api/videos/videos-views-cleaner.ts
@@ -5,10 +5,9 @@ import * as chai from 'chai'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   killallServers,
-  reRunServer,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   wait,
   waitJobs
@@ -17,7 +16,7 @@ import {
 const expect = chai.expect
 
 describe('Test video views cleaner', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
 
   let videoIdServer1: string
   let videoIdServer2: string
@@ -25,7 +24,7 @@ describe('Test video views cleaner', function () {
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
     await setAccessTokensToServers(servers)
 
     await doubleFollow(servers[0], servers[1])
@@ -48,7 +47,7 @@ describe('Test video views cleaner', function () {
 
     await killallServers([ servers[0] ])
 
-    await reRunServer(servers[0], { views: { videos: { remote: { max_age: '10 days' } } } })
+    await servers[0].run({ views: { videos: { remote: { max_age: '10 days' } } } })
 
     await wait(6000)
 
@@ -74,7 +73,7 @@ describe('Test video views cleaner', function () {
 
     await killallServers([ servers[0] ])
 
-    await reRunServer(servers[0], { views: { videos: { remote: { max_age: '5 seconds' } } } })
+    await servers[0].run({ views: { videos: { remote: { max_age: '5 seconds' } } } })
 
     await wait(6000)
 
diff --git a/server/tests/cli/create-import-video-file-job.ts b/server/tests/cli/create-import-video-file-job.ts
index 26f4bdc8d..e8cd71e09 100644
--- a/server/tests/cli/create-import-video-file-job.ts
+++ b/server/tests/cli/create-import-video-file-job.ts
@@ -2,7 +2,7 @@
 
 import 'mocha'
 import * as chai from 'chai'
-import { cleanupTests, doubleFollow, flushAndRunMultipleServers, ServerInfo, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
+import { cleanupTests, doubleFollow, createMultipleServers, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils'
 import { VideoFile } from '@shared/models'
 
 const expect = chai.expect
@@ -20,7 +20,7 @@ function assertVideoProperties (video: VideoFile, resolution: number, extname: s
 describe('Test create import video jobs', function () {
   this.timeout(60000)
 
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let video1UUID: string
   let video2UUID: string
 
@@ -28,7 +28,7 @@ describe('Test create import video jobs', function () {
     this.timeout(90000)
 
     // Run server 2 to have transcoding enabled
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
     await setAccessTokensToServers(servers)
 
     await doubleFollow(servers[0], servers[1])
diff --git a/server/tests/cli/create-transcoding-job.ts b/server/tests/cli/create-transcoding-job.ts
index c9bbab802..53f187f90 100644
--- a/server/tests/cli/create-transcoding-job.ts
+++ b/server/tests/cli/create-transcoding-job.ts
@@ -5,8 +5,8 @@ import * as chai from 'chai'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
-  ServerInfo,
+  createMultipleServers,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs
 } from '../../../shared/extra-utils'
@@ -14,7 +14,7 @@ import {
 const expect = chai.expect
 
 describe('Test create transcoding jobs', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   const videosUUID: string[] = []
 
   const config = {
@@ -39,7 +39,7 @@ describe('Test create transcoding jobs', function () {
     this.timeout(60000)
 
     // Run server 2 to have transcoding enabled
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
     await setAccessTokensToServers(servers)
 
     await servers[0].config.updateCustomSubConfig({ newConfig: config })
diff --git a/server/tests/cli/optimize-old-videos.ts b/server/tests/cli/optimize-old-videos.ts
index eefc95a6d..53f47a85e 100644
--- a/server/tests/cli/optimize-old-videos.ts
+++ b/server/tests/cli/optimize-old-videos.ts
@@ -6,9 +6,9 @@ import { join } from 'path'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   generateHighBitrateVideo,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   wait,
   waitJobs
@@ -20,13 +20,13 @@ import { VIDEO_TRANSCODING_FPS } from '../../initializers/constants'
 const expect = chai.expect
 
 describe('Test optimize old videos', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
 
   before(async function () {
     this.timeout(200000)
 
     // Run server 2 to have transcoding enabled
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
     await setAccessTokensToServers(servers)
 
     await doubleFollow(servers[0], servers[1])
diff --git a/server/tests/cli/peertube.ts b/server/tests/cli/peertube.ts
index a83aa7724..f19b6ae22 100644
--- a/server/tests/cli/peertube.ts
+++ b/server/tests/cli/peertube.ts
@@ -8,16 +8,16 @@ import {
   cleanupTests,
   CLICommand,
   doubleFollow,
-  flushAndRunServer,
+  createSingleServer,
   ImportsCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   testHelloWorldRegisteredSettings,
   waitJobs
 } from '../../../shared/extra-utils'
 
 describe('Test CLI wrapper', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let userAccessToken: string
 
   let cliCommand: CLICommand
@@ -27,7 +27,7 @@ describe('Test CLI wrapper', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
 
     await server.users.create({ username: 'user_1', password: 'super_password' })
@@ -210,14 +210,14 @@ describe('Test CLI wrapper', function () {
   })
 
   describe('Manage video redundancies', function () {
-    let anotherServer: ServerInfo
+    let anotherServer: PeerTubeServer
     let video1Server2: number
-    let servers: ServerInfo[]
+    let servers: PeerTubeServer[]
 
     before(async function () {
       this.timeout(120000)
 
-      anotherServer = await flushAndRunServer(2)
+      anotherServer = await createSingleServer(2)
       await setAccessTokensToServers([ anotherServer ])
 
       await doubleFollow(server, anotherServer)
diff --git a/server/tests/cli/plugins.ts b/server/tests/cli/plugins.ts
index 178a7a2d9..42651d79c 100644
--- a/server/tests/cli/plugins.ts
+++ b/server/tests/cli/plugins.ts
@@ -4,21 +4,20 @@ import 'mocha'
 import { expect } from 'chai'
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   killallServers,
   PluginsCommand,
-  reRunServer,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '../../../shared/extra-utils'
 
 describe('Test plugin scripts', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
   })
 
@@ -40,7 +39,7 @@ describe('Test plugin scripts', function () {
     this.timeout(30000)
 
     await killallServers([ server ])
-    await reRunServer(server)
+    await server.run()
 
     const config = await server.config.getConfig()
 
@@ -63,7 +62,7 @@ describe('Test plugin scripts', function () {
     this.timeout(30000)
 
     await killallServers([ server ])
-    await reRunServer(server)
+    await server.run()
 
     const config = await server.config.getConfig()
 
diff --git a/server/tests/cli/prune-storage.ts b/server/tests/cli/prune-storage.ts
index 9912a36e0..5bf86462b 100644
--- a/server/tests/cli/prune-storage.ts
+++ b/server/tests/cli/prune-storage.ts
@@ -10,10 +10,10 @@ import {
   cleanupTests,
   CLICommand,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   killallServers,
   makeGetRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   wait,
@@ -23,13 +23,13 @@ import { VideoPlaylistPrivacy } from '@shared/models'
 
 const expect = chai.expect
 
-async function countFiles (server: ServerInfo, directory: string) {
+async function countFiles (server: PeerTubeServer, directory: string) {
   const files = await readdir(server.servers.buildDirectory(directory))
 
   return files.length
 }
 
-async function assertNotExists (server: ServerInfo, directory: string, substring: string) {
+async function assertNotExists (server: PeerTubeServer, directory: string, substring: string) {
   const files = await readdir(server.servers.buildDirectory(directory))
 
   for (const f of files) {
@@ -37,7 +37,7 @@ async function assertNotExists (server: ServerInfo, directory: string, substring
   }
 }
 
-async function assertCountAreOkay (servers: ServerInfo[]) {
+async function assertCountAreOkay (servers: PeerTubeServer[]) {
   for (const server of servers) {
     const videosCount = await countFiles(server, 'videos')
     expect(videosCount).to.equal(8)
@@ -57,13 +57,13 @@ async function assertCountAreOkay (servers: ServerInfo[]) {
 }
 
 describe('Test prune storage scripts', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
   const badNames: { [directory: string]: string[] } = {}
 
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(2, { transcoding: { enabled: true } })
+    servers = await createMultipleServers(2, { transcoding: { enabled: true } })
     await setAccessTokensToServers(servers)
     await setDefaultVideoChannel(servers)
 
diff --git a/server/tests/cli/regenerate-thumbnails.ts b/server/tests/cli/regenerate-thumbnails.ts
index 2df1a1157..d532a5c2b 100644
--- a/server/tests/cli/regenerate-thumbnails.ts
+++ b/server/tests/cli/regenerate-thumbnails.ts
@@ -7,14 +7,14 @@ import { Video } from '@shared/models'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   makeRawRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs
 } from '../../../shared/extra-utils'
 
-async function testThumbnail (server: ServerInfo, videoId: number | string) {
+async function testThumbnail (server: PeerTubeServer, videoId: number | string) {
   const video = await server.videos.get({ id: videoId })
 
   const requests = [
@@ -29,7 +29,7 @@ async function testThumbnail (server: ServerInfo, videoId: number | string) {
 }
 
 describe('Test regenerate thumbnails script', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
 
   let video1: Video
   let video2: Video
@@ -41,7 +41,7 @@ describe('Test regenerate thumbnails script', function () {
   before(async function () {
     this.timeout(60000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
     await setAccessTokensToServers(servers)
 
     await doubleFollow(servers[0], servers[1])
diff --git a/server/tests/cli/reset-password.ts b/server/tests/cli/reset-password.ts
index e0d6f220a..4a02db35d 100644
--- a/server/tests/cli/reset-password.ts
+++ b/server/tests/cli/reset-password.ts
@@ -1,12 +1,12 @@
 import 'mocha'
-import { cleanupTests, CLICommand, flushAndRunServer, ServerInfo, setAccessTokensToServers } from '../../../shared/extra-utils'
+import { cleanupTests, CLICommand, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '../../../shared/extra-utils'
 
 describe('Test reset password scripts', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
 
   before(async function () {
     this.timeout(30000)
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
 
     await server.users.create({ username: 'user_1', password: 'super password' })
diff --git a/server/tests/cli/update-host.ts b/server/tests/cli/update-host.ts
index d2d196456..fcbcb55ba 100644
--- a/server/tests/cli/update-host.ts
+++ b/server/tests/cli/update-host.ts
@@ -4,18 +4,17 @@ import 'mocha'
 import { expect } from 'chai'
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   killallServers,
   makeActivityPubGetRequest,
   parseTorrentVideo,
-  reRunServer,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs
 } from '@shared/extra-utils'
 
 describe('Test update host scripts', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
 
   before(async function () {
     this.timeout(60000)
@@ -26,7 +25,7 @@ describe('Test update host scripts', function () {
       }
     }
     // Run server 2 to have transcoding enabled
-    server = await flushAndRunServer(2, overrideConfig)
+    server = await createSingleServer(2, overrideConfig)
     await setAccessTokensToServers([ server ])
 
     // Upload two videos for our needs
@@ -56,7 +55,7 @@ describe('Test update host scripts', function () {
 
     await killallServers([ server ])
     // Run server with standard configuration
-    await reRunServer(server)
+    await server.run()
 
     await server.cli.execWithEnv(`npm run update-host`)
   })
diff --git a/server/tests/client.ts b/server/tests/client.ts
index caf6fb00c..959b34653 100644
--- a/server/tests/client.ts
+++ b/server/tests/client.ts
@@ -8,10 +8,10 @@ import { Account, HTMLServerConfig, ServerConfig, VideoPlaylistCreateResult, Vid
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   makeGetRequest,
   makeHTMLRequest,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   waitJobs
@@ -29,7 +29,7 @@ function checkIndexTags (html: string, title: string, description: string, css:
 }
 
 describe('Test a client controllers', function () {
-  let servers: ServerInfo[] = []
+  let servers: PeerTubeServer[] = []
   let account: Account
 
   const videoName = 'my super name for server 1'
@@ -51,7 +51,7 @@ describe('Test a client controllers', function () {
   before(async function () {
     this.timeout(120000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
 
     await setAccessTokensToServers(servers)
 
diff --git a/server/tests/external-plugins/auth-ldap.ts b/server/tests/external-plugins/auth-ldap.ts
index ef624152e..aaaf23278 100644
--- a/server/tests/external-plugins/auth-ldap.ts
+++ b/server/tests/external-plugins/auth-ldap.ts
@@ -3,17 +3,17 @@
 import 'mocha'
 import { expect } from 'chai'
 import { HttpStatusCode } from '@shared/core-utils'
-import { cleanupTests, flushAndRunServer, ServerInfo, setAccessTokensToServers } from '@shared/extra-utils'
+import { cleanupTests, createSingleServer, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
 
 describe('Official plugin auth-ldap', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let accessToken: string
   let userId: number
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
 
     await server.plugins.install({ npmName: 'peertube-plugin-auth-ldap' })
diff --git a/server/tests/external-plugins/auto-block-videos.ts b/server/tests/external-plugins/auto-block-videos.ts
index 3b4b48bf0..9cb86310b 100644
--- a/server/tests/external-plugins/auto-block-videos.ts
+++ b/server/tests/external-plugins/auto-block-videos.ts
@@ -5,17 +5,16 @@ import { expect } from 'chai'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   killallServers,
   MockBlocklist,
-  reRunServer,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   wait
 } from '@shared/extra-utils'
 import { Video } from '@shared/models'
 
-async function check (server: ServerInfo, videoUUID: string, exists = true) {
+async function check (server: PeerTubeServer, videoUUID: string, exists = true) {
   const { data } = await server.videos.list()
 
   const video = data.find(v => v.uuid === videoUUID)
@@ -25,7 +24,7 @@ async function check (server: ServerInfo, videoUUID: string, exists = true) {
 }
 
 describe('Official plugin auto-block videos', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
   let blocklistServer: MockBlocklist
   let server1Videos: Video[] = []
   let server2Videos: Video[] = []
@@ -34,7 +33,7 @@ describe('Official plugin auto-block videos', function () {
   before(async function () {
     this.timeout(60000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
     await setAccessTokensToServers(servers)
 
     for (const server of servers) {
@@ -161,7 +160,7 @@ describe('Official plugin auto-block videos', function () {
     await check(servers[0], video.uuid, true)
 
     await killallServers([ servers[0] ])
-    await reRunServer(servers[0])
+    await servers[0].run()
     await wait(2000)
 
     await check(servers[0], video.uuid, true)
diff --git a/server/tests/external-plugins/auto-mute.ts b/server/tests/external-plugins/auto-mute.ts
index 25b56a546..771201505 100644
--- a/server/tests/external-plugins/auto-mute.ts
+++ b/server/tests/external-plugins/auto-mute.ts
@@ -6,26 +6,25 @@ import { HttpStatusCode } from '@shared/core-utils'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   killallServers,
   makeGetRequest,
   MockBlocklist,
-  reRunServer,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   wait
 } from '@shared/extra-utils'
 
 describe('Official plugin auto-mute', function () {
   const autoMuteListPath = '/plugins/auto-mute/router/api/v1/mute-list'
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
   let blocklistServer: MockBlocklist
   let port: number
 
   before(async function () {
     this.timeout(30000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
     await setAccessTokensToServers(servers)
 
     for (const server of servers) {
@@ -150,7 +149,7 @@ describe('Official plugin auto-mute', function () {
     }
 
     await killallServers([ servers[0] ])
-    await reRunServer(servers[0])
+    await servers[0].run()
     await wait(2000)
 
     {
diff --git a/server/tests/feeds/feeds.ts b/server/tests/feeds/feeds.ts
index 8bdafc644..7735299d3 100644
--- a/server/tests/feeds/feeds.ts
+++ b/server/tests/feeds/feeds.ts
@@ -7,9 +7,9 @@ import { HttpStatusCode } from '@shared/core-utils'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
-  flushAndRunServer,
-  ServerInfo,
+  createMultipleServers,
+  createSingleServer,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs
 } from '@shared/extra-utils'
@@ -21,8 +21,8 @@ chai.config.includeStack = true
 const expect = chai.expect
 
 describe('Test syndication feeds', () => {
-  let servers: ServerInfo[] = []
-  let serverHLSOnly: ServerInfo
+  let servers: PeerTubeServer[] = []
+  let serverHLSOnly: PeerTubeServer
   let userAccessToken: string
   let rootAccountId: number
   let rootChannelId: number
@@ -34,8 +34,8 @@ describe('Test syndication feeds', () => {
     this.timeout(120000)
 
     // Run servers
-    servers = await flushAndRunMultipleServers(2)
-    serverHLSOnly = await flushAndRunServer(3, {
+    servers = await createMultipleServers(2)
+    serverHLSOnly = await createSingleServer(3, {
       transcoding: {
         enabled: true,
         webtorrent: { enabled: false },
diff --git a/server/tests/misc-endpoints.ts b/server/tests/misc-endpoints.ts
index f7c9e6c26..a4f344fcc 100644
--- a/server/tests/misc-endpoints.ts
+++ b/server/tests/misc-endpoints.ts
@@ -3,18 +3,18 @@
 import 'mocha'
 import * as chai from 'chai'
 import { HttpStatusCode } from '@shared/core-utils'
-import { cleanupTests, flushAndRunServer, makeGetRequest, ServerInfo, setAccessTokensToServers } from '@shared/extra-utils'
+import { cleanupTests, createSingleServer, makeGetRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
 import { VideoPrivacy } from '@shared/models'
 
 const expect = chai.expect
 
 describe('Test misc endpoints', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
 
   before(async function () {
     this.timeout(120000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
   })
 
diff --git a/server/tests/plugins/action-hooks.ts b/server/tests/plugins/action-hooks.ts
index 12d5c23c5..b96de4e90 100644
--- a/server/tests/plugins/action-hooks.ts
+++ b/server/tests/plugins/action-hooks.ts
@@ -3,18 +3,17 @@
 import 'mocha'
 import {
   cleanupTests,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   killallServers,
+  PeerTubeServer,
   PluginsCommand,
-  reRunServer,
-  ServerInfo,
   setAccessTokensToServers,
   setDefaultVideoChannel
 } from '@shared/extra-utils'
 import { ServerHookName, VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models'
 
 describe('Test plugin action hooks', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
   let videoUUID: string
   let threadId: number
 
@@ -25,7 +24,7 @@ describe('Test plugin action hooks', function () {
   before(async function () {
     this.timeout(30000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
     await setAccessTokensToServers(servers)
     await setDefaultVideoChannel(servers)
 
@@ -33,7 +32,7 @@ describe('Test plugin action hooks', function () {
 
     await killallServers([ servers[0] ])
 
-    await reRunServer(servers[0], {
+    await servers[0].run({
       live: {
         enabled: true
       }
diff --git a/server/tests/plugins/external-auth.ts b/server/tests/plugins/external-auth.ts
index 48f942f7f..c0834a14c 100644
--- a/server/tests/plugins/external-auth.ts
+++ b/server/tests/plugins/external-auth.ts
@@ -6,16 +6,16 @@ import { HttpStatusCode } from '@shared/core-utils'
 import {
   cleanupTests,
   decodeQueryString,
-  flushAndRunServer,
+  createSingleServer,
   PluginsCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   wait
 } from '@shared/extra-utils'
 import { UserRole } from '@shared/models'
 
 async function loginExternal (options: {
-  server: ServerInfo
+  server: PeerTubeServer
   npmName: string
   authName: string
   username: string
@@ -46,7 +46,7 @@ async function loginExternal (options: {
 }
 
 describe('Test external auth plugins', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
 
   let cyanAccessToken: string
   let cyanRefreshToken: string
@@ -59,7 +59,7 @@ describe('Test external auth plugins', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
 
     for (const suffix of [ 'one', 'two', 'three' ]) {
diff --git a/server/tests/plugins/filter-hooks.ts b/server/tests/plugins/filter-hooks.ts
index 18479dcf5..5d94303a9 100644
--- a/server/tests/plugins/filter-hooks.ts
+++ b/server/tests/plugins/filter-hooks.ts
@@ -6,11 +6,11 @@ import { HttpStatusCode } from '@shared/core-utils'
 import {
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   ImportsCommand,
   makeRawRequest,
   PluginsCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   waitJobs
@@ -20,14 +20,14 @@ import { VideoDetails, VideoImportState, VideoPlaylist, VideoPlaylistPrivacy, Vi
 const expect = chai.expect
 
 describe('Test plugin filter hooks', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
   let videoUUID: string
   let threadId: number
 
   before(async function () {
     this.timeout(60000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
     await setAccessTokensToServers(servers)
     await setDefaultVideoChannel(servers)
     await doubleFollow(servers[0], servers[1])
diff --git a/server/tests/plugins/html-injection.ts b/server/tests/plugins/html-injection.ts
index 0cb89f511..2902c39b7 100644
--- a/server/tests/plugins/html-injection.ts
+++ b/server/tests/plugins/html-injection.ts
@@ -4,23 +4,23 @@ import 'mocha'
 import * as chai from 'chai'
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   makeHTMLRequest,
   PluginsCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '../../../shared/extra-utils'
 
 const expect = chai.expect
 
 describe('Test plugins HTML injection', function () {
-  let server: ServerInfo = null
+  let server: PeerTubeServer = null
   let command: PluginsCommand
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
 
     command = server.plugins
diff --git a/server/tests/plugins/id-and-pass-auth.ts b/server/tests/plugins/id-and-pass-auth.ts
index 203996af8..981bcad91 100644
--- a/server/tests/plugins/id-and-pass-auth.ts
+++ b/server/tests/plugins/id-and-pass-auth.ts
@@ -3,11 +3,11 @@
 import 'mocha'
 import { expect } from 'chai'
 import { HttpStatusCode } from '@shared/core-utils'
-import { cleanupTests, flushAndRunServer, PluginsCommand, ServerInfo, setAccessTokensToServers, wait } from '@shared/extra-utils'
+import { cleanupTests, createSingleServer, PluginsCommand, PeerTubeServer, setAccessTokensToServers, wait } from '@shared/extra-utils'
 import { UserRole } from '@shared/models'
 
 describe('Test id and pass auth plugins', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
 
   let crashAccessToken: string
   let crashRefreshToken: string
@@ -18,7 +18,7 @@ describe('Test id and pass auth plugins', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
 
     for (const suffix of [ 'one', 'two', 'three' ]) {
diff --git a/server/tests/plugins/plugin-helpers.ts b/server/tests/plugins/plugin-helpers.ts
index cf16aaa9d..1d87b84ae 100644
--- a/server/tests/plugins/plugin-helpers.ts
+++ b/server/tests/plugins/plugin-helpers.ts
@@ -7,16 +7,16 @@ import {
   checkVideoFilesWereRemoved,
   cleanupTests,
   doubleFollow,
-  flushAndRunMultipleServers,
+  createMultipleServers,
   makeGetRequest,
   makePostBodyRequest,
   PluginsCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   waitJobs
 } from '@shared/extra-utils'
 
-function postCommand (server: ServerInfo, command: string, bodyArg?: object) {
+function postCommand (server: PeerTubeServer, command: string, bodyArg?: object) {
   const body = { command }
   if (bodyArg) Object.assign(body, bodyArg)
 
@@ -29,12 +29,12 @@ function postCommand (server: ServerInfo, command: string, bodyArg?: object) {
 }
 
 describe('Test plugin helpers', function () {
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
 
   before(async function () {
     this.timeout(60000)
 
-    servers = await flushAndRunMultipleServers(2)
+    servers = await createMultipleServers(2)
     await setAccessTokensToServers(servers)
 
     await doubleFollow(servers[0], servers[1])
diff --git a/server/tests/plugins/plugin-router.ts b/server/tests/plugins/plugin-router.ts
index 1c53dd80c..dec8ca4bb 100644
--- a/server/tests/plugins/plugin-router.ts
+++ b/server/tests/plugins/plugin-router.ts
@@ -5,16 +5,16 @@ import { expect } from 'chai'
 import { HttpStatusCode } from '@shared/core-utils'
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   makeGetRequest,
   makePostBodyRequest,
   PluginsCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers
 } from '@shared/extra-utils'
 
 describe('Test plugin helpers', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   const basePaths = [
     '/plugins/test-five/router/',
     '/plugins/test-five/0.0.1/router/'
@@ -23,7 +23,7 @@ describe('Test plugin helpers', function () {
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
 
     await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-five') })
diff --git a/server/tests/plugins/plugin-storage.ts b/server/tests/plugins/plugin-storage.ts
index 30e231439..5745914a5 100644
--- a/server/tests/plugins/plugin-storage.ts
+++ b/server/tests/plugins/plugin-storage.ts
@@ -5,15 +5,22 @@ import { expect } from 'chai'
 import { pathExists, readdir, readFile } from 'fs-extra'
 import { join } from 'path'
 import { HttpStatusCode } from '@shared/core-utils'
-import { cleanupTests, flushAndRunServer, makeGetRequest, PluginsCommand, ServerInfo, setAccessTokensToServers } from '@shared/extra-utils'
+import {
+  cleanupTests,
+  createSingleServer,
+  makeGetRequest,
+  PeerTubeServer,
+  PluginsCommand,
+  setAccessTokensToServers
+} from '@shared/extra-utils'
 
 describe('Test plugin storage', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
 
     await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-six') })
diff --git a/server/tests/plugins/plugin-transcoding.ts b/server/tests/plugins/plugin-transcoding.ts
index 3a03065b0..3c54d3796 100644
--- a/server/tests/plugins/plugin-transcoding.ts
+++ b/server/tests/plugins/plugin-transcoding.ts
@@ -6,9 +6,9 @@ import { join } from 'path'
 import { getAudioStream, getVideoFileFPS, getVideoStreamFromFile } from '@server/helpers/ffprobe-utils'
 import {
   cleanupTests,
-  flushAndRunServer,
+  createSingleServer,
   PluginsCommand,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel,
   testFfmpegStreamError,
@@ -16,7 +16,7 @@ import {
 } from '@shared/extra-utils'
 import { VideoPrivacy } from '@shared/models'
 
-async function createLiveWrapper (server: ServerInfo) {
+async function createLiveWrapper (server: PeerTubeServer) {
   const liveAttributes = {
     name: 'live video',
     channelId: server.store.channel.id,
@@ -28,7 +28,7 @@ async function createLiveWrapper (server: ServerInfo) {
   return uuid
 }
 
-function updateConf (server: ServerInfo, vodProfile: string, liveProfile: string) {
+function updateConf (server: PeerTubeServer, vodProfile: string, liveProfile: string) {
   return server.config.updateCustomSubConfig({
     newConfig: {
       transcoding: {
@@ -64,12 +64,12 @@ function updateConf (server: ServerInfo, vodProfile: string, liveProfile: string
 }
 
 describe('Test transcoding plugins', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
 
   before(async function () {
     this.timeout(60000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
     await setDefaultVideoChannel([ server ])
 
diff --git a/server/tests/plugins/plugin-unloading.ts b/server/tests/plugins/plugin-unloading.ts
index 26a27abca..6c405b7f5 100644
--- a/server/tests/plugins/plugin-unloading.ts
+++ b/server/tests/plugins/plugin-unloading.ts
@@ -3,17 +3,24 @@
 import 'mocha'
 import { expect } from 'chai'
 import { HttpStatusCode } from '@shared/core-utils'
-import { cleanupTests, flushAndRunServer, makeGetRequest, PluginsCommand, ServerInfo, setAccessTokensToServers } from '@shared/extra-utils'
+import {
+  cleanupTests,
+  createSingleServer,
+  makeGetRequest,
+  PeerTubeServer,
+  PluginsCommand,
+  setAccessTokensToServers
+} from '@shared/extra-utils'
 
 describe('Test plugins module unloading', function () {
-  let server: ServerInfo = null
+  let server: PeerTubeServer = null
   const requestPath = '/plugins/test-unloading/router/get'
   let value: string = null
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
 
     await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-unloading') })
diff --git a/server/tests/plugins/translations.ts b/server/tests/plugins/translations.ts
index d8d878026..8b25c6b75 100644
--- a/server/tests/plugins/translations.ts
+++ b/server/tests/plugins/translations.ts
@@ -2,19 +2,18 @@
 
 import 'mocha'
 import * as chai from 'chai'
-import { PluginsCommand, setAccessTokensToServers } from '../../../shared/extra-utils'
-import { cleanupTests, flushAndRunServer, ServerInfo } from '../../../shared/extra-utils/server/servers'
+import { cleanupTests, createSingleServer, PeerTubeServer, PluginsCommand, setAccessTokensToServers } from '@shared/extra-utils'
 
 const expect = chai.expect
 
 describe('Test plugin translations', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
   let command: PluginsCommand
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
 
     command = server.plugins
diff --git a/server/tests/plugins/video-constants.ts b/server/tests/plugins/video-constants.ts
index facc6bbc1..953916e8e 100644
--- a/server/tests/plugins/video-constants.ts
+++ b/server/tests/plugins/video-constants.ts
@@ -3,18 +3,18 @@
 import 'mocha'
 import * as chai from 'chai'
 import { HttpStatusCode } from '@shared/core-utils'
-import { cleanupTests, flushAndRunServer, PluginsCommand, ServerInfo, setAccessTokensToServers } from '@shared/extra-utils'
+import { cleanupTests, createSingleServer, PluginsCommand, PeerTubeServer, setAccessTokensToServers } from '@shared/extra-utils'
 import { VideoPlaylistPrivacy } from '@shared/models'
 
 const expect = chai.expect
 
 describe('Test plugin altering video constants', function () {
-  let server: ServerInfo
+  let server: PeerTubeServer
 
   before(async function () {
     this.timeout(30000)
 
-    server = await flushAndRunServer(1)
+    server = await createSingleServer(1)
     await setAccessTokensToServers([ server ])
 
     await server.plugins.install({ path: PluginsCommand.getPluginTestPath('-video-constants') })
diff --git a/server/tools/cli.ts b/server/tools/cli.ts
index 7d5eb72ed..52e6ea593 100644
--- a/server/tools/cli.ts
+++ b/server/tools/cli.ts
@@ -2,7 +2,7 @@ import { Command } from 'commander'
 import { Netrc } from 'netrc-parser'
 import { join } from 'path'
 import { createLogger, format, transports } from 'winston'
-import { assignCommands, ServerInfo } from '@shared/extra-utils'
+import { PeerTubeServer } from '@shared/extra-utils'
 import { UserRole } from '@shared/models'
 import { VideoPrivacy } from '../../shared/models/videos'
 import { getAppNumber, isTestInstance, root } from '../helpers/core-utils'
@@ -14,7 +14,7 @@ const config = require('application-config')(configName)
 
 const version = require('../../../package.json').version
 
-async function getAdminTokenOrDie (server: ServerInfo, username: string, password: string) {
+async function getAdminTokenOrDie (server: PeerTubeServer, username: string, password: string) {
   const token = await server.login.getAccessToken(username, password)
   const me = await server.users.getMyInfo({ token })
 
@@ -124,7 +124,7 @@ function buildCommonVideoOptions (command: Command) {
     .option('-v, --verbose <verbose>', 'Verbosity, from 0/\'error\' to 4/\'debug\'', 'info')
 }
 
-async function buildVideoAttributesFromCommander (server: ServerInfo, command: Command, defaultAttributes: any = {}) {
+async function buildVideoAttributesFromCommander (server: PeerTubeServer, command: Command, defaultAttributes: any = {}) {
   const options = command.opts()
 
   const defaultBooleanAttributes = {
@@ -179,14 +179,11 @@ function getServerCredentials (program: Command) {
                 })
 }
 
-function buildServer (url: string): ServerInfo {
-  const server = { url, internalServerNumber: undefined }
-  assignCommands(server)
-
-  return server
+function buildServer (url: string) {
+  return new PeerTubeServer({ url })
 }
 
-async function assignToken (server: ServerInfo, username: string, password: string) {
+async function assignToken (server: PeerTubeServer, username: string, password: string) {
   const bodyClient = await server.login.getClient()
   const client = { id: bodyClient.client_id, secret: bodyClient.client_secret }
 
diff --git a/server/tools/peertube-import-videos.ts b/server/tools/peertube-import-videos.ts
index caf1facc7..52aae3d2c 100644
--- a/server/tools/peertube-import-videos.ts
+++ b/server/tools/peertube-import-videos.ts
@@ -20,7 +20,7 @@ import {
   getLogger,
   getServerCredentials
 } from './cli'
-import { ServerInfo } from '@shared/extra-utils'
+import { PeerTubeServer } from '@shared/extra-utils'
 
 const processOptions = {
   maxBuffer: Infinity
@@ -270,7 +270,7 @@ async function uploadVideoOnPeerTube (parameters: {
 
 /* ---------------------------------------------------------- */
 
-async function getCategory (server: ServerInfo, categories: string[]) {
+async function getCategory (server: PeerTubeServer, categories: string[]) {
   if (!categories) return undefined
 
   const categoryString = categories[0]
diff --git a/server/tools/test-live.ts b/server/tools/test-live.ts
index bc31b6926..0cb0c3668 100644
--- a/server/tools/test-live.ts
+++ b/server/tools/test-live.ts
@@ -1,10 +1,10 @@
 import { program } from 'commander'
 import { LiveVideoCreate, VideoPrivacy } from '@shared/models'
 import {
-  flushAndRunServer,
+  createSingleServer,
   killallServers,
   sendRTMPStream,
-  ServerInfo,
+  PeerTubeServer,
   setAccessTokensToServers,
   setDefaultVideoChannel
 } from '../../shared/extra-utils'
@@ -36,7 +36,7 @@ async function run () {
 
   console.log('Starting server.')
 
-  const server = await flushAndRunServer(1, {}, [], { hideLogs: false, execArgv: [ '--inspect' ] })
+  const server = await createSingleServer(1, {}, [], { hideLogs: false, execArgv: [ '--inspect' ] })
 
   const cleanup = async () => {
     console.log('Killing server')
@@ -81,7 +81,7 @@ async function run () {
 
 // ----------------------------------------------------------------------------
 
-async function buildConfig (server: ServerInfo, commandType: CommandType) {
+async function buildConfig (server: PeerTubeServer, commandType: CommandType) {
   await server.config.updateCustomSubConfig({
     newConfig: {
       instance: {
diff --git a/shared/extra-utils/miscs/checks.ts b/shared/extra-utils/miscs/checks.ts
index 8f7bdb9b5..c81460330 100644
--- a/shared/extra-utils/miscs/checks.ts
+++ b/shared/extra-utils/miscs/checks.ts
@@ -6,7 +6,7 @@ import { join } from 'path'
 import { root } from '@server/helpers/core-utils'
 import { HttpStatusCode } from '@shared/core-utils'
 import { makeGetRequest } from '../requests'
-import { ServerInfo } from '../server'
+import { PeerTubeServer } from '../server'
 
 // Default interval -> 5 minutes
 function dateIsValid (dateString: string, interval = 300000) {
@@ -33,7 +33,7 @@ async function testImage (url: string, imageName: string, imagePath: string, ext
   expect(data.length).to.be.below(maxLength, 'the generated image is way larger than the recorded fixture')
 }
 
-async function testFileExistsOrNot (server: ServerInfo, directory: string, filePath: string, exist: boolean) {
+async function testFileExistsOrNot (server: PeerTubeServer, directory: string, filePath: string, exist: boolean) {
   const base = server.servers.buildDirectory(directory)
 
   expect(await pathExists(join(base, filePath))).to.equal(exist)
diff --git a/shared/extra-utils/miscs/webtorrent.ts b/shared/extra-utils/miscs/webtorrent.ts
index 84e390b2a..815ea3d56 100644
--- a/shared/extra-utils/miscs/webtorrent.ts
+++ b/shared/extra-utils/miscs/webtorrent.ts
@@ -2,7 +2,7 @@ import { readFile } from 'fs-extra'
 import * as parseTorrent from 'parse-torrent'
 import { join } from 'path'
 import * as WebTorrent from 'webtorrent'
-import { ServerInfo } from '../server'
+import { PeerTubeServer } from '../server'
 
 let webtorrent: WebTorrent.Instance
 
@@ -15,7 +15,7 @@ function webtorrentAdd (torrent: string, refreshWebTorrent = false) {
   return new Promise<WebTorrent.Torrent>(res => webtorrent.add(torrent, res))
 }
 
-async function parseTorrentVideo (server: ServerInfo, videoUUID: string, resolution: number) {
+async function parseTorrentVideo (server: PeerTubeServer, videoUUID: string, resolution: number) {
   const torrentName = videoUUID + '-' + resolution + '.torrent'
   const torrentPath = server.servers.buildDirectory(join('torrents', torrentName))
 
diff --git a/shared/extra-utils/server/directories.ts b/shared/extra-utils/server/directories.ts
index 3cd38a561..b6465cbf4 100644
--- a/shared/extra-utils/server/directories.ts
+++ b/shared/extra-utils/server/directories.ts
@@ -4,9 +4,9 @@ import { expect } from 'chai'
 import { pathExists, readdir } from 'fs-extra'
 import { join } from 'path'
 import { root } from '@server/helpers/core-utils'
-import { ServerInfo } from './servers'
+import { PeerTubeServer } from './server'
 
-async function checkTmpIsEmpty (server: ServerInfo) {
+async function checkTmpIsEmpty (server: PeerTubeServer) {
   await checkDirectoryIsEmpty(server, 'tmp', [ 'plugins-global.css', 'hls', 'resumable-uploads' ])
 
   if (await pathExists(join('test' + server.internalServerNumber, 'tmp', 'hls'))) {
@@ -14,7 +14,7 @@ async function checkTmpIsEmpty (server: ServerInfo) {
   }
 }
 
-async function checkDirectoryIsEmpty (server: ServerInfo, directory: string, exceptions: string[] = []) {
+async function checkDirectoryIsEmpty (server: PeerTubeServer, directory: string, exceptions: string[] = []) {
   const testDirectory = 'test' + server.internalServerNumber
 
   const directoryPath = join(root(), testDirectory, directory)
diff --git a/shared/extra-utils/server/follows-command.ts b/shared/extra-utils/server/follows-command.ts
index 4e1e56d7a..4e9ed9494 100644
--- a/shared/extra-utils/server/follows-command.ts
+++ b/shared/extra-utils/server/follows-command.ts
@@ -2,7 +2,7 @@ import { pick } from 'lodash'
 import { ActivityPubActorType, ActorFollow, FollowState, ResultList } from '@shared/models'
 import { HttpStatusCode } from '../../core-utils/miscs/http-error-codes'
 import { AbstractCommand, OverrideCommandOptions } from '../shared'
-import { ServerInfo } from './servers'
+import { PeerTubeServer } from './server'
 
 export class FollowsCommand extends AbstractCommand {
 
@@ -70,7 +70,7 @@ export class FollowsCommand extends AbstractCommand {
   }
 
   async unfollow (options: OverrideCommandOptions & {
-    target: ServerInfo
+    target: PeerTubeServer
   }) {
     const path = '/api/v1/server/following/' + options.target.host
 
@@ -112,7 +112,7 @@ export class FollowsCommand extends AbstractCommand {
   }
 
   removeFollower (options: OverrideCommandOptions & {
-    follower: ServerInfo
+    follower: PeerTubeServer
   }) {
     const path = '/api/v1/server/followers/peertube@' + options.follower.host
 
diff --git a/shared/extra-utils/server/follows.ts b/shared/extra-utils/server/follows.ts
index 50ae898cc..0188be1aa 100644
--- a/shared/extra-utils/server/follows.ts
+++ b/shared/extra-utils/server/follows.ts
@@ -1,7 +1,7 @@
 import { waitJobs } from './jobs'
-import { ServerInfo } from './servers'
+import { PeerTubeServer } from './server'
 
-async function doubleFollow (server1: ServerInfo, server2: ServerInfo) {
+async function doubleFollow (server1: PeerTubeServer, server2: PeerTubeServer) {
   await Promise.all([
     server1.follows.follow({ targets: [ server2.url ] }),
     server2.follows.follow({ targets: [ server1.url ] })
diff --git a/shared/extra-utils/server/index.ts b/shared/extra-utils/server/index.ts
index 669b004cd..9055dfc57 100644
--- a/shared/extra-utils/server/index.ts
+++ b/shared/extra-utils/server/index.ts
@@ -9,6 +9,7 @@ export * from './jobs-command'
 export * from './plugins-command'
 export * from './plugins'
 export * from './redundancy-command'
+export * from './server'
 export * from './servers-command'
 export * from './servers'
 export * from './stats-command'
diff --git a/shared/extra-utils/server/jobs.ts b/shared/extra-utils/server/jobs.ts
index 754530977..64a0353eb 100644
--- a/shared/extra-utils/server/jobs.ts
+++ b/shared/extra-utils/server/jobs.ts
@@ -1,17 +1,17 @@
 
 import { JobState } from '../../models'
 import { wait } from '../miscs'
-import { ServerInfo } from './servers'
+import { PeerTubeServer } from './server'
 
-async function waitJobs (serversArg: ServerInfo[] | ServerInfo) {
+async function waitJobs (serversArg: PeerTubeServer[] | PeerTubeServer) {
   const pendingJobWait = process.env.NODE_PENDING_JOB_WAIT
     ? parseInt(process.env.NODE_PENDING_JOB_WAIT, 10)
     : 250
 
-  let servers: ServerInfo[]
+  let servers: PeerTubeServer[]
 
-  if (Array.isArray(serversArg) === false) servers = [ serversArg as ServerInfo ]
-  else servers = serversArg as ServerInfo[]
+  if (Array.isArray(serversArg) === false) servers = [ serversArg as PeerTubeServer ]
+  else servers = serversArg as PeerTubeServer[]
 
   const states: JobState[] = [ 'waiting', 'active', 'delayed' ]
   const repeatableJobs = [ 'videos-views', 'activitypub-cleaner' ]
diff --git a/shared/extra-utils/server/plugins.ts b/shared/extra-utils/server/plugins.ts
index d1cc7e383..0f5fabd5a 100644
--- a/shared/extra-utils/server/plugins.ts
+++ b/shared/extra-utils/server/plugins.ts
@@ -1,9 +1,9 @@
 /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
 
 import { expect } from 'chai'
-import { ServerInfo } from '../server/servers'
+import { PeerTubeServer } from '../server/server'
 
-async function testHelloWorldRegisteredSettings (server: ServerInfo) {
+async function testHelloWorldRegisteredSettings (server: PeerTubeServer) {
   const body = await server.plugins.getRegisteredSettings({ npmName: 'peertube-plugin-hello-world' })
 
   const registeredSettings = body.registeredSettings
diff --git a/shared/extra-utils/server/server.ts b/shared/extra-utils/server/server.ts
new file mode 100644
index 000000000..b1347661f
--- /dev/null
+++ b/shared/extra-utils/server/server.ts
@@ -0,0 +1,376 @@
+import { ChildProcess, fork } from 'child_process'
+import { copy } from 'fs-extra'
+import { join } from 'path'
+import { root } from '@server/helpers/core-utils'
+import { randomInt } from '../../core-utils/miscs/miscs'
+import { VideoChannel } from '../../models/videos'
+import { BulkCommand } from '../bulk'
+import { CLICommand } from '../cli'
+import { CustomPagesCommand } from '../custom-pages'
+import { FeedCommand } from '../feeds'
+import { LogsCommand } from '../logs'
+import { parallelTests, SQLCommand } from '../miscs'
+import { AbusesCommand } from '../moderation'
+import { OverviewsCommand } from '../overviews'
+import { SearchCommand } from '../search'
+import { SocketIOCommand } from '../socket'
+import { AccountsCommand, BlocklistCommand, LoginCommand, NotificationsCommand, SubscriptionsCommand, UsersCommand } from '../users'
+import {
+  BlacklistCommand,
+  CaptionsCommand,
+  ChangeOwnershipCommand,
+  ChannelsCommand,
+  HistoryCommand,
+  ImportsCommand,
+  LiveCommand,
+  PlaylistsCommand,
+  ServicesCommand,
+  StreamingPlaylistsCommand,
+  VideosCommand
+} from '../videos'
+import { CommentsCommand } from '../videos/comments-command'
+import { ConfigCommand } from './config-command'
+import { ContactFormCommand } from './contact-form-command'
+import { DebugCommand } from './debug-command'
+import { FollowsCommand } from './follows-command'
+import { JobsCommand } from './jobs-command'
+import { PluginsCommand } from './plugins-command'
+import { RedundancyCommand } from './redundancy-command'
+import { ServersCommand } from './servers-command'
+import { StatsCommand } from './stats-command'
+
+export type RunServerOptions = {
+  hideLogs?: boolean
+  execArgv?: string[]
+}
+
+export class PeerTubeServer {
+  app?: ChildProcess
+
+  url: string
+  host?: string
+  hostname?: string
+  port?: number
+
+  rtmpPort?: number
+
+  parallel?: boolean
+  internalServerNumber: number
+
+  serverNumber?: number
+  customConfigFile?: string
+
+  store?: {
+    client?: {
+      id?: string
+      secret?: string
+    }
+
+    user?: {
+      username: string
+      password: string
+      email?: string
+    }
+
+    channel?: VideoChannel
+
+    video?: {
+      id: number
+      uuid: string
+      shortUUID: string
+      name?: string
+      url?: string
+
+      account?: {
+        name: string
+      }
+
+      embedPath?: string
+    }
+
+    videos?: { id: number, uuid: string }[]
+  }
+
+  accessToken?: string
+  refreshToken?: string
+
+  bulk?: BulkCommand
+  cli?: CLICommand
+  customPage?: CustomPagesCommand
+  feed?: FeedCommand
+  logs?: LogsCommand
+  abuses?: AbusesCommand
+  overviews?: OverviewsCommand
+  search?: SearchCommand
+  contactForm?: ContactFormCommand
+  debug?: DebugCommand
+  follows?: FollowsCommand
+  jobs?: JobsCommand
+  plugins?: PluginsCommand
+  redundancy?: RedundancyCommand
+  stats?: StatsCommand
+  config?: ConfigCommand
+  socketIO?: SocketIOCommand
+  accounts?: AccountsCommand
+  blocklist?: BlocklistCommand
+  subscriptions?: SubscriptionsCommand
+  live?: LiveCommand
+  services?: ServicesCommand
+  blacklist?: BlacklistCommand
+  captions?: CaptionsCommand
+  changeOwnership?: ChangeOwnershipCommand
+  playlists?: PlaylistsCommand
+  history?: HistoryCommand
+  imports?: ImportsCommand
+  streamingPlaylists?: StreamingPlaylistsCommand
+  channels?: ChannelsCommand
+  comments?: CommentsCommand
+  sql?: SQLCommand
+  notifications?: NotificationsCommand
+  servers?: ServersCommand
+  login?: LoginCommand
+  users?: UsersCommand
+  videos?: VideosCommand
+
+  constructor (options: { serverNumber: number } | { url: string }) {
+    if ((options as any).url) {
+      this.setUrl((options as any).url)
+    } else {
+      this.setServerNumber((options as any).serverNumber)
+    }
+
+    this.store = {
+      client: {
+        id: null,
+        secret: null
+      },
+      user: {
+        username: null,
+        password: null
+      }
+    }
+
+    this.assignCommands()
+  }
+
+  setServerNumber (serverNumber: number) {
+    this.serverNumber = serverNumber
+
+    this.parallel = parallelTests()
+
+    this.internalServerNumber = this.parallel ? this.randomServer() : this.serverNumber
+    this.rtmpPort = this.parallel ? this.randomRTMP() : 1936
+    this.port = 9000 + this.internalServerNumber
+
+    this.url = `http://localhost:${this.port}`
+    this.host = `localhost:${this.port}`
+    this.hostname = 'localhost'
+  }
+
+  setUrl (url: string) {
+    const parsed = new URL(url)
+
+    this.url = url
+    this.host = parsed.host
+    this.hostname = parsed.hostname
+    this.port = parseInt(parsed.port)
+  }
+
+  async flushAndRun (configOverride?: Object, args = [], options: RunServerOptions = {}) {
+    await ServersCommand.flushTests(this.internalServerNumber)
+
+    return this.run(configOverride, args, options)
+  }
+
+  async run (configOverrideArg?: any, args = [], options: RunServerOptions = {}) {
+    // These actions are async so we need to be sure that they have both been done
+    const serverRunString = {
+      'HTTP server listening': false
+    }
+    const key = 'Database peertube_test' + this.internalServerNumber + ' is ready'
+    serverRunString[key] = false
+
+    const regexps = {
+      client_id: 'Client id: (.+)',
+      client_secret: 'Client secret: (.+)',
+      user_username: 'Username: (.+)',
+      user_password: 'User password: (.+)'
+    }
+
+    await this.assignCustomConfigFile()
+
+    const configOverride = this.buildConfigOverride()
+
+    if (configOverrideArg !== undefined) {
+      Object.assign(configOverride, configOverrideArg)
+    }
+
+    // Share the environment
+    const env = Object.create(process.env)
+    env['NODE_ENV'] = 'test'
+    env['NODE_APP_INSTANCE'] = this.internalServerNumber.toString()
+    env['NODE_CONFIG'] = JSON.stringify(configOverride)
+
+    const forkOptions = {
+      silent: true,
+      env,
+      detached: true,
+      execArgv: options.execArgv || []
+    }
+
+    return new Promise<void>(res => {
+      this.app = fork(join(root(), 'dist', 'server.js'), args, forkOptions)
+      this.app.stdout.on('data', function onStdout (data) {
+        let dontContinue = false
+
+        // Capture things if we want to
+        for (const key of Object.keys(regexps)) {
+          const regexp = regexps[key]
+          const matches = data.toString().match(regexp)
+          if (matches !== null) {
+            if (key === 'client_id') this.store.client.id = matches[1]
+            else if (key === 'client_secret') this.store.client.secret = matches[1]
+            else if (key === 'user_username') this.store.user.username = matches[1]
+            else if (key === 'user_password') this.store.user.password = matches[1]
+          }
+        }
+
+        // Check if all required sentences are here
+        for (const key of Object.keys(serverRunString)) {
+          if (data.toString().indexOf(key) !== -1) serverRunString[key] = true
+          if (serverRunString[key] === false) dontContinue = true
+        }
+
+        // If no, there is maybe one thing not already initialized (client/user credentials generation...)
+        if (dontContinue === true) return
+
+        if (options.hideLogs === false) {
+          console.log(data.toString())
+        } else {
+          this.app.stdout.removeListener('data', onStdout)
+        }
+
+        process.on('exit', () => {
+          try {
+            process.kill(this.server.app.pid)
+          } catch { /* empty */ }
+        })
+
+        res()
+      })
+    })
+  }
+
+  async kill () {
+    if (!this.app) return
+
+    await this.sql.cleanup()
+
+    process.kill(-this.app.pid)
+
+    this.app = null
+  }
+
+  private randomServer () {
+    const low = 10
+    const high = 10000
+
+    return randomInt(low, high)
+  }
+
+  private randomRTMP () {
+    const low = 1900
+    const high = 2100
+
+    return randomInt(low, high)
+  }
+
+  private async assignCustomConfigFile () {
+    if (this.internalServerNumber === this.serverNumber) return
+
+    const basePath = join(root(), 'config')
+
+    const tmpConfigFile = join(basePath, `test-${this.internalServerNumber}.yaml`)
+    await copy(join(basePath, `test-${this.serverNumber}.yaml`), tmpConfigFile)
+
+    this.customConfigFile = tmpConfigFile
+  }
+
+  private buildConfigOverride () {
+    if (!this.parallel) return {}
+
+    return {
+      listen: {
+        port: this.port
+      },
+      webserver: {
+        port: this.port
+      },
+      database: {
+        suffix: '_test' + this.internalServerNumber
+      },
+      storage: {
+        tmp: `test${this.internalServerNumber}/tmp/`,
+        avatars: `test${this.internalServerNumber}/avatars/`,
+        videos: `test${this.internalServerNumber}/videos/`,
+        streaming_playlists: `test${this.internalServerNumber}/streaming-playlists/`,
+        redundancy: `test${this.internalServerNumber}/redundancy/`,
+        logs: `test${this.internalServerNumber}/logs/`,
+        previews: `test${this.internalServerNumber}/previews/`,
+        thumbnails: `test${this.internalServerNumber}/thumbnails/`,
+        torrents: `test${this.internalServerNumber}/torrents/`,
+        captions: `test${this.internalServerNumber}/captions/`,
+        cache: `test${this.internalServerNumber}/cache/`,
+        plugins: `test${this.internalServerNumber}/plugins/`
+      },
+      admin: {
+        email: `admin${this.internalServerNumber}@example.com`
+      },
+      live: {
+        rtmp: {
+          port: this.rtmpPort
+        }
+      }
+    }
+  }
+
+  private assignCommands () {
+    this.bulk = new BulkCommand(this)
+    this.cli = new CLICommand(this)
+    this.customPage = new CustomPagesCommand(this)
+    this.feed = new FeedCommand(this)
+    this.logs = new LogsCommand(this)
+    this.abuses = new AbusesCommand(this)
+    this.overviews = new OverviewsCommand(this)
+    this.search = new SearchCommand(this)
+    this.contactForm = new ContactFormCommand(this)
+    this.debug = new DebugCommand(this)
+    this.follows = new FollowsCommand(this)
+    this.jobs = new JobsCommand(this)
+    this.plugins = new PluginsCommand(this)
+    this.redundancy = new RedundancyCommand(this)
+    this.stats = new StatsCommand(this)
+    this.config = new ConfigCommand(this)
+    this.socketIO = new SocketIOCommand(this)
+    this.accounts = new AccountsCommand(this)
+    this.blocklist = new BlocklistCommand(this)
+    this.subscriptions = new SubscriptionsCommand(this)
+    this.live = new LiveCommand(this)
+    this.services = new ServicesCommand(this)
+    this.blacklist = new BlacklistCommand(this)
+    this.captions = new CaptionsCommand(this)
+    this.changeOwnership = new ChangeOwnershipCommand(this)
+    this.playlists = new PlaylistsCommand(this)
+    this.history = new HistoryCommand(this)
+    this.imports = new ImportsCommand(this)
+    this.streamingPlaylists = new StreamingPlaylistsCommand(this)
+    this.channels = new ChannelsCommand(this)
+    this.comments = new CommentsCommand(this)
+    this.sql = new SQLCommand(this)
+    this.notifications = new NotificationsCommand(this)
+    this.servers = new ServersCommand(this)
+    this.login = new LoginCommand(this)
+    this.users = new UsersCommand(this)
+    this.videos = new VideosCommand(this)
+  }
+}
diff --git a/shared/extra-utils/server/servers-command.ts b/shared/extra-utils/server/servers-command.ts
index a7c5a868d..1a7b2aade 100644
--- a/shared/extra-utils/server/servers-command.ts
+++ b/shared/extra-utils/server/servers-command.ts
@@ -37,7 +37,7 @@ export class ServersCommand extends AbstractCommand {
     if (isGithubCI()) {
       await ensureDir('artifacts')
 
-      const origin = this.server.servers.buildDirectory('logs/peertube.log')
+      const origin = this.buildDirectory('logs/peertube.log')
       const destname = `peertube-${this.server.internalServerNumber}.log`
       console.log('Saving logs %s.', destname)
 
diff --git a/shared/extra-utils/server/servers.ts b/shared/extra-utils/server/servers.ts
index ea3f19a92..87d7e9449 100644
--- a/shared/extra-utils/server/servers.ts
+++ b/shared/extra-utils/server/servers.ts
@@ -1,391 +1,30 @@
-/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/no-floating-promises */
+import { ensureDir } from 'fs-extra'
+import { isGithubCI } from '../miscs'
+import { PeerTubeServer, RunServerOptions } from './server'
 
-import { ChildProcess, fork } from 'child_process'
-import { copy, ensureDir } from 'fs-extra'
-import { join } from 'path'
-import { root } from '@server/helpers/core-utils'
-import { randomInt } from '../../core-utils/miscs/miscs'
-import { VideoChannel } from '../../models/videos'
-import { BulkCommand } from '../bulk'
-import { CLICommand } from '../cli'
-import { CustomPagesCommand } from '../custom-pages'
-import { FeedCommand } from '../feeds'
-import { LogsCommand } from '../logs'
-import { isGithubCI, parallelTests, SQLCommand } from '../miscs'
-import { AbusesCommand } from '../moderation'
-import { OverviewsCommand } from '../overviews'
-import { SearchCommand } from '../search'
-import { SocketIOCommand } from '../socket'
-import { AccountsCommand, BlocklistCommand, LoginCommand, NotificationsCommand, SubscriptionsCommand, UsersCommand } from '../users'
-import {
-  BlacklistCommand,
-  CaptionsCommand,
-  ChangeOwnershipCommand,
-  ChannelsCommand,
-  HistoryCommand,
-  ImportsCommand,
-  LiveCommand,
-  PlaylistsCommand,
-  ServicesCommand,
-  StreamingPlaylistsCommand,
-  VideosCommand
-} from '../videos'
-import { CommentsCommand } from '../videos/comments-command'
-import { ConfigCommand } from './config-command'
-import { ContactFormCommand } from './contact-form-command'
-import { DebugCommand } from './debug-command'
-import { FollowsCommand } from './follows-command'
-import { JobsCommand } from './jobs-command'
-import { PluginsCommand } from './plugins-command'
-import { RedundancyCommand } from './redundancy-command'
-import { ServersCommand } from './servers-command'
-import { StatsCommand } from './stats-command'
+async function createSingleServer (serverNumber: number, configOverride?: Object, args = [], options: RunServerOptions = {}) {
+  const server = new PeerTubeServer({ serverNumber })
 
-interface ServerInfo {
-  app?: ChildProcess
-
-  url: string
-  host?: string
-  hostname?: string
-  port?: number
-
-  rtmpPort?: number
-
-  parallel?: boolean
-  internalServerNumber: number
-
-  serverNumber?: number
-  customConfigFile?: string
-
-  store?: {
-    client?: {
-      id?: string
-      secret?: string
-    }
-
-    user?: {
-      username: string
-      password: string
-      email?: string
-    }
-
-    channel?: VideoChannel
-
-    video?: {
-      id: number
-      uuid: string
-      shortUUID: string
-      name?: string
-      url?: string
-
-      account?: {
-        name: string
-      }
-
-      embedPath?: string
-    }
-
-    videos?: { id: number, uuid: string }[]
-  }
-
-  accessToken?: string
-  refreshToken?: string
-
-  bulk?: BulkCommand
-  cli?: CLICommand
-  customPage?: CustomPagesCommand
-  feed?: FeedCommand
-  logs?: LogsCommand
-  abuses?: AbusesCommand
-  overviews?: OverviewsCommand
-  search?: SearchCommand
-  contactForm?: ContactFormCommand
-  debug?: DebugCommand
-  follows?: FollowsCommand
-  jobs?: JobsCommand
-  plugins?: PluginsCommand
-  redundancy?: RedundancyCommand
-  stats?: StatsCommand
-  config?: ConfigCommand
-  socketIO?: SocketIOCommand
-  accounts?: AccountsCommand
-  blocklist?: BlocklistCommand
-  subscriptions?: SubscriptionsCommand
-  live?: LiveCommand
-  services?: ServicesCommand
-  blacklist?: BlacklistCommand
-  captions?: CaptionsCommand
-  changeOwnership?: ChangeOwnershipCommand
-  playlists?: PlaylistsCommand
-  history?: HistoryCommand
-  imports?: ImportsCommand
-  streamingPlaylists?: StreamingPlaylistsCommand
-  channels?: ChannelsCommand
-  comments?: CommentsCommand
-  sql?: SQLCommand
-  notifications?: NotificationsCommand
-  servers?: ServersCommand
-  login?: LoginCommand
-  users?: UsersCommand
-  videos?: VideosCommand
-}
-
-function flushAndRunMultipleServers (totalServers: number, configOverride?: Object) {
-  const apps = []
-  let i = 0
-
-  return new Promise<ServerInfo[]>(res => {
-    function anotherServerDone (serverNumber, app) {
-      apps[serverNumber - 1] = app
-      i++
-      if (i === totalServers) {
-        return res(apps)
-      }
-    }
-
-    for (let j = 1; j <= totalServers; j++) {
-      flushAndRunServer(j, configOverride).then(app => anotherServerDone(j, app))
-    }
-  })
-}
-
-function randomServer () {
-  const low = 10
-  const high = 10000
-
-  return randomInt(low, high)
-}
-
-function randomRTMP () {
-  const low = 1900
-  const high = 2100
-
-  return randomInt(low, high)
-}
-
-type RunServerOptions = {
-  hideLogs?: boolean
-  execArgv?: string[]
-}
-
-async function flushAndRunServer (serverNumber: number, configOverride?: Object, args = [], options: RunServerOptions = {}) {
-  const parallel = parallelTests()
-
-  const internalServerNumber = parallel ? randomServer() : serverNumber
-  const rtmpPort = parallel ? randomRTMP() : 1936
-  const port = 9000 + internalServerNumber
-
-  await ServersCommand.flushTests(internalServerNumber)
-
-  const server: ServerInfo = {
-    app: null,
-    port,
-    internalServerNumber,
-    rtmpPort,
-    parallel,
-    serverNumber,
-    url: `http://localhost:${port}`,
-    host: `localhost:${port}`,
-    hostname: 'localhost',
-    store: {
-      client: {
-        id: null,
-        secret: null
-      },
-      user: {
-        username: null,
-        password: null
-      }
-    }
-  }
-
-  return runServer(server, configOverride, args, options)
-}
-
-async function runServer (server: ServerInfo, configOverrideArg?: any, args = [], options: RunServerOptions = {}) {
-  // These actions are async so we need to be sure that they have both been done
-  const serverRunString = {
-    'HTTP server listening': false
-  }
-  const key = 'Database peertube_test' + server.internalServerNumber + ' is ready'
-  serverRunString[key] = false
-
-  const regexps = {
-    client_id: 'Client id: (.+)',
-    client_secret: 'Client secret: (.+)',
-    user_username: 'Username: (.+)',
-    user_password: 'User password: (.+)'
-  }
-
-  if (server.internalServerNumber !== server.serverNumber) {
-    const basePath = join(root(), 'config')
-
-    const tmpConfigFile = join(basePath, `test-${server.internalServerNumber}.yaml`)
-    await copy(join(basePath, `test-${server.serverNumber}.yaml`), tmpConfigFile)
-
-    server.customConfigFile = tmpConfigFile
-  }
-
-  const configOverride: any = {}
-
-  if (server.parallel) {
-    Object.assign(configOverride, {
-      listen: {
-        port: server.port
-      },
-      webserver: {
-        port: server.port
-      },
-      database: {
-        suffix: '_test' + server.internalServerNumber
-      },
-      storage: {
-        tmp: `test${server.internalServerNumber}/tmp/`,
-        avatars: `test${server.internalServerNumber}/avatars/`,
-        videos: `test${server.internalServerNumber}/videos/`,
-        streaming_playlists: `test${server.internalServerNumber}/streaming-playlists/`,
-        redundancy: `test${server.internalServerNumber}/redundancy/`,
-        logs: `test${server.internalServerNumber}/logs/`,
-        previews: `test${server.internalServerNumber}/previews/`,
-        thumbnails: `test${server.internalServerNumber}/thumbnails/`,
-        torrents: `test${server.internalServerNumber}/torrents/`,
-        captions: `test${server.internalServerNumber}/captions/`,
-        cache: `test${server.internalServerNumber}/cache/`,
-        plugins: `test${server.internalServerNumber}/plugins/`
-      },
-      admin: {
-        email: `admin${server.internalServerNumber}@example.com`
-      },
-      live: {
-        rtmp: {
-          port: server.rtmpPort
-        }
-      }
-    })
-  }
-
-  if (configOverrideArg !== undefined) {
-    Object.assign(configOverride, configOverrideArg)
-  }
-
-  // Share the environment
-  const env = Object.create(process.env)
-  env['NODE_ENV'] = 'test'
-  env['NODE_APP_INSTANCE'] = server.internalServerNumber.toString()
-  env['NODE_CONFIG'] = JSON.stringify(configOverride)
-
-  const forkOptions = {
-    silent: true,
-    env,
-    detached: true,
-    execArgv: options.execArgv || []
-  }
-
-  return new Promise<ServerInfo>(res => {
-    server.app = fork(join(root(), 'dist', 'server.js'), args, forkOptions)
-    server.app.stdout.on('data', function onStdout (data) {
-      let dontContinue = false
-
-      // Capture things if we want to
-      for (const key of Object.keys(regexps)) {
-        const regexp = regexps[key]
-        const matches = data.toString().match(regexp)
-        if (matches !== null) {
-          if (key === 'client_id') server.store.client.id = matches[1]
-          else if (key === 'client_secret') server.store.client.secret = matches[1]
-          else if (key === 'user_username') server.store.user.username = matches[1]
-          else if (key === 'user_password') server.store.user.password = matches[1]
-        }
-      }
-
-      // Check if all required sentences are here
-      for (const key of Object.keys(serverRunString)) {
-        if (data.toString().indexOf(key) !== -1) serverRunString[key] = true
-        if (serverRunString[key] === false) dontContinue = true
-      }
-
-      // If no, there is maybe one thing not already initialized (client/user credentials generation...)
-      if (dontContinue === true) return
-
-      if (options.hideLogs === false) {
-        console.log(data.toString())
-      } else {
-        server.app.stdout.removeListener('data', onStdout)
-      }
-
-      process.on('exit', () => {
-        try {
-          process.kill(server.app.pid)
-        } catch { /* empty */ }
-      })
-
-      assignCommands(server)
-
-      res(server)
-    })
-  })
-}
-
-function assignCommands (server: ServerInfo) {
-  server.bulk = new BulkCommand(server)
-  server.cli = new CLICommand(server)
-  server.customPage = new CustomPagesCommand(server)
-  server.feed = new FeedCommand(server)
-  server.logs = new LogsCommand(server)
-  server.abuses = new AbusesCommand(server)
-  server.overviews = new OverviewsCommand(server)
-  server.search = new SearchCommand(server)
-  server.contactForm = new ContactFormCommand(server)
-  server.debug = new DebugCommand(server)
-  server.follows = new FollowsCommand(server)
-  server.jobs = new JobsCommand(server)
-  server.plugins = new PluginsCommand(server)
-  server.redundancy = new RedundancyCommand(server)
-  server.stats = new StatsCommand(server)
-  server.config = new ConfigCommand(server)
-  server.socketIO = new SocketIOCommand(server)
-  server.accounts = new AccountsCommand(server)
-  server.blocklist = new BlocklistCommand(server)
-  server.subscriptions = new SubscriptionsCommand(server)
-  server.live = new LiveCommand(server)
-  server.services = new ServicesCommand(server)
-  server.blacklist = new BlacklistCommand(server)
-  server.captions = new CaptionsCommand(server)
-  server.changeOwnership = new ChangeOwnershipCommand(server)
-  server.playlists = new PlaylistsCommand(server)
-  server.history = new HistoryCommand(server)
-  server.imports = new ImportsCommand(server)
-  server.streamingPlaylists = new StreamingPlaylistsCommand(server)
-  server.channels = new ChannelsCommand(server)
-  server.comments = new CommentsCommand(server)
-  server.sql = new SQLCommand(server)
-  server.notifications = new NotificationsCommand(server)
-  server.servers = new ServersCommand(server)
-  server.login = new LoginCommand(server)
-  server.users = new UsersCommand(server)
-  server.videos = new VideosCommand(server)
-}
-
-async function reRunServer (server: ServerInfo, configOverride?: any) {
-  const newServer = await runServer(server, configOverride)
-  server.app = newServer.app
+  await server.flushAndRun(configOverride, args, options)
 
   return server
 }
 
-async function killallServers (servers: ServerInfo[]) {
-  for (const server of servers) {
-    if (!server.app) continue
+function createMultipleServers (totalServers: number, configOverride?: Object) {
+  const serverPromises: Promise<PeerTubeServer>[] = []
 
-    await server.sql.cleanup()
-
-    process.kill(-server.app.pid)
-
-    server.app = null
+  for (let i = 1; i <= totalServers; i++) {
+    serverPromises.push(createSingleServer(i, configOverride))
   }
+
+  return Promise.all(serverPromises)
 }
 
-async function cleanupTests (servers: ServerInfo[]) {
+async function killallServers (servers: PeerTubeServer[]) {
+  return Promise.all(servers.map(s => s.kill()))
+}
+
+async function cleanupTests (servers: PeerTubeServer[]) {
   await killallServers(servers)
 
   if (isGithubCI()) {
@@ -403,11 +42,8 @@ async function cleanupTests (servers: ServerInfo[]) {
 // ---------------------------------------------------------------------------
 
 export {
-  ServerInfo,
+  createSingleServer,
+  createMultipleServers,
   cleanupTests,
-  flushAndRunMultipleServers,
-  flushAndRunServer,
-  killallServers,
-  reRunServer,
-  assignCommands
+  killallServers
 }
diff --git a/shared/extra-utils/shared/abstract-command.ts b/shared/extra-utils/shared/abstract-command.ts
index 5fddcf639..967f8f2ac 100644
--- a/shared/extra-utils/shared/abstract-command.ts
+++ b/shared/extra-utils/shared/abstract-command.ts
@@ -9,7 +9,7 @@ import {
   unwrapBody,
   unwrapText
 } from '../requests/requests'
-import { ServerInfo } from '../server/servers'
+import { PeerTubeServer } from '../server/server'
 
 export interface OverrideCommandOptions {
   token?: string
@@ -38,7 +38,7 @@ interface InternalGetCommandOptions extends InternalCommonCommandOptions {
 abstract class AbstractCommand {
 
   constructor (
-    protected server: ServerInfo
+    protected server: PeerTubeServer
   ) {
 
   }
diff --git a/shared/extra-utils/users/accounts.ts b/shared/extra-utils/users/accounts.ts
index 2c9a4b71c..9fc1bcfc4 100644
--- a/shared/extra-utils/users/accounts.ts
+++ b/shared/extra-utils/users/accounts.ts
@@ -4,10 +4,10 @@ import { expect } from 'chai'
 import { pathExists, readdir } from 'fs-extra'
 import { join } from 'path'
 import { root } from '@server/helpers/core-utils'
-import { ServerInfo } from '../server'
+import { PeerTubeServer } from '../server'
 
 async function expectAccountFollows (options: {
-  server: ServerInfo
+  server: PeerTubeServer
   handle: string
   followers: number
   following: number
diff --git a/shared/extra-utils/users/login.ts b/shared/extra-utils/users/login.ts
index d0c26a4f0..f1df027d3 100644
--- a/shared/extra-utils/users/login.ts
+++ b/shared/extra-utils/users/login.ts
@@ -1,6 +1,6 @@
-import { ServerInfo } from '../server/servers'
+import { PeerTubeServer } from '../server/server'
 
-function setAccessTokensToServers (servers: ServerInfo[]) {
+function setAccessTokensToServers (servers: PeerTubeServer[]) {
   const tasks: Promise<any>[] = []
 
   for (const server of servers) {
diff --git a/shared/extra-utils/users/notifications.ts b/shared/extra-utils/users/notifications.ts
index 9196f0bf5..4c42fad3e 100644
--- a/shared/extra-utils/users/notifications.ts
+++ b/shared/extra-utils/users/notifications.ts
@@ -5,8 +5,9 @@ import { inspect } from 'util'
 import { AbuseState, PluginType } from '@shared/models'
 import { UserNotification, UserNotificationSetting, UserNotificationSettingValue, UserNotificationType } from '../../models/users'
 import { MockSmtpServer } from '../mock-servers/mock-email'
+import { PeerTubeServer } from '../server'
 import { doubleFollow } from '../server/follows'
-import { flushAndRunMultipleServers, ServerInfo } from '../server/servers'
+import { createMultipleServers } from '../server/servers'
 import { setAccessTokensToServers } from './login'
 
 function getAllNotificationsSettings (): UserNotificationSetting {
@@ -31,7 +32,7 @@ function getAllNotificationsSettings (): UserNotificationSetting {
 }
 
 type CheckerBaseParams = {
-  server: ServerInfo
+  server: PeerTubeServer
   emails: any[]
   socketNotifications: UserNotification[]
   token: string
@@ -642,7 +643,7 @@ async function prepareNotificationsTest (serversCount = 3, overrideConfigArg: an
       limit: 20
     }
   }
-  const servers = await flushAndRunMultipleServers(serversCount, Object.assign(overrideConfig, overrideConfigArg))
+  const servers = await createMultipleServers(serversCount, Object.assign(overrideConfig, overrideConfigArg))
 
   await setAccessTokensToServers(servers)
 
diff --git a/shared/extra-utils/videos/channels.ts b/shared/extra-utils/videos/channels.ts
index 81e818094..756c47453 100644
--- a/shared/extra-utils/videos/channels.ts
+++ b/shared/extra-utils/videos/channels.ts
@@ -1,6 +1,6 @@
-import { ServerInfo } from '../server/servers'
+import { PeerTubeServer } from '../server/server'
 
-function setDefaultVideoChannel (servers: ServerInfo[]) {
+function setDefaultVideoChannel (servers: PeerTubeServer[]) {
   const tasks: Promise<any>[] = []
 
   for (const server of servers) {
diff --git a/shared/extra-utils/videos/live.ts b/shared/extra-utils/videos/live.ts
index 353595811..502964b1a 100644
--- a/shared/extra-utils/videos/live.ts
+++ b/shared/extra-utils/videos/live.ts
@@ -5,7 +5,7 @@ import * as ffmpeg from 'fluent-ffmpeg'
 import { pathExists, readdir } from 'fs-extra'
 import { join } from 'path'
 import { buildAbsoluteFixturePath, wait } from '../miscs'
-import { ServerInfo } from '../server/servers'
+import { PeerTubeServer } from '../server/server'
 
 function sendRTMPStream (rtmpBaseUrl: string, streamKey: string, fixtureName = 'video_short.mp4') {
   const fixture = buildAbsoluteFixturePath(fixtureName)
@@ -70,13 +70,13 @@ async function stopFfmpeg (command: ffmpeg.FfmpegCommand) {
   await wait(500)
 }
 
-async function waitUntilLivePublishedOnAllServers (servers: ServerInfo[], videoId: string) {
+async function waitUntilLivePublishedOnAllServers (servers: PeerTubeServer[], videoId: string) {
   for (const server of servers) {
     await server.live.waitUntilPublished({ videoId })
   }
 }
 
-async function checkLiveCleanup (server: ServerInfo, videoUUID: string, resolutions: number[] = []) {
+async function checkLiveCleanup (server: PeerTubeServer, videoUUID: string, resolutions: number[] = []) {
   const basePath = server.servers.buildDirectory('streaming-playlists')
   const hlsPath = join(basePath, 'hls', videoUUID)
 
diff --git a/shared/extra-utils/videos/streaming-playlists.ts b/shared/extra-utils/videos/streaming-playlists.ts
index e8fd2f232..002ae08b2 100644
--- a/shared/extra-utils/videos/streaming-playlists.ts
+++ b/shared/extra-utils/videos/streaming-playlists.ts
@@ -2,10 +2,10 @@ import { expect } from 'chai'
 import { sha256 } from '@server/helpers/core-utils'
 import { HttpStatusCode } from '@shared/core-utils'
 import { VideoStreamingPlaylist } from '@shared/models'
-import { ServerInfo } from '../server'
+import { PeerTubeServer } from '../server'
 
 async function checkSegmentHash (options: {
-  server: ServerInfo
+  server: PeerTubeServer
   baseUrlPlaylist: string
   baseUrlSegment: string
   videoUUID: string
@@ -36,7 +36,7 @@ async function checkSegmentHash (options: {
 }
 
 async function checkLiveSegmentHash (options: {
-  server: ServerInfo
+  server: PeerTubeServer
   baseUrlSegment: string
   videoUUID: string
   segmentName: string
@@ -52,7 +52,7 @@ async function checkLiveSegmentHash (options: {
 }
 
 async function checkResolutionsInMasterPlaylist (options: {
-  server: ServerInfo
+  server: PeerTubeServer
   playlistUrl: string
   resolutions: number[]
 }) {
diff --git a/shared/extra-utils/videos/videos-command.ts b/shared/extra-utils/videos/videos-command.ts
index 5556cddf6..feef5a771 100644
--- a/shared/extra-utils/videos/videos-command.ts
+++ b/shared/extra-utils/videos/videos-command.ts
@@ -22,7 +22,7 @@ import {
 } from '@shared/models'
 import { buildAbsoluteFixturePath, wait } from '../miscs'
 import { unwrapBody } from '../requests'
-import { ServerInfo, waitJobs } from '../server'
+import { PeerTubeServer, waitJobs } from '../server'
 import { AbstractCommand, OverrideCommandOptions } from '../shared'
 
 export type VideoEdit = Partial<Omit<VideoCreate, 'thumbnailfile' | 'previewfile'>> & {
@@ -33,7 +33,7 @@ export type VideoEdit = Partial<Omit<VideoCreate, 'thumbnailfile' | 'previewfile
 
 export class VideosCommand extends AbstractCommand {
 
-  constructor (server: ServerInfo) {
+  constructor (server: PeerTubeServer) {
     super(server)
 
     loadLanguages()
diff --git a/shared/extra-utils/videos/videos.ts b/shared/extra-utils/videos/videos.ts
index 86f49384d..b41533808 100644
--- a/shared/extra-utils/videos/videos.ts
+++ b/shared/extra-utils/videos/videos.ts
@@ -9,12 +9,12 @@ import { VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_PRIVACIES } fr
 import { dateIsValid, testImage, webtorrentAdd } from '../miscs'
 import { makeRawRequest } from '../requests/requests'
 import { waitJobs } from '../server'
-import { ServerInfo } from '../server/servers'
+import { PeerTubeServer } from '../server/server'
 import { VideoEdit } from './videos-command'
 
 async function checkVideoFilesWereRemoved (
   videoUUID: string,
-  server: ServerInfo,
+  server: PeerTubeServer,
   directories = [
     'redundancy',
     'videos',
@@ -40,7 +40,7 @@ async function checkVideoFilesWereRemoved (
 }
 
 function checkUploadVideoParam (
-  server: ServerInfo,
+  server: PeerTubeServer,
   token: string,
   attributes: Partial<VideoEdit>,
   expectedStatus = HttpStatusCode.OK_200,
@@ -52,7 +52,7 @@ function checkUploadVideoParam (
 }
 
 async function completeVideoCheck (
-  server: ServerInfo,
+  server: PeerTubeServer,
   video: any,
   attributes: {
     name: string
@@ -197,7 +197,7 @@ async function completeVideoCheck (
 
 // serverNumber starts from 1
 async function uploadRandomVideoOnServers (
-  servers: ServerInfo[],
+  servers: PeerTubeServer[],
   serverNumber: number,
   additionalParams?: VideoEdit & { prefixName?: string }
 ) {