diff --git a/README.md b/README.md
@@ -6,8 +6,8 @@ the client is a native install, because putting a machine behind a proxy means
owning its routing table and a container is the wrong shape for that.
```
-curl -fsSLO https://raw.githubusercontent.com/sqzer-x/transtation/v1.0.17/install.sh
-sha256sum install.sh # compare against the hash in the v1.0.17 release notes
+curl -fsSLO https://raw.githubusercontent.com/sqzer-x/transtation/v1.0.18/install.sh
+sha256sum install.sh # compare against the hash in the v1.0.18 release notes
less install.sh # please actually read it
sudo sh install.sh
```
@@ -49,8 +49,8 @@ how you feel about a container runtime on your VPS.
### In a container (default)
```
-curl -fsSLO https://raw.githubusercontent.com/sqzer-x/transtation/v1.0.17/install.sh
-sha256sum install.sh # compare against the hash in the v1.0.17 release notes
+curl -fsSLO https://raw.githubusercontent.com/sqzer-x/transtation/v1.0.18/install.sh
+sha256sum install.sh # compare against the hash in the v1.0.18 release notes
less install.sh # please actually read it
sudo sh install.sh
```
diff --git a/install.sh b/install.sh
@@ -15,11 +15,11 @@
# last line. If the download is truncated, nothing runs.
set -eu
-VERSION=${TT_VERSION:-v1.0.17}
+VERSION=${TT_VERSION:-v1.0.18}
IMAGE_SERVER=${TT_IMAGE_SERVER:-ghcr.io/sqzer-x/transtation}
# Filled in by the release workflow. A tag is mutable -- the same stolen-token
# compromise we already concede for Xray's .dgst would let someone retag
-# v1.0.17, and the hash-verified installer you read would vouch for nothing.
+# v1.0.18, and the hash-verified installer you read would vouch for nothing.
SERVER_DIGEST=${TT_SERVER_DIGEST:-}
# sing-box ships no checksum file, so these were computed once from the official
diff --git a/server/transtation b/server/transtation
@@ -24,6 +24,13 @@ TAB=$(printf '\t')
TT_MANAGED=${TT_MANAGED:-systemd}
restart_hint() { [ "$TT_MANAGED" = docker ] && printf 'docker compose up -d' || printf 'systemctl restart transtation'; }
env_hint() { [ "$TT_MANAGED" = docker ] && printf '/opt/transtation/.env' || printf '/etc/transtation/server.env'; }
+# Is the server up, or on its way up? Under docker this command only runs at all
+# because `docker exec` found a live container, so the answer is yes by
+# construction; natively, ask the init system.
+server_starting() {
+ [ "$TT_MANAGED" = docker ] && return 0
+ systemctl is-active --quiet transtation 2>/dev/null
+}
set_paths() {
# The container mounts its volume at /data; a native install keeps state
@@ -323,6 +330,15 @@ write_runtime() {
}
load_runtime() {
+ # The runtime file is written a moment into startup, after the dest probe.
+ # Running `transtation show` straight after `systemctl start` therefore used
+ # to be told to restart -- advice that loops you, because waiting was all it
+ # needed. Wait briefly when the thing is genuinely coming up, and only then
+ # say so.
+ if [ ! -f "$RUNTIME" ] && server_starting; then
+ _w=0
+ while [ ! -f "$RUNTIME" ] && [ "$_w" -lt 15 ]; do sleep 1; _w=$((_w + 1)); done
+ fi
[ -f "$RUNTIME" ] || die "server has not started yet -- run '$(restart_hint)' first"
HOST=""; PORT=""; LISTEN_PORT=""; SNI=""; DEST=""; WARP=""; WARP_READY=""; SNI_REASON=""
while IFS='=' read -r _k _v; do
diff --git a/test.sh b/test.sh
@@ -121,7 +121,23 @@ wrapper_backup_is_0600() (
transtation restore "$_t/junk.tgz" >/dev/null 2>&1 && return 1
return 0
)
+# `transtation show` straight after `systemctl start` used to be told to restart,
+# which loops you: waiting was all it needed. It now waits -- but only while the
+# service is actually coming up. A stopped server must still fail immediately,
+# or every command on a down server hangs for fifteen seconds.
+down_server_fails_fast() (
+ _d=$(mktemp -d) _b=$(mktemp -d) || return 1
+ trap 'rm -rf "$_d" "$_b"' EXIT
+ printf 'SCHEMA=1\nREALITY_PRIV=x\nREALITY_PUB=y\nCREATED=2026-01-01\n' >"$_d/state.env"
+ printf 'main\t8f3e21c4-7a09-4b2e-9d51-6c0f1a2b3c4d\t1c69b566b0480c74\n' >"$_d/users.tsv"
+ printf '#!/bin/sh\nexit 3\n' >"$_b/systemctl" # "inactive"
+ chmod +x "$_b/systemctl"
+ _t0=$(date +%s)
+ PATH="$_b:$PATH" TT_MANAGED=systemd TT_DATA=$_d sh server/transtation status >/dev/null 2>&1 && return 1
+ [ $(( $(date +%s) - _t0 )) -lt 3 ]
+)
check "both install paths implement the same transtation verbs" wrapper_parity
+check "a stopped server fails immediately instead of waiting for it" down_server_fails_fast
check "native backup is 0600 even under root's umask, and will not clobber" wrapper_backup_is_0600
|