Applications
Docker, systemd and Compose apps: sources, ports, health checks and resource limits.
An application is a long-running service on one server, built from a Git repository or pulled from a registry. Each successful deployment becomes a release you can roll back to.
Runtimes
Pick how the app runs when you create it. It can't be changed later; create a new app to switch.
systemd and Compose apps deploy from Git and need agent 1.1.0 or later on the server.
systemd (native) apps
- The stack is detected the same way as Docker builds (npm, pnpm, Yarn; pip, Poetry, uv, Pipenv). If the server's Node.js major version doesn't match what the project asks for, the right one is downloaded from nodejs.org and checksum-verified. Python uses the server's
python3with a virtualenv per release. - Your app must listen on
$PORT, which VPSPilot sets to the app's public port. Bind to0.0.0.0so the domain proxy can reach it. - Builds run as the app's own user in a sandboxed, time-limited systemd unit; your repository's scripts never run as root.
- Each release is a new folder; files written there are gone after the next deploy. Keep uploads and SQLite files in
$VPSPILOT_SHARED_DIR, which survives releases. - The service is hardened (read-only system, private
/tmp, no new privileges). Logs go to the systemd journal.
Compose apps
- VPSPilot finds
compose.yaml(ordocker-compose.yml) in the root directory, or the file you name. With more than one service, name the public service that receives traffic and its port. - Refused for safety: privileged mode, added capabilities, devices, host networking or namespaces, security options, bind mounts outside the repository, the Docker socket, and external volumes or networks.
- Published
ports:and fixedcontainer_namevalues are ignored (with a warning), since they would clash with other apps. VPSPilot publishes the public service itself and joins it to the private network asvp-<name>. - The app's variables are available for
${VAR}substitution in the file and are set on the public service. Named volumes keep their data across deploys and aren't deleted when the app is removed.
Sources
Git repository
Pick a repository from your connected GitHub App, or paste any public HTTPS clone URL. Choose a branch, which defaults to main. Each deploy makes a shallow checkout of that branch, or of a specific branch, tag or commit you ask for.
Container image
Give an image reference such as ghcr.io/acme/api:1.4.2. VPSPilot pulls it and runs it; there is no build step. Deploying a different tag is a deploy with a new image reference.
Settings
namestringruntimedocker · systemd · composecompose_file / compose_servicepath / namecontainer_port1–65535PORT.host_port1024–65535dockerfilepath · Dockerfilebuild_contextpath · .build_command / start_commandstringhealth_pathpath · /health_timeout_seconds5–600 · 60cpu_limite.g. 0.5, 2memory_limite.g. 512m, 2gauto_deploybool · trueNetworking
The app joins the private vpspilot Docker network, where the domain proxy reaches it as vp-<name>:<container_port> and where it can reach managed databases by name. Its host port is also published on all interfaces, which is handy for testing.
Once an app has a domain, traffic goes through Caddy on 80 and 443. Use a firewall such as ufw to block the app’s host port from the internet if you don’t want it reachable directly.
systemd apps listen directly on their public port on the server; the domain proxy reaches them through the private network's gateway (and VPSPilot opens that path in ufw if it's on).
Apps keep running
Containers run with Docker’s unless-stopped restart policy and systemd apps with Restart=always, so they survive reboots and restart after crashes. The Application down alert tells you if one stays down.
A Docker or Compose app that connects to localhost:5432 reaches itself, not a database on the server. Use a managed database (reachable by name, e.g. vpdb-main) and attach it, or a systemd app, which does share the server's localhost.