warn when the services can't reach moved folders

- list, new, import and enable check TERRARIA_BASE and TERRARIA_DIST
  against the units' ProtectSystem/ProtectHome/ReadWritePaths
  (terraria@ always, terractld when it's on) and print the drop-in
  to add. prepare explains why it can't create an instance folder.
- Guide: bind mounts and drop-ins under "Changing locations", and a
  new section for instances or zips under /home.
- journal-access in tab completion and the command reference.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adamandClaude Opus 5.5 committed 2026-10-02 21:51:29 +00:00
1 parent 96f7876729
commit 7adf5c2999
5 files changed
+195 -9

No files matched your search

+77 -2
View File
@@ -199,16 +199,86 @@ The version comes from the `VERSION` file. Set `Maintainer:` in `packaging/deb/c
### Changing locations
`/etc/default/terractl` can move the instances or zips directory. If you move the instances directory, the service also needs permission to write to the new location:
The servers run in a systemd sandbox: they can write only to `/var/lib/terraria/instances`, they can read but not change the rest of the system, and they can't see `/home` at all. These rules are in the unit files, which can't read `/etc/default/terractl`. So if the instances or zips go somewhere else, the services must be told as well.
**The simplest way: mount the storage at the usual place.** To keep instances on another disk, mount it (or a folder on it) at `/var/lib/terraria/instances`, and change no settings at all. For a folder on a disk that's already mounted, add a bind mount to `/etc/fstab`:
```
/srv/bigdisk/terraria /var/lib/terraria/instances none bind 0 0
```
```bash
sudo systemctl stop 'terraria@*' # if servers are running
sudo cp -a /var/lib/terraria/instances/. /srv/bigdisk/terraria/ # copy existing instances over
sudo mount /var/lib/terraria/instances
sudo chown terraria:terraria /var/lib/terraria/instances
sudo chmod 0750 /var/lib/terraria/instances
```
The old copies stay hidden underneath the mount. Once everything works, you can free that space: `sudo umount /var/lib/terraria/instances`, delete the old instance folders, and `sudo mount /var/lib/terraria/instances` again.
The same works for `dist/`. Use a mount, not a symbolic link: systemd follows a link to where it really points, and that place isn't covered by the sandbox rules.
**Or change the setting, and add a drop-in.** Set `TERRARIA_BASE` and/or `TERRARIA_DIST` in `/etc/default/terractl`, create the folders with the same owners and modes as the default ones, and let the servers write to the new instances folder:
```bash
sudo install -d -o terraria -g terraria -m 0750 /srv/terraria/instances
sudo install -d -o root -g terraria -m 2775 /srv/terraria/dist
sudo systemctl edit terraria@.service
```
```ini
[Service]
ReadWritePaths=/your/new/path
ReadWritePaths=/srv/terraria/instances
```
A zips folder outside `/home` needs no drop-in, because the servers only read it.
`terractl list`, `new`, `import` and `enable` check that the services can reach both folders, and print the exact drop-in to add if they can't. A server that can't create its folder says so in its log, with the same advice. If the daemon for other hosts (`terractld.service`) is on, it's checked too; it only needs a drop-in for folders under `/home` (see below).
### Instances or zips under `/home`
This works, but needs more changes, because the services are set up to never touch home folders (`ProtectHome=yes`). That hides `/home`, `/root` and `/run/user` from them completely. Prefer a folder outside `/home`, or a bind mount (above), if you can.
If they must be under `/home`:
1. **Let the services see `/home`, read-only, and write to the instances folder.** For the servers:
```bash
sudo systemctl edit terraria@.service
```
```ini
[Service]
ProtectHome=read-only
ReadWritePaths=/home/you/terraria/instances
```
If the daemon for other hosts is on, it also needs to write to the zips folder, because copying an instance here can bring its server zip along:
```bash
sudo systemctl edit terractld.service
```
```ini
[Service]
ProtectHome=read-only
ReadWritePaths=/home/you/terraria/instances /home/you/terraria/dist
```
`ProtectHome=read-only` lets the servers see all home folders. Normal file permissions still apply, so as the `terraria` user they can only read what other users can.
2. **Let the `terraria` user into the folders above.** On Ubuntu (21.04 and later) and some other systems, home folders are private (mode `750`), so the `terraria` user can't even pass through `/home/you`. Give it just that, without letting it list or read anything there:
```bash
sudo setfacl -m u:terraria:x /home/you
```
Do the same for every folder between `/home/you` and the instances or zips folder that isn't open to others. `sudo -u terraria ls /home/you/terraria/instances` tells you whether it worked.
3. **Create the folders** with the right owners and modes, and set `TERRARIA_BASE` and/or `TERRARIA_DIST` in `/etc/default/terractl`, as above.
4. **Restart running servers** so they pick up the drop-in: `sudo terractl restart <name>`. If the daemon is on: `sudo systemctl restart terractld`.
`terractl list` stops warning once the drop-ins match. Members of the `terraria` group also need to get through `/home/you` to use `list`, `info` and tab completion without `sudo`.
---
## Migrating from the manual install
@@ -948,6 +1018,9 @@ sudo cp -a /var/lib/terraria/instances/other/server/dotnet /var/lib/terraria/ins
sudo systemctl start terraria@<name>
```
**The server won't start: "Read-only file system" or "No such file or directory" for its folder.**
The instances folder was moved (`TERRARIA_BASE`) to where the service isn't allowed to write, or under `/home`. The log names the drop-in to add, and so does `terractl list`. See [Changing locations](#changing-locations).
**The server can't save, or you see "Permission denied" errors.**
Some files are owned by root, or have the wrong modes. Run `sudo terractl fix-perms <name>`.
@@ -1056,6 +1129,8 @@ Used by the service:
terractl prepare <name> Create dirs/configs, unpack zip if needed
terractl run <name> Run the server
terractl service-stop <name> <pid> Save and shut down via the console (service only)
terractl journal-access Let the terraria group read the servers' journal
(runs before every start; safe to run by hand)
terractl daemon serve Run the daemon (terractld.service)
```