Reference

Files and services

Everything the installer sets up, and where each app's builds, data, settings and logs live on the server.

Nothing is hidden: every app is a folder, a Linux user, a systemd unit and a Caddy file, and this page lists where each one is.

What the installer does

In order:

  1. Checks: the OS and CPU architecture, that systemd runs the server (containers and WSL aren't supported), free disk, that ports 80 and 443 are free, and the public IP address. If one fails, it stops before changing anything.
  2. Swap: on servers with less than 4 GB of RAM, a 2 GB swap file, so a next build can't exhaust memory and take the server down.
  3. Packages:
    • Caddy, from its own apt repository.
    • ufw, and fail2ban watching SSH logins.
    • unattended-upgrades, for security updates.
  4. Node: official Node.js builds, checked against their published checksums, unpacked read-only in /opt/layer/node/<version>/. Each app's unit names the exact version it runs. There's no nvm, fnm or pm2.
  5. Users: layer for the panel, a layer-apps group for app users, and a layer-web group that lets Caddy reach the panel's socket. Each app gets its own user later, when you create it.
  6. Caddy: a main config that loads one file per site from /etc/caddy/sites/. Its admin API listens on a unix socket, not a port.
  7. The release: the panel, the agent and the layer command, unpacked read-only in /opt/layer/releases/<version>/ and linked as /opt/layer/current. The last 3 releases are kept.
  8. Secrets: the key that encrypts environment variables and other secrets in the panel's database (/etc/layer/secret.key), and the setup token's hash.
  9. Services:
    • layer-agent: runs as root, but only takes a fixed list of actions over a unix socket.
    • layer-panel: the web UI, running as layer.
  10. The panel's site: /etc/caddy/sites/_panel.caddy, which proxies to the panel's unix socket.
  11. Firewall: incoming traffic is denied except SSH, 80 and 443 (TCP, plus UDP for HTTP/3).
  12. SSH, if an SSH key is present and you agree (or pass --yes): password login off, root only with a key.

The full log is in /var/log/layer-install.log.

Where things are

Where What
/opt/layer/current, /opt/layer/releases/<version>/ The panel, the agent and the CLI. Read-only, owned by root.
/opt/layer/node/<version>/ Node runtimes, shared by all apps.
/srv/apps/<app>/ Each app's builds (releases/<sha>/, current) and its data/ folder, owned by the app's own Linux user, app-<app>.
/etc/layer/apps/<app>/ The app's env files: app.env (your variables), services.env (database URLs), blue.env and green.env (ports). All root-only.
/etc/systemd/system/app-<app>@.service The app's sandboxed unit, with instances blue and green. Cron jobs are app-<app>-cron-<name>.timer units; Redis is layer-redis-<app>.service.
/etc/caddy/sites/<app>.caddy The app's Caddy site. _panel.caddy is the panel.
/var/log/caddy/<app>.log The app's access log, as JSON.
/etc/layer/config.json The server's settings: panel address, apps domain, who can open the panel, update feed.
/var/lib/layer/panel.db The panel's database (SQLite, owned by layer).
/var/log/layer/audit.jsonl Every change the agent made. Root-only.
/var/lib/layer-agent/archive/ Final dumps and data folders kept when you remove a database or delete an app. Root-only.

Services

systemctl status layer-panel layer-agent caddy   # the panel, the agent and the web server
systemctl list-units 'app-*'                     # every app, cron job and Redis
journalctl -u layer-agent -f                     # what the agent is doing