Skip to content

Commit 18afa7e

Browse files
committed
Add Start9 (StartOS) package for Hydra-Pool
Bundles hydrapool, Prometheus, and Grafana into a single container managed by supervisord, packaged as an .s9pk for sideloading onto StartOS instances with a bitcoind dependency.
1 parent 9553363 commit 18afa7e

21 files changed

Lines changed: 989 additions & 1 deletion

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,9 @@ store*.db
33
p2pool.log
44
.env
55
docker/.env
6-
logs/*
6+
logs/*
7+
8+
# Start9 build artifacts
9+
start9/*.s9pk
10+
start9/docker-images/
11+
start9/scripts/embassy.js

justfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,8 @@ run config="config.toml":
1717

1818
check:
1919
cargo check
20+
21+
# Build the Start9 .s9pk package
22+
start9:
23+
@echo "Building Start9 package..."
24+
cd start9 && make

start9/Dockerfile

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Stage 1: Build Hydra-Pool from source
2+
FROM rust:1.88-slim-bullseye AS builder
3+
4+
RUN apt-get update && apt-get install -y \
5+
build-essential \
6+
clang \
7+
pkg-config \
8+
libzmq3-dev \
9+
git \
10+
cmake \
11+
libzstd-dev \
12+
libsnappy-dev \
13+
libbz2-dev \
14+
liblz4-dev \
15+
zlib1g-dev \
16+
libssl-dev \
17+
&& rm -rf /var/lib/apt/lists/*
18+
19+
WORKDIR /hydrapool
20+
21+
COPY src/ ./src/
22+
COPY Cargo.lock Cargo.toml ./
23+
24+
RUN cargo build --release
25+
26+
# Stage 2: Grab Prometheus binary
27+
FROM prom/prometheus:v3.6.0 AS prometheus
28+
29+
# Stage 3: Grab Grafana
30+
FROM grafana/grafana:12.2.0 AS grafana
31+
32+
# Stage 4: Runtime image
33+
FROM debian:bullseye-slim
34+
35+
# Install runtime dependencies
36+
RUN apt-get update && apt-get install -y \
37+
libzmq5 \
38+
libssl1.1 \
39+
libzstd1 \
40+
libsnappy1v5 \
41+
libbz2-1.0 \
42+
liblz4-1 \
43+
ca-certificates \
44+
wget \
45+
curl \
46+
supervisor \
47+
jq \
48+
netcat-openbsd \
49+
tini \
50+
&& rm -rf /var/lib/apt/lists/*
51+
52+
# Install yq (not available in Debian Bullseye repos)
53+
ARG TARGETARCH
54+
RUN YQ_ARCH=$(echo ${TARGETARCH} | sed 's/amd64/amd64/;s/arm64/arm64/') && \
55+
wget -qO /usr/local/bin/yq "https://github.com/mikefarah/yq/releases/download/v4.44.6/yq_linux_${YQ_ARCH}" && \
56+
chmod +x /usr/local/bin/yq
57+
58+
# Create hydrapool user
59+
RUN groupadd --system hydrapool && \
60+
useradd --system --gid hydrapool --home-dir /data/hydrapool \
61+
--no-create-home --shell /usr/sbin/nologin hydrapool
62+
63+
# Copy Hydra-Pool binaries
64+
COPY --from=builder /hydrapool/target/release/hydrapool /usr/local/bin/
65+
COPY --from=builder /hydrapool/target/release/hydrapool_cli /usr/local/bin/
66+
RUN chmod +x /usr/local/bin/hydrapool /usr/local/bin/hydrapool_cli
67+
68+
# Copy Prometheus binary
69+
COPY --from=prometheus /bin/prometheus /usr/local/bin/prometheus
70+
COPY --from=prometheus /bin/promtool /usr/local/bin/promtool
71+
RUN chmod +x /usr/local/bin/prometheus /usr/local/bin/promtool
72+
73+
# Copy Grafana
74+
COPY --from=grafana /usr/share/grafana /usr/share/grafana
75+
COPY --from=grafana /run.sh /usr/share/grafana/run.sh
76+
RUN ln -s /usr/share/grafana/bin/grafana /usr/local/bin/grafana-server || \
77+
ln -s /usr/share/grafana/bin/grafana-server /usr/local/bin/grafana-server || true
78+
79+
# Copy Prometheus config template
80+
COPY prometheus/prometheus.yml /etc/prometheus/prometheus.yml.template
81+
82+
# Copy Grafana provisioning and dashboards
83+
COPY prometheus/grafana/provisioning/ /etc/grafana/provisioning/
84+
COPY prometheus/grafana/dashboards/ /etc/grafana/dashboards/
85+
86+
# Copy config template
87+
COPY docker/config-example.toml /etc/hydrapool/config-example.toml
88+
89+
# Copy Start9 runtime files
90+
COPY start9/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
91+
COPY start9/docker_entrypoint.sh /usr/local/bin/docker_entrypoint.sh
92+
COPY start9/health_check.sh /usr/local/bin/health_check.sh
93+
COPY start9/check-api.sh /usr/local/bin/check-api.sh
94+
COPY start9/check-stratum.sh /usr/local/bin/check-stratum.sh
95+
96+
RUN chmod +x /usr/local/bin/docker_entrypoint.sh \
97+
/usr/local/bin/health_check.sh \
98+
/usr/local/bin/check-api.sh \
99+
/usr/local/bin/check-stratum.sh
100+
101+
# Create data directories
102+
RUN mkdir -p /data/hydrapool /data/prometheus/data /data/grafana \
103+
/data/logs /data/start9 && \
104+
chown -R hydrapool:hydrapool /data/hydrapool /data/logs && \
105+
chown -R nobody:nogroup /data/prometheus && \
106+
chown -R 472:0 /data/grafana
107+
108+
# Expose ports: Stratum, API, Prometheus, Grafana
109+
EXPOSE 3333 46884 9090 3000
110+
111+
ENTRYPOINT ["tini", "--", "docker_entrypoint.sh"]

start9/Makefile

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
PKG_VERSION := $(shell yq e ".version" manifest.yaml)
2+
PKG_ID := $(shell yq e ".id" manifest.yaml)
3+
TS_FILES := $(shell find scripts -name '*.ts' 2>/dev/null)
4+
5+
.DELETE_ON_ERROR:
6+
7+
all: verify
8+
9+
clean:
10+
rm -f $(PKG_ID).s9pk
11+
rm -rf docker-images
12+
rm -f scripts/embassy.js
13+
14+
verify: $(PKG_ID).s9pk
15+
start-sdk verify s9pk $(PKG_ID).s9pk
16+
17+
# Pack the s9pk archive
18+
$(PKG_ID).s9pk: manifest.yaml instructions.md icon.png scripts/embassy.js docker-images/aarch64.tar docker-images/x86_64.tar assets/compat/config_spec.yaml
19+
start-sdk pack
20+
21+
# Bundle TypeScript procedures
22+
scripts/embassy.js: $(TS_FILES) deps.ts
23+
cd scripts && deno run --allow-read --allow-write --allow-net --allow-env bundle.ts
24+
25+
# Build Docker images for both architectures
26+
docker-images/aarch64.tar: Dockerfile ../src/**/* ../Cargo.toml ../Cargo.lock
27+
mkdir -p docker-images
28+
docker buildx build \
29+
--tag start9/$(PKG_ID)/main:$(PKG_VERSION) \
30+
--platform linux/arm64 \
31+
-o type=docker,dest=docker-images/aarch64.tar \
32+
-f Dockerfile ..
33+
34+
docker-images/x86_64.tar: Dockerfile ../src/**/* ../Cargo.toml ../Cargo.lock
35+
mkdir -p docker-images
36+
docker buildx build \
37+
--tag start9/$(PKG_ID)/main:$(PKG_VERSION) \
38+
--platform linux/amd64 \
39+
-o type=docker,dest=docker-images/x86_64.tar \
40+
-f Dockerfile ..
41+
42+
# Install on a running StartOS instance
43+
install: $(PKG_ID).s9pk
44+
start-cli package install $(PKG_ID).s9pk
45+
46+
.PHONY: all clean verify install

