Add packwiz-http service and --scheme flag
The reverse proxy runs on a different host than the game server, so it cannot alias the share directly — serving the pack needs an HTTP server on the game server itself. packwiz-http.py is a threaded static server over an allowlist: mods/, packs/, and setup-*.html. Everything else 404s, since the same directory holds server.properties, ops.json, whitelist.json, logs and the world. Threading matters because installing a pack is one request per mod and a single-threaded server serialises a whole lobby behind one download. pack.toml and index.toml are sent no-cache so a proxy cannot serve a stale pack. Installed as packwiz-http.service on port 18080 by default, configurable with -H/-B, skippable with --no-http, and read-only via ReadOnlyPaths. packwiz-setup.sh gains -S/--scheme, for when the pack is built against a mirror reachable only over plain HTTP but clients must be handed the public HTTPS URL. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>main
parent
7a84ef3117
commit
b32b47f020
19
README.md
19
README.md
|
|
@ -65,6 +65,25 @@ pack directory survive.
|
||||||
| `mc-refresh-restart.sh` | you | Re-sync the pack after changing mods, then restart |
|
| `mc-refresh-restart.sh` | you | Re-sync the pack after changing mods, then restart |
|
||||||
| `build.sh` | you | Builds the release zip |
|
| `build.sh` | you | Builds the release zip |
|
||||||
|
|
||||||
|
## Pack HTTP server
|
||||||
|
|
||||||
|
`packwiz-http.service` serves the pack, the mod jars and the setup guides on
|
||||||
|
port 18080 (`-H` to change, `-B` to change the bind address, `--no-http` to skip
|
||||||
|
it). Put a reverse proxy in front of it.
|
||||||
|
|
||||||
|
It serves an **allowlist**, not the whole share: `mods/`, `packs/`, and
|
||||||
|
`setup-*.html`. Everything else 404s. That is deliberate — the same directory
|
||||||
|
holds `server.properties` (which can carry an rcon password), `ops.json`,
|
||||||
|
`whitelist.json`, `usercache.json`, logs and the world.
|
||||||
|
|
||||||
|
`pack.toml` and `index.toml` are sent with `Cache-Control: no-cache`, so the
|
||||||
|
proxy can't hand clients a stale pack. Jars are pinned by hash in the index and
|
||||||
|
cache freely.
|
||||||
|
|
||||||
|
If the mirror is only reachable over plain HTTP from the machine building the
|
||||||
|
pack, but clients need the public HTTPS URL, use `-S https` — it rewrites the
|
||||||
|
scheme on every generated URL.
|
||||||
|
|
||||||
## Memory
|
## Memory
|
||||||
|
|
||||||
The heap defaults to 10 GB (`-X`/`-x` to change it). `-XX:+AlwaysPreTouch` means
|
The heap defaults to 10 GB (`-X`/`-x` to change it). `-XX:+AlwaysPreTouch` means
|
||||||
|
|
|
||||||
Binary file not shown.
4
build.sh
4
build.sh
|
|
@ -25,6 +25,7 @@ FILES=(
|
||||||
mc-service-setup.sh
|
mc-service-setup.sh
|
||||||
packwiz-setup.sh
|
packwiz-setup.sh
|
||||||
mc-refresh-restart.sh
|
mc-refresh-restart.sh
|
||||||
|
packwiz-http.py
|
||||||
)
|
)
|
||||||
|
|
||||||
die() { echo "error: $*" >&2; exit 1; }
|
die() { echo "error: $*" >&2; exit 1; }
|
||||||
|
|
@ -69,6 +70,7 @@ fail=0
|
||||||
for f in "${FILES[@]}"; do
|
for f in "${FILES[@]}"; do
|
||||||
case "$f" in
|
case "$f" in
|
||||||
*.sh) bash -n "$f" || { echo " FAILED: $f" >&2; fail=1; } ;;
|
*.sh) bash -n "$f" || { echo " FAILED: $f" >&2; fail=1; } ;;
|
||||||
|
*.py) python3 -m py_compile "$f" || { echo " FAILED: $f" >&2; fail=1; } ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
(( fail )) && die "refusing to build a zip containing scripts that don't parse"
|
(( fail )) && die "refusing to build a zip containing scripts that don't parse"
|
||||||
|
|
@ -84,7 +86,7 @@ mkdir -p "$DEST"
|
||||||
|
|
||||||
for f in "${FILES[@]}"; do
|
for f in "${FILES[@]}"; do
|
||||||
case "$f" in
|
case "$f" in
|
||||||
*.sh) install -m 755 "$f" "$DEST/$f" ;;
|
*.sh|*.py) install -m 755 "$f" "$DEST/$f" ;;
|
||||||
*) install -m 644 "$f" "$DEST/$f" ;;
|
*) install -m 644 "$f" "$DEST/$f" ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
|
||||||
13
deploy.sh
13
deploy.sh
|
|
@ -22,7 +22,7 @@
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
NAME=""; AUTHOR=""; BASEURL=""; NFVER="latest"; MCVER="1.21.1"
|
NAME=""; AUTHOR=""; BASEURL=""; NFVER="latest"; MCVER="1.21.1"
|
||||||
SHARE="/minecraft"; XMX="10G"; XMS="10G"; ACCEPT_EULA=""; PORT="25565"; KEEP_PACK=0; SNAPSHOT=1
|
SHARE="/minecraft"; XMX="10G"; XMS="10G"; ACCEPT_EULA=""; PORT="25565"; KEEP_PACK=0; SNAPSHOT=1; HTTP_PORT="18080"; HTTP_BIND="0.0.0.0"; SCHEME=""
|
||||||
HERE="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
HERE="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
die() { echo "error: $*" >&2; exit 1; }
|
die() { echo "error: $*" >&2; exit 1; }
|
||||||
|
|
@ -38,6 +38,9 @@ while [ $# -gt 0 ]; do
|
||||||
-m|--mc) MCVER="${2:-}"; shift 2 ;;
|
-m|--mc) MCVER="${2:-}"; shift 2 ;;
|
||||||
-s|--share) SHARE="${2:-}"; shift 2 ;;
|
-s|--share) SHARE="${2:-}"; shift 2 ;;
|
||||||
-p|--port) PORT="${2:-}"; shift 2 ;;
|
-p|--port) PORT="${2:-}"; shift 2 ;;
|
||||||
|
-H|--http-port) HTTP_PORT="${2:-}"; shift 2 ;;
|
||||||
|
-B|--http-bind) HTTP_BIND="${2:-}"; shift 2 ;;
|
||||||
|
-S|--scheme) SCHEME="${2:-}"; shift 2 ;;
|
||||||
-X|--xmx) XMX="${2:-}"; shift 2 ;;
|
-X|--xmx) XMX="${2:-}"; shift 2 ;;
|
||||||
-x|--xms) XMS="${2:-}"; shift 2 ;;
|
-x|--xms) XMS="${2:-}"; shift 2 ;;
|
||||||
--accept-eula) ACCEPT_EULA="--accept-eula"; shift ;;
|
--accept-eula) ACCEPT_EULA="--accept-eula"; shift ;;
|
||||||
|
|
@ -91,21 +94,23 @@ fi
|
||||||
|
|
||||||
step "1/2 Minecraft systemd service"
|
step "1/2 Minecraft systemd service"
|
||||||
sudo "$HERE/mc-service-setup.sh" \
|
sudo "$HERE/mc-service-setup.sh" \
|
||||||
-s "$SHARE" -A "$USER" -X "$XMX" -x "$XMS" -m "$MCVER" -p "$PORT" \
|
-s "$SHARE" -A "$USER" -X "$XMX" -x "$XMS" -m "$MCVER" -p "$PORT" -H "$HTTP_PORT" -B "$HTTP_BIND" \
|
||||||
${NFVER:+-N "$NFVER"} ${ACCEPT_EULA}
|
${NFVER:+-N "$NFVER"} ${ACCEPT_EULA}
|
||||||
|
|
||||||
PACK_FORCE=""
|
PACK_FORCE=""
|
||||||
(( KEEP_PACK )) || PACK_FORCE="--force"
|
(( KEEP_PACK )) || PACK_FORCE="--force"
|
||||||
|
PACK_SCHEME=""
|
||||||
|
[ -z "$SCHEME" ] || PACK_SCHEME="-S $SCHEME"
|
||||||
|
|
||||||
step "2/2 packwiz pack and player guides"
|
step "2/2 packwiz pack and player guides"
|
||||||
# The admin group membership from step 1 isn't active in this shell yet, so run
|
# The admin group membership from step 1 isn't active in this shell yet, so run
|
||||||
# the pack setup under the new group explicitly rather than telling you to log
|
# the pack setup under the new group explicitly rather than telling you to log
|
||||||
# out and back in.
|
# out and back in.
|
||||||
if id -nG "$USER" | tr ' ' '\n' | grep -qx minecraft; then
|
if id -nG "$USER" | tr ' ' '\n' | grep -qx minecraft; then
|
||||||
"$HERE/packwiz-setup.sh" -n "$NAME" -a "$AUTHOR" -m "$MCVER" -u "$BASEURL" -s "$SHARE" -p "$PORT" ${PACK_FORCE}
|
"$HERE/packwiz-setup.sh" -n "$NAME" -a "$AUTHOR" -m "$MCVER" -u "$BASEURL" -s "$SHARE" -p "$PORT" ${PACK_FORCE} ${PACK_SCHEME}
|
||||||
else
|
else
|
||||||
sg minecraft -c "$(printf '%q ' "$HERE/packwiz-setup.sh" -n "$NAME" -a "$AUTHOR" \
|
sg minecraft -c "$(printf '%q ' "$HERE/packwiz-setup.sh" -n "$NAME" -a "$AUTHOR" \
|
||||||
-m "$MCVER" -u "$BASEURL" -s "$SHARE" -p "$PORT" ${PACK_FORCE})"
|
-m "$MCVER" -u "$BASEURL" -s "$SHARE" -p "$PORT" ${PACK_FORCE} ${PACK_SCHEME})"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if (( WAS_ACTIVE )); then
|
if (( WAS_ACTIVE )); then
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,9 @@ set -euo pipefail
|
||||||
SHARE="/minecraft"
|
SHARE="/minecraft"
|
||||||
MCUSER="minecraft"
|
MCUSER="minecraft"
|
||||||
PORT="25565" # Minecraft server port
|
PORT="25565" # Minecraft server port
|
||||||
|
HTTP_PORT="18080" # packwiz/pack HTTP server port
|
||||||
|
HTTP_BIND="0.0.0.0" # address the pack server listens on
|
||||||
|
HTTP=1 # install the pack HTTP service
|
||||||
XMS="10G"
|
XMS="10G"
|
||||||
XMX="10G"
|
XMX="10G"
|
||||||
NFVER="" # version, or "latest" to resolve one; empty = don't install
|
NFVER="" # version, or "latest" to resolve one; empty = don't install
|
||||||
|
|
@ -38,6 +41,9 @@ while [ $# -gt 0 ]; do
|
||||||
-s|--share) SHARE="${2:-}"; shift 2 ;;
|
-s|--share) SHARE="${2:-}"; shift 2 ;;
|
||||||
-U|--user) MCUSER="${2:-}"; shift 2 ;;
|
-U|--user) MCUSER="${2:-}"; shift 2 ;;
|
||||||
-p|--port) PORT="${2:-}"; shift 2 ;;
|
-p|--port) PORT="${2:-}"; shift 2 ;;
|
||||||
|
-H|--http-port) HTTP_PORT="${2:-}"; shift 2 ;;
|
||||||
|
-B|--http-bind) HTTP_BIND="${2:-}"; shift 2 ;;
|
||||||
|
--no-http) HTTP=0; shift ;;
|
||||||
-x|--xms) XMS="${2:-}"; shift 2 ;;
|
-x|--xms) XMS="${2:-}"; shift 2 ;;
|
||||||
-X|--xmx) XMX="${2:-}"; shift 2 ;;
|
-X|--xmx) XMX="${2:-}"; shift 2 ;;
|
||||||
-N|--neoforge) NFVER="${2:-}"; shift 2 ;;
|
-N|--neoforge) NFVER="${2:-}"; shift 2 ;;
|
||||||
|
|
@ -52,6 +58,9 @@ done
|
||||||
[ "$(id -u)" -eq 0 ] || die "run this with sudo — it creates a user and writes unit files"
|
[ "$(id -u)" -eq 0 ] || die "run this with sudo — it creates a user and writes unit files"
|
||||||
[[ "$PORT" =~ ^[0-9]+$ ]] && [ "$PORT" -ge 1 ] && [ "$PORT" -le 65535 ] \
|
[[ "$PORT" =~ ^[0-9]+$ ]] && [ "$PORT" -ge 1 ] && [ "$PORT" -le 65535 ] \
|
||||||
|| die "-p wants a port between 1 and 65535, got: $PORT"
|
|| die "-p wants a port between 1 and 65535, got: $PORT"
|
||||||
|
[[ "$HTTP_PORT" =~ ^[0-9]+$ ]] && [ "$HTTP_PORT" -ge 1 ] && [ "$HTTP_PORT" -le 65535 ] \
|
||||||
|
|| die "-H wants a port between 1 and 65535, got: $HTTP_PORT"
|
||||||
|
[ "$HTTP_PORT" != "$PORT" ] || die "the HTTP port and the Minecraft port cannot both be $PORT"
|
||||||
|
|
||||||
# ----------------------------------------------------------------- share ----
|
# ----------------------------------------------------------------- share ----
|
||||||
|
|
||||||
|
|
@ -217,6 +226,50 @@ cat > "$SHARE/user_jvm_args.txt" <<EOF
|
||||||
EOF
|
EOF
|
||||||
chown "$MCUSER":"$MCUSER" "$SHARE/user_jvm_args.txt"
|
chown "$MCUSER":"$MCUSER" "$SHARE/user_jvm_args.txt"
|
||||||
|
|
||||||
|
# ------------------------------------------------------------ pack http ----
|
||||||
|
|
||||||
|
if (( HTTP )); then
|
||||||
|
SRV_SRC="$(dirname -- "$(readlink -f -- "$0")")/packwiz-http.py"
|
||||||
|
[ -f "$SRV_SRC" ] || die "packwiz-http.py not found next to this script"
|
||||||
|
|
||||||
|
info "installing /usr/local/bin/packwiz-http"
|
||||||
|
install -m 755 "$SRV_SRC" /usr/local/bin/packwiz-http
|
||||||
|
|
||||||
|
info "writing $UNIT_DIR/packwiz-http.service (${HTTP_BIND}:${HTTP_PORT})"
|
||||||
|
cat > "$UNIT_DIR/packwiz-http.service" <<EOF
|
||||||
|
[Unit]
|
||||||
|
Description=packwiz pack and mod mirror (HTTP)
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
RequiresMountsFor=$SHARE
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=$MCUSER
|
||||||
|
Group=$MCUSER
|
||||||
|
WorkingDirectory=$SHARE
|
||||||
|
ExecStart=/usr/local/bin/packwiz-http --root $SHARE --bind $HTTP_BIND --port $HTTP_PORT
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
|
||||||
|
# Serves an allowlist only, and never writes anything.
|
||||||
|
NoNewPrivileges=true
|
||||||
|
PrivateTmp=true
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=true
|
||||||
|
ReadOnlyPaths=$SHARE
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if systemctl is-active --quiet firewalld; then
|
||||||
|
info "opening $HTTP_PORT/tcp"
|
||||||
|
firewall-cmd --quiet --permanent --add-port="$HTTP_PORT/tcp"
|
||||||
|
firewall-cmd --quiet --reload
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# ----------------------------------------------------------------- units ----
|
# ----------------------------------------------------------------- units ----
|
||||||
|
|
||||||
info "writing $UNIT_DIR/minecraft.socket"
|
info "writing $UNIT_DIR/minecraft.socket"
|
||||||
|
|
@ -282,6 +335,11 @@ EOF
|
||||||
info "reloading systemd"
|
info "reloading systemd"
|
||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
systemctl enable minecraft.socket minecraft.service >/dev/null
|
systemctl enable minecraft.socket minecraft.service >/dev/null
|
||||||
|
if (( HTTP )); then
|
||||||
|
systemctl enable packwiz-http.service >/dev/null
|
||||||
|
systemctl restart packwiz-http.service
|
||||||
|
info "packwiz-http listening on ${HTTP_BIND}:${HTTP_PORT}"
|
||||||
|
fi
|
||||||
|
|
||||||
echo
|
echo
|
||||||
info "installed. Start it with:"
|
info "installed. Start it with:"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Serve the packwiz pack, the mod jars and the player setup guides over HTTP.
|
||||||
|
|
||||||
|
Sits behind a reverse proxy. Deliberately serves an allowlist rather than the
|
||||||
|
whole share: the same directory holds server.properties (which can carry an
|
||||||
|
rcon password), ops.json, whitelist.json, usercache.json, logs and the world,
|
||||||
|
and none of that should be reachable.
|
||||||
|
|
||||||
|
packwiz-http --root /minecraft --bind 0.0.0.0 --port 18080
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import http.server
|
||||||
|
import os
|
||||||
|
import posixpath
|
||||||
|
import sys
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
|
# Top-level prefixes clients legitimately need.
|
||||||
|
ALLOWED_DIRS = ("mods/", "packs/")
|
||||||
|
|
||||||
|
|
||||||
|
def is_allowed(path: str) -> bool:
|
||||||
|
"""True if the URL path is something we publish."""
|
||||||
|
p = urllib.parse.urlparse(path).path
|
||||||
|
p = urllib.parse.unquote(p).lstrip("/")
|
||||||
|
|
||||||
|
# Collapse any traversal before deciding — posixpath.normpath turns
|
||||||
|
# "packs/../server.properties" into "server.properties", which then fails
|
||||||
|
# the allowlist instead of sneaking through on its prefix.
|
||||||
|
if p:
|
||||||
|
p = posixpath.normpath(p)
|
||||||
|
if p.startswith("..") or p == ".":
|
||||||
|
return False
|
||||||
|
|
||||||
|
if p in ("", "."):
|
||||||
|
return True
|
||||||
|
if any(p == d.rstrip("/") or p.startswith(d) for d in ALLOWED_DIRS):
|
||||||
|
return True
|
||||||
|
if p.startswith("setup-") and p.endswith(".html") and "/" not in p:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class Handler(http.server.SimpleHTTPRequestHandler):
|
||||||
|
server_version = "packwiz-http/1.0"
|
||||||
|
|
||||||
|
def do_GET(self):
|
||||||
|
if not is_allowed(self.path):
|
||||||
|
# 404 rather than 403: no reason to confirm what else is here.
|
||||||
|
self.send_error(404, "Not Found")
|
||||||
|
return
|
||||||
|
super().do_GET()
|
||||||
|
|
||||||
|
def do_HEAD(self):
|
||||||
|
if not is_allowed(self.path):
|
||||||
|
self.send_error(404, "Not Found")
|
||||||
|
return
|
||||||
|
super().do_HEAD()
|
||||||
|
|
||||||
|
def end_headers(self):
|
||||||
|
p = urllib.parse.urlparse(self.path).path
|
||||||
|
# The pack manifest and index must never be cached, or clients keep
|
||||||
|
# resolving an old pack after an update. The jars are content-addressed
|
||||||
|
# by hash in the index, so they cache freely.
|
||||||
|
if p.endswith(("pack.toml", "index.toml")):
|
||||||
|
self.send_header("Cache-Control", "no-cache, must-revalidate")
|
||||||
|
elif p.endswith(".pw.toml"):
|
||||||
|
self.send_header("Cache-Control", "no-cache")
|
||||||
|
super().end_headers()
|
||||||
|
|
||||||
|
def log_message(self, format, *args): # noqa: A002 - signature fixed by base class
|
||||||
|
# journald adds its own timestamps.
|
||||||
|
sys.stderr.write("%s %s\n" % (self.address_string(), format % args))
|
||||||
|
|
||||||
|
|
||||||
|
Handler.extensions_map = dict(Handler.extensions_map)
|
||||||
|
Handler.extensions_map.update({
|
||||||
|
".toml": "text/plain",
|
||||||
|
".jar": "application/java-archive",
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
ap = argparse.ArgumentParser(description=__doc__,
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||||
|
ap.add_argument("--root", default="/minecraft", help="directory to serve")
|
||||||
|
ap.add_argument("--bind", default="0.0.0.0", help="address to listen on")
|
||||||
|
ap.add_argument("--port", type=int, default=18080, help="port to listen on")
|
||||||
|
args = ap.parse_args()
|
||||||
|
|
||||||
|
if not os.path.isdir(args.root):
|
||||||
|
sys.exit("error: root does not exist: %s" % args.root)
|
||||||
|
if not os.path.ismount(args.root):
|
||||||
|
# Same guard as the shell scripts: an unmounted dataset means we would
|
||||||
|
# be serving an empty directory on the root filesystem.
|
||||||
|
print("warning: %s is not a mountpoint" % args.root, file=sys.stderr)
|
||||||
|
|
||||||
|
handler = lambda *a, **kw: Handler(*a, directory=args.root, **kw)
|
||||||
|
|
||||||
|
# Threading matters: a full pack install is one request per mod, and a
|
||||||
|
# single-threaded server serialises an entire lobby behind one download.
|
||||||
|
httpd = http.server.ThreadingHTTPServer((args.bind, args.port), handler)
|
||||||
|
httpd.daemon_threads = True
|
||||||
|
|
||||||
|
print("serving %s on %s:%d" % (args.root, args.bind, args.port), file=sys.stderr)
|
||||||
|
try:
|
||||||
|
httpd.serve_forever()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
httpd.server_close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
@ -29,6 +29,7 @@ SITE_URL="" # defaults to the origin of $BASEURL
|
||||||
PACK_URL="" # defaults to $SITE_URL/packs/<slug>
|
PACK_URL="" # defaults to $SITE_URL/packs/<slug>
|
||||||
SERVER_ADDR="" # defaults to the hostname of $SITE_URL
|
SERVER_ADDR="" # defaults to the hostname of $SITE_URL
|
||||||
MCPORT="25565" # Minecraft port, shown in the guides
|
MCPORT="25565" # Minecraft port, shown in the guides
|
||||||
|
SCHEME="" # force http or https on every generated URL
|
||||||
GUIDES=1 # write the player setup guides
|
GUIDES=1 # write the player setup guides
|
||||||
FORCE=0 # move an existing pack aside and rebuild it
|
FORCE=0 # move an existing pack aside and rebuild it
|
||||||
|
|
||||||
|
|
@ -54,6 +55,7 @@ while [ $# -gt 0 ]; do
|
||||||
-P|--pack-url) PACK_URL="${2:-}"; shift 2 ;;
|
-P|--pack-url) PACK_URL="${2:-}"; shift 2 ;;
|
||||||
-A|--server) SERVER_ADDR="${2:-}"; shift 2 ;;
|
-A|--server) SERVER_ADDR="${2:-}"; shift 2 ;;
|
||||||
-p|--port) MCPORT="${2:-}"; shift 2 ;;
|
-p|--port) MCPORT="${2:-}"; shift 2 ;;
|
||||||
|
-S|--scheme) SCHEME="${2:-}"; shift 2 ;;
|
||||||
--no-guides) GUIDES=0; shift ;;
|
--no-guides) GUIDES=0; shift ;;
|
||||||
--force) FORCE=1; shift ;;
|
--force) FORCE=1; shift ;;
|
||||||
-h|--help) usage 0 ;;
|
-h|--help) usage 0 ;;
|
||||||
|
|
@ -100,6 +102,19 @@ if [ -n "$MODSDIR$BASEURL" ]; then
|
||||||
fi
|
fi
|
||||||
BASEURL="${BASEURL%/}"
|
BASEURL="${BASEURL%/}"
|
||||||
|
|
||||||
|
# The pack is usually built on the server, where the mirror may only be
|
||||||
|
# reachable over plain HTTP, while clients must be handed the public HTTPS URL.
|
||||||
|
# --scheme rewrites the scheme on every URL this run generates.
|
||||||
|
if [ -n "$SCHEME" ]; then
|
||||||
|
case "$SCHEME" in
|
||||||
|
http|https) ;;
|
||||||
|
*) die "--scheme wants http or https, got: $SCHEME" ;;
|
||||||
|
esac
|
||||||
|
[ -z "$BASEURL" ] || BASEURL="$SCHEME://${BASEURL#*://}"
|
||||||
|
[ -z "$SITE_URL" ] || SITE_URL="$SCHEME://${SITE_URL#*://}"
|
||||||
|
[ -z "$PACK_URL" ] || PACK_URL="$SCHEME://${PACK_URL#*://}"
|
||||||
|
fi
|
||||||
|
|
||||||
# ------------------------------------------------------------------ site ----
|
# ------------------------------------------------------------------ site ----
|
||||||
|
|
||||||
# Everything the guides need is derivable from the mirror URL, so one -u is
|
# Everything the guides need is derivable from the mirror URL, so one -u is
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue