Configuration
Everything on this page can be changed after the application exists, and most of it without redeploying.
The form and the flags
Section titled “The form and the flags”The panel and the CLI set the same fields. Add application and Edit open the same form — the one shown in the overview — and this is what each of its fields is called on the command line:
| Field in the panel | Flag | Explained under |
|---|---|---|
| Name | the positional argument | Set once, at creation; it names the unit and the socket |
| Published on | --domain | Where it is published |
| Path | --path | Where it is published |
| Start command | everything after -- | The start command |
| Internal port | --port | The internal port |
| Health path | --health | The health path |
| Linked directories | --link, --clear-links | Linked directories |
| Memory (MB), CPU (%), Max tasks | --mem, --cpu, --tasks | Resource limits |
Two differences worth knowing before you use the form. Name is absent when editing,
because it cannot be changed. And Linked directories is a single field of
space-separated names, where the CLI repeats --link; clearing the field is what
--clear-links does.
The start command
Section titled “The start command”The program and its arguments go after a -- separator, as a path relative to the
release root:
corepanel app create <account-id> api --domain example.com --port 8080 -- ./server --config prod.tomlThe -- is what keeps your application’s flags from competing with the CLI’s, so
--config above belongs to your program. The working directory is the release root — the
current symlink, not the release it was deployed from, so a rollback changes what runs
without rewriting the unit.
Where it is published
Section titled “Where it is published”| Flag | Meaning |
|---|---|
--domain <fqdn> | The domain or subdomain of the account. A domain alias is refused: it has no site file of its own, so the route belongs on the domain it points at |
--path </sub> | / for the whole site, or a path under it. A sub-path mount strips the prefix before the request reaches your program |
Both can be changed later with update; the route is moved for you.
corepanel app update <account-id> api --domain app.example.com --path /The internal port
Section titled “The internal port”corepanel app create <account-id> api --domain example.com --port 8080 -- ./serverYour program listens on this port inside its own network namespace, where nothing else
on the server can reach it. CorePanel exports it as $PORT, which nearly every framework
reads without configuration.
It must be 1024–65535: the process runs unprivileged and without
CAP_NET_BIND_SERVICE, so a lower port could never be bound. Two applications may use the
same number without conflicting — the namespaces are separate — but keeping them distinct
makes a ps listing easier to read.
The health path
Section titled “The health path”corepanel app create <account-id> api --domain example.com --port 8080 --health /healthz -- ./serverAfter every deploy and rollback, CorePanel connects to the endpoint and — if a health path
is set — requests it. Without one, the check only proves that something accepted the
connection, which means bind succeeded and nothing more. A process that binds and then
fails every request would pass.
The path is the one your program sees, after the prefix strip: an application mounted
at /api with --health /healthz is checked at /healthz, and the visitor-facing URL is
https://example.com/api/healthz.
Make it cheap. It runs on every deploy, and a health check that touches a database turns a slow database into a failed deploy.
Environment and secrets
Section titled “Environment and secrets”The Environment card on the application lists every variable, with a pencil to change one and a bin to remove it:

Add variable asks for three things — a name, a value, and whether it is a secret:

Turning Secret on is what makes the value unreadable afterwards, in the panel and the CLI alike. Editing one later opens with the value empty and says so: what is stored was never sent to your browser, and saving replaces it with whatever you type. Leaving the field blank therefore sets an empty value rather than keeping the old one.
The same, from corepanel:
corepanel app env list <account-id> apicorepanel app env set <account-id> api LOG_LEVEL=debugcorepanel app env set <account-id> api DATABASE_PASSWORD='...' --secretcorepanel app env unset <account-id> api LOG_LEVELThe variables live in a file systemd reads as root before dropping privileges, so your application receives them while the account cannot read the file that holds them — not over FTP, not from a shell, not from the application itself.
A --secret value is never displayed back, in the panel or the CLI. It can be
replaced, only not read. That is the point: the copy in CorePanel is not a place to look
values up, it is a place to set them.
Setting or removing a variable restarts a running application, because a value stored but absent from the running process is the kind of half-applied setting that costs an afternoon to diagnose.
Variables CorePanel sets for you
Section titled “Variables CorePanel sets for you”| Variable | Value |
|---|---|
PORT | The internal port you chose |
CP_APP_NAME | The application’s slug |
CP_APP_DATA | The persistent data directory |
CP_APP_TMP | A private /tmp, invisible to the rest of the server |
Those four names are reserved; your own variables cannot override them. The panel refuses
them in the editor rather than after a round trip, and applies the same rule to the name
itself: it starts with a letter or _ and contains only letters, digits and _.
Persistent data
Section titled “Persistent data”$CP_APP_DATA points at a directory that survives deploys, rollbacks and even deleting
the application:
/var/opt/userapps/<account>/<app>/dataThe program tree does not survive: every release replaces it. Anything your
application must keep — uploads, a SQLite file, generated configuration — belongs under
$CP_APP_DATA.
Linked directories
Section titled “Linked directories”Some programs insist on writing inside their own tree and cannot be told otherwise.
--link handles those: the named directory, relative to the release root, is replaced by
a symlink into the data volume on every deploy.
corepanel app create <account-id> gitea --domain git.example.com --port 3000 \ --link data --link custom -- ./gitea web./data then keeps its contents while everything around it is replaced. Repeat the flag
per directory; corepanel app update ... --clear-links removes them all.
Resource limits
Section titled “Resource limits”Every application has all three, and they are mandatory — an unbounded process on the same machine as the control panel is the straight road to an out-of-memory event that takes the panel down with it.
| Flag | Default | Meaning |
|---|---|---|
--mem <mb> | 256 | Hard memory ceiling. Exceeding it means the kernel kills the process; systemd restarts it |
--cpu <pct> | 50 | Percentage of one core. 100 is a whole core, 200 is two |
--tasks <n> | 64 | Threads and processes together |
corepanel app update <account-id> api --mem 1024 --cpu 200They are applied as cgroup properties, so they are enforced by the kernel rather than requested politely. If the application stops serving under the new settings, the previous ones are restored.
Sizing, roughly: a small Go or Rust API is comfortable at the defaults; a service with an
embedded database, background jobs and a template cache wants 512–1024 MB and a full core;
a program that spawns workers needs --tasks raised or it will fail to fork under load.
Changing the specification
Section titled “Changing the specification”In the panel, Edit on the application opens the creation form again with the current values, minus the name. Only the fields you actually change are sent, so saving does not re-apply — or re-validate — settings nobody touched; if nothing changed, the form says so instead of writing.
corepanel app update <account-id> api --mem 512 --health /healthz -- ./server --addr :8080Omitted fields are left as they are. The change is applied to the release already running — no redeploy — and if the application stops serving under the new settings, the previous ones are put back. An application that was stopped stays stopped.
Per-account allowance
Section titled “Per-account allowance”Each account has a maximum number of applications, in parallel with its subdomain and addon-domain limits, and hosting packages carry it to the accounts they provision.
Zero means none here, not unlimited — this is the one limit in CorePanel that reads
the other way round, and it has no unlimited value at all. An application is a resident
program with its own memory, socket and network namespace, so an account gets to run them
only when somebody grants a number: on the account (Edit account → Applications, or
corepanel account update <id> --max-apps N) or on its
hosting package.
Lowering the number below the applications already running is refused, exactly like any other limit below current usage; the applications themselves are never deleted to make room.
Full flag reference
Section titled “Full flag reference”The complete list, with every default, lives in the CLI reference.