Server Management
Listing servers
Request:
GET /api/servers/servers/
Starred servers can be listed using boolean filter starred
.
GET /api/servers/servers/?starred=true
Adding a server
Request:
POST /api/servers/servers/
{
"name": "test",
"platform": "debian" or "rhel",
}
Platform should be either debian
or rhel
.
Response:
HTTP 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"name": "testing",
"id": "821b93bd-6913-4416-bb21-0e04f0a8b267",
"instruction_1": "curl http://host.docker.internal:8000/api/servers/installers/4052825a-16cb-4226-a486-881601f87561/ | sudo bash",
"instruction_2": "#!/bin/bash\n\napt-get update && apt-get -y install python3 python3-pip\n\ncurl -sSLf -o /tmp/alpamon-1.0.0-py3-none-any.whl http://host.docker.internal:8000/api/packages/python/entries/f6c9bc4b-83b6-498c-9a06-11fbd9be7309/download/\npip3 install -U /tmp/alpamon-1.0.0-py3-none-any.whl\nrm -f /tmp/alpamon-1.0.0-py3-none-any.whl\n\nexport ALPACON_URL=\"http://host.docker.internal:8000\"\nexport ALPAMON_ID=\"821b93bd-6913-4416-bb21-0e04f0a8b267\"\nexport ALPAMON_KEY=\"z7k5gYDPf7fUVekS5TEP6JqryWAFdyrf\"\n\nalpamon-deploy install\n"
}
Clients may use two installation instructions. As they contains the server's id
and a secret key
, clients should handle them safely.
Retrieving a specific server
GET /api/servers/servers/<id>/
An example response data looks like the followings.
Request:
GET /api/servers/servers/7a50ea6c-2138-4d3f-9633-e50694c847c4/
Response:
HTTP 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"id": "7a50ea6c-2138-4d3f-9633-e50694c847c4",
"name": "test",
"remote_ip": "127.0.0.1",
"status": {
"code": "ok",
"icon": "circle-check",
"meta": {
"delay_1d": 127.24366,
"delay_1h": 0.902331,
"delay_1w": 122.499982,
"delay_now": 0.804537
},
"text": "Good",
"color": "success",
"messages": [
"Server is okay."
]
},
"is_connected": true,
"commissioned": true,
"starred": false,
"version": "1.0.0",
"osquery_version": "5.1.0",
"cpu_physical_cores": 4,
"cpu_logical_cores": 8,
"cpu_type": "x86_64h",
"physical_memory": 17179869184,
"os_name": "macOS",
"os_version": "12.6",
"uptime": 351540.592445,
"boot_time": "2022-09-27T13:17:07Z",
"last_connectivity": "2022-09-30T16:20:13.343055Z",
"started_at": "2022-09-27T23:36:27.634597+09:00",
"added_at": "2022-09-22T23:26:17.303065+09:00",
"updated_at": "2022-10-01T01:20:16.566762+09:00",
"user": "7bbcbaf3-aae3-4b6d-b2f2-ba374a878abb"
}
id
: Server idname
: Server nameremote_ip
: The IP address seen byalpacon
status
: Detailed description about the server status in json format.code
:ok
if status is good,warn
orerror
if something is wrong.text
: A description about the code. Ignore this field if the client implements its own description.icon
,color
: Icon and color to show the status. Ignore this field if the client implements its own icons. This fields can be used like<i class="text-{{ object.status.color }} fa-solid fa-{{ object.status.icon }}"></i>
messages
: The list of detailed messages that show server status. If errors are found, they are listed here.meta
: Usedelay_now
inmeta
to display current delay of a server.
is_connected
: Whetheralpamon
is connected nowcommissioned
: Whetheralpamon
has reported the system statusstarred
: Whetheralpamon
is starredversion
:alpamon
versionosquery_version
:osquery
version (osquery
is used byalpamon
to gather system information)uptime
: Time since the system has bootedboot_time
: Time when the system bootedlast_connectivity
: Time whenalpamon
last contactedstarted_at
: Time whenalpamon
startedadded_at
: Time whenalpamon
was addedupdated_at
: Time whenalpamon
was updateduser
: User who added this server
Following URLs provide more detailed information about a server.
/api/servers/servers/<id>/info/
: System hardware information/api/servers/servers/<id>/os/
: Operating system information/api/servers/servers/<id>/time/
: Timezone and uptime/api/servers/servers/<id>/users/
: System users/api/servers/servers/<id>/groups/
: System groups/api/servers/servers/<id>/interfaces/
: Network interfaces/api/servers/servers/<id>/packages/
: System packages
You can also list system packages with the following API. This API provides more detailed query arguments and supports pagination.
Request:
GET /api/proc/packages/?server=7a50ea6c-2138-4d3f-9633-e50694c847c4&search=postgresql
Supported query arguments: search
, server
, name
, arch
Response:
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": "48369fcc-742d-4ed3-8740-0fa1960c0d17",
"added_at": "2022-10-14T18:55:44.198382+09:00",
"name": "postgresql@14",
"version": "14.5_5",
"source": "/opt/homebrew/Cellar/postgresql@14/",
"arch": null
}
]
}
Starring a server
Request:
POST /api/servers/servers/7a50ea6c-2138-4d3f-9633-e50694c847c4/star/
{
"status": true
}
If you want to star a server, set status
to true
. Otherwise, set it false
.
Please note that up to 5 servers can be starred by a user.
Updating or deleting a server
- URL:
/api/servers/servers/<id>/
- HTTP method:
PUT
,PATCH
,DELETE
- Request data:
name
,key
,enabled
, (alpamon only:version
,osquery_version
)
Getting or updating server itself
[alpamon
only] An authenticated server can access the above API with id
field set to -
.
- URL:
/api/servers/servers/-/
- HTTP method:
GET
,PUT
Commit information
[alpamon
only] Servers may commit gathered information using the following API.
- URL:
/api/servers/servers/-/commit/
Websh: A Web-based terminal
Websh is a new protocol to access servers remotely. Should clients use the following API to start and manage websh sessions.
New terminal
You can obtain a websh session using the following API.
- URL:
/api/websh/sessions/<uuid:id>/
- HTTP method:
POST
- Request data:
rows
,cols
(Both are positive numbers indicating the terminal size on the client.) - Response data
websocket
: A one-time websocket url that can be used to access terminal. The actual URL would look likewss://alpacon.io/ws/websh/<session_id>/<token>/
.api
: An API url for session object that can be used to adjust terminal size dynamically. Clients can call this API when a user resizes the terminal window.
- Status codes:
200 OK
on success.
Session adjustment
You can adjust the size of a websh session. Please note that session resizing takes a round trip time to alpamon.
- URL:
/api/websh/sessions/<uuid:id>/
- HTTP methods:
PUT
,PATCH
- Request data:
rows
,cols
- Response data:
rows
,cols
- Status codes:
200 OK
on success.
Implementation example
Here is an example implementing this feature at Javascript front. Following example is written based on xterm
3.x. The latest xterm
is 4.x.
<script src="{% static 'xterm/xterm.js' %}"></script>
<script src="{% static 'xterm/addons/attach/attach.js' %}"></script>
<script src="{% static 'xterm/addons/fit/fit.js' %}"></script>
<script src="{% static 'xterm/addons/webLinks/webLinks.js' %}"></script>
<script>
var resizeDelay = 500;
var timer = null;
Terminal.applyAddon(attach);
Terminal.applyAddon(fit);
Terminal.applyAddon(webLinks);
var term = new Terminal({
fontFamily: '"Monaco", monospace',
fontSize: 14,
scrollback: 100000,
});
term.open(document.getElementById('terminal'));
term.fit();
term.webLinksInit();
term.focus();
// obtain a new websh session
$.post("{% url 'api:servers:server-websh' object.pk %}", {
rows: term.rows,
cols: term.cols,
}, function(data) {
// data contains url for websocket and api endpoints
// make a websocket connection and register a resize event handler
var api_url = data.api;
var socket = new WebSocket(data.websocket);
socket.onclose = function onClose(event) {
term.writeln('\r\n\r\n(offline)');
};
term.attach(socket);
// resize terminal via api endpoint. delay applied on resize event.
window.addEventListener('resize', function() {
clearTimeout(timer);
timer = setTimeout(function() {
if (typeof api_url !== 'undefined') {
term.fit();
$.ajax({
url: api_url,
method: 'patch',
data: {
rows: term.rows,
cols: term.cols,
}
});
}
}, resizeDelay);
});
});
// alert when user is about to leave the screen
window.addEventListener('beforeunload', function(e) {
var message = 'You are about to leave this page. Please make sure you really want to leave.';
(e || window.event).returnValue = message;
return message;
});
</script>
Web-based FTP
Websh implements Web-based FTP service to support transferring files between users and servers.
Uploading files
You can post a file to /api/websh/uploads/
to upload a file to a server.
- URL:
/api/websh/uploads/
- HTTP method:
POST
- Request data
content
: A file content for uploading. A multipart form should be submitted as JSON does not support binary files.path
: Destination path for the file. If omitted, your home directory will be used as default.server
: Server instance id (It should be a uuid, not a name). You should have valid permission on the server.
- Response data: A file upload instance. For now, it does not include any meaningful result.
- Status codes:
201 CREATED
on success.
When POST finishes successfully, alpacon
will transfer the file to alpamon
. We are planning to report the transfer status via API.
Cancelling transfer
(🚧 Working in Progress) You can cancel a transfer request before it actually reaches to the server.
- URL:
/api/websh/uploads/<uuid:id>/
- HTTP method:
DELETE
Controlling servers
Running a pre-defined command
We provide a set of pre-defined commands which are frequently used when managing servers.
Request:
POST /api/servers/servers/7a50ea6c-2138-4d3f-9633-e50694c847c4/actions/
{
"action": "update_information"
}
You need to include action
in the request data. Supported actions are available in the browsable API.
Response:
HTTP 201 CREATED
Allow: POST, OPTIONS
Content-Type: application/json
Vary: Accept
{
"id": "2e458d4c-f85a-4a83-badf-90d62991cc12",
...
}
Once the request finished successfully, alpacon
will execute it via alpamon
. Corresponding command instance will be returned. You can check the result later via GET /api/events/commands/<id>/
.
Running an arbitrary command
You can run an arbitrary command on the system that alpamon
is installed. Your commands will run with your account privilege.
Request:
POST /api/events/commands/
{
"shell": "system",
"line": "pwd",
"data": "",
"scheduled_at": null,
"server": "7a50ea6c-2138-4d3f-9633-e50694c847c4"
}
As you can see in the example, shell
, line
, and server
are mandatory fields. data
and scheduled_at
are optional.
shell
:system
for system shell commands,osquery
for osquery commands,internal
for alpamon's internal commands.line
: Arbitrary command line that you want to rundata
: Optional data for the command. This field only works forinternal
commands.scheduled_at
: If specified,alpacon
will run the command at the scheduled time. Otherwise, it will be run now.server
: The instance ID of the server you want to run this command on.
Response:
HTTP 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"id": "83bf3f02-f70e-49a3-bf47-a39a8d06a9df",
"shell": "system",
"line": "pwd",
"data": "",
"success": null,
"result": null,
"status": {
"text": "Sent",
"color": "warning",
"cancellable": true,
"message": "Sent command to server, waiting response."
},
"response_delay": null,
"elapsed_time": null,
"added_at": "2022-10-10T12:02:28.532238+09:00",
"scheduled_at": "2022-10-10T12:02:28.528700+09:00",
"delivered_at": "2022-10-10T12:02:28.571022+09:00",
"acked_at": null,
"handled_at": null,
"server": "7a50ea6c-2138-4d3f-9633-e50694c847c4",
"requested_by": "a540bf0f-8b37-4f03-8546-dd71c6b03329",
"run_after": []
}
If you are going to test a scheduled command (commands that will run in the future), you need to execute celery background workers. For more about how to run celery
, you may refer to Alpacon README (opens in a new tab).
For the information about each response fields, please refer to the next section of this document.
Fetching list of commands
- URL:
/api/events/commands/
- HTTP method:
GET
Request:
GET /api/events/commands/?server=7a50ea6c-2138-4d3f-9633-e50694c847c4&requested_by=
Supported filters are server
and requested_by
. search
keywords are accepted at well.
We use page number pagination. Add page number as a request argument. Examples are ?page=1
, page=2
, and page=last
. We also accept page_size
argument no more than 100
for arbitrary page sizing. For more about pagination, please refer to this document (opens in a new tab).
Response:
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"count": 110,
"next": "http://localhost:8000/api/events/commands/?page=2&requested_by=&server=7a50ea6c-2138-4d3f-9633-e50694c847c4",
"previous": null,
"results": [
{
{
"id": "8befa6c4-9620-4aea-9fde-cac1335e01f8",
"shell": "internal",
"line": "ping",
"data": null,
"success": true,
"result": "2022-10-10T11:45:32.109641+09:00",
"status": {
"text": "Success",
"color": "success",
"cancellable": false,
"message": "Finished at 2022-10-10 11:45:32.244418+09:00."
},
"response_delay": 0.132617,
"elapsed_time": 0.067553,
"added_at": "2022-10-10T11:45:32.044390+09:00",
"scheduled_at": "2022-10-10T11:45:32.044248+09:00",
"delivered_at": "2022-10-10T11:45:32.044248+09:00",
"acked_at": "2022-10-10T11:45:32.176865+09:00",
"handled_at": "2022-10-10T11:45:32.244418+09:00",
"server": "7a50ea6c-2138-4d3f-9633-e50694c847c4",
"requested_by": null,
"run_after": []
},
{
"id": "869a1600-681e-409a-acd3-a63d621dce22",
"shell": "system",
"line": "pwd",
"data": "",
"success": true,
"result": "/Users/eunyoung/projects/alpacanetworks/alpamon",
"status": {
"text": "Success",
"color": "success",
"cancellable": false,
"message": "Finished at 2022-10-10 11:48:00.628272+09:00."
},
"response_delay": 0.370961,
"elapsed_time": 0.072433,
"added_at": "2022-10-09T22:12:00.077467+09:00",
"scheduled_at": "2022-10-09T23:11:00+09:00",
"delivered_at": "2022-10-10T11:48:00.184878+09:00",
"acked_at": "2022-10-10T11:48:00.555839+09:00",
"handled_at": "2022-10-10T11:48:00.628272+09:00",
"server": "7a50ea6c-2138-4d3f-9633-e50694c847c4",
"requested_by": "a540bf0f-8b37-4f03-8546-dd71c6b03329",
"run_after": []
},
...
]
success
:true
if the command succeeded,false
otherwise. We useexitcode
to determine this for system commands. This field isnull
until the command is executed.result
: The output result of the command. This field isnull
until the command is executed.status
: A dictionary showing the status of commandtext
: A short description about the command. Possible values areScheduled
,Queued
,Sent
,Acked
,Success
,Failed
,Stuck
, andError
.color
: Which text color to use. You can prefix this color withtext-
orbg-
if you are using Bootstrap.cancellable
: Whether this command can be cancelled. A command can be cancelled if it has not been sent to the server.message
: A detailed message describing the command status
response_delay
: The time taken to deliver this command. If the command has not been acked by the server, this field will benull
.elapsed_time
: The time taken to run the command. If the command has not run, this field will benull
.scheduled_at
: The scheduled time for this command. If this field is not specified, the command will be executed immediately.delivered_at
: The time that alpacon sent this command to alpamon.acked_at
: The time that alpamon acknowledged the command. The response delay meansacked_at - delivered_at
.handled_at
: The time that alpamon finished executing the command. The elapsed time meanshandled_at - acked_at
.server
: The id of the server targeted by this command.requested_by
: The id of the operator who requested the command.run_after
: The list of commands that should be run prior to this command.
Fetching list of logs
- URL:
/api/history/logs/
- HTTP method:
GET
Request:
GET /api/history/logs/?server=7a50ea6c-2138-4d3f-9633-e50694c847c4&program=&level=&name=&pid=&tid=
Supported filters are server
and more. search
keywords are accepted at well. Page number is accepted.
Response header:
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
Response data:
date
: Log date recorded by the server itself oralpamon
added_at
: Added time recorded byalpacon
. Logs are ordered by this field by default.level
:10
(DEBUG),20
(INFO),30
(WARN),40
(ERROR),50
(CRITICAL)msg
: Log message
{
"count": 128,
"next": "http://localhost:8000/api/history/logs/?level=&name=&page=2&pid=&program=&server=7a50ea6c-2138-4d3f-9633-e50694c847c4&tid=",
"previous": null,
"results": [
{
"id": 128,
"added_at": "2022-10-02T00:05:14.660008+09:00",
"date": "2022-10-02T00:05:14.456662+09:00",
"program": "alpamon",
"level": 30,
"name": "websocket",
"path": "/Users/eunyoung/projects/alpacanetworks/alpamon/env/lib/python3.9/site-packages/websocket/_logging.py",
"lineno": 66,
"pid": 10456,
"tid": 4393072128,
"process": "MainProcess",
"thread": "MainThread",
"msg": "websocket connected",
"server": "7a50ea6c-2138-4d3f-9633-e50694c847c4"
},
{
"id": 127,
"added_at": "2022-10-01T01:20:13.555034+09:00",
"date": "2022-10-01T01:20:13.347561+09:00",
"program": "alpamon",
"level": 30,
"name": "websocket",
"path": "/Users/eunyoung/projects/alpacanetworks/alpamon/env/lib/python3.9/site-packages/websocket/_logging.py",
"lineno": 66,
"pid": 10456,
"tid": 4393072128,
"process": "MainProcess",
"thread": "MainThread",
"msg": "websocket connected",
"server": "7a50ea6c-2138-4d3f-9633-e50694c847c4"
},
...
]
Notes on servers
Users can leave a note to a server so that they can memorize some details about it. Notes can be private or pinned.
Making a note
Use POST
to leave a note.
Request:
POST /api/servers/notes/
{
"server": "a7282bea-31d7-4b55-a43e-97e1240c90ab",
"content": "hello world.",
"private": false,
}
The length of content is limited to 512
. Markdown is supported.
Response:
{
"id": "57649aa5-dfca-4041-9b94-d6b61f5842e7",
"server": "a7282bea-31d7-4b55-a43e-97e1240c90ab",
"author": "a540bf0f-8b37-4f03-8546-dd71c6b03329",
"content": "hello world.",
"private": false,
"pinned": false,
"updated_at": "2022-12-04T12:44:43.248506+09:00"
}
Listing notes
You can list notes for a server.
GET /api/servers/notes/?server=a7282bea-31d7-4b55-a43e-97e1240c90ab
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"id": "e2fb88fb-00e3-49f0-9256-eb01734c7f09",
"server": "a7282bea-31d7-4b55-a43e-97e1240c90ab",
"author": "a540bf0f-8b37-4f03-8546-dd71c6b03329",
"content": "private message.",
"private": true,
"pinned": false,
"updated_at": "2022-12-04T12:49:35.704106+09:00"
},
{
"id": "57649aa5-dfca-4041-9b94-d6b61f5842e7",
"server": "a7282bea-31d7-4b55-a43e-97e1240c90ab",
"author": "a540bf0f-8b37-4f03-8546-dd71c6b03329",
"content": "hello world.",
"private": false,
"pinned": false,
"updated_at": "2022-12-04T12:44:43.248506+09:00"
}
]
}
- Pinned notes are listed first.
- Notes are ordered by
updated_at
in descending order. - Private notes are only visible to the authors.
Editing a note
You can edit a note using the note ID.
Request:
PATCH /api/servers/notes/57649aa5-dfca-4041-9b94-d6b61f5842e7/
{
"content": "hi world.",
"private": true,
}
You can't alter server
field.
Pinning a note
You can pin a note so that they can show up at first in the list.
PATCH /api/servers/notes/57649aa5-dfca-4041-9b94-d6b61f5842e7/
{
"pinned": true,
}
Deleting a note
If the note is not needed, you can delete a note.
DELETE /api/servers/notes/57649aa5-dfca-4041-9b94-d6b61f5842e7/
Please be aware that the editing or deleting a note is only allowed to following users.
- Note author
- Staffs
- Superusers
Private notes can only be edited or deleted by the note author.