Skip to content

Applications

An application is a long-lived program CorePanel runs for a hosting account and publishes under one of the account’s domains. Unlike a PHP site, it is a process that stays up: you deploy a build, CorePanel starts it, keeps it alive across crashes and reboots, and puts your domain’s HTTPS, WAF and logs in front of it.

https://example.com/api/orders ──▶ your program (supervised by CorePanel)
https://example.com/index.html ──▶ ~/public_html (the docroot, untouched)
PageWhat it covers
Use casesThe shapes an application takes — an API beside a site, a whole app on a subdomain, an SPA backend, a self-hosted service — and the exact configuration for each
DeployingThe artifact, releases, automatic rollback and going back to an earlier version
Deploying from CI/CDUpload and deploy in one call, or trigger a deploy by URL: tokens, GitHub Actions and GitLab CI, signatures, what each status code means
ConfigurationEvery setting: publication target, port, health path, environment and secrets, resource limits, linked directories
Running and troubleshootingStart/stop, reading the journal, diagnosing a 502 or a crash loop, deleting, and what is not backed up

Everything here can be done two ways, and they are the same operations: the panel, in the account’s own workspace, and the corepanel app commands. Each page shows both.

SupervisionA systemd unit of its own, Restart=on-failure, enabled across reboots
IsolationRuns as the account user, in a private network namespace, with ProtectSystem=strict, ProtectHome, PrivateTmp and NoNewPrivileges
EndpointA unix socket, never a TCP port the rest of the server can reach
LimitsMemory, CPU and task ceilings applied as cgroup properties
ReleasesEach deploy is a new directory; the three newest are kept and any of them can be made current again
Safety netA release that does not answer is rolled back automatically and the previous one keeps serving
LogsThe unit’s journal, readable from the panel and the CLI

Both publish a local service under one of your domains. The difference is who keeps it running.

Reverse proxy routeApplication
Who writes the systemd unitYouCorePanel
Who restarts it after a crash or a rebootYouCorePanel
Resource limitsWhatever you configureMandatory, enforced
Deploying a new versionYour own processdeploy, with automatic rollback
EndpointA host:port you chooseA unix socket, unreachable from other accounts
Good forSomething you already run and want to keep managing yourself; a service on another machineAnything you would rather CorePanel supervised

If you are starting from scratch, use an application. Reach for a plain route when the process is not yours to manage — a service on another host, or one installed by a package that brings its own unit.

Your application listens on a normal TCP port — but inside a network namespace of its own, where nothing else on the server can reach it. CorePanel binds a unix socket for it and the web server proxies to that:

/run/corepanel/apps/<account>/<app>.sock

This matters on a shared machine. A port on 127.0.0.1 is reachable by every process on the server, another customer’s account included, so their traffic could arrive at your backend behind the web server, the WAF and whatever authentication you put in front. A socket file cannot be reached that way: it is owned by the account, group-readable only by the web server, mode 0660, inside a directory closed to everyone else. The permissions are the isolation, and you can check them with ls.

Two applications can therefore never collide on a port, because there are no ports to allocate.

Almost nothing. CorePanel adapts to the application, not the other way round.

  • Listen on the port in $PORT. CorePanel sets it to the internal port you chose, which is the convention nearly every framework already reads. A stock application usually needs no configuration at all.
  • Write persistent data under $CP_APP_DATA. That directory survives deploys, rollbacks and deletion. The program tree does not — it is replaced on every release.
  • Offer a health path (optional, strongly recommended). Without one, the check after a deploy stops at “something accepted the connection”, which only proves bind succeeded. With one, it proves the release actually serves.

CorePanel also sets CP_APP_NAME and CP_APP_TMP. Those three names are reserved: your own variables cannot override them.

An application belongs to an account, so that is where it is managed: Accounts → the account → AdvancedApplications.

The Applications section of an account: one running application and one failed, with their state, publication target, socket and active release

Five columns, and each answers a different question:

