| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- [Unit]
- Description=x-ui Service
- After=network.target
- Wants=network.target
- StartLimitIntervalSec=180
- StartLimitBurst=10
- [Service]
- EnvironmentFile=-/etc/conf.d/x-ui
- Environment="XRAY_VMESS_AEAD_FORCED=false"
- Type=simple
- WorkingDirectory=/usr/local/x-ui/
- ExecStart=/usr/local/x-ui/x-ui
- ExecReload=/bin/kill -USR1 $MAINPID
- Restart=on-failure
- RestartSec=5s
- # The panel intentionally stays root: it supervises the Xray child processes,
- # edits netfilter state and reads TLS private keys. These settings only bound
- # what a panel-level flaw can reach.
- #
- # PrivateTmp=yes is deliberately absent: the web updater writes its script into
- # /tmp and hands the absolute path to a "systemd-run" transient unit, which
- # does not share this service's private /tmp (the download would vanish).
- NoNewPrivileges=yes
- ProtectSystem=full
- # Default stores: DB/update status/node-token in XUI_DB_FOLDER (/etc/x-ui),
- # xray binary/config/geo in XUI_BIN_FOLDER under /usr/local/x-ui, logs in
- # XUI_LOG_FOLDER (/var/log/x-ui). These are the plain-install defaults and the
- # floor, not the whole list: install.sh and update.sh regenerate a drop-in
- # (x-ui.service.d/10-xui-sandbox.conf) with the folders resolved from the XUI_*
- # variables, so a relocated XUI_DB_FOLDER or XUI_LOG_FOLDER stays writable and
- # the list survives an update instead of being reset to these defaults. Changing
- # one of those variables in the env file is not enough by itself: the drop-in has
- # to be refreshed as well, i.e. install or update the panel again.
- # Add local extras in your own drop-in (e.g. 20-local.conf).
- # The leading '-' keeps the unit startable if a path does not exist yet.
- # What ProtectSystem=full covers, precisely: /usr, /boot, /efi and /etc become
- # read-only, everything else stays writable. So this list matters for stores
- # under those trees -- the default main folder under /usr/local is one.
- #
- # The in-panel updater is expected to leave this sandbox: it runs update.sh
- # through a transient systemd-run unit, which does not inherit these settings.
- # Its plain-child fallback (taken when systemd-run is unavailable) cannot work
- # here -- update.sh stages the release archive beside the main folder, replaces
- # /usr/bin/x-ui and calls the package manager -- so it stops with one clear
- # message instead of failing halfway, and the sandbox deliberately does not
- # grant /usr or /etc to accommodate it.
- # ReadWritePaths= requires systemd >= 231; ReadWriteDirectories= is the deprecated
- # alias for older systemd, needed so ProtectSystem=full keeps /etc/x-ui writable.
- ReadWritePaths=-/etc/x-ui -/usr/local/x-ui -/var/log/x-ui
- ReadWriteDirectories=-/etc/x-ui -/usr/local/x-ui -/var/log/x-ui
- ProtectKernelTunables=yes
- ProtectKernelModules=yes
- ProtectKernelLogs=yes
- ProtectClock=yes
- ProtectHostname=yes
- # read-only rather than yes: installs keep TLS certs under /root/cert, and the
- # panel must still be able to read them.
- ProtectHome=read-only
- LockPersonality=yes
- RestrictRealtime=yes
- RestrictSUIDSGID=yes
- RestrictNamespaces=yes
- UMask=0077
- # AF_NETLINK for interface/route lookups and the ip(8) child used by the
- # AmneziaWG IPv6-alias feature.
- RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX AF_NETLINK
- # NET_ADMIN for ip(8)/tproxy, NET_BIND_SERVICE for ports below 1024, NET_RAW
- # for raw sockets and SO_BINDTODEVICE.
- #
- # DAC_OVERRIDE has to stay. The panel runs as root, but a bounding set is
- # subtracted from root's own privileges too: without it root can only read a
- # file when the owner/group/other bits let uid 0 through, and any TLS private
- # key belonging to another account becomes unreadable -- a certificate issued to
- # Caddy, an acme.sh home, any 0600 file that root does not own. TLS then fails
- # quietly: the panel listener catches the tls.LoadX509KeyPair error, logs it and
- # keeps serving plain HTTP, and every Xray inbound using that key stops. Those
- # reads worked before the sandbox because the panel is root.
- # DAC_READ_SEARCH is deliberately absent: directory search is already covered by
- # DAC_OVERRIDE, so it would only widen the set without adding anything.
- CapabilityBoundingSet=CAP_DAC_OVERRIDE CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW
- SystemCallArchitectures=native
- # No seccomp whitelist here on purpose. @system-service needs systemd >= 239
- # (other @-named groups exist since 231), and older systemd does not ignore an
- # unknown group name gracefully: on
- # <231 the name fails to resolve and the filter stays the built-in whitelist of
- # execve/exit/exit_group/rt_sigreturn/sigreturn, on 231..238 it degrades to
- # @default -- either way the panel then gets EPERM on read/openat/mmap/clone and
- # cannot start. install.sh and update.sh add SystemCallFilter=@system-service and
- # SystemCallErrorNumber=EPERM to the generated drop-in, but only when
- # "systemctl --version" reports 239 or newer.
- [Install]
- WantedBy=multi-user.target
|