---
title: "How to Deploy Astro on Your VPS with EasyPanel"
description: "Learn how to deploy an Astro static site on your VPS using EasyPanel. Covers project setup, GitHub integration, Nixpacks build, and custom domain configuration."
date: 2026-07-10
categories: ["web-development"]
tags: ["easypanel","astro","self-hosted"]
---

import Button from "../../components/widgets/Button.astro";
import { Picture } from "astro:assets";
import YouTubeEmbed from "../../components/widgets/YouTubeEmbed.astro";
import imag1 from "../../assets/images/23/11/easypanel-general.png";
import imag2 from "../../assets/images/23/11/ep-domains.png";

Astro is a modern web framework built for content-driven sites. It renders pages to static HTML by default, which means fast load times and good SEO out of the box. You can use React, Svelte, Vue, or just Astro's own template syntax — and mix them in the same project.

This tutorial walks through deploying an Astro static site on your own VPS using [EasyPanel](https://easypanel.io/). EasyPanel is a self-hosted PaaS that sits on top of Docker and gives you a web UI to deploy apps, manage databases, and handle SSL. If you haven't installed it yet, start here: [Easypanel.io: A Modern Hosting Panel for Applications and Databases](https://www.bitdoze.com/easypanel-modern-server-control-panel/).

**Related articles:**

- [How To Deploy Static Website Astro.JS on VPS Servers](https://www.bitdoze.com/deploy-astro-on-vps/)
- [Coolify Install A Free Heroku and Netlify Self-Hosted Alternative](https://www.bitdoze.com/coolify-install-heroku-alternative/)
- [How To Deploy An Astro.JS Blog On Cloudflare](https://www.bitdoze.com/deploy-astrojs-cloudflare/)
- [How To Monitor Server and Docker Resources](https://www.bitdoze.com/sever-monitoring/)

## Prerequisites

Before you start, you need:

- A VPS with EasyPanel installed (2 GB RAM minimum, Ubuntu 20.04+)
- A GitHub account
- Node.js v22.12.0+ on your local machine (required by Astro 5+)
- A domain pointed to your VPS IP (for production deployment)

If you don't have a VPS yet, Hetzner is a solid, affordable option:

<Button link="https://go.bitdoze.com/hetzner" text="Hetzner €20 free credit" />
<Button link="https://go.bitdoze.com/hostinger-vps" text="Hostinger VPS" />

## Video walkthrough

<YouTubeEmbed
  url="https://www.youtube.com/embed/l-yohC7xD38"
  label="Deploy Astro on Your VPS with EasyPanel"
/>

## Step 1: Create a GitHub repository

Create a new repo on GitHub. You can use a public or private repo — if private, you'll need to add a GitHub token in EasyPanel under **Settings > GitHub**.

If you need help setting up SSH keys for GitHub, see [Link GitHub with A SSH Key to MacOS or Linux](https://www.bitdoze.com/link-github-with-ssh-maco-linux/).

Clone the empty repo locally:

```sh
git clone git@github.com:yourusername/your-astro-site.git
cd your-astro-site
```

## Step 2: Initialize Astro

Run the Astro CLI wizard inside your repo directory:

```sh
npm create astro@latest
```

When prompted:
- **Project name:** use `.` to scaffold in the current directory
- **Template:** choose a starter template or "Empty" for a blank project
- **Install dependencies:** yes
- **Initialize git repo:** no (you already have one)

This creates the standard Astro project structure with `src/`, `public/`, and `astro.config.mjs`.

## Step 3: Configure for static hosting

Astro outputs static HTML by default (`output: 'static'`), which is what we want. But EasyPanel needs a way to serve the built files. There are two approaches.

### Option A: Use `serve` (recommended for Nixpacks)

Install the `serve` package — a lightweight static file server:

```sh
npm install serve
```

Update your `package.json` scripts so EasyPanel knows how to start the app:

```json
{
  "scripts": {
    "dev": "astro dev",
    "start": "serve dist/",
    "build": "astro build",
    "preview": "astro preview"
  }
}
```

The `start` script tells EasyPanel to serve the `dist/` directory after the build completes.

### Option B: Use a custom Dockerfile

If you prefer more control, create a `Dockerfile` in your project root:

```dockerfile
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM joseluisq/static-web-server:2-alpine
COPY --from=build /app/dist /public
ENV SERVER_PORT=80
```

When deploying in EasyPanel, choose "Dockerfile" as the build method instead of Nixpacks.

## Step 4: Verify the build locally

Run these commands before pushing to make sure everything works:

```sh
npm run build
npm run start
```

The build should complete without errors, and `serve` should start on port 3000. Open `http://localhost:3000` to verify.

If you see issues, fix them now — debugging build failures is much easier locally than in EasyPanel's deployment logs.

## Step 5: Push to GitHub

```sh
git add .
git commit -m "initial astro site"
git push
```

## Step 6: Deploy in EasyPanel

### Create a project and service

1. In EasyPanel, click **Create Project**
2. Inside the project, click **Service** and select **App**
3. Connect your GitHub repository

### Configure the build

In the **Source** section, set the repository owner and name:

<Picture
  src={imag1}
  alt="EasyPanel GitHub source configuration"
/>

In the **Build** section:
- Choose **Nixpacks** as the builder
- Nixpacks will auto-detect Astro and run `npm install` then `npm run build`
- The start command will use your `package.json` `start` script (`serve dist/`)

Click **Save**, then **Deploy**. Watch the deployment logs to confirm the build succeeds.

### Enable auto-deploy

Auto-deploy triggers a new build whenever you push to your repo. Set it up in one of two ways:

- **Auto Deploy button:** If you're using a GitHub token, click the **Auto Deploy** button in your project settings. This creates a webhook on your repo automatically.
- **Manual webhook:** Copy the webhook URL from **General** in your project settings and add it to your GitHub repo under **Settings > Webhooks**.

### Add your domain

<Picture
  src={imag2}
  alt="EasyPanel domain configuration"
/>

1. Create an **A record** in your DNS provider pointing your domain (or subdomain) to your VPS IP
2. In EasyPanel, go to **Domains** in your project
3. Add your domain — EasyPanel will automatically provision a Let's Encrypt SSL certificate

## Project structure tips

For a typical Astro blog or documentation site, your structure will look like this:

```
your-astro-site/
├── src/
│   ├── pages/          # Route-based pages
│   ├── content/        # Markdown/MDX content
│   ├── components/     # Reusable UI components
│   └── layouts/        # Page layouts
├── public/             # Static assets (images, fonts)
├── astro.config.mjs    # Astro configuration
├── package.json
└── tsconfig.json
```

Add any integrations you need with:

```sh
npx astro add mdx sitemap
```

This installs and configures the MDX and sitemap integrations automatically.

## Troubleshooting

**Build fails in EasyPanel but works locally.** Check the Node.js version. EasyPanel's Nixpacks may use a different version than your local machine. You can specify the version in your `package.json`:

```json
{
  "engines": {
    "node": ">=22.12.0"
  }
}
```

**Site shows "Cannot GET /".** The `start` script is missing or wrong. Make sure `"start": "serve dist/"` is in your `package.json` scripts.

**Deployments don't trigger on push.** Verify the webhook is set up correctly. In your GitHub repo, go to **Settings > Webhooks** and check that the payload URL matches your EasyPanel project's webhook URL. The content type should be `application/json`.

**Large Docker images.** Nixpacks can produce large images. If disk space is a concern, use the Dockerfile approach (Option B above) with a multi-stage build for smaller images.

**External content not rebuilding.** If your Astro site pulls content from a CMS (Sanity, Contentful, etc.), the webhook won't detect changes in external data. You'll need to manually trigger a **Force Rebuild** in EasyPanel, or set up a `CACHEBUST` environment variable that you increment before each rebuild.

## Conclusions

Deploying Astro on EasyPanel is straightforward once you have the `serve` package configured. The free EasyPanel plan supports up to 3 projects, which is enough for most personal sites. Every push to your repo triggers a rebuild, and EasyPanel handles SSL and reverse proxy automatically.

For developers who want full control over their hosting without paying for managed platforms like Netlify or Vercel, this setup gives you that — you just pay for the VPS.

<Button link="https://go.bitdoze.com/hetzner" text="Hetzner €20 free credit" />
<Button link="https://go.bitdoze.com/hostinger-vps" text="Hostinger VPS" />