Skip to content

Deploy an app from a Git repository

Updated November 2, 20268 min read

Create an instance from a Git repository: Nextify clones it at the first boot, builds it and runs it as a service. Use a read-only deploy key for private repositories, pass settings and secrets as environment variables, read the deploy's output, and redeploy after each push.

You can create an instance straight from a Git repository. At its first boot, Nextify clones the repository, builds it and runs your app as a service that restarts if it stops. When you push new code, Redeploy pulls it, builds it and restarts the app. Public repositories need only their URL; private ones use a deploy key that Nextify creates for you.

This article covers:

  1. Deploying a public repository
  2. Private repositories and deploy keys
  3. Runtime, build and start commands
  4. The port and the firewall
  5. Environment variables and secrets
  6. The deploy's output, and when a deploy fails
  7. Redeploying
  8. Doing it through the API

1. Deploy a public repository

  1. In the portal, open Instances → Create instance and choose the region, plan and SSH keys as usual. Choose an Ubuntu or Debian image: the deploy installs what your app needs with apt.
  2. Open 6. Startup script, labels and environment and choose Deploy from Git.
  3. Enter the Repository URL, for example https://github.com/your-org/your-app.git. Leave the other fields as they are to start with.
  4. Click Create instance.

A deploy from Git replaces the startup script: an instance has one or the other. An instance restored from a snapshot does neither.

Use the https:// URL exactly as your Git host shows it, without a user name or token in it. For a private repository, use its SSH URL and a deploy key instead (section 2).

2. Private repositories and deploy keys

