check the terraria user can run terractl before switching to it
upgrade (before stopping anything) and prepare/run started as root now refuse with an explanation when terractl is somewhere the terraria user can't open, such as a copy under /root, instead of failing with "env: Permission denied". upgrade also says when it started the server again after a failure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7adf5c2999
commit
8a509f1398
2 files changed
+14
-3
No files matched your search
@@ -11,6 +11,7 @@
|
|||||||
- `list`, `new`, `import` and `enable` warn when `TERRARIA_BASE` or `TERRARIA_DIST` is somewhere the services' sandbox doesn't allow (the instances folder not in `ReadWritePaths=`, or either folder under `/home`), and print the exact drop-in to add. The daemon (`terractld.service`) is checked too when it's on. A server that can't create its folder now says why in its log, instead of only "Read-only file system".
|
- `list`, `new`, `import` and `enable` warn when `TERRARIA_BASE` or `TERRARIA_DIST` is somewhere the services' sandbox doesn't allow (the instances folder not in `ReadWritePaths=`, or either folder under `/home`), and print the exact drop-in to add. The daemon (`terractld.service`) is checked too when it's on. A server that can't create its folder now says why in its log, instead of only "Read-only file system".
|
||||||
- The guide's "Changing locations" now covers bind mounts (the simplest way to use another disk) as well as drop-ins, and a new section explains keeping instances or zips under `/home`.
|
- The guide's "Changing locations" now covers bind mounts (the simplest way to use another disk) as well as drop-ins, and a new section explains keeping instances or zips under `/home`.
|
||||||
- `journal-access` is offered by tab completion and listed in the guide's command reference.
|
- `journal-access` is offered by tab completion and listed in the guide's command reference.
|
||||||
|
- `upgrade`, and `prepare`/`run` started as root, check first that the `terraria` user can run the terractl being used. A copy under `/root` is refused with an explanation, before `upgrade` stops the server, instead of failing with `env: Permission denied`.
|
||||||
- `terractl` run by a relative path (e.g. `sudo ./bin/terractl prepare <name>` from a source tree) no longer fails to switch to the `terraria` user.
|
- `terractl` run by a relative path (e.g. `sudo ./bin/terractl prepare <name>` from a source tree) no longer fails to switch to the `terraria` user.
|
||||||
- New `fix-perms` command: `sudo terractl fix-perms <name>` gives every file of an instance back to the `terraria` user and reapplies the usual modes (group can read, others nothing; server binaries executable), e.g. after copying worlds in as root. Symlinks are not followed. Works with `--host` too.
|
- New `fix-perms` command: `sudo terractl fix-perms <name>` gives every file of an instance back to the `terraria` user and reapplies the usual modes (group can read, others nothing; server binaries executable), e.g. after copying worlds in as root. Symlinks are not followed. Works with `--host` too.
|
||||||
- `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.
|
- `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.
|
||||||
|
|||||||
+13
-3
@@ -1074,6 +1074,15 @@ svc_can_read() {
|
|||||||
else (( 8#$mode & 0004 )); fi
|
else (( 8#$mode & 0004 )); fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check that the service user can run this script, which prepare/run (as root)
|
||||||
|
# and upgrade switch to. Not so for a copy in a private folder, such as a
|
||||||
|
# development copy under /root.
|
||||||
|
need_svc_can_run_self() {
|
||||||
|
command -v runuser >/dev/null || die "runuser not found; run as '$SVC_USER' instead"
|
||||||
|
runuser -u "$SVC_USER" -- test -x "$SELF" 2>/dev/null ||
|
||||||
|
die "$1 runs $SELF as the '$SVC_USER' user, who can't open it (it's in a folder only root can open, e.g. /root). Use the installed terractl, or a copy somewhere '$SVC_USER' can read."
|
||||||
|
}
|
||||||
|
|
||||||
# Zips in dist/ the servers can't unpack, e.g. copied in with 'scp -p' from a
|
# 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.
|
# private file. Instances fail on their first start with such a zip.
|
||||||
unreadable_zips() {
|
unreadable_zips() {
|
||||||
@@ -1373,6 +1382,7 @@ cmd_upgrade() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
command -v unzip >/dev/null || die "unzip is not installed"
|
command -v unzip >/dev/null || die "unzip is not installed"
|
||||||
|
need_svc_can_run_self "upgrade"
|
||||||
listing=$(unzip -Z1 "$f" 2>/dev/null) || die "$f isn't a readable zip (damaged, or not fully downloaded?)"
|
listing=$(unzip -Z1 "$f" 2>/dev/null) || die "$f isn't a readable zip (damaged, or not fully downloaded?)"
|
||||||
case $TYPE in
|
case $TYPE in
|
||||||
vanilla) grep -q '/Linux/TerrariaServer\.bin\.x86_64$' <<< "$listing" ||
|
vanilla) grep -q '/Linux/TerrariaServer\.bin\.x86_64$' <<< "$listing" ||
|
||||||
@@ -1402,7 +1412,7 @@ cmd_upgrade() {
|
|||||||
backup_file+=.tar.gz
|
backup_file+=.tar.gz
|
||||||
# In a subshell, so a failure comes back here instead of exiting
|
# In a subshell, so a failure comes back here instead of exiting
|
||||||
if ! ( trap cleanup EXIT; cmd_export "$name" "$backup_file" ) >/dev/null; then
|
if ! ( trap cleanup EXIT; cmd_export "$name" "$backup_file" ) >/dev/null; then
|
||||||
if [[ $was_running -eq 1 ]]; then systemctl start "$unit"; fi
|
if [[ $was_running -eq 1 ]]; then systemctl start "$unit"; echo "$unit started again"; fi
|
||||||
die "backing up '$name' failed, so its version wasn't changed"
|
die "backing up '$name' failed, so its version wasn't changed"
|
||||||
fi
|
fi
|
||||||
echo "backup of worlds and configs: $backup_file"
|
echo "backup of worlds and configs: $backup_file"
|
||||||
@@ -1414,7 +1424,7 @@ cmd_upgrade() {
|
|||||||
# new server/ is complete, the old one is left in place.
|
# new server/ is complete, the old one is left in place.
|
||||||
if ! runuser -u "$SVC_USER" -- env HOME="$dir" "$SELF" prepare "$name"; then
|
if ! runuser -u "$SVC_USER" -- env HOME="$dir" "$SELF" prepare "$name"; then
|
||||||
set_zip_pin "$name" "$old_pin"
|
set_zip_pin "$name" "$old_pin"
|
||||||
if [[ $was_running -eq 1 ]]; then systemctl start "$unit"; fi
|
if [[ $was_running -eq 1 ]]; then systemctl start "$unit"; echo "$unit started again"; fi
|
||||||
die "unpacking $zip failed (see above); '$name' still runs ${installed:-its old version}"
|
die "unpacking $zip failed (see above); '$name' still runs ${installed:-its old version}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -1529,7 +1539,7 @@ valid_name "$1"
|
|||||||
# debugging), switch to the service user so nothing ends up owned by root.
|
# debugging), switch to the service user so nothing ends up owned by root.
|
||||||
if [[ $command == prepare || $command == run ]]; then
|
if [[ $command == prepare || $command == run ]]; then
|
||||||
if [[ $EUID -eq 0 ]]; then
|
if [[ $EUID -eq 0 ]]; then
|
||||||
command -v runuser >/dev/null || die "runuser not found; run as '$SVC_USER' instead"
|
need_svc_can_run_self "'$command'"
|
||||||
exec runuser -u "$SVC_USER" -- env HOME="$(inst_dir "$1")" \
|
exec runuser -u "$SVC_USER" -- env HOME="$(inst_dir "$1")" \
|
||||||
"$SELF" "$command" "$@"
|
"$SELF" "$command" "$@"
|
||||||
elif [[ $(id -un) != "$SVC_USER" ]]; then
|
elif [[ $(id -un) != "$SVC_USER" ]]; then
|
||||||
|
|||||||
Reference in new issue
Block a user