# Deploy a Next.js app from GitHub to a London server

> How to deploy a Next.js app from GitHub to a server in London: what Next.js needs to run outside Vercel, environment variables, standalone output, previews and custom domains.

Source: https://wharfcloud.co.uk/guides/deploy-nextjs-from-github-to-a-london-server · Last updated 21 October 2026 · WharfCloud

Published 21 October 2026. Reading time about 8 minutes.

## Short answer

Next.js does not need a special platform. Its documentation says it can run on any provider that supports Node.js or Docker, and both options support every Next.js feature. To deploy from GitHub to a London server you need a repository with `build` and `start` scripts, Node.js 20.9 or later, your environment variables set before the build (anything starting with `NEXT_PUBLIC_` is fixed into the browser code at build time), and a reverse proxy in front of the Next.js server, which the Next.js team recommends when self-hosting. You can wire that up yourself on a Linux server, or use a platform that builds every push for you.

## Three ways Next.js can run

The Next.js deployment documentation lists a Node.js server, a Docker container and a static export, plus adapters for specific platforms. For a London server, the first two are the ones that matter:

Table: Next.js deployment options, from the Next.js documentation

| Option | Feature support | What it means for you |
| --- | --- | --- |
| Node.js server (`next build`, then `next start`) | All features | Any server with Node.js can run it. The simplest route. |
| Docker container | All features | The same, packaged as an image. Easier to roll back and to run several apps on one server. |
| Static export (`output: 'export'`) | Limited | Plain HTML, CSS and JavaScript. No features that need a server, such as cookies, Server Actions, Proxy, Incremental Static Regeneration or Image Optimization with the default loader. |

If your app reads cookies, uses Server Actions or Proxy, or relies on `next/image` with the default loader, you need one of the first two.

## Get the repository ready

1. **Check the scripts.** Your `package.json` needs a `build` script (`next build`) and a `start` script (`next start`). Projects made with `create-next-app` have both.
2. **Pin the Node.js version.** Next.js 16 needs Node.js 20.9 or later. Set `engines.node` in `package.json` (or add an `.nvmrc`) so a build server that reads it uses the same major version as your laptop.
3. **Commit the lock file.** Commit `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock` or `bun.lock`, so the server installs exactly the versions you tested.
4. **Keep secrets out of Git.** The default `create-next-app` template adds `.env` files to `.gitignore`, and the Next.js documentation says you almost never want to commit them. Set the values on the server or platform instead.
5. **Build once locally.** Run the production build on your own machine. If `next build` fails there, it will fail on the server too, and the error is easier to read locally.

## Environment variables: build time or run time

This is the part that catches most people out when they leave a platform that hides it.

- **By default a variable is only available on the server.** Your database URL or API key stays out of the browser unless you expose it.
- **`NEXT_PUBLIC_` variables are inlined at build time.** Next.js replaces them with their value in the JavaScript sent to the browser during `next build`. After the build, changing the variable does nothing: you have to build again. Treat anything with this prefix as public.
- **Server-side values can change at run time.** The Next.js self-hosting guide shows reading `process.env` during dynamic rendering, so one build can run with different values. That is how one image can move from preview to production.

> **Previews** Give pull request previews their own values, such as a test database and test payment keys. A preview runs code that has not been reviewed yet.

## Optional: standalone output for smaller images

Setting `output: 'standalone'` in `next.config.js` makes `next build` create a `.next/standalone` folder with only the files needed in production, including the parts of `node_modules` your app uses, and a small `server.js` you can run instead of `next start`. Docker images built this way are much smaller.

- The standalone server does not copy `public` or `.next/static` by default. Copy them into `.next/standalone/public` and `.next/standalone/.next/static`, and `server.js` serves them.
- Set `PORT` and `HOSTNAME` to choose where it listens, for example `PORT=8080 HOSTNAME=0.0.0.0 node server.js`.
- You do not need standalone output to deploy. `next start` supports every feature too; standalone is about image size.

## What the server around Next.js has to do

Next.js is only the app. Someone still has to look after what sits around it:

Table: Jobs around a self-hosted Next.js app

| Job | Why it matters |
| --- | --- |
| A reverse proxy in front | The Next.js self-hosting guide recommends one (it names nginx) rather than exposing the Next.js server directly, to deal with malformed requests, slow connection attacks, payload size limits and rate limiting. |
| HTTPS certificates | Issued for each hostname and renewed before they expire. |
| No response buffering | Streaming and Suspense need the proxy to pass responses through without buffering them; the guide shows the `X-Accel-Buffering: no` header for nginx. |
| Persistent disk for the cache | By default Next.js caches pages and data on the local disk of each server, which works automatically for one `next start` instance with a persistent disk. Several instances need a shared cache handler. |
| Restarts and graceful shutdown | On `SIGTERM` or `SIGINT`, Next.js finishes in-flight requests and pending `after()` work; the documentation suggests allowing 10 to 30 seconds. |
| Operating system updates | The server underneath needs security updates like any other. |

