Source previews
callback.sh
349 bytes · SHA-256 ca6a4d5d79d716fc53e96700823e78ee26ecf344d83b5994656cc5e21d0832b6
#!/bin/sh
send_callback() {
if [ -z "$CALLBACK_URL" ]; then
return
fi
curl -s -X POST "$CALLBACK_URL" \
-H "Content-Type: application/json" \
-d "$1"
}
report_error() {
send_callback "{\"event\":\"error\",\"message\":\"${1}\"}"
}
send_log() {
send_callback "{\"event\":\"log\",\"message\":\"${1}\"}"
}
getifaddrs_override.c
1055 bytes · SHA-256 6b1fc22d4b2f104a033af3a4410bff0249bcdb144d875b80d3c999e7b055b00d
#include <ifaddrs.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
int getifaddrs(struct ifaddrs **ifap) {
struct ifaddrs *ifa = calloc(1, sizeof(struct ifaddrs));
if (!ifa) return -1;
ifa->ifa_next = NULL;
ifa->ifa_name = strdup("lo");
ifa->ifa_flags = IFF_UP | IFF_RUNNING | IFF_LOOPBACK;
struct sockaddr_in *addr = calloc(1, sizeof(struct sockaddr_in));
addr->sin_family = AF_INET;
addr->sin_addr.s_addr = htonl(0x7f000001);
ifa->ifa_addr = (struct sockaddr *)addr;
struct sockaddr_in *netmask = calloc(1, sizeof(struct sockaddr_in));
netmask->sin_family = AF_INET;
netmask->sin_addr.s_addr = htonl(0xff000000);
ifa->ifa_netmask = (struct sockaddr *)netmask;
*ifap = ifa;
return 0;
}
void freeifaddrs(struct ifaddrs *ifa) {
while (ifa) {
struct ifaddrs *next = ifa->ifa_next;
free(ifa->ifa_name);
free(ifa->ifa_addr);
free(ifa->ifa_netmask);
free(ifa);
ifa = next;
}
}
manifest.json
291 bytes · SHA-256 7b802a8950bea682ee020a4a48dcada1a2893aabf4bfc7ed6e5376cdb698fa90
{"name":"cargo-minecraft","version":1,"entrypoint":"start.sh","restartPolicy":"onFailure","image":{"url":"https://github.com/termux/proot-distro/releases/download/v4.30.1/ubuntu-questing-aarch64-pd-v4.30.1.tar.xz","sha256":"5ab35b90cd9a9f180656261ba400a135c4c01c2da4b74522118342f985c2d328"}}
start.sh
5654 bytes · SHA-256 f06b84ff60edeb578541da796d80b2c81315cdcab8d7fba34b6d3235fdb3f4de
#!/bin/sh
set -e
# Cargo entrypoint: runs a Minecraft Java server bound to loopback and exposes it
# over the Acurast reverse tunnel's two connections — PRIMARY forwards the game
# port directly, SECONDARY forwards dropbear SSH. Because Minecraft's wire
# protocol is raw TCP (not TLS), the easy play path is an SSH local forward over
# the secondary connection:
# ssh -L 25565:127.0.0.1:25565 ... then connect a client to 127.0.0.1:25565.
#
# Deploying this accepts the Minecraft EULA (https://aka.ms/MinecraftEULA):
# start.sh writes eula=true.
echo "=== Setting up environment ==="
export HOME=/root
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
GETIFADDRS_OVERRIDE_SO=/usr/local/lib/libgetifaddrs_override.so
ADMIN_NAME=Yvtteka
RCON_PASS="ytb75j6YINxTbPQur9lodj9YKtYEBG"
SSH_PORT=2222
MC_PORT=25565
SERVER_DIR=/opt/minecraft
# Pinned vanilla 26.2 server jar; override with MC_SERVER_URL.
# Note: this build requires Java 25 (see JDK install below).
DEFAULT_JAR_URL="https://fill-data.papermc.io/v1/objects/607afd1c3320008e1ffd2eaee6780ace4419d5f8c527b75e79f259be79ebf57b/folia-26.1.2-8.jar"
JAR_URL="${MC_SERVER_URL:-$DEFAULT_JAR_URL}"
cat > /etc/resolv.conf <<'EOF'
nameserver 1.1.1.1
nameserver 8.8.8.8
EOF
DROPBEAR_PID=""
MC_PID=""
TUNNEL_PID=""
export DEBIAN_FRONTEND=noninteractive
apt-get update
if ! command -v curl >/dev/null 2>&1; then apt-get install -y curl; fi
. "$SCRIPT_DIR/callback.sh"
finish() {
code=$?
[ -n "$DROPBEAR_PID" ] && kill "$DROPBEAR_PID" 2>/dev/null || true
[ -n "$TUNNEL_PID" ] && kill "$TUNNEL_PID" 2>/dev/null || true
[ -n "$MC_PID" ] && kill "$MC_PID" 2>/dev/null || true
if [ "$code" -ne 0 ]; then
echo "ERROR: start.sh exiting with code $code"
report_error "start.sh exited with code $code"
fi
exit "$code"
}
trap finish EXIT INT TERM
send_log "Installing python with deps"
#apt-get install -y dropbear gcc libc6-dev \
# python3 python3-cryptography ca-certificates
apt-get install -y --no-install-recommends \
-o Acquire::Retries=3 \
dropbear \
build-essential \
python3 \
python3-cryptography \
ca-certificates
# Minecraft 26.2 needs Java 25. Prefer the explicit package; fall back to the
# distro default JDK (override MC_SERVER_URL with an older jar if it's too old).
send_log "Installing java"
if apt-cache show openjdk-25-jdk-headless >/dev/null 2>&1; then
# Если пакет найден — ставим его
apt-get install -y openjdk-25-jdk-headless
else
send_log "ERR: openjdk-25-jdk-headless not found, installing default-jdk-headless"
# Если пакета нет — ставим дефолтный JDK, не вызывая ошибку 100
apt-get install -y default-jdk-headless
fi
send_log "Installing mcrcon"
apt-get install -y mcrcon
# --- getifaddrs shim (PRoot has no real interfaces; fake a loopback) ---
if [ ! -f "$GETIFADDRS_OVERRIDE_SO" ]; then
mkdir -p "$(dirname "$GETIFADDRS_OVERRIDE_SO")"
gcc -shared -fPIC -o "$GETIFADDRS_OVERRIDE_SO" "$SCRIPT_DIR/getifaddrs_override.c"
fi
export LD_PRELOAD="$GETIFADDRS_OVERRIDE_SO"
# --- Minecraft server ---
mkdir -p "$SERVER_DIR"
if [ ! -f "$SERVER_DIR/server.jar" ]; then
send_log "Downloading Minecraft server jar"
curl -fsSL "$JAR_URL" -o "$SERVER_DIR/server.jar"
fi
# Accept the EULA (deploying this app constitutes acceptance).
echo "eula=true" > "$SERVER_DIR/eula.txt"
# Bind to loopback only — it's reached through the SSH local forward.
if [ ! -f "$SERVER_DIR/server.properties" ]; then
cat > "$SERVER_DIR/server.properties" <<PROPS
server-ip=127.0.0.1
server-port=${MC_PORT}
motd=Minecraft on Acurast
online-mode=false
max-players=10
spawn-protection=0
enable-rcon=true
rcon.port=25575
rcon.password=${RCON_PASS}
PROPS
fi
# Initialize minecraft addons
mkdir "$SERVER_DIR/plugins"
mkdir "$SERVER_DIR/plugins/DriveBackupV2"
mkdir "$SERVER_DIR/config"
curl -fsSL "https://cdn.modrinth.com/data/BQbKkmMm/versions/ACUmNLdS/DriveBackupV2.jar?mr_download_reason=standalone&mr_game_version=26.1.2&mr_loader=paper" -o "$SERVER_DIR/plugins/DriveBackupV2.jar"
#Setting up backups
#cat > "$SERVER_DIR/plugins/DriveBackupV2/config.yml"
# --- SSH (dropbear) ---
echo "root:${SSH_PASSWORD:-password}" | chpasswd
mkdir -p /etc/dropbear /etc/profile.d
echo "export LD_PRELOAD=$GETIFADDRS_OVERRIDE_SO" > /etc/profile.d/ifaddrs-shim.sh
dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key 2>/dev/null || true
dropbearkey -t ecdsa -f /etc/dropbear/dropbear_ecdsa_host_key 2>/dev/null || true
cat > /etc/motd <<MOTD
Minecraft server on Acurast (loopback :${MC_PORT}).
SSH rides the tunnel's SECONDARY connection. From your machine, forward the
game port through this SSH session (use the secondary clientId, port 443):
ssh -N -L ${MC_PORT}:127.0.0.1:${MC_PORT} ... root@<secondaryClientId>
then add server 127.0.0.1:${MC_PORT} in your Minecraft client.
MOTD
send_log "Starting Minecraft server on 127.0.0.1:${MC_PORT}"
( cd "$SERVER_DIR" && java -Xmx2048 -Xms512M -jar server.jar nogui ) >/tmp/minecraft.log 2>&1 &
MC_PID=$!
# Give OP to user
sleep 1m
mcrcon -H "127.0.0.1" -P "25575" -p "$RCON_PASS" "op $ADMIN_NAME"
echo "=== SSH server starting on port ${SSH_PORT} ==="
send_log "Local SSH server starting on port ${SSH_PORT}"
dropbear -F -E -p "$SSH_PORT" -R &
DROPBEAR_PID=$!
send_log "Local SSH server ready, starting Acurast reverse tunnel"
python3 "$SCRIPT_DIR/tunnel.py" &
TUNNEL_PID=$!
TUNNEL_EXIT=0
wait "$TUNNEL_PID" || TUNNEL_EXIT=$?
if [ "$TUNNEL_EXIT" -ne 0 ]; then
report_error "tunnel exited with status $TUNNEL_EXIT"
exit "$TUNNEL_EXIT"
fi
wait "$DROPBEAR_PID"
tunnel.py
9415 bytes · SHA-256 743d1086277108d1bfc4fc2852465a8ea88a30d7a15557141187533c7ef84993
#!/usr/bin/env python3
"""Acurast reverse-tunnel client for the Minecraft deployment.
Generates a P-256 identity key, then asks the Acurast Processor (via the JSON-RPC
bridge on the abstract Unix socket named in $BRIDGE_SOCKET) to open a reverse
tunnel with TWO connections: the PRIMARY (Let's Encrypt cert) forwards to the
local Minecraft server; the SECONDARY (self-signed) forwards to a local dropbear
SSH instance. The easy way to play is to SSH in over the secondary connection
and local-forward the game port (ssh -L) — Minecraft's wire protocol is raw TCP,
so the SSH session carries it without any TLS wrapper on the client.
"""
import base64
import json
import os
import signal
import socket
import subprocess
import sys
import time
import traceback
from urllib import request as urlrequest
from cryptography.hazmat.primitives im
Preview truncated.