A deploy key is an SSH key that gives read access to one repository. Nextify creates the key pair, keeps the private half encrypted and gives it only to the instances that use the key. You add the public half to your repository.

  1. Open Account → Deploy keys, enter a name (for example the repository's name) and click Create deploy key. You can also click Create a deploy key in the Deploy from Git form, without leaving it.
  2. Copy the public key that is shown. It starts with ssh-ed25519.
  3. Add it to the repository as a read-only deploy key:
    • GitHub: the repository's Settings → Deploy keys → Add deploy key. Paste the key, give it a title and leave Allow write access unticked.
    • GitLab: the project's Settings → Repository → Deploy keys → Add new key. Paste the key, give it a title and leave Grant write permissions to this key unticked.
  4. In the Deploy from Git form, enter the repository's SSH URL, for example git@github.com:your-org/your-app.git, and choose the key under Deploy key.

Good to know:

  • An SSH URL always needs a deploy key, and a deploy key only works with an SSH URL. The form tells you if they do not match, and offers the SSH form of an https URL.
  • GitHub accepts each deploy key on one repository only. Create one key per repository.
  • The page shows each key's fingerprint (SHA256:...), the same one GitHub and GitLab show, so you can tell which key is which.
  • Deleting a key on Account → Deploy keys stops new instances from using it. Instances that already have it keep their copy and can still redeploy: remove the key from the repository to cut them off.
  • An account can hold up to 50 deploy keys.

3. Runtime, build and start commands

Runtime is Auto by default: Nextify looks at the repository and picks one:

The repository hasRuntimeBuild, when left emptyStart, when left empty
package.jsonNode.jsnpm ci (or npm install), then npm run build if there is onenpm start
requirements.txt or pyproject.tomlPythonpip install into a virtualenvnone: give one
go.modGogo buildthe built program
GemfileRubybundle installbundle exec rackup on $PORT
composer.json or index.phpPHPnonePHP's built-in server on $PORT, from public/ if there is one
anything elseStaticnonea small web server for dist/, build/ or public/ (else the whole repository)
  • A Procfile with a web: line sets the start command, unless you enter one.
  • Build command and Start command are one line each. To run several commands, join them with &&, or put them in a script in your repository.
  • Both run as the user app in the checkout (/opt/app/src), with your environment variables and PORT set. A Python app gets its own virtualenv, already on the PATH.
  • Python has no default start command: enter one, for example gunicorn app:app --bind 0.0.0.0:$PORT, or add a Procfile.
  • The runtime comes from the image's own packages, for example the Node.js version that Ubuntu ships. If your app needs another version, install it in a startup script on a plain instance instead.
  • Choose a runtime yourself when the detection picks the wrong one, for example a static site that has a package.json for its tooling.

4. The port and the firewall

Your app must listen on the port in the PORT environment variable, on all addresses (0.0.0.0). The Port field sets it: 8080 unless you change it. Port 22 is SSH and cannot be used.

Nextify opens that port to the internet for you: the security group app-tcp-<port> (for example app-tcp-8080), which allows inbound TCP on that port from anywhere, is created the first time it is needed and added to the instance. The instance's page links to http://<public IP>:<port>/.

To serve your app on port 80 or 443 with a domain and a certificate, put a load balancer in front of it.

5. Environment variables and secrets

Add settings under Environment & secrets, as for any instance: plain variables, and secrets for passwords and API keys, which Nextify stores encrypted and never shows again. The build and the app get them all in their environment. Keep secrets out of the repository.

When you change a variable later on the instance's Setup & environment tab, redeploy (section 7) so the app restarts with the new value.

See Startup scripts and secrets for how variables and secrets work.

6. The deploy's output, and when a deploy fails

On the instance's page, open Setup & environment. The App from Git card shows the repository, branch or tag, runtime, port and deploy key. Below it, the Setup log shows the deploy's status and output: the first boot's, or the last redeploy's. It is read from the server and follows the deploy while it runs.

A deploy ends when the app has started and is still running a few seconds later. If it fails, the end of the setup log says why. Common causes:

  • The clone failed: the URL is wrong, the repository is private and has no deploy key, or the deploy key was not added to the repository (or not to this one).
  • The build failed: read the build's error in the log. Run the same command on your own computer first.
  • The app did not stay up: the log ends with the app's last lines of output. Often the app listens on another port than PORT, or only on 127.0.0.1, or a setting is missing.
  • No start command: add one, or a Procfile with a web: line.

On the server itself: the app runs as the service nextify-app (journalctl -u nextify-app shows its output), the checkout is in /opt/app/src, and every deploy's output is in /var/log/nextify-app-deploy.log.

7. Redeploy

After you push to the branch or tag, click Redeploy on the App from Git card. Nextify pulls the latest commit, builds it and restarts the app. The card shows the progress, and the setup log shows the new deploy's output when it ends.

  • The instance must be running. One deploy runs at a time.
  • If the build fails, the app is not restarted.
  • The repository, branch and commands are set when the instance is created. To change them, create a new instance.

8. Through the API

Create a deploy key with POST /v1/deploy-keys, then create the instance with source instead of user_data:

curl -sS -X POST https://api.nextifynow.com/v1/instances \
  -H "Authorization: Bearer $NEXTIFY_TOKEN" -H "Content-Type: application/json" \
  -d '{"name": "shop-1", "machine_type": "sm1.s1-1", "region": "us-west-1", "image": "ubuntu-24.04",
       "source": {"git": {"url": "git@github.com:your-org/shop.git", "ref": "main", "port": 3000,
                          "deploy_key_id": "<id from POST /v1/deploy-keys>"}}}'

POST /v1/instances/{id}/redeploy redeploys and answers a job_id to follow. A webhook endpoint can get instance.app_deployed and instance.app_deploy_failed after every deploy, so you can redeploy from your CI pipeline and hear back. The API documentation has a complete example.

Good to know

  • The first deploy runs at the first boot, so the app is up a few minutes after the instance is.
  • The setup log keeps the last deploy's output only. The file /var/log/nextify-app-deploy.log on the server keeps them all.
  • Deploying from Git sets up one app per instance. For several instances behind one address, create them from the same repository and add them to a load balancer.