Add cross-compilation, Linux binary build, and systemd service installer

- Dockerfile.cross: builds static x86_64 musl binary from macOS via Docker
- scripts/build-linux.sh: one-command cross-compilation
- scripts/install-service.sh: systemd service with security hardening
- Bump Rust Docker images to 1.86 for edition2024 support

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Siavash Sameni
2026-03-31 12:52:20 +04:00
parent d9007dc169
commit e604fdb2e7
5 changed files with 157 additions and 1 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
/target /target
/dist
btest_original btest_original
.claude/ .claude/

View File

@@ -1,5 +1,5 @@
# Stage 1: Build # Stage 1: Build
FROM rust:1.82-slim AS builder FROM rust:1.86-slim AS builder
WORKDIR /build WORKDIR /build
COPY Cargo.toml Cargo.lock ./ COPY Cargo.toml Cargo.lock ./

17
Dockerfile.cross Normal file
View File

@@ -0,0 +1,17 @@
# Cross-compile for x86_64 Linux using an x86_64 builder (emulated via QEMU on ARM hosts)
FROM --platform=linux/amd64 rust:1.86-slim AS builder
RUN apt-get update && apt-get install -y --no-install-recommends \
musl-tools \
&& rustup target add x86_64-unknown-linux-musl \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /build
COPY Cargo.toml Cargo.lock ./
COPY src/ src/
RUN cargo build --release --target x86_64-unknown-linux-musl
# Extract the binary
FROM scratch AS export
COPY --from=builder /build/target/x86_64-unknown-linux-musl/release/btest /btest

17
scripts/build-linux.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/usr/bin/env bash
# Build a static x86_64 Linux binary using Docker (works from macOS)
set -euo pipefail
cd "$(dirname "$0")/.."
echo "=== Building x86_64 Linux binary via Docker ==="
DOCKER_BUILDKIT=1 docker build \
-f Dockerfile.cross \
--output type=local,dest=./dist \
.
ls -lh dist/btest
file dist/btest
echo ""
echo "Binary ready at: dist/btest"
echo "Copy to your server: scp dist/btest user@server:/usr/local/bin/btest"

121
scripts/install-service.sh Executable file
View File

@@ -0,0 +1,121 @@
#!/usr/bin/env bash
# Install btest as a systemd service on Linux
# Usage: sudo ./install-service.sh [--auth-user USER --auth-pass PASS] [--port PORT]
set -euo pipefail
BTEST_BIN="/usr/local/bin/btest"
BTEST_USER="btest"
BTEST_PORT="2000"
AUTH_USER=""
AUTH_PASS=""
while [[ $# -gt 0 ]]; do
case $1 in
--auth-user) AUTH_USER="$2"; shift 2 ;;
--auth-pass) AUTH_PASS="$2"; shift 2 ;;
--port) BTEST_PORT="$2"; shift 2 ;;
--help|-h)
echo "Usage: sudo $0 [OPTIONS]"
echo ""
echo "Options:"
echo " --auth-user USER Authentication username"
echo " --auth-pass PASS Authentication password"
echo " --port PORT Listen port (default: 2000)"
echo ""
echo "Examples:"
echo " sudo $0"
echo " sudo $0 --auth-user admin --auth-pass secret"
echo " sudo $0 --port 2000 --auth-user admin --auth-pass mypass"
exit 0
;;
*) echo "Unknown option: $1"; exit 1 ;;
esac
done
if [[ $EUID -ne 0 ]]; then
echo "Error: This script must be run as root (use sudo)"
exit 1
fi
# Check binary exists
if [[ ! -f "$BTEST_BIN" ]]; then
# Try to find it in current directory or dist/
if [[ -f "./btest" ]]; then
cp ./btest "$BTEST_BIN"
elif [[ -f "./dist/btest" ]]; then
cp ./dist/btest "$BTEST_BIN"
else
echo "Error: btest binary not found. Copy it to $BTEST_BIN first."
echo " scp dist/btest root@server:/usr/local/bin/btest"
exit 1
fi
fi
chmod +x "$BTEST_BIN"
# Create service user
if ! id -u "$BTEST_USER" &>/dev/null; then
useradd --system --no-create-home --shell /usr/sbin/nologin "$BTEST_USER"
echo "Created system user: $BTEST_USER"
fi
# Build ExecStart command
EXEC_START="$BTEST_BIN -s -P $BTEST_PORT"
if [[ -n "$AUTH_USER" ]]; then
EXEC_START="$EXEC_START -a $AUTH_USER"
fi
if [[ -n "$AUTH_PASS" ]]; then
EXEC_START="$EXEC_START -p $AUTH_PASS"
fi
# Create systemd unit
cat > /etc/systemd/system/btest.service << UNIT
[Unit]
Description=MikroTik Bandwidth Test Server (btest)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=$BTEST_USER
ExecStart=$EXEC_START
Restart=always
RestartSec=5
# Security hardening
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
PrivateTmp=yes
ProtectKernelTunables=yes
ProtectControlGroups=yes
# Allow binding to port 2000 (< 1024 needs capability)
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
# Resource limits
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
UNIT
echo "Created /etc/systemd/system/btest.service"
# Reload and enable
systemctl daemon-reload
systemctl enable btest.service
systemctl restart btest.service
echo ""
echo "=== btest service installed and started ==="
echo ""
systemctl status btest.service --no-pager
echo ""
echo "Useful commands:"
echo " systemctl status btest # Check status"
echo " systemctl stop btest # Stop"
echo " systemctl restart btest # Restart"
echo " journalctl -u btest -f # Follow logs"
echo " systemctl disable btest # Disable autostart"