--- title: Runtime model description: The three places an app can run — this machine, your own server over SSH, or Openship Cloud — and how a build and deploy flow in each. --- import { Step, Steps } from 'fumadocs-ui/components/steps'; Openship can run your app in three different places. Think of your finished app as a meal: you can cook and serve it in **your own kitchen** (this machine), send the recipe to a **friend's kitchen** (your own server), or hand it to a **restaurant that cooks and serves it for you** (Openship Cloud). The food is the same — only the kitchen changes. You pick the kitchen when you deploy. Openship calls it the **deploy target**, and there are exactly three: | Target | Where it runs | How Openship reaches it | |---|---|---| | **Local** | The same machine Openship itself is running on | Directly — no network hop | | **Server** | Your own machine (a VPS, a box in a closet) | Over **SSH** (a secure remote connection) | | **Cloud** | Openship Cloud, run for you | Openship's hosted API | The target is a per-deploy choice. Deploy to your laptop today to try something, then redeploy the same project to a real server or the cloud later — nothing about the app has to change. ## Two ways to run it: sandboxed or direct For the two self-hosted targets (local and server), Openship also picks *how* the app runs on that machine. This is the **isolation mode**, and there are two: - **Sandboxed (Docker)** — your app runs inside a **container**: a sealed box with its own files and dependencies, kept apart from everything else on the machine. This is the default. - **Direct (bare)** — your app runs as a plain process on the machine, with no box around it. Lighter, but it shares the machine's environment. Sandboxed is the default everywhere because the isolation is worth it and the overhead is tiny. The one time Direct earns its keep is on a very small machine — under about **2 GB of RAM** — where the container engine would compete with your app for memory. Openship surfaces that as a note when you pick Direct, rather than silently switching for you. A Direct (bare) app is kept alive by the machine's own process supervisor — **systemd** on Linux, **nohup** on macOS — so it restarts if it crashes or the box reboots. A Sandboxed app is kept alive by Docker. ## Build first, then hand off Whatever the target, every deploy runs the **same two stages** in order. ### Build — turn source into something runnable The build pipeline always runs the same steps: **prepare → clone → install → build**. - **Prepare** gets the environment ready (installs the toolchain, transfers local files) — this is counted separately so first-time setup doesn't inflate your build time. - **Clone** fetches your code (skipped when you're deploying a local folder — the files are already there). - **Install** runs your install command (e.g. `npm install`). - **Build** runs your build command (e.g. `npm run build`) — skipped if the app doesn't need one. ### Deploy — start the new version and send traffic to it Once the build succeeds, Openship starts the new version, waits for it, points your web address at it, and then stops the old one. For Sandboxed and Cloud apps this happens **without downtime**: the old version keeps serving until the exact moment traffic is repointed, so a failure before that moment leaves the old one untouched. See [Zero-downtime and auto-revert](#zero-downtime-and-auto-revert) below. *Where the build happens* is separate from *where the app runs*. For a server (or cloud) deploy you can build on **This Machine** — the machine running Openship — and transfer only the finished output to the target, or build **on the deploy target** itself. Openship suggests one based on your framework — for most stacks that's **This Machine** — and you can change it per deploy or save a default under **Settings**. Building on This Machine is faster when it's the more powerful box and spares a small target VPS a heavy build; building on the target is best when the Openship machine has limited resources. In Cloud mode the build runs in the cloud workspace by default, though a self-hosted box can build locally and upload just the output. ## The three targets, up close **Local** runs your app on the very machine Openship is installed on — great for trying things out on the desktop app or a single box. - **Sandboxed** talks to the machine's Docker socket directly. - **Direct** runs the process on the machine and supervises it with systemd or nohup. Web addresses and HTTPS are handled by Openship's built-in router on that same machine (see [Routing and certificates](#routing-and-certificates)). **Server** runs your app on a machine you own, reached over **SSH** — the same secure connection you'd use from a terminal. You add the server once — on the **Servers** page, or right in the deploy flow with **Add your own server** — and Openship keeps a pooled connection to it, so repeat deploys reuse the same link instead of dialing in fresh each time. - **Sandboxed** drives the remote machine's Docker engine over an SSH tunnel. - **Direct** runs shell commands on the server over that same SSH connection. The router and certificate tooling are set up on *your* server, so traffic never detours through Openship. If you choose the Server target but haven't added a machine, the deploy screen offers **Add your own server** so you can connect one over SSH right there — and you can manage servers any time on the **Servers** page. See [Deploy to your own server](/docs/guides/custom-servers). **Cloud** hands the whole job to Openship Cloud — we build it, run it, route it, and handle HTTPS. Your app gets a free `your-app.opsh.io` address out of the box, and you can add a custom domain on top. A self-hosted Openship instance does **not** run the cloud pipeline itself; cloud projects are handled by Openship Cloud directly. The one exception is the "build here, run there" path: your own machine can build the app and upload the finished output to a cloud workspace to run. ## Routing and certificates Once your app is running, something has to send visitors to it and serve HTTPS. - **Self-hosted (local and server)** uses **OpenResty** (a build of the nginx web server) to route requests, and **certbot** to get free HTTPS certificates from **Let's Encrypt** and renew them automatically. - **Cloud** delegates routing, HTTPS, and static-file hosting to Openship Cloud's edge — there's nothing to install or renew. For attaching your own domain, verifying DNS, and managing certificates, see the [Domains API](/docs/api/domains) and [Add a custom domain](/docs/guides/custom-domains). ## Zero-downtime and auto-revert The deploy stage adapts to whether the new version can run **alongside** the old one: - **Sandboxed and Cloud apps can overlap.** Each version gets its own container or workspace, so Openship starts the new one, checks it, repoints traffic, and only *then* stops the old one. If anything fails before the switch, the old version was never touched — it keeps serving, and the failed deploy simply doesn't take. - **Direct apps can't overlap**, because the new process needs the same fixed port the old one is holding. So Openship stops the old process, starts the new one, and — if the new one fails — restarts the old one to bring you back. This path has a brief unavoidable gap while the port changes hands. Deploys to the same machine are serialized with a lock, so two projects deploying at once can't clobber each other's router config or shared state. ## What next?