Skip to content
Dashboard
Getting Started 6 min read

Your First Deployment

Deploy a project from a source archive or repository and verify the release in the dashboard.

Your First Deployment#

This guide takes you from local code on your machine to a recorded, verifiable NexHost release you can open in a browser. It follows the dashboard path (Dashboard → New Project) and deliberately selects the service type before source configuration so the platform applies the right runtime model.

You will finish with a project that has a release history, a build log, and — for public services — a hostname you can share.

When to use this guide#

Use this flow the first time you ship an app to NexHost, when you are validating a new framework stack, or when you want a repeatable baseline before moving a team’s repository into the platform. If you already ship daily to NexHost, the same steps apply but you can select a repository source instead of a ZIP.

Before you begin#

  • A NexHost workspace and permission to create a project.
  • An application that builds locally with the production command you intend to use remotely.
  • For a server-rendered app or API, a persistent server that binds to 0.0.0.0. NexHost supplies PORT=3000 as a compatibility default and discovers the listener automatically.

1. Prepare the project#

Keep generated dependency folders and local secrets out of a source archive. For a static project, either upload source with a build command or an output folder that already contains index.html. For a server-rendered application, upload the project source and use a Frontend App rather than trying to serve .next or another server build as static files.

A safe packaging command for a Node project:

bash
zip -r my-app.zip . -x "node_modules/*" ".git/*" ".env*"

What this does:

  • Includes source, configuration, and lockfiles so the platform can reproduce the install.
  • Excludes ephemeral or machine-specific state (node_modules, .git history, per-developer .env files) that bloat the archive and can hide the real build signal.

For Python, Ruby, Go, or other stacks, the same principle applies: keep the archive limited to what your build command needs to recreate the output. In every case, do not commit or pack secrets — set them as environment variables in the dashboard instead.

Tip

Run the same build command locally right before you archive. If it passes on your machine, the remote log is much easier to interpret when it does not — you already know the source was buildable in isolation.

2. Create the service#

  1. Open Dashboard → New Project.
  2. Select the service type that matches the application — for example Frontend App for a Next.js app that uses server rendering, or Static Site for a Vite site you export as dist.
  3. Choose the source method offered by that service. For this walkthrough, pick ZIP upload or local folder and attach the archive you just created. Other flows include NexHost Git, GitHub, GitLab, a public Git URL, or an existing container image when the dashboard offers it.
  4. Select a stack when it matches your framework, then review the proposed commands. A stack is a starter preset; you remain responsible for the final values.

For a Next.js application that uses server rendering, choose Frontend App, use the normal build command (npm run build), and set the start command to the application’s production start command (typically npm run start, which often resolves to next start -p $PORT). Do not use a build command as the start command — the runtime needs a long-lived server after the build completes.

Double-check the Root directory when it is shown. It should point at the directory that contains the build manifest (package.json, requirements.txt, etc.). A repository with a frontend in apps/web and a backend in apps/api will fail if the root is left at the repository root.

3. Configure runtime services#

Runtime services need a process that accepts connections on the container interface. NexHost supplies PORT=3000 as a compatibility default, discovers the TCP listener actually opened by the process, and assigns its own isolated ingress port. The host binding is the contract, not a user-entered port number or HTTP endpoint.

For Node applications, the usual shape is:

ts
const port = Number(process.env.PORT);
server.listen(port, "0.0.0.0");

For Express, Next.js with a custom server, Koa, or Fastify, the same idea applies:

js
const port = Number(process.env.PORT);
app.listen(port, "0.0.0.0", () => {
  console.log(`Listening on ${port}`);
});

For Flask or FastAPI behind gunicorn/uvicorn, pass the value through the start command:

bash
# Flask
gunicorn app:app --bind 0.0.0.0:$PORT
# FastAPI
uvicorn app:app --host 0.0.0.0 --port $PORT

NexHost does not require you to add or configure a health URL. It waits for a reachable TCP listener during startup, then routes the final container through a unique internal Docker port. You may still provide a /health endpoint for your own clients or monitoring, but it is not part of the deployment contract.

4. Deploy and verify#

Start the deployment from the review screen. The deployment detail page shows source preparation, dependencies, build, and release status in order. Each row has a timestamp and output so you can distinguish a build failure from a runtime one.

Expected outcome for a successful release:

  • The deployment status becomes successful.
  • For public services, the dashboard shows a generated hostname for that service.
  • Opening the hostname loads the application page once NexHost has detected and routed its listener.

If the deployment stops during startup readiness, confirm all of the following before changing anything else:

  • The selected service is Frontend App or Web Service, not a Static Site. A static service never starts a process, so it cannot satisfy runtime startup readiness.
  • The start command starts a persistent process (for example npm run start / next start -p $PORT for Node, gunicorn … --bind 0.0.0.0:$PORT for Python). A bare build command (npm run build) starts nothing and the release will always time out.
  • The process binds to 0.0.0.0, not only to 127.0.0.1. It may use process.env.PORT, which defaults to 3000, or its normal fixed internal port. Each container has its own network namespace, so two services can safely use 3000.
  • The process reaches its server listen call after required initialization. A database connection that never resolves, or a start command that launches only a build, prevents NexHost from discovering the listener.
Info

Change one deployment input at a time. For a startup failure, begin with the start command and application binding; this makes the next deployment log much easier to compare.

See Deployment Troubleshooting for a guided, symptom-by-symptom diagnosis, or Logs for how to read each stage’s output without sharing secrets.

What comes next#

  • Add a persistent database with Postgres and wire the connection string as an environment variable on the application service.
  • Attach a real hostname after the first successful public release: Custom Domains.
  • Move from archive uploads to hosted source: NexHost Git and the Next CLI.
  • Understand pricing and workspace scope: Workspaces and Access and Billing.