Setting up Zelie

How Zelie is set up: what the server needs, the three ways to reach the panel, what changes on the server, troubleshooting and removal.

EN, noch nicht übersetzt

Requirements

  • Debian or Ubuntu with systemd and cgroup v2, on amd64 or arm64.
  • Root, plus curl, openssl and sha256sum.
  • For a domain: a DNS record pointing at the server, and ports 80 and 443 free. For a Cloudflare Tunnel: a domain on Cloudflare.

Docker can keep running next to Zelie. Zelie brings its own containerd and never touches Docker's containers or firewall rules.

Install

Setup starts from your account: Install Zelie shows the three steps. The one-time install command is shown only to you, signed in, on your account page. It works once, within an hour. Run it as root. It checks the release's signature first, and if the check fails, nothing is installed. Then it asks how people will reach the panel.

The three modes

1. A domain. Zelie listens on ports 80 and 443 and gets Let's Encrypt certificates for the panel and each app. It asks for the panel's domain, which must already point to the server, and an email address. If ports 80 or 443 are taken, the install stops before changing anything.

2. A Cloudflare Tunnel. No port opens to the internet. Cloudflare's connector brings traffic to one local port, 8480 on a first install, and handles HTTPS. Choose this when your domain is on Cloudflare, another web server holds ports 80 and 443, or the server is behind NAT. If no connector runs yet, Zelie asks for the install command Cloudflare shows for a new tunnel (Zero Trust, Networks, Tunnels, then Debian). It reads the token from it and never gets access to your Cloudflare account. In Cloudflare, add a public hostname for the panel, and one for each app domain later, all pointing to http://127.0.0.1:8480. Settings, under General, shows this address.

3. The server's IP address. For trying Zelie out. The certificate is self-signed, and passkeys need a domain, so use an authenticator app.

Without questions

FlagMeaning
--modedomain, tunnel or ip
--hostthe panel's domain, or the IP address with --mode ip
--emailthe Let's Encrypt email, with --mode domain
--portthe local tunnel port; if left out, the one an earlier install used, or 8480
--no-sftpinstall with SFTP turned off

The flags go at the end of the install command from your account.

--mode tunnel without a terminal needs a connector already running.

Creating the administrator

The install ends with a link like https://panel.example.com/setup#…. It works once and for 24 hours. zelie setup-link prints a new one while no administrator exists.

The link asks for an email, a password of at least ten characters, and a passkey or an authenticator app. Zelie then shows ten recovery codes, once.

After the install

  • GitHub. Settings, under GitHub, creates a GitHub App in your account. Deploying on every push needs the panel to be reachable from the internet.
  • Game servers. The first game server asks for a block of ports for players; add more from a game server's Network tab. Settings, under Game servers, shows the address players connect to. Replace a private address with the public IP or a domain.
  • SFTP. It listens on port 2222. If another program holds that port, the install finishes anyway and says so. Choose another in Settings, under Game servers.
  • Backups. Settings, under Backups, takes any S3-compatible storage. Download the recovery file there too. Without it, no other server can open your backups.

A firewall at your hosting provider is yours to open.

