How to Deploy Astro on Your VPS with EasyPanel
Learn how to deploy an Astro static site on your VPS using EasyPanel. Covers project setup, GitHub integration, Nixpacks build, and custom domain configuration.

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. 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.
Related articles:
- How To Deploy Static Website Astro.JS on VPS Servers
- Coolify Install A Free Heroku and Netlify Self-Hosted Alternative
- How To Deploy An Astro.JS Blog On Cloudflare
- How To Monitor Server and Docker Resources
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:
Hetzner €20 free credit Hostinger VPSVideo walkthrough
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.
Clone the empty repo locally:
git clone [email protected]:yourusername/your-astro-site.git
cd your-astro-site
Step 2: Initialize Astro
Run the Astro CLI wizard inside your repo directory:
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:
npm install serve
Update your package.json scripts so EasyPanel knows how to start the app:
{
"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:
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:
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
git add .
git commit -m "initial astro site"
git push
Step 6: Deploy in EasyPanel
Create a project and service
- In EasyPanel, click Create Project
- Inside the project, click Service and select App
- Connect your GitHub repository
Configure the build
In the Source section, set the repository owner and name:

In the Build section:
- Choose Nixpacks as the builder
- Nixpacks will auto-detect Astro and run
npm installthennpm run build - The start command will use your
package.jsonstartscript (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

- Create an A record in your DNS provider pointing your domain (or subdomain) to your VPS IP
- In EasyPanel, go to Domains in your project
- 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:
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:
{
"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.
Hetzner €20 free credit Hostinger VPS