start9/README.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# Hydra-Pool for StartOS
2+
3+
This directory contains the Start9 package for Hydra-Pool, allowing it to run as a service on [StartOS](https://start9.com/).
4+
5+
The package bundles Hydra-Pool, Prometheus, and Grafana into a single container managed by supervisord.
6+
7+
## Prerequisites
8+
9+
- [start-sdk](https://github.com/Start9Labs/start-os) (v0.3.5+)
10+
- Docker with buildx (multi-platform support)
11+
- [Deno](https://deno.land/)
12+
- [yq](https://github.com/mikefarah/yq)
13+
14+
### Installing start-sdk
15+
16+
```bash
17+
git clone -b latest --recursive https://github.com/Start9Labs/start-os.git
18+
cd start-os/core
19+
./install-sdk.sh
20+
start-sdk init
21+
```
22+
23+
## Building
24+
25+
From the `start9/` directory:
26+
27+
```bash
28+
# Full build (Docker images + pack + verify)
29+
make
30+
31+
# Or from the project root with just:
32+
just start9
33+
```
34+
35+
This will:
36+
1. Bundle the TypeScript procedures (`scripts/embassy.js`)
37+
2. Build Docker images for aarch64 and x86_64
38+
3. Pack everything into `hydrapool.s9pk`
39+
4. Verify the package
40+
41+
## Installing
42+
43+
Sideload the `.s9pk` onto a running StartOS instance:
44+
45+
```bash
46+
start-cli package install hydrapool.s9pk
47+
```
48+
49+
Or upload `hydrapool.s9pk` through the StartOS web UI under **System > Sideload**.
50+
51+
## Architecture
52+
53+
```
54+
StartOS
55+
└── Hydra-Pool container (supervisord)
56+
├── hydrapool — Mining pool (ports 3333, 46884)
57+
├── prometheus — Metrics collection (port 9090)
58+
└── grafana — Monitoring dashboards (port 3000)
59+
```
60+
61+
### Interfaces
62+
63+
| Interface | Port | Access | Description |
64+
|-----------|------|--------|-------------|
65+
| Stratum | 3333 | Tor | Mining protocol for connecting miners |
66+
| API | 46884 | Tor + LAN | REST API and Prometheus metrics |
67+
| Grafana | 3000 | Tor + LAN | Monitoring dashboard (UI) |
68+
69+
### Dependencies
70+
71+
- **Bitcoin Core** — required, auto-configured for RPC and ZMQ
72+
73+
### Configuration
74+
75+
User-configurable settings are defined in `assets/compat/config_spec.yaml`. Bitcoin RPC and ZMQ settings are auto-configured from the bitcoind dependency.
76+
77+
## File Structure
78+
79+
```
80+
start9/
81+
├── Makefile # Build automation
82+
├── manifest.yaml # Start9 package manifest
83+
├── Dockerfile # Multi-service container (multi-stage)
84+
├── docker_entrypoint.sh # Init script + config generation
85+
├── supervisord.conf # Process manager for 3 services
86+
├── health_check.sh # Health check dispatcher
87+
├── check-api.sh # API health check
88+
├── check-stratum.sh # Stratum port check
89+
├── instructions.md # User-facing setup guide
90+
├── icon.png # Service icon
91+
├── deps.ts # Embassy SDK dependency
92+
├── assets/
93+
│ └── compat/
94+
│ └── config_spec.yaml # Configuration UI schema
95+
└── scripts/
96+
├── embassy.ts # Entry point for TS procedures
97+
├── bundle.ts # Deno bundler
98+
└── services/
99+
├── getConfig.ts # Read config
100+
├── setConfig.ts # Validate + write config
101+
├── properties.ts # UI properties
102+
└── migrations.ts # Version migrations
103+
```
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
bitcoin-network:
2+
type: enum
3+
name: Bitcoin Network
4+
description: The Bitcoin network to mine on.
5+
default: main
6+
values:
7+
- main
8+
- testnet4
9+
- signet
10+
11+
bootstrap-address:
12+
type: string
13+
name: Bootstrap Address
14+
description: |
15+
Bitcoin address used for initial block templates before any miners
16+
have submitted shares. The default is the 256 Foundation donation
17+
address. Change this to your own address.
18+
nullable: false
19+
default: "bc1qypskemx80lznv4tjpnmpw9c5pgpy32fpkk3sw2"
20+
pattern: "^(bc1|[13]|tb1|bcrt1)[a-zA-HJ-NP-Z0-9]{25,62}$"
21+
pattern-description: Must be a valid Bitcoin address (mainnet, testnet, or signet).
22+
23+
pool-fee:
24+
type: number
25+
name: Pool Fee
26+
description: |
27+
Fee charged by the pool operator, in basis points (100 = 1%).
28+
Set to 0 for no fee. Maximum 10% (1000 bips).
29+
nullable: false
30+
integral: true
31+
range: "[0,1000]"
32+
default: 0
33+
units: basis points
34+
35+
pool-fee-address:
36+
type: string
37+
name: Pool Fee Address
38+
description: |
39+
Bitcoin address to receive pool fees. Required if pool fee is
40+
greater than 0.
41+
nullable: true
42+
default: ~
43+
pattern: "^(bc1|[13]|tb1|bcrt1)[a-zA-HJ-NP-Z0-9]{25,62}$"
44+
pattern-description: Must be a valid Bitcoin address.
45+
46+
donation:
47+
type: number
48+
name: Developer Donation
49+
description: |
50+
Optional donation to Hydra-Pool developers, in basis points
51+
(100 = 1%). Default is 0.5%. Set to 0 to disable.
52+
nullable: false
53+
integral: true
54+
range: "[0,10000]"
55+
default: 50
56+
units: basis points
57+
58+
difficulty-multiplier:
59+
type: number
60+
name: Difficulty Multiplier
61+
description: |
62+
Defines the PPLNS window size for calculating payout proportions.
63+
Higher values mean a larger window. See the project wiki for
64+
guidance on choosing this value.
65+
nullable: false
66+
integral: false
67+
range: "[0.1,10.0]"
68+
default: 1.0
69+
70+
pplns-ttl-days:
71+
type: number
72+
name: PPLNS Share TTL
73+
description: |
74+
Number of days shares remain valid in the PPLNS window before
75+
they expire.
76+
nullable: false
77+
integral: true
78+
range: "[1,30]"
79+
default: 7
80+
units: days
81+
82+
pool-signature:
83+
type: string
84+
name: Pool Signature
85+
description: |
86+
Optional signature included in mined blocks to identify your pool.
87+
Maximum 16 characters. Leave empty for anonymous mining.
88+
nullable: true
89+
default: "hydrapool"
90+
maxlength: 16
91+
92+
log-level:
93+
type: enum
94+
name: Log Level
95+
description: Logging verbosity level for the Hydra-Pool service.
96+
default: info
97+
values:
98+
- error
99+
- warn
100+
- info
101+
- debug

0 commit comments

Comments
 (0)