> ## Documentation Index
> Fetch the complete documentation index at: https://docs.instapods.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Add a "Deploy to InstaPods" button

> Let anyone deploy your open-source project to a real server in one click. Add the badge, test it, and verify the deploy end to end.

If you maintain an open-source web project, a **Deploy to InstaPods** button lets anyone run it on a real Linux server -- with HTTPS and auto-deploy on every push -- in one click. No Dockerfile, no CI, no setup.

[![Deploy to InstaPods](https://instapods.com/deploy-button.svg)](https://app.instapods.com/dashboard/pods/create?repo=https://github.com/OWNER/REPO)

It works for **Node.js, PHP, Python, and static** projects. When someone clicks the button, InstaPods reads your repo's root files to detect the stack, creates a pod, clones the repo, installs dependencies, builds, and starts your app behind HTTPS.

## Add the button

The badge is a Markdown image wrapped in a link. Paste this into your `README.md` and replace `OWNER/REPO` with your repository:

```markdown theme={null}
[![Deploy to InstaPods](https://instapods.com/deploy-button.svg)](https://app.instapods.com/dashboard/pods/create?repo=https://github.com/OWNER/REPO)
```

> [!TIP]
>
> Don't want to hand-edit it? Open the builder at [instapods.com/deploy/github](https://instapods.com/deploy/github), paste your repo URL, and copy the generated snippet.

### Link options

The button is just a link to the create page with query parameters:

| Parameter | Required | Description |
| - | - | - |
| `repo` | Yes | Your GitHub repository URL, e.g. `https://github.com/OWNER/REPO` |
| `branch` | No | Deploy a specific branch (defaults to the repo's default branch) |
| `ref` | No | Your referral code, if you have one. Signups that arrive through your button are credited to it. |

```markdown theme={null}
<!-- deploy a specific branch -->
[![Deploy to InstaPods](https://instapods.com/deploy-button.svg)](https://app.instapods.com/dashboard/pods/create?repo=https://github.com/OWNER/REPO&branch=production)
```

GitHub URLs don't need URL-encoding here -- they contain no `&`, `?`, or `#`.

## Test it

**1. Open the deploy link**

Click your badge (or open the URL directly). You land in the create wizard with **From GitHub** preselected and your repo pre-filled. If you're not signed in, you'll sign in or sign up first, then continue.

**2. Check detection**

The wizard inspects your repo and shows the detected stack, e.g. **Detected nodejs (package.json)**, plus a suggested plan. If it can't detect a supported stack, pick a preset from the dropdown to continue.

**3. Deploy**

Confirm the plan and pod name, then deploy. You're taken to the pod's **Git** tab, where the first build streams live.

Prefer the terminal? The [CLI](/cli/deploy) does the same thing:

```bash theme={null}
instapods deploy --repo https://github.com/OWNER/REPO
# detects the stack, creates the pod, and follows the first build to completion
```

## Verify the deploy end to end

Use this checklist to confirm everything works -- it's the exact path the button triggers.

**1. Stack detected correctly**

On the create wizard (or in the CLI output) confirm the detected preset matches your project: `nodejs`, `php`, `python`, or `static`. If it's wrong, your manifest may not be at the repo root -- see [Make detection reliable](#make-detection-reliable).

**2. Pod reaches Running**

The pod goes `creating` -> `running` in about 10-30 seconds. The Git tab opens automatically and the first deployment appears.

**3. Build log shows clone -> install -> build -> start**

Open the deployment on the Git tab and read the build log. A successful Python deploy ends like this:

```text theme={null}
=== Cloning/pulling repository ===
Cloning into '/home/instapod/app'...

=== Installing dependencies ===
Successfully installed fastapi-0.x uvicorn-0.x ...

=== Restarting services ===
Set start command (AI): source ~/app/venv/bin/activate && uvicorn app:app --host 0.0.0.0 --port 8000

=== Health check ===
Service app: active

=== Deploy successful ===
```

Node shows `npm install` + `npm run build`; PHP shows `composer install`; static skips install. If the build fails, the error and the log tail are right there -- fix it in your repo and push, or hit **Redeploy**.

**4. App serves over HTTPS**

Visit the pod's URL (shown on the dashboard), e.g. `https://your-app.nbg1-1.instapods.app`, or check from a terminal:

```bash theme={null}
curl -I https://your-app.nbg1-1.instapods.app
# HTTP/2 200
```

**5. Push redeploys automatically**

Push a commit to the tracked branch. A new deployment starts on its own (auto-deploy is on by default) and appears in the Git tab with its own build log.

**6. Rollback works**

From the Git tab's deployment history, roll back to any previous commit in one click (or `instapods git rollback <pod>`). The previous build is restored.

## Supported stacks

| Stack | Detected by | What InstaPods runs |
| - | - | - |
| **Node.js** | `package.json` (or `tsconfig.json`, `next.config.*`, a lockfile) | `npm install`, `npm run build` if a `build` script exists, then your `start` script |
| **PHP** | `composer.json` (or `*.php`, `artisan`) | `composer install`, served by nginx + PHP-FPM 8.3 (Laravel `public/` detected) |
| **Python** | `requirements.txt` / `pyproject.toml` | `pip install` in a virtualenv; gunicorn/uvicorn auto-detected for WSGI/ASGI apps |
| **Static** | `index.html` | Served straight from nginx |

> [!NOTE]
>
> Dockerfile-based projects and other languages (Rust, Java, Ruby) aren't supported yet -- the button currently builds Node, PHP, Python, Go, and static projects.

## Databases, secrets and migrations

You don't add a config file for any of this. When someone clicks your button, InstaPods reads what your repo already ships -- `.env.example`, `docker-compose.yml`, your ORM config, the README -- and the create screen shows what it worked out:

* **Database.** If your app needs PostgreSQL, MySQL or Redis, it's installed in the same pod before dependencies, and `DATABASE_URL` / `REDIS_URL` are written into the app's env. Apps that need one start on the **Build** plan or higher.
* **Secrets.** Anything your `.env.example` says to generate (`openssl rand -base64 32` -- session keys, `AUTH_SECRET`) is generated per pod and kept stable across deploys, so a redeploy never signs your users out.
* **What only a person can give.** OAuth client ids, third-party API keys: these are the only fields the deploying user is asked to fill, each with the description from your `.env.example`.
* **Migrations.** A migration command (`prisma migrate deploy`, `python manage.py migrate`, `php artisan migrate --force`) is detected and run on every deploy, after the build. A failed migration fails the deploy rather than starting your app against a schema that never applied.

The best thing you can do for your button is keep `.env.example` honest: every variable your app reads, with a one-line comment saying what it is and whether it's optional. It is effectively your deploy manifest -- you just don't have to write a second one.

> [!NOTE]
>
> Apps that need **several always-on processes** (a web app plus a separate API server or worker) aren't supported yet -- a pod runs one process. Single-process apps with a database are the sweet spot.

## Make detection reliable

A few things make the one-click experience smooth for your users:

* **Keep your manifest at the repo root.** Detection reads root-level files only -- `package.json`, `composer.json`, `requirements.txt`/`pyproject.toml`, or `index.html`.
* **Provide a start command.** Node: a `start` (or `server`/`serve`) script in `package.json`. Python: a gunicorn/uvicorn entry such as `app:app`.
* **Listen on the right host and port.** InstaPods sets `HOST=0.0.0.0` and `PORT` (3000 for Node, 8000 for Python). Read those env vars, or bind to that port directly, so the app is reachable.
* **Commit a lockfile** (`package-lock.json`, `composer.lock`, etc.) for reproducible installs.

## Troubleshooting

> **The build failed**
>
> Open the failed deployment on the pod's **Git** tab -- the error message and the tail of the build log are shown. Common causes: a dependency that needs a system package, a missing build/start script, or the app not listening on the expected port. Fix it in your repo and push (or hit **Redeploy**).

> **It detected the wrong stack (or none)**
>
> Pick a preset in the wizard before deploying, or pass `--preset` to the CLI. This usually means the manifest isn't at the repo root.

> **It's a private repository**
>
> Connect your GitHub account in the dashboard first (Settings -> GitHub). Once the InstaPods GitHub App can see the repo, the button deploys it like any other. The public button targets public repos.

> **The app deploys but the URL doesn't respond**
>
> Make sure your app listens on `0.0.0.0` and the port InstaPods sets (`PORT` env var: 3000 for Node, 8000 for Python). Apps that hardcode `localhost` or a different port won't be reachable through the proxy.

## Maintaining a popular project?

If your project gets real traffic, [get in touch](https://instapods.com/support) -- we partner with open-source maintainers (an "Official Cloud Hosting Partner" listing and revenue share) and are happy to help tune the deploy experience for your stack.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.