mirror of
https://github.com/0x1d/rcond.git
synced 2025-12-14 18:25:21 +01:00
209 lines
7.6 KiB
Markdown
209 lines
7.6 KiB
Markdown
# rcond
|
|
|
|
[](https://github.com/0x1d/rcond/actions/workflows/main.yaml)
|
|
|
|
A distributed management daemon designed to remotely configure system components, including:
|
|
- Network connections: Manage network connections through NetworkManager's D-Bus interface
|
|
- System hostname: Update the system's hostname
|
|
- Authorized SSH keys: Manage the user's authorized_keys file to add, remove, or modify authorized SSH keys
|
|
- System state: Restart and shutdown the system
|
|
- Cluster: Join and manage a cluster of rcond nodes
|
|
|
|
## Requirements
|
|
|
|
- Make
|
|
- Go
|
|
- NetworkManager
|
|
- systemd
|
|
- Linux
|
|
|
|
## Installation
|
|
|
|
In order to build and install `rcond` as a systemd service, you need to specify the target architecture and then run the install make target.
|
|
|
|
```sh
|
|
export ARCH=arm64
|
|
make install
|
|
```
|
|
|
|
## Development
|
|
|
|
There are several make targets available:
|
|
|
|
```sh
|
|
Available targets:
|
|
generate: Generate Swagger Spec
|
|
test: run tests
|
|
build: build binary for target $ARCH
|
|
install: build and install binary for target $ARCH as systemd service
|
|
uninstall: uninstall systemd service
|
|
run: run and build binary for target $ARCH
|
|
dev: run go programm
|
|
dev-agent: run go programm with agent config
|
|
upload: upload binary of given $ARCH to rpi-test
|
|
```
|
|
|
|
## Configuration
|
|
|
|
The default config file location is `/etc/rcond/config.yaml`.
|
|
It can be overwritten by environment variables and flags.
|
|
An full example configuration with comments can be found in `config/rcond.yaml`
|
|
|
|
### API Server
|
|
|
|
The API server is the main component of the rcond daemon. It is responsible for managing the host and providing a REST API for managing the system.
|
|
|
|
Example configuration:
|
|
```yaml
|
|
rcond:
|
|
addr: 0.0.0.0:8080
|
|
api_token: 1234567890
|
|
```
|
|
|
|
### Cluster
|
|
|
|
The cluster agent is a component of rcond that is responsible for joining and managing a cluster of rcond nodes.
|
|
This functionality can be used to manage and configure multiple hosts through a single API server.
|
|
In the background, the cluster agent will use [Serf](https://github.com/hashicorp/serf) to form a cluster, handle node discovery and gossip.
|
|
|
|
Forming a cluster is optional and can be enabled by configuring the cluster section in the config file.
|
|
|
|
Example configuration:
|
|
```yaml
|
|
cluster:
|
|
# Enable the cluster agent
|
|
enabled: true
|
|
# Name of the node in the cluster
|
|
node_name: rcond
|
|
# Secret key for the cluster agent used for message encryption.
|
|
# Must be 32 bytes long and base64 encoded.
|
|
# Generate with: base64 /dev/urandom | tr -d '\n' | head -c 32
|
|
secret_key: DMXnaJUUbIBMj1Df0dPsQY+Sks1VxWTa
|
|
# Advertise address for the cluster agent
|
|
advertise_addr: 0.0.0.0
|
|
# Advertise port for the cluster agent
|
|
advertise_port: 7946
|
|
# Bind address for the cluster agent
|
|
bind_addr: 0.0.0.0
|
|
# Bind port for the cluster agent
|
|
bind_port: 7946
|
|
# Join addresses for the cluster agent
|
|
join:
|
|
- 127.0.0.1:7947
|
|
```
|
|
|
|
### Environment Variables
|
|
|
|
| Environment Variable | Description | Default |
|
|
|----------------------|-----------------------------------------|---------------|
|
|
| RCOND_ADDR | Address to bind the HTTP server to. | 0.0.0.0:8080 |
|
|
| RCOND_API_TOKEN | API token to use for authentication. | N/A |
|
|
|
|
## API
|
|
|
|
The full API specification can be found in [api/rcond.yaml](api/rcond.yaml).
|
|
|
|
### Authentication
|
|
|
|
All endpoints except `/health` require authentication via an API token passed in the `X-API-Token` header. The token is configured via the `RCOND_API_TOKEN` environment variable when starting the daemon.
|
|
|
|
### Endpoints
|
|
| Method | Path | Description |
|
|
|---------|-------------------------------------|-----------------------------------------|
|
|
| GET | `/health` | Health check endpoint |
|
|
| POST | `/network/ap` | Create a WiFi access point |
|
|
| POST | `/network/sta` | Connect to a WiFi access point |
|
|
| PUT | `/network/interface/{interface}` | Activate a connection |
|
|
| DELETE | `/network/interface/{interface}` | Deactivate a connection |
|
|
| DELETE | `/network/connection/{uuid}` | Remove a connection |
|
|
| GET | `/hostname` | Get the hostname |
|
|
| POST | `/hostname` | Set the hostname |
|
|
| POST | `/users/{user}/keys` | Add an authorized SSH key |
|
|
| DELETE | `/users/{user}/keys/{fingerprint}` | Remove an authorized SSH key |
|
|
| POST | `/system/restart` | Restart the system |
|
|
| POST | `/system/shutdown` | Shutdown the system |
|
|
| GET | `/cluster/members` | Get the cluster members |
|
|
| POST | `/cluster/join` | Join cluster nodes |
|
|
| POST | `/cluster/leave` | Leave the cluster |
|
|
| POST | `/cluster/event` | Send a cluster event |
|
|
|
|
### Response Codes
|
|
|
|
- 200: Success
|
|
- 400: Bad request (invalid JSON payload)
|
|
- 405: Method not allowed
|
|
- 500: Internal server error
|
|
|
|
### Request/Response Format
|
|
All endpoints use JSON for request and response payloads.
|
|
|
|
## Cluster Events
|
|
|
|
Cluster events are used for broadcast messages to all nodes in the cluster. They are sent as HTTP POST requests to the `/cluster/event` endpoint.
|
|
|
|
The request body should be a JSON object with the following fields:
|
|
|
|
| Field | Description | Optional |
|
|
|----------|-----------------------------------------|-----------|
|
|
| `name` | The name of the event | No |
|
|
| `payload`| The payload of the event | Yes |
|
|
|
|
The response will be a JSON object with the following fields:
|
|
|
|
| Field | Description | Optional |
|
|
|----------|----------------------------------------------------------------------------------|-----------|
|
|
| `status` | The status of the event. This is a string, either "success" or "error". | No |
|
|
| `error` | If the status is "error", this field will contain a string describing the error. | Yes |
|
|
|
|
Following events are implemented:
|
|
|
|
| Event Name | Description | Payload |
|
|
|------------|----------------------|---------|
|
|
| restart | Restart the cluster | N/A |
|
|
| shutdown | Shutdown the cluster | N/A |
|
|
|
|
## Examples
|
|
|
|
### Connect to a WiFi Access Point
|
|
|
|
This example will automatically connect to a WiFi access point with the given SSID and password on the interface "wlan0".
|
|
|
|
```bash
|
|
curl -X POST "http://rpi-test:8080/network/sta" \
|
|
-H "Content-Type: application/json" \
|
|
-H "X-API-Token: 1234567890" \
|
|
-d '{
|
|
"interface": "wlan0",
|
|
"ssid": "MyAccessPoint",
|
|
"password": "StrongPassword",
|
|
"autoconnect": true
|
|
}'
|
|
```
|
|
|
|
### Setup an Access Point
|
|
|
|
This example will create an access point on the interface "wlan0" with the given SSID and password.
|
|
|
|
```bash
|
|
curl -X POST "http://rpi-test:8080/network/ap" \
|
|
-H "Content-Type: application/json" \
|
|
-H "X-API-Token: 1234567890" \
|
|
-d '{
|
|
"interface": "wlan0",
|
|
"ssid": "MyAccessPoint",
|
|
"password": "StrongPassword",
|
|
"autoconnect": true
|
|
}'
|
|
```
|
|
### Restart the cluster
|
|
|
|
This example will restart all nodes in the cluster
|
|
|
|
```bash
|
|
curl -X POST "http://rpi-test:8080/cluster/event" \
|
|
-H "accept: application/json" \
|
|
-H "X-API-Token: 1234567890" \
|
|
-d '{
|
|
"name": "restart"
|
|
}'
|
|
``` |