Block Assets Manager (BAM) Agent
This is an agent that is intended to be installed on miners to help facilitate management of them via HTTP as well
as monitoring for issues internal to the miner. The documentation below assumes you have the latest version of the
agent installed.
Currently, the agent targets the BW-L21 miner, but in the future we will target all miners. Pull requests welcome.
Thanks to HyperBitShop.io for sponsoring this project.
Running (defaults):
./bam_agent-linux-arm -port=1111 -no-update=false
A config file is writen to /etc/bam_agent.json
.
Automatic updates
By default, the BAM Agent will automatically attempt to self update from the Github
latest release tab. It chooses a random hour of the day to update.
This way, if you have a number of machines, they will not all DDOS Github and your network. You can override the update
behavior to not perform any updates by setting -no-update=true
when starting the agent.
Automatic updates brings security into question. You don't want someone being able to install a binary on your
machine that has not been developed in a secure fashion. We employ a strict process around this that is completely
transparent on github.
The authors have 2FA setup on their Github accounts and the project requires 2FA. All commits are required to be
signed. All merges to master require a PR and passing unit tests. Builds are tested to ensure the binary starts up
and serves the /status page. Travis CI automates the updates to the release page. Updates have their downloaded
binaries hash checked. Updates are zero downtime.
Install onto miner
The releases tab has master
binaries cross compiled for ARM
suitable for running on the miner. These are built automatically on
Travis.
Included in the repository is an install.sh script
which can be used to install onto any number of machines.
Automated
- Install the required software (sshpass) and
(parallel)
- Clone the repository
- Download the latest bam_agent binary from the releases tab,
into the cloned folder. Keep it compressed with the .gz extension
- Create a
workers.txt
file in the folder and add all your IP addresses, one per line
- Run
./install.sh
Manual
The ./install.sh
script automates the manual steps, which are described below:
Download the latest release and copy the gunzipped
bam_agent-linux-arm
binary to /usr/bin
gunzip bam_agent-linux-arm.gz
chmod ugo+x bam_agent-linux-arm
scp bam_agent-linux-arm root@MINER_IP:/usr/bin
Create /etc/systemd/system/bam_agent.service
ssh root@MINER_IP "echo '
[Unit]
Description=bam_agent
After=init.service
[Service]
Type=simple
ExecStart=/usr/bin/bam_agent-linux-arm
Restart=always
RestartSec=4s
StandardOutput=journal+console
[Install]
WantedBy=multi-user.target
' > /etc/systemd/system/bam_agent.service"
Enable the service:
ssh root@MINER_IP "systemctl enable bam_agent; systemctl start bam_agent"
Building from source
We recommend that you download prebuilt binaries from the releases tab. However, if you would like to build your own...
- Install golang (OSX, use brew)
- Install dep (OSX, use brew)
git clone https://github.com/blockassets/bam_agent.git
make dep
make arm
(Builds binary for arm)
API
GET /cgminer/start
Presents a page with a button to start cgminer.
POST /cgminer/start
Starts cgminer
GET /cgminer/quit
Presents a page with a button to stop cgminer.
POST /cgminer/quit
Stops cgminer via cgminer API call (systemd will restart it). Does not work with BW-L21.
GET /cgminer/restart
Presents a page with a button to restart cgminer.
POST /cgminer/restart
Stops cgminer via cgminer API call (systemd will restart it)
PUT /config/frequency
Send PUT request with json body:
{"frequency": "684"}
Restarts cgminer.
GET /config/pools
{"pool1": "", "pool2": "", "pool3": ""}
PUT /config/pools
Send PUT request with json body:
{"pool1": "", "pool2": "", "pool3": ""}
Restarts cgminer.
PUT /config/dhcp
Updates /usr/app/conf.default
and /etc/network/interfaces
NO BODY NECESSARY
Call /reboot
to make the changes take effect.
Note, we don't recommend using DHCP for miners. While it sounds good, in practice, it makes it difficult to locate
the miner, takes longer to boot, prevents wasted IP space, and has a dependency on a DHCP server. Since the miners
are all in specific locations, it is better just to maintain a mapping of location to ip address. This keeps things
simple. See below for managing locations.
PUT /config/ip
Updates /usr/app/conf.default
and /etc/network/interfaces
{"ip": "10.10.0.11", "mask": "255.255.252.0", "gateway": "10.10.0.1", "dns": "8.8.8.8"}
Call /reboot
to make the changes take effect
PUT /config/location
Store the physical location of the miner. This is saved in /etc/bam_agent.json
and exposed in the /status
call.
{"facility": "", "rack": "", "row": "", "shelf": 1, "position": 1}
Facility is your 'data center'. Each rack of machines is numbered from the bottom to the top.
Each row resets the count. So if you have 3 miners on a shelf, you might say: row B, rack 20, self 5, position 3 or
more simply: DC1-B20-5-3
Assign each location an IP address and you're done. Easy to find a needle in a haystack and no chance for duplicate IPs.
GET /status
{
"agent": "39892e1 2018-03-06 02:06:09",
"miner": "value in /usr/app/version.txt",
"uptime": "0s",
"mac": "ab:bc:32:b2:81:79",
"location": {
"facility": "",
"rack": "",
"row": "",
"shelf": 1,
"position": 1
}
}
GET /reboot
Presents a page with a button to reboot the miner.
POST /reboot
Reboots the miner based on a timer so that a proper response can be sent to the client.
GET /reboot/force
Presents a page with a button to reboot the miner.
POST /reboot/force
Reboots the miner without the timer.
GET /ntpdate
Presents a page with a button to run ntpdate.
POST /ntpdate
Calls ntpdate -u time.google.com
to set the date on the miner.
POST /update
Upload a compressed archive of files and execute an enclosed shell script. This allows one to easily distribute
updates to the miners.
- Create a folder and put a script in it called
update.sh
- .tar.gz the folder
- HTTP file upload the compressed archive with the form parameter name of
file
- Optionally add a
script
form parameter to override the default update.sh
name
Returns the stdout/stderr of the script.
Example: curl -F "script=update.sh" -F "file=@/tmp/update.tar.gz" http://IP:1111/update
Monitors
Monitors allow us to execute code periodically.
Monitors are configured by editing the /etc/bam_agent.json
file. This file is created when the agent first starts.
Accepted shares
Enabled by default. Runs every 5m. If the miner has not accepted any new shares since the last run, reboot.
This works around a bug where the miner software stops submitting shares to the pool, yet continues doing work.
High load
Enabled by default. Runs every 1m. If the 1m average load is above 5, reboot -f
the miner.
This works around a bug where the load spikes and the miner stops submitting shares to the pool.
High temp
Enabled by default. Runs every 5m and checks to see if the temperature is over 100c. If so, it uses systemd to
shut cgminer down. A reboot will enable things again.
Low memory
Enabled by default. Runs every 1m and checks to see if the available system memory is under 140mb.
If so, it reboots. This works around a bug where cgminer will randomly eat up available memory and freeze the machine.
Quit cgminer
Disabled by default. Periodically quit the miner app to free up memory and start fresh.
Reboot
Disabled by default. Periodically reboot the entire miner to free up memory and start fresh.
Prometheus exporters
Prometheus is an amazing metrics collection system. Combine it with
Grafana and you have an extremely powerful visualization and performance tracking tool
for your miners.
Included in the agent are two prometheus exporters:
- node_exporter (operating system metrics)
- cgminer_exporter (cgminer metrics)
By including them in the agent, you don't need to install those binaries separately.
In order to configure prometheus, use configuration like this:
prometheus.yml
- job_name: 'cgminer_exporter'
metrics_path: /metrics/cgminer_exporter
file_sd_configs:
- files:
- 'workers.json'
- job_name: 'node_exporter'
metrics_path: /metrics/node_exporter
file_sd_configs:
- files:
- 'workers.json'
workers.json
[{
"targets": [
"10.10.0.11:1111",
"10.10.0.12:1111",
"10.10.0.13:1111"
]
}]