1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209# Socket.IO Admin UI

## Table of contents
- [How to use](#how-to-use)
- [Server-side](#server-side)
- [Client-side](#client-side)
- [Available options](#available-options)
- [`auth`](#auth)
- [`namespaceName`](#namespacename)
- [`readonly`](#readonly)
- [`serverId`](#serverid)
- [`store`](#store)
- [`mode`](#mode)
- [How it works](#how-it-works)
- [License](#license)
## How to use
### Server-side
First, install the `@socket.io/admin-ui` package:
```
npm i @socket.io/admin-ui
```
And then invoke the `instrument` method on your Socket.IO server:
```js
const { createServer } = require("http");
const { Server } = require("socket.io");
const { instrument } = require("@socket.io/admin-ui");
const httpServer = createServer();
const io = new Server(httpServer, {
cors: {
origin: ["https://admin.socket.io"],
credentials: true
}
});
instrument(io, {
auth: false
});
httpServer.listen(3000);
```
The module is compatible with:
- Socket.IO v4 server
- Socket.IO v3 server (>= 3.1.0), but without the operations on rooms (join, leave, disconnection)
### Client-side
You can then head up to https://admin.socket.io, or host the files found in the `ui/dist` folder.
**Important note**: the website at https://admin.socket.io is totally static (hosted on [Vercel](https://vercel.com)), we do not (and will never) store any information about yourself or your browser (no tracking, no analytics, ...). That being said, hosting the files yourself is totally fine.
You should see the following modal:

Please enter the URL of your server (for example, `http://localhost:3000` or `https://example.com`) and the credentials, if applicable (see the `auth` option [below](#auth)).
### Available options
#### `auth`
Default value: `-`
This option is mandatory. You can either disable authentication (please use with caution):
```js
instrument(io, {
auth: false
});
```
Or use basic authentication:
```js
instrument(io, {
auth: {
type: "basic",
username: "admin",
password: "$2b$10$heqvAkYMez.Va6Et2uXInOnkCT6/uQj1brkrbyG3LpopDklcq7ZOS" // "changeit" encrypted with bcrypt
},
});
```
WARNING! Please note that the `bcrypt` package does not currently support hashes starting with the `$2y$` prefix, which is used by some BCrypt implementations (for example https://bcrypt-generator.com/ or https://www.bcrypt.fr/). You can check the validity of the hash with:
```
$ node
> require("bcrypt").compareSync("<the password>", "<the hash>")
true
```
You can generate a valid hash with:
```
$ node
> require("bcrypt").hashSync("changeit", 10)
'$2b$10$LQUE...'
```
See also:
- https://github.com/kelektiv/node.bcrypt.js/issues/849
- https://stackoverflow.com/a/36225192/5138796
#### `namespaceName`
Default value: `/admin`
The name of the namespace which will be created to handle the administrative tasks.
```js
instrument(io, {
namespaceName: "/custom"
});
```
This namespace is a classic Socket.IO namespace, you can access it with:
```js
const adminNamespace = io.of("/admin");
```
More information [here](https://socket.io/docs/v4/namespaces/).
#### `readonly`
Default value: `false`
Whether to put the admin UI in read-only mode (no join, leave or disconnect allowed).
```js
instrument(io, {
readonly: true
});
```
#### `serverId`
Default value: `require("os").hostname()`
The ID of the given server. If you have several Socket.IO servers on the same machine, please give them a distinct ID:
```js
instrument(io, {
serverId: `${require("os").hostname()}#${process.pid}`
});
```
#### `store`
Default value: `new InMemoryStore()`
The store is used to store the session IDs so the user do not have to retype the credentials upon reconnection.
If you use basic authentication in a multi-server setup, you should provide a custom store:
```js
const { instrument, RedisStore } = require("@socket.io/admin-ui");
instrument(io, {
store: new RedisStore(redisClient)
});
```
#### `mode`
Default value: `development`
In production mode, the server won't send all details about the socket instances and the rooms, thus reducing the memory footprint of the instrumentation.
```js
instrument(io, {
mode: "production"
});
```
The production mode can also be enabled with the NODE_ENV environment variable:
```
NODE_ENV=production node index.js
```
## How it works
You can check the details of the implementation in the [lib/index.ts](lib/index.ts) file.
The `instrument` method simply:
- creates a [namespace](https://socket.io/docs/v4/namespaces/) and adds an authentication [middleware](https://socket.io/docs/v4/middlewares/) if applicable
- register listeners for the `connection` and `disconnect` event for each existing namespaces to track socket instances
- register a timer which will periodically send stats from the server to the UI
- register handlers for the `join`, `leave` and `_disconnect` commands sent from the UI
## License
MIT