better permission warnings
release / deb (push) Successful in 14s

This commit is contained in:
abrown38 committed 2026-09-30 21:34:05 +00:00
1 parent 52998de8f4
commit c4a12727d4
3 files changed
+40 -1

No files matched your search

+4
View File
@@ -1,5 +1,9 @@
# Changelog # Changelog
## Unreleased
- `list` warns about zips in `dist/` that the `terraria` user can't read (e.g. copied in with `scp -p` from a private file), and `info` lists them as `unreadable_zip=`. A server that fails to install because of one now says how to fix it (`sudo chmod 644 <zip>`) instead of just "cannot read", and a missing zip is reported as not found.
## 0.0.11 - 2026-09-30 ## 0.0.11 - 2026-09-30
- The servers now log to their own journal (systemd log namespace `terraria`), which members of the `terraria` group can read. `attach` and `cmd` therefore show output to `terraria` group members without `sudo` or the `systemd-journal` group, and without access to the rest of the system's logs. Read it directly with `journalctl --namespace=terraria -u terraria@<name>`. - The servers now log to their own journal (systemd log namespace `terraria`), which members of the `terraria` group can read. `attach` and `cmd` therefore show output to `terraria` group members without `sudo` or the `systemd-journal` group, and without access to the rest of the system's logs. Read it directly with `journalctl --namespace=terraria -u terraria@<name>`.
+34 -1
View File
@@ -229,7 +229,8 @@ install_server() {
command -v unzip >/dev/null || die "unzip is not installed" command -v unzip >/dev/null || die "unzip is not installed"
zip=$(pick_zip) zip=$(pick_zip)
[[ -r $zip ]] || die "cannot read $zip" [[ -e $zip ]] || die "$zip not found"
[[ -r $zip ]] || die "the '$SVC_USER' user can't read $zip; fix it with: sudo chmod 644 $zip"
log "installing $TYPE from $(basename "$zip") into $dir/server" log "installing $TYPE from $(basename "$zip") into $dir/server"
EXTRACT_TMP=$(mktemp -d "$dir/.extract.XXXXXX") EXTRACT_TMP=$(mktemp -d "$dir/.extract.XXXXXX")
@@ -1049,6 +1050,36 @@ cmd_enable() {
fi fi
} }
# Can the service user read <file>? Worked out from the file's owner, group and
# mode, because whoever runs terractl may be someone else.
svc_can_read() {
local owner group mode
read -r owner group mode < <(stat -c '%U %G %a' "$1" 2>/dev/null) || return 1
if [[ $owner == "$SVC_USER" ]]; then (( 8#$mode & 0400 ))
elif [[ $group == "$SVC_USER" ]]; then (( 8#$mode & 0040 ))
else (( 8#$mode & 0004 )); fi
}
# Zips in dist/ the servers can't unpack, e.g. copied in with 'scp -p' from a
# private file. Instances fail on their first start with such a zip.
unreadable_zips() {
local f
for f in "$DIST_DIR"/*.zip; do
if [[ -f $f ]] && ! svc_can_read "$f"; then echo "$f"; fi
done
}
zip_warning() {
local where=""
local -a bad=()
mapfile -t bad < <(unreadable_zips)
[[ ${#bad[@]} -gt 0 ]] || return 0
if [[ -n ${TERRACTL_VIA:-} ]]; then where=" (on $(hostname 2>/dev/null || echo that host))"; fi
log "warning: the '$SVC_USER' user can't read these zips, so servers can't be installed from them:"
printf ' %s\n' "${bad[@]}" >&2
log "fix it with$where: sudo chmod 644 ${bad[*]@Q}"
}
cmd_list() { cmd_list() {
local d n port boot state local d n port boot state
printf '%-20s %-11s %-6s %-9s %s\n' INSTANCE TYPE PORT BOOT STATE printf '%-20s %-11s %-6s %-9s %s\n' INSTANCE TYPE PORT BOOT STATE
@@ -1065,6 +1096,7 @@ cmd_list() {
printf '%-20s %-11s %-6s %-9s %s\n' "$n" "$TYPE" "${port:--}" "${boot:--}" "$state" printf '%-20s %-11s %-6s %-9s %s\n' "$n" "$TYPE" "${port:--}" "${boot:--}" "$state"
) 2>/dev/null || printf '%-20s %s\n' "$n" "(cannot read config - try sudo)" ) 2>/dev/null || printf '%-20s %s\n' "$n" "(cannot read config - try sudo)"
done done
zip_warning
} }
cmd_reinstall() { cmd_reinstall() {
@@ -1101,6 +1133,7 @@ cmd_info() {
for f in "$DIST_DIR"/*.zip; do for f in "$DIST_DIR"/*.zip; do
if [[ -f $f ]]; then echo "dist_zip=$(basename "$f")"; fi if [[ -f $f ]]; then echo "dist_zip=$(basename "$f")"; fi
done done
while IFS= read -r f; do echo "unreadable_zip=$(basename "$f")"; done < <(unreadable_zips)
for f in "$BASE_DIR"/*/instance.conf; do for f in "$BASE_DIR"/*/instance.conf; do
if [[ -f $f ]]; then echo "instance=$(basename "$(dirname "$f")")"; fi if [[ -f $f ]]; then echo "instance=$(basename "$(dirname "$f")")"; fi
done done
+2
View File
@@ -268,6 +268,8 @@ Zips are only read, never changed, and one zip can serve any number of instances
**tModLoader zips don't include .NET.** Each tModLoader instance downloads the .NET runtime it needs into `server/dotnet/` on its first start, so that start needs internet access and `curl`. The download is kept when you upgrade or re-unpack the instance. tModLoader checks the .NET version on every start and fetches a different one itself if a new release needs it. **tModLoader zips don't include .NET.** Each tModLoader instance downloads the .NET runtime it needs into `server/dotnet/` on its first start, so that start needs internet access and `curl`. The download is kept when you upgrade or re-unpack the instance. tModLoader checks the .NET version on every start and fetches a different one itself if a new release needs it.
**The `terraria` user must be able to read the zips.** Files copied in normally are fine, but `scp -p` or `cp -p` of a private file keeps its `600` mode, and a server can't be installed from that. `terractl list` warns about such zips, and a server that fails to start because of one says so in its log. Fix them with `sudo chmod 644 /var/lib/terraria/dist/*.zip`.
Members of the `terraria` group can copy zips into `dist/` without `sudo`: Members of the `terraria` group can copy zips into `dist/` without `sudo`:
```bash ```bash