ColumnWhat it tells you
StateWhat CorePanel last recorded — Running, Stopped, Failed, or Not deployed for one that exists but has never shipped a release
NameThe application’s slug. It names the systemd unit and the socket, and cannot be changed later
Published atThe site, and the path under it, that reaches the program
EndpointThe unix socket the web server proxies to
Active releaseThe version serving right now

Selecting a row opens the application itself: its live systemd status, its releases, its environment, its deploy webhook and its journal, with the actions that change any of them. That detail is reached from the table, not from a URL of its own.

An application is only available to an account whose Applications limit is above zero. That limit starts at 0 — which here means none, not unlimited, unlike every other limit in CorePanel — so the runtime is granted deliberately, per account:

  • From the panel: the account → OverviewEdit accountApplications.
  • From the CLI: corepanel account update <account-id> --max-apps 5.
  • From a plan: set Applications on the hosting package the account is provisioned from.

Until then Add application stays disabled and says why, and the API refuses a creation with applications are not enabled for this account.

1. Register it. Press Add application. The form asks for the name, the site and path it is published under, the command that starts it, the port it listens on inside its namespace, an optional health path, and the limits it runs within. Every field is explained on Configuration.

The Add application form, filled in: name, publication target and path, start command, internal port, health path, linked directories and the memory, CPU and task limits

Saving takes you straight to the application, which now exists but serves nothing: Not deployed, no active release, and no unit for systemd to report on — that is written by the first successful deploy.

The application right after creation: state "Not deployed", no active release, no last deploy, with Start and Restart unavailable

Note what is greyed out: Start and Restart do nothing until a release exists, and the panel says why rather than failing when pressed.

2. Deploy the build. Press Deploy and drop the .tar.gz on the dialog: the panel uploads it and deploys it in one act. CorePanel extracts it, starts it, checks that it answers, and only then publishes the path. If it does not answer, the previous release is put back — Deploying covers the whole sequence.

For an archive that is already on the server — put there over FTPS at ~/apps/<name>.tar.gz, or by a pipeline that POSTs it and deploys in the same call — switch the dialog to Already on the server and leave the field empty. The account’s FTP password is set in the account’s Access section.

4. Watch it. The detail refreshes itself every 15 seconds, so the state, the restart count and the socket are what the machine says now, not what the last action returned.

A first application, from the command line

Section titled “A first application, from the command line”

Every corepanel app command starts with the account id — the numeric identifier of the hosting account the application belongs to. It is printed when the account is created; afterwards, recover it with corepanel account list, or resolve a domain to it directly:

Terminal window
corepanel account list --search example.com
+----+-------------+---------+--------+
| ID | Domain | User | … |
+----+-------------+---------+--------+
| 12 | example.com | example | … |
+----+-------------+---------+--------+

That 12 is what goes where the examples say <account-id>.

Terminal window
# 1. Register it (does not publish yet)
corepanel app create <account-id> api --domain example.com --path /api --port 8080 \
--health /healthz -- ./server
# 2. Upload the build as the account, over FTPS: ~/apps/api.tar.gz
# (hosting accounts have no shell, so scp/sftp are not available)
curl --ssl-reqd --ftp-create-dirs -T api.tar.gz \
--user 'example:<ftp password>' ftp://example.com/apps/api.tar.gz
# 3. Deploy — extracts, starts, verifies, publishes
corepanel app deploy <account-id> api
# 4. Check what the machine says, not what CorePanel recorded
corepanel app show <account-id> api

From there: use cases for other shapes, configuration for every setting, and CI/CD to replace steps 2 and 3 with a single POST that carries the artifact.

Deliberately, so that what exists is solid:

  • Building on the server. You ship a built artifact; CorePanel does not compile it. A git origin and a build step are in development.
  • Node and Python runtimes. The runtime field exists and the machinery is shared, but only Go artifacts are accepted today.
  • Containers. A Podman backend is planned; today an application is a native process.
  • Live log streaming and periodic health checks. The health probe runs on deploy.
  • Zero-downtime restarts. A deploy costs a restart of roughly 200 ms behind the web server, with retry — measurable, but not something a visitor notices.