Use cases
An application is always the same machinery; what changes is where it is published and what it owns. This page walks the shapes that come up in practice and gives the exact configuration for each.
Two settings do most of the work:
- The target — which domain or subdomain the application is published under.
- The mount path —
/for the whole site, or/somethingfor one path under it.
A sub-path mount strips the prefix: an application mounted at /api receives
/orders when a visitor requests /api/orders, so the same build works whether you mount
it at the root or under a path.
Each shape below is written as a create command, because that is the compact way to show
a whole specification at once. In the panel the same values go into the Add application
form, field by field — which field is which flag
is a single table.
An API beside an existing website
Section titled “An API beside an existing website”The classic case: a PHP or static site keeps serving, and one path goes to a program.
corepanel app create <account-id> api --domain example.com --path /api --port 8080 \ --health /healthz -- ./serverhttps://example.com/ | the docroot, as before |
https://example.com/api/orders | your program, which sees /orders |
Nothing about the site changes: the document root, its PHP version, its certificates and
its WAF policy stay exactly as they were. Removing the application later puts /api back
to being served from the docroot.
Watch out for: a real directory named api inside the docroot. The application wins,
and the files become unreachable while it exists.
A whole application on its own subdomain
Section titled “A whole application on its own subdomain”The cleanest shape when the program is the site — a dashboard, an internal tool, an API with its own hostname.
corepanel subdomain add <account-id> app example.comcorepanel app create <account-id> app --domain app.example.com --path / --port 3000 \ --health /healthz -- ./serverThe subdomain gets its own certificate automatically. Because the mount is /, every path
— including /favicon.ico and any 404 — is your program’s responsibility; there is no
docroot fallback behind it.
Watch out for: deploying for the first time before pointing anyone at the hostname. Until the first successful deploy the application is not published, and that is deliberate — publishing earlier would 502 the whole site until the artifact arrived.
A single-page app with a backend
Section titled “A single-page app with a backend”Static build served by the web server, API calls handled by the program. This is faster and cheaper than routing everything through the application.
# The SPA build lives in the docroot; unknown paths fall back to index.html.# The web mode is chosen when the domain or subdomain is created…corepanel subdomain add <account-id> app example.com --web-mode spa
# …and the backend takes one path under itcorepanel app create <account-id> api --domain app.example.com --path /api --port 8080 \ --health /healthz -- ./serverOn a domain that already exists, change the web mode from the panel — the domain’s Web
settings — since the CLI only takes --web-mode at creation time.
https://app.example.com/assets/app.js | the docroot |
https://app.example.com/dashboard | index.html, so client-side routing works |
https://app.example.com/api/me | your program, which sees /me |
The spa web mode is what makes a client-side route like /dashboard return the app
instead of a 404. The application’s path is matched first, so API calls never fall into
that fallback.
A self-hosted service that owns its data
Section titled “A self-hosted service that owns its data”A Git server, a metrics dashboard, a bookmarking tool — something that writes files and must keep them across upgrades.
corepanel app create <account-id> gitea --domain git.example.com --path / --port 3000 \ --health /api/healthz --mem 1024 --cpu 200 --tasks 256 \ --link data --link custom -- ./gitea webThree settings matter here:
$CP_APP_DATAis the directory that survives everything: deploys, rollbacks, even deleting the application. Configure the service to write there if it lets you.--link <dir>is for services that insist on writing inside their own tree. The named directory is replaced by a symlink into the data volume on every deploy, so./datakeeps its contents while the rest of the program is replaced. Repeat the flag per directory.- Higher limits. The defaults (256 MB, half a core) fit a small API, not a service with a database and background jobs. See Configuration.
Several applications on the same domain
Section titled “Several applications on the same domain”Each gets its own unit, its own socket and its own limits. There is nothing to coordinate: no ports to allocate, no conflicts to avoid.
corepanel app create <account-id> api --domain example.com --path /api --port 8080 -- ./apicorepanel app create <account-id> admin --domain example.com --path /admin --port 8081 -- ./adminThe paths are matched most-specific first, and everything that matches neither keeps being served from the docroot. The internal ports only have to differ from each other within the same account, and even that is a convention rather than a requirement — each application runs in its own network namespace.
A webhook or callback receiver
Section titled “A webhook or callback receiver”Small, stateless, and it must be up when a third party calls.
corepanel app create <account-id> hooks --domain example.com --path /hooks --port 8090 \ --health /healthz --mem 128 --cpu 25 --tasks 32 -- ./receiverTwo things worth doing for this shape:
- Keep the limits small. A receiver that leaks memory should hit its ceiling and be restarted, not consume the machine.
- Give it a health path anyway. A receiver that accepts connections but fails every request would otherwise pass the deploy check and start dropping deliveries silently.
The WAF sits in front, as it does for every path on the domain. If a legitimate provider trips a rule, add a trusted IP or a per-path exception rather than disabling protection for the whole site.
A service you want to reach only from your own network
Section titled “A service you want to reach only from your own network”CorePanel publishes an application under a public hostname with a public certificate. There is no “internal only” switch today, so the access control has to be yours:
- Put it on a hostname nobody guesses, and require authentication in the application itself. A hostname is not a secret — it appears in certificate transparency logs — so this alone is not enough.
- Or restrict at the firewall, and reach it over a VPN or an SSH tunnel to the socket.
Do not rely on the port being unreachable: it already is. What is reachable is the hostname, and that is what needs the lock.
When an application is the wrong answer
Section titled “When an application is the wrong answer”- A cron job. Something that runs and exits is a cron job, not a supervised process. An application that exits is restarted, forever.
- A worker with no HTTP. The deploy check and the publication both assume the program
serves HTTP on
$PORT. A queue worker with no listener will fail its health check. - A service you did not build. If it ships its own systemd unit and its own upgrade path, a reverse proxy route leaves both alone.
- A WordPress or PHP site. Those are sites, with their own tooling — see the WordPress section of the panel.