What the install changes

  • Files in /usr/local/bin/zelie, /usr/local/lib/zelie (Zelie's own containerd, runc and CNI plugins) and /etc/zelie. Data in /var/lib/zelie*.
  • Users zelie, zelie-proxy and zelie-sftp, none able to log in.
  • Systemd services zelie-containerd, zelie-core, zelie-proxy, zelie-panel and zelie-sftp, plus zelie-sftp.socket. Containers run in zelie.slice.
  • nftables tables zelie and zelie-nat, and with iptables the chains ZELIE-INPUT and ZELIE-FORWARD. Other rules are left alone.
  • Bridges zelie0, zelie1 and so on, in 10.210.0.0/16.
  • With ufw on, a rule for port 2222, unless you use --no-sftp.
  • With a tunnel, the cloudflared package, unless it was there.

Running the install again is safe. It finishes a half-done install and updates an older one. If you pass a different --port behind a tunnel, the Cloudflare routes must follow.

Updating

Settings, under General, shows new releases and their notes. The release server wants a license or a download key for every download. A server linked to a Caria Core account uses its license; one that is not linked uses a key. Both are set in Settings, under License. Updating checks the signature and restarts only Zelie's own services. If the new version does not answer within a minute and a half, the old one is put back with the panel's database as it was.

The old binary stays as /usr/local/bin/zelie.old. Going back to it by hand after a good update also needs a copy of /var/lib/zelie-panel/panel.db from before the update, because a newer version may change the database in a way an older one cannot open.

Troubleshooting

  • The install stops about ports 80 and 443. Another web server holds them. Use the tunnel mode.
  • Behind a tunnel, the page does not load and the tunnel's log says connection refused. The hostname points to the wrong port. It must be http://127.0.0.1:<port>: 8480 on a first install, and Settings, under General, shows yours. Every app domain needs the same address.
  • Where the logs are. journalctl -u zelie-core covers containers, databases and builds. zelie-panel and zelie-proxy have their own. Add -f to follow, or --since "10 min ago" for the recent part.
  • The setup link ran out. Run zelie setup-link.
  • Locked out. Run zelie reset-login [email] on the server. It prints a link, valid once for an hour, to set a new password. It removes the account's passkeys, authenticator, recovery codes and SSH keys and logs it out everywhere. With more than one administrator, name the account.
  • An update fails. The old version comes back and the page says why.
  • Version. zelie version prints it.

Uninstall

There is no zelie uninstall yet. Run these as root, in order. Each step is safe to repeat. Step 8 deletes /var/lib/zelie, which holds your volumes, game files and local backups, so copy what you need first. Off-site backups are not touched.

1. Stop the services.

systemctl disable --now zelie-core zelie-panel zelie-proxy zelie-sftp.socket zelie-sftp 2>/dev/null || true

2. Stop the containers. Stopping containerd does not stop them.

systemctl stop zelie.slice 2>/dev/null || true
CTR="/usr/local/lib/zelie/bin/ctr -a /run/zelie/containerd.sock -n zelie"
if [ -S /run/zelie/containerd.sock ]; then
  for t in $($CTR tasks ls -q 2>/dev/null); do $CTR tasks kill -s SIGKILL "$t" 2>/dev/null || true; done
  sleep 2
  for t in $($CTR tasks ls -q 2>/dev/null); do $CTR tasks delete -f "$t" 2>/dev/null || true; done
fi

3. Stop containerd and its shims.

systemctl disable --now zelie-containerd 2>/dev/null || true
for u in zelie-core zelie-containerd; do
  k=/sys/fs/cgroup/system.slice/$u.service/cgroup.kill
  [ -e "$k" ] && echo 1 > "$k"
done
pkill -f /usr/local/lib/zelie/bin/containerd-shim-runc-v2 || true

4. Unmount what is left.

findmnt -rn -o TARGET | awk '$1 ~ "^/(run|var/lib)/zelie/"' | sort -r | while read -r m; do
  umount "$m" 2>/dev/null || umount -l "$m" 2>/dev/null || true
done

5. Remove the firewall rules and bridges.

nft delete table inet zelie 2>/dev/null || true
nft delete table ip zelie-nat 2>/dev/null || true
if command -v iptables >/dev/null; then
  while iptables -D INPUT -j ZELIE-INPUT 2>/dev/null; do :; done
  while iptables -D FORWARD -j ZELIE-FORWARD 2>/dev/null; do :; done
  for c in ZELIE-INPUT ZELIE-FORWARD; do iptables -F "$c" 2>/dev/null; iptables -X "$c" 2>/dev/null; done
fi
for l in $(ip -o link show | awk -F'[ :@]+' '$2 ~ /^zelie[0-9]+$/ {print $2}'); do ip link del "$l" 2>/dev/null || true; done

A crash may leave CNI- chains behind. Podman and k3s use the same names, so leave them if you run either. Otherwise check them:

iptables -t nat -S | grep CNI
iptables -S | grep CNI

Remove them only if every address in the output is inside 10.210.0.0/16: delete the jump with iptables -t nat -D POSTROUTING ... (or -D FORWARD ...), then flush with -F and remove with -X. Without iptables, the same care applies to the nftables table inet cni_plugins_masquerade. Leave net.ipv4.ip_forward and the overlay module alone.

6. Remove the ufw rule. Skip this if ufw is absent.

command -v ufw >/dev/null && ufw status | grep -q 'Zelie SFTP' && ufw delete allow 2222/tcp || true

7. Remove the Cloudflare connector. Only if Zelie installed it.

if command -v cloudflared >/dev/null; then cloudflared service uninstall; apt-get remove -y cloudflared; fi

Then delete the tunnel and its hostnames in Cloudflare.

8. Remove the units and files.

rm -f /etc/systemd/system/zelie-containerd.service /etc/systemd/system/zelie-core.service \
  /etc/systemd/system/zelie-proxy.service /etc/systemd/system/zelie-panel.service \
  /etc/systemd/system/zelie-sftp.service /etc/systemd/system/zelie-sftp.socket
rm -rf /etc/systemd/system/zelie-sftp.socket.d
systemctl daemon-reload
systemctl reset-failed 'zelie*' 2>/dev/null || true
rm -f /usr/local/bin/zelie /usr/local/bin/zelie.old /usr/local/bin/zelie.new \
  /usr/local/bin/zelie.tmp-* /usr/local/bin/zelie.old.tmp-*
rm -rf /usr/local/lib/zelie /etc/zelie /etc/zelie-sftp
rm -rf /var/lib/zelie /var/lib/zelie-panel /var/lib/zelie-proxy /var/lib/zelie-sftp
rm -rf /run/zelie /run/zelie-panel /run/zelie-proxy

If rm says a path is busy, run step 4 again.

9. Remove the users.

for u in zelie zelie-proxy zelie-sftp; do userdel "$u" 2>/dev/null || true; done
for g in zelie zelie-proxy zelie-sftp; do getent group "$g" >/dev/null && groupdel "$g" || true; done

To check, each of these should print nothing, apart from a zero-unit heading from systemctl:

systemctl list-units --all 'zelie*'
nft list tables | grep zelie
iptables -S 2>/dev/null | grep -i zelie
ip link | grep zelie
findmnt | grep zelie
getent passwd zelie zelie-proxy zelie-sftp
ls -d /usr/local/bin/zelie* /usr/local/lib/zelie /etc/zelie* /var/lib/zelie* /run/zelie* \
  /etc/systemd/system/zelie* 2>/dev/null
Setting up Zelie: requirements, troubleshooting, removal