Doing all of this by hand on a Linux server is a reasonable weekend project. Doing it again for every push and every pull request is where a deployment platform earns its keep.

## Connecting GitHub safely

Most deployment platforms connect through a GitHub App. When you install one, GitHub shows the permissions it asks for, and if it needs repository access you choose **All repositories** or **Only select repositories**. Choose only the repositories you want to deploy. GitHub notes that an app always has at least read-only access to public repositories.

Read the permission list before you click Install. A deployment tool needs to read code; it should not need to write to it. For comparison, this is everything WharfCloud Deploy asks for:

Table: Permissions requested by the WharfCloud Deploy GitHub App

| Permission | Access | Why |
| --- | --- | --- |
| Repository contents | Read | To read your code and build it. Read only: we never push commits. |
| Metadata | Read | To list the repositories you chose and their branches. |
| Pull requests | Read | To know when a pull request opens, updates or closes, for previews. |
| Deployments | Read and write | To show each deployment and its URL on GitHub. |
| Commit statuses | Read and write | To mark each commit as building, ready or failed. |
| Members (organisation) | Read | To check that the person connecting an organisation is one of its admins. Never used to build or deploy. |

## Doing it with WharfCloud Deploy

[WharfCloud Deploy](https://wharfcloud.co.uk/deploy) runs your projects on your own App Server in London and handles the proxy, certificates, builds and rollbacks above. The steps:

1. **Order an App Server.** Pick a size and pay by card. It is not instant: a person checks every first order, then we set up your App Server by hand, ready within 1 working day of approval.
2. **Connect GitHub.** Install the app and choose only the repositories you want to deploy.
3. **Import the repository.** We detect Next.js and suggest `next build` and `next start`; change them if you need to, and set the root folder for a monorepo.
4. **Add environment variables.** Set production and preview values separately and mark which are needed at build time, such as `NEXT_PUBLIC_` variables. Values are encrypted so only your App Server can read them.
5. **Deploy.** The first deploy takes minutes. Your app is live at an address like `shop.northwind.apps.wharfcloud.co.uk` with HTTPS.
6. **Keep pushing.** Each push to the production branch deploys again. Each pull request gets a preview such as `pr-12-shop.northwind.apps.wharfcloud.co.uk`, stopped after 7 days without a push and removed when the pull request closes.
7. **Add your domain.** Create the TXT record shown in the panel (for example `_wharfcloud-verify.www.example.co.uk`), point the domain at your App Server, and the certificate follows automatically.

WharfCloud Deploy does not include a managed database, and our support covers the platform rather than your application code. If you need both looked after, a [Managed Linux Server](https://wharfcloud.co.uk/managed-servers/linux) may suit you better.

## Frequently asked questions

### Do I need Vercel to run Next.js?

No. The Next.js documentation says Next.js can be deployed to any provider that supports Node.js or Docker containers, and both options support all Next.js features.

### Why did my NEXT_PUBLIC_ variable not change after I updated it?

Because Next.js inlines NEXT_PUBLIC_ values into the browser code during the build. After the build the value is fixed; change it and build again.

### Do I need output: 'standalone'?

No. It makes a smaller set of files for production, which helps with Docker images, but next start supports every feature without it.

### Which Node.js version does Next.js 16 need?

Node.js 20.9 or later, according to the Next.js installation documentation. Pin it in package.json so your build server and laptop match.

### Can I run several Next.js apps on one server?

Yes, as long as each listens on its own port behind the reverse proxy and the server has the memory for them. On WharfCloud Deploy each project runs in its own container on your App Server, and you can add projects until the server's resources are used.

### Is a London server faster for UK visitors?

Usually closer means less network delay, but the size of the difference depends on your visitors and your app, so measure it rather than assume it. Hosting in London also keeps your app and its data in the UK.

## Sources

- [Next.js: Deploying (deployment options and feature support)](https://nextjs.org/docs/app/getting-started/deploying)
- [Next.js: How to self-host your Next.js application](https://nextjs.org/docs/app/guides/self-hosting)
- [Next.js: output (standalone)](https://nextjs.org/docs/app/api-reference/config/next-config-js/output)
- [Next.js: How to use environment variables](https://nextjs.org/docs/app/guides/environment-variables)
- [Next.js: Static exports (unsupported features)](https://nextjs.org/docs/app/guides/static-exports)
- [Next.js: Installation (system requirements)](https://nextjs.org/docs/app/getting-started/installation)
- [GitHub Docs: Installing a GitHub App from a third party](https://docs.github.com/en/apps/using-github-apps/installing-a-github-app-from-a-third-party)

---

WharfCloud is a trading name of Sunucu Internet Services Consultancy Ltd, registered in England and Wales, company number 12963678. Not VAT registered.
Support: engineers Monday to Friday, 08:00 to 18:00 UK time. Critical incidents: A person responds to critical incidents within 1 hour (Every day, 07:00 to 23:00 UK time). Automated monitoring and automated recovery overnight and at weekends.
Contact: hello@wharfcloud.co.uk · https://wharfcloud.co.uk/contact