diff --git a/CloudronPackages/Rathole/.dockerignore b/CloudronPackages/Rathole/.dockerignore new file mode 100644 index 0000000..d5efcff --- /dev/null +++ b/CloudronPackages/Rathole/.dockerignore @@ -0,0 +1,7 @@ +.git +.gitignore +*.log +dist +build +.DS_Store + diff --git a/CloudronPackages/Rathole/CloudronManifest.json b/CloudronPackages/Rathole/CloudronManifest.json new file mode 100644 index 0000000..25b9387 --- /dev/null +++ b/CloudronPackages/Rathole/CloudronManifest.json @@ -0,0 +1,18 @@ +{ + "manifestVersion": 2, + "id": "io.knel.rathole", + "title": "Rathole", + "author": "KNEL", + "description": "A reverse proxy that enables secure tunnels between local services and the internet.", + "website": "https://github.com/rathole-org/rathole", + "contactEmail": "admin@knownelement.com", + "version": "0.1.0", + "changelog": "Initial Cloudron package (server/client configurable).", + "healthCheckPath": "/", + "httpPort": 3000, + "addons": { + "localstorage": {} + }, + "tags": ["network", "tunnel", "reverse-proxy"] +} + diff --git a/CloudronPackages/Rathole/Dockerfile b/CloudronPackages/Rathole/Dockerfile new file mode 100644 index 0000000..da66c0b --- /dev/null +++ b/CloudronPackages/Rathole/Dockerfile @@ -0,0 +1,43 @@ +FROM cloudron/base:5.0.0 + +ARG RATHOLE_VERSION=v0.5.0 +ARG ARCH=x86_64-unknown-linux-gnu + +USER root +RUN apt-get update \ + && apt-get install -y --no-install-recommends curl ca-certificates tar \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /app/pkg + +# Download Rathole release binary (adjust version/arch via build args) +RUN set -eux; \ + url="https://github.com/rathole-org/rathole/releases/download/${RATHOLE_VERSION}/rathole-${ARCH}.tar.gz"; \ + echo "Fetching ${url}"; \ + curl -fsSL "$url" -o rathole.tar.gz; \ + tar -xzf rathole.tar.gz; \ + rm rathole.tar.gz; \ + mv rathole /app/pkg/rathole; \ + chmod +x /app/pkg/rathole; \ + chown cloudron:cloudron /app/pkg/rathole + +# Start script +COPY start.sh /app/pkg/start.sh +RUN chmod +x /app/pkg/start.sh && chown cloudron:cloudron /app/pkg/start.sh + +WORKDIR /app/code +RUN mkdir -p /app/data && chown -R cloudron:cloudron /app/data + +USER cloudron + +ENV APP_PORT=3000 \ + RATHOLE_MODE=server \ + RATHOLE_CONFIG_PATH=/app/data/rathole.toml + +EXPOSE 3000 + +HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ + CMD curl -fsS http://127.0.0.1:${APP_PORT}/ || exit 1 + +CMD ["/app/pkg/start.sh"] + diff --git a/CloudronPackages/Rathole/README.md b/CloudronPackages/Rathole/README.md new file mode 100644 index 0000000..d584c88 --- /dev/null +++ b/CloudronPackages/Rathole/README.md @@ -0,0 +1,37 @@ +# Rathole (Cloudron Package) + +Rathole is a reverse proxy that provides secure tunnels for local services. +Upstream project: https://github.com/rathole-org/rathole + +This Cloudron package runs Rathole and a lightweight HTTP health endpoint. + +## Defaults +- Mode: `server` (set `RATHOLE_MODE=client` to run client) +- Config path: `/app/data/rathole.toml` +- Health port: `3000` (Cloudron `httpPort`) + +## Configuration +- Put your Rathole TOML config at `/app/data/rathole.toml`, or provide it via the `RATHOLE_CONFIG` environment variable on first start. +- Example minimal server config is auto-generated if none exists. + +## Build (inside packaging container) +``` +scripts/packaging-up.sh +scripts/packaging-exec.sh "docker build -t rathole:dev CloudronPackages/Rathole" +``` + +## Run locally (inside packaging container) +``` +scripts/packaging-exec.sh "docker run --rm -p 3000:3000 -p 2333:2333 -v rathole-data:/app/data rathole:dev" +``` + +Note: expose additional service ports as needed per your TOML. + +## Deploy to Cloudron +Use Cloudron CLI from inside the packaging container: +``` +scripts/packaging-enter.sh +cloudron login +cloudron install --image rathole:dev +``` + diff --git a/CloudronPackages/Rathole/start.sh b/CloudronPackages/Rathole/start.sh new file mode 100644 index 0000000..2b32e22 --- /dev/null +++ b/CloudronPackages/Rathole/start.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +set -euo pipefail + +log() { echo "[rathole] $(date -Is) $*"; } +abort() { echo "[rathole] ERROR: $*" >&2; exit 1; } + +: "${APP_PORT:=3000}" +: "${RATHOLE_MODE:=server}" # server|client +: "${RATHOLE_CONFIG_PATH:=/app/data/rathole.toml}" + +# Ensure data dir exists +mkdir -p /app/data +chown -R cloudron:cloudron /app/data || true + +# If RATHOLE_CONFIG is provided, write it to config path if file not present +if [[ ! -f "$RATHOLE_CONFIG_PATH" && -n "${RATHOLE_CONFIG:-}" ]]; then + log "Writing config from RATHOLE_CONFIG env to ${RATHOLE_CONFIG_PATH}" + printf "%s\n" "${RATHOLE_CONFIG}" > "$RATHOLE_CONFIG_PATH" +fi + +# If still no config, create a minimal example for server mode +if [[ ! -f "$RATHOLE_CONFIG_PATH" ]]; then + log "No config found. Writing a minimal example config (server). Adjust in /app/data/rathole.toml" + cat > "$RATHOLE_CONFIG_PATH" <<'TOML' +# Minimal Rathole server config example +[server] +bind_addr = "0.0.0.0:2333" + +# Define services below as needed, for example: +# [server.services.echo] +# type = "tcp" +# local_addr = "127.0.0.1:7" +TOML +fi + +# Background: lightweight HTTP health endpoint +python3 -m http.server "$APP_PORT" --bind 0.0.0.0 >/dev/null 2>&1 & +HEALTH_PID=$! +log "Started health endpoint on :${APP_PORT} (pid ${HEALTH_PID})" + +log "Launching rathole in ${RATHOLE_MODE} mode with config ${RATHOLE_CONFIG_PATH}" +exec /app/pkg/rathole "$RATHOLE_MODE" -c "$RATHOLE_CONFIG_PATH" +