-
-
Save kustomzone/d76a8aa8c568ce583da5c56c02746157 to your computer and use it in GitHub Desktop.
Freenet Peer Manager - Systemd-based peer lifecycle management
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| set -e | |
| BASE_DIR="/mnt/media/freenet-peers" | |
| PEERS_DIR="$BASE_DIR/peers" | |
| STATE_DIR="$BASE_DIR/state" | |
| CONFIG_FILE="$STATE_DIR/peer-config.json" | |
| FREENET_BIN="/usr/local/bin/freenet" | |
| GATEWAY_ADDR="127.0.0.1:31337" | |
| NETWORK_PORT_START=40000 | |
| WS_PORT_START=45000 | |
| START_DELAY=30 | |
| init_config() { | |
| if [ ! -f "$CONFIG_FILE" ]; then | |
| echo '{"peers":{},"next_network_port":40000,"next_ws_port":45000}' | \ | |
| sudo tee "$CONFIG_FILE" > /dev/null | |
| sudo chown freenet:freenet "$CONFIG_FILE" | |
| sudo chmod 664 "$CONFIG_FILE" | |
| fi | |
| } | |
| get_next_ports() { | |
| local network_port=$(jq -r '.next_network_port' "$CONFIG_FILE") | |
| local ws_port=$(jq -r '.next_ws_port' "$CONFIG_FILE") | |
| echo "$network_port $ws_port" | |
| } | |
| update_next_ports() { | |
| local network_port=$1 | |
| local ws_port=$2 | |
| local tmp_file=$(mktemp) | |
| jq ".next_network_port = $network_port | .next_ws_port = $ws_port" "$CONFIG_FILE" > "$tmp_file" | |
| sudo cp "$tmp_file" "$CONFIG_FILE" | |
| sudo chown freenet:freenet "$CONFIG_FILE" | |
| rm "$tmp_file" | |
| } | |
| generate_keypair() { | |
| local peer_id=$1 | |
| local keypair_path="$PEERS_DIR/$peer_id/keypair.pem" | |
| if [ ! -f "$keypair_path" ]; then | |
| local tmp_dir=$(mktemp -d) | |
| cd "$tmp_dir" | |
| openssl genpkey -algorithm RSA -out private.pem -pkeyopt rsa_keygen_bits:2048 | |
| sudo cp private.pem "$keypair_path" | |
| sudo chown freenet:freenet "$keypair_path" | |
| sudo chmod 600 "$keypair_path" | |
| cd - > /dev/null | |
| rm -rf "$tmp_dir" | |
| fi | |
| } | |
| create_peer_config() { | |
| local peer_id=$1 | |
| local network_port=$2 | |
| local ws_port=$3 | |
| local peer_dir="$PEERS_DIR/$peer_id" | |
| local config_toml="$peer_dir/config/config.toml" | |
| local gateways_toml="$peer_dir/config/gateways.toml" | |
| if [ ! -f "$config_toml" ]; then | |
| local tmp_file=$(mktemp) | |
| cat > "$tmp_file" <<EOF | |
| mode = "network" | |
| network-address = "0.0.0.0" | |
| network-port = $network_port | |
| ws-api-address = "127.0.0.1" | |
| ws-api-port = $ws_port | |
| transport_keypair = "$peer_dir/keypair.pem" | |
| log_level = "info" | |
| contracts_dir = "$peer_dir/data/contracts" | |
| delegates_dir = "$peer_dir/data/delegates" | |
| secrets_dir = "$peer_dir/data/secrets" | |
| db_dir = "$peer_dir/data/db" | |
| event_log = "$peer_dir/data/_EVENT_LOG" | |
| data_dir = "$peer_dir/data" | |
| config_dir = "$peer_dir/config" | |
| is_gateway = false | |
| actor_clients = true | |
| EOF | |
| sudo cp "$tmp_file" "$config_toml" | |
| sudo chown freenet:freenet "$config_toml" | |
| rm "$tmp_file" | |
| fi | |
| if [ ! -f "$gateways_toml" ]; then | |
| local tmp_file=$(mktemp) | |
| cat > "$tmp_file" <<EOF | |
| gateways = ["$GATEWAY_ADDR"] | |
| EOF | |
| sudo cp "$tmp_file" "$gateways_toml" | |
| sudo chown freenet:freenet "$gateways_toml" | |
| rm "$tmp_file" | |
| fi | |
| } | |
| create_peer() { | |
| local peer_id=$1 | |
| local network_port=$2 | |
| local ws_port=$3 | |
| local location=$(awk 'BEGIN{srand(); print rand()}') | |
| echo "Creating peer $peer_id..." | |
| local peer_dir="$PEERS_DIR/$peer_id" | |
| sudo mkdir -p "$peer_dir"/{data,config} | |
| sudo chown -R freenet:freenet "$peer_dir" | |
| generate_keypair "$peer_id" | |
| create_peer_config "$peer_id" "$network_port" "$ws_port" | |
| local tmp_file=$(mktemp) | |
| jq ".peers[\"$peer_id\"] = { | |
| \"network_port\": $network_port, | |
| \"ws_port\": $ws_port, | |
| \"data_dir\": \"$peer_dir/data\", | |
| \"config_dir\": \"$peer_dir/config\", | |
| \"keypair\": \"$peer_dir/keypair.pem\", | |
| \"location\": $location, | |
| \"gateway\": \"$GATEWAY_ADDR\", | |
| \"status\": \"stopped\" | |
| }" "$CONFIG_FILE" > "$tmp_file" | |
| sudo cp "$tmp_file" "$CONFIG_FILE" | |
| sudo chown freenet:freenet "$CONFIG_FILE" | |
| rm "$tmp_file" | |
| create_systemd_service "$peer_id" "$network_port" "$ws_port" | |
| echo "Created peer $peer_id (network:$network_port, ws:$ws_port, location:$location)" | |
| } | |
| create_systemd_service() { | |
| local peer_id=$1 | |
| local network_port=$2 | |
| local ws_port=$3 | |
| local peer_dir="$PEERS_DIR/$peer_id" | |
| local service_file="/etc/systemd/system/freenet-$peer_id.service" | |
| sudo tee "$service_file" > /dev/null <<EOF | |
| [Unit] | |
| Description=Freenet Peer $peer_id | |
| After=network.target freenet-gateway.service | |
| [Service] | |
| Type=simple | |
| User=freenet | |
| Group=freenet | |
| Environment="RUST_LOG=info,freenet=info" | |
| Environment="RUST_BACKTRACE=1" | |
| ExecStart=$FREENET_BIN \\ | |
| --data-dir $peer_dir/data \\ | |
| --config-dir $peer_dir/config \\ | |
| --network-port $network_port \\ | |
| --ws-api-port $ws_port \\ | |
| network \\ | |
| --transport-keypair $peer_dir/keypair.pem | |
| StandardOutput=append:$peer_dir/peer.log | |
| StandardError=append:$peer_dir/peer.log | |
| Restart=always | |
| RestartSec=10s | |
| [Install] | |
| WantedBy=multi-user.target | |
| EOF | |
| sudo systemctl daemon-reload | |
| sudo systemctl enable "freenet-$peer_id.service" | |
| } | |
| start_peer() { | |
| local peer_id=$1 | |
| if ! jq -e ".peers[\"$peer_id\"]" "$CONFIG_FILE" > /dev/null 2>&1; then | |
| echo "Error: Peer $peer_id does not exist" | |
| return 1 | |
| fi | |
| echo "Starting peer $peer_id..." | |
| sudo systemctl start "freenet-$peer_id" | |
| local tmp_file=$(mktemp) | |
| jq ".peers[\"$peer_id\"].status = \"running\" | .peers[\"$peer_id\"].started = \"$(date -Iseconds)\"" \ | |
| "$CONFIG_FILE" > "$tmp_file" | |
| sudo cp "$tmp_file" "$CONFIG_FILE" | |
| sudo chown freenet:freenet "$CONFIG_FILE" | |
| rm "$tmp_file" | |
| echo "Started peer $peer_id" | |
| } | |
| stop_peer() { | |
| local peer_id=$1 | |
| if [ "$peer_id" = "all" ]; then | |
| echo "Stopping all peers..." | |
| for peer in $(jq -r '.peers | keys[]' "$CONFIG_FILE"); do | |
| stop_peer "$peer" | |
| done | |
| return | |
| fi | |
| echo "Stopping peer $peer_id..." | |
| sudo systemctl stop "freenet-$peer_id" 2>/dev/null || true | |
| local tmp_file=$(mktemp) | |
| jq ".peers[\"$peer_id\"].status = \"stopped\"" "$CONFIG_FILE" > "$tmp_file" | |
| sudo cp "$tmp_file" "$CONFIG_FILE" | |
| sudo chown freenet:freenet "$CONFIG_FILE" | |
| rm "$tmp_file" | |
| echo "Stopped peer $peer_id" | |
| } | |
| status_all() { | |
| echo "=== Freenet Peer Status ===" | |
| echo "" | |
| if [ ! -f "$CONFIG_FILE" ]; then | |
| echo "No peers configured" | |
| return | |
| fi | |
| local peer_count=$(jq '.peers | length' "$CONFIG_FILE") | |
| echo "Total peers: $peer_count" | |
| echo "" | |
| printf "%-12s %-10s %-12s %-10s %-10s %s\n" "PEER" "STATUS" "NETWORK" "WS_API" "LOCATION" "STARTED" | |
| printf "%-12s %-10s %-12s %-10s %-10s %s\n" "----" "------" "-------" "------" "--------" "-------" | |
| for peer in $(jq -r '.peers | keys[]' "$CONFIG_FILE" | sort); do | |
| local status=$(jq -r ".peers[\"$peer\"].status" "$CONFIG_FILE") | |
| local network_port=$(jq -r ".peers[\"$peer\"].network_port" "$CONFIG_FILE") | |
| local ws_port=$(jq -r ".peers[\"$peer\"].ws_port" "$CONFIG_FILE") | |
| local location=$(jq -r ".peers[\"$peer\"].location" "$CONFIG_FILE" | awk '{printf "%.6f", $1}') | |
| local started=$(jq -r ".peers[\"$peer\"].started // \"never\"" "$CONFIG_FILE") | |
| local systemd_status="" | |
| if systemctl is-active --quiet "freenet-$peer" 2>/dev/null; then | |
| systemd_status="running" | |
| else | |
| systemd_status="stopped" | |
| fi | |
| printf "%-12s %-10s %-12s %-10s %-10s %s\n" \ | |
| "$peer" "$systemd_status" "$network_port" "$ws_port" "$location" "$started" | |
| done | |
| } | |
| list_peers() { | |
| if [ ! -f "$CONFIG_FILE" ]; then | |
| echo "No peers configured" | |
| return | |
| fi | |
| jq -r '.peers | keys[]' "$CONFIG_FILE" | sort | |
| } | |
| show_logs() { | |
| local peer_id=$1 | |
| if [ -z "$peer_id" ]; then | |
| echo "Showing unified logs..." | |
| sudo tail -f "$BASE_DIR"/peers/*/peer.log 2>/dev/null || echo "No logs available" | |
| else | |
| local log_file="$PEERS_DIR/$peer_id/peer.log" | |
| if [ -f "$log_file" ]; then | |
| sudo tail -f "$log_file" | |
| else | |
| echo "No log file for peer $peer_id" | |
| fi | |
| fi | |
| } | |
| info_peer() { | |
| local peer_id=$1 | |
| if ! jq -e ".peers[\"$peer_id\"]" "$CONFIG_FILE" > /dev/null 2>&1; then | |
| echo "Error: Peer $peer_id does not exist" | |
| return 1 | |
| fi | |
| echo "=== Peer $peer_id Info ===" | |
| jq ".peers[\"$peer_id\"]" "$CONFIG_FILE" | |
| } | |
| cmd_start() { | |
| local count=${1:-5} | |
| init_config | |
| echo "Starting $count peers with $START_DELAY second delay between each..." | |
| for i in $(seq 1 "$count"); do | |
| local peer_id=$(printf "peer-%02d" "$i") | |
| if jq -e ".peers[\"$peer_id\"]" "$CONFIG_FILE" > /dev/null 2>&1; then | |
| echo "Peer $peer_id already exists, starting it..." | |
| start_peer "$peer_id" | |
| else | |
| read network_port ws_port < <(get_next_ports) | |
| create_peer "$peer_id" "$network_port" "$ws_port" | |
| update_next_ports $((network_port + 1)) $((ws_port + 1)) | |
| start_peer "$peer_id" | |
| fi | |
| if [ "$i" -lt "$count" ]; then | |
| echo "Waiting $START_DELAY seconds before starting next peer..." | |
| sleep "$START_DELAY" | |
| fi | |
| done | |
| echo "" | |
| echo "All peers started!" | |
| status_all | |
| } | |
| enable_all() { | |
| echo "Enabling all peer services..." | |
| for peer in $(jq -r '.peers | keys[]' "$CONFIG_FILE"); do | |
| echo " Enabling freenet-$peer.service..." | |
| sudo systemctl enable "freenet-$peer.service" | |
| done | |
| echo "All peer services enabled" | |
| } | |
| start_all() { | |
| echo "Starting all configured peers..." | |
| for peer in $(jq -r '.peers | keys[]' "$CONFIG_FILE" | sort); do | |
| if ! systemctl is-active --quiet "freenet-$peer" 2>/dev/null; then | |
| echo " Starting $peer..." | |
| start_peer "$peer" | |
| else | |
| echo " $peer already running" | |
| fi | |
| done | |
| echo "" | |
| status_all | |
| } | |
| case "${1:-}" in | |
| init) | |
| init_config | |
| echo "Initialized configuration" | |
| ;; | |
| start) | |
| if [ "${2:-}" = "all" ]; then | |
| start_all | |
| else | |
| cmd_start "${2:-5}" | |
| fi | |
| ;; | |
| stop) | |
| stop_peer "${2:-all}" | |
| ;; | |
| restart) | |
| stop_peer "${2}" | |
| sleep 2 | |
| start_peer "${2}" | |
| ;; | |
| enable) | |
| enable_all | |
| ;; | |
| status) | |
| status_all | |
| ;; | |
| list) | |
| list_peers | |
| ;; | |
| logs) | |
| show_logs "${2:-}" | |
| ;; | |
| info) | |
| info_peer "${2}" | |
| ;; | |
| *) | |
| echo "Usage: $0 {init|start [N|all]|stop [peer-id|all]|restart [peer-id]|enable|status|list|logs [peer-id]|info [peer-id]}" | |
| echo "" | |
| echo "Commands:" | |
| echo " init Initialize configuration" | |
| echo " start [N] Start N peers (default: 5)" | |
| echo " start all Start all configured peers" | |
| echo " stop [peer-id] Stop specific peer or all" | |
| echo " restart [peer-id] Restart specific peer" | |
| echo " enable Enable all peer services for auto-start" | |
| echo " status Show all peer status" | |
| echo " list List all peer IDs" | |
| echo " logs [peer-id] Tail logs (specific peer or all)" | |
| echo " info [peer-id] Show peer configuration" | |
| exit 1 | |
| ;; | |
| esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment