# Use cases

> The shapes an application takes on a CorePanel server — an API beside a site, a whole app on a subdomain, an SPA backend, a self-hosted service — with the configuration each one needs.

Source: https://www.corepanel.net/docs/applications/use-cases/
Last updated: 2026-08-17
Part of the CorePanel documentation — https://www.corepanel.net/docs

---

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 `/something` for 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](https://www.corepanel.net/docs/applications/configuration/#the-form-and-the-flags)
is a single table.

---

## An API beside an existing website

The classic case: a PHP or static site keeps serving, and one path goes to a program.

```bash
corepanel app create <account-id> api --domain example.com --path /api --port 8080 \
    --health /healthz -- ./server
```

| | |
|---|---|
| `https://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

The cleanest shape when the program *is* the site — a dashboard, an internal tool, an API
with its own hostname.

```bash
corepanel subdomain add <account-id> app example.com
corepanel app create <account-id> app --domain app.example.com --path / --port 3000 \
    --health /healthz -- ./server
```

The 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

Static build served by the web server, API calls handled by the program. This is faster
and cheaper than routing everything through the application.

```bash
# 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 it
corepanel app create <account-id> api --domain app.example.com --path /api --port 8080 \
    --health /healthz -- ./server
```

On 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

A Git server, a metrics dashboard, a bookmarking tool — something that writes files and
must keep them across upgrades.

```bash
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 web
```

Three settings matter here:

- **`$CP_APP_DATA`** is 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
  `./data` keeps 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](https://www.corepanel.net/docs/applications/configuration/).

> **Note**
>
> That data directory **is** part of the account backup, and comes back before the restored
> release is deployed — see
> [Running and troubleshooting](https://www.corepanel.net/docs/applications/operations/#applications-in-an-account-backup).
---

## 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.

```bash
corepanel app create <account-id> api    --domain example.com --path /api    --port 8080 -- ./api
corepanel app create <account-id> admin  --domain example.com --path /admin  --port 8081 -- ./admin
```

The 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

Small, stateless, and it must be up when a third party calls.

```bash
corepanel app create <account-id> hooks --domain example.com --path /hooks --port 8090 \
    --health /healthz --mem 128 --cpu 25 --tasks 32 -- ./receiver
```

Two 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](https://www.corepanel.net/docs/reverse-proxy/) rather than
disabling protection for the whole site.

---

## 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

- **A cron job.** Something that runs and exits is a
  [cron job](https://www.corepanel.net/docs/cli/#cron-jobs), 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](https://www.corepanel.net/docs/reverse-proxy/) leaves both alone.
- **A WordPress or PHP site.** Those are sites, with their own tooling — see the WordPress
  section of the panel.
