feat: add Easypanel persistent volume support for Astro DB

- Change Dockerfile from nginx (static) to Node.js (SSR)
- Add @astrojs/node adapter for SSR mode
- Add OUT_DIR=/data for persistent SQLite storage
- Add .env.example with persistent storage config
- Update README with Easypanel deployment instructions
- Database persists across redeployments at /data/astro.db
This commit is contained in:
2026-04-17 22:54:12 +07:00
parent 628298183a
commit 97df5aac8d
5 changed files with 100 additions and 27 deletions

View File

@@ -0,0 +1,17 @@
# Astro + Tina CMS Environment Variables
# Site URL
PUBLIC_SITE_URL=https://your-domain.com
# Tina CMS (optional - for production Tina admin)
TINA_TOKEN=your-tina-token-from-tina-cloud
TINA_CLIENT_ID=your-client-id
# Astro DB - Persistent Storage
# IMPORTANT: Set OUT_DIR to /data for Docker/Easypanel persistent volume
# This ensures database persists across redeployments
OUT_DIR=/data
# Optional: External Turso database (if using external DB instead of local SQLite)
# TURSO_DATABASE_URL=libsql://your-db.turso.io
# TURSO_AUTH_TOKEN=your-auth-token

View File

@@ -3,17 +3,23 @@ FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM nginx:alpine AS runner
FROM node:20-alpine AS runner
COPY --from=builder /app/dist /usr/share/nginx/html
WORKDIR /app
RUN mkdir -p /data
EXPOSE 80
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./
RUN npm install --omit=dev
CMD ["nginx", "-g", "daemon off;"]
ENV HOST=0.0.0.0
ENV PORT=4321
ENV NODE_ENV=production
EXPOSE 4321
CMD ["node", "dist/server/entry.mjs"]

View File

@@ -4,10 +4,11 @@ Astro 6.1.7 + Tina CMS starter template with Tailwind CSS 4.x
## Tech Stack
- **Framework:** Astro 6.1.7
- **Framework:** Astro 6.1.7 (SSR mode)
- **CMS:** Tina CMS (self-hosted)
- **Styling:** Tailwind CSS 4.x with `@tailwindcss/vite`
- **Database:** Astro DB (LibSQL)
- **Database:** Astro DB (LibSQL/SQLite)
- **Adapter:** @astrojs/node (SSR)
- **State:** Nano Stores + React
- **Language:** TypeScript
@@ -16,9 +17,9 @@ Astro 6.1.7 + Tina CMS starter template with Tailwind CSS 4.x
- Self-hosted Tina CMS with schema-based content
- Tailwind CSS 4.x using `@tailwindcss/vite` plugin
- Astro DB for consent logging (PDPA compliant)
- Nano Stores for client-side state management
- SSR mode for API routes
- Docker-ready with persistent storage
- Thai language support foundation
- Docker-ready deployment
## Quick Start
@@ -40,6 +41,41 @@ During development, access Tina CMS at:
For production, you'll need a TINA_TOKEN environment variable.
## Easypanel Deployment
This template is designed for **Easypanel** with persistent volume support.
### Important: Persistent Storage
**Astro DB stores SQLite at `/data/`** - this directory is mounted as a persistent volume in Easypanel.
When deploying:
1. Set environment variable `OUT_DIR=/data`
2. Mount persistent volume to `/data` in Easypanel
3. Database will persist across redeployments
### Environment Variables
```bash
# Required for persistent storage
OUT_DIR=/data
# Optional - Tina CMS
TINA_TOKEN=your-tina-token
# Optional - External database (instead of local SQLite)
# TURSO_DATABASE_URL=libsql://your-db.turso.io
# TURSO_AUTH_TOKEN=your-auth-token
```
### Easypanel Setup
1. Create new service from Git repo
2. Set build command: `npm run build`
3. Set start command: `node dist/server/entry.mjs`
4. Add environment variable: `OUT_DIR=/data`
5. Mount persistent volume to `/data`
## Project Structure
```
@@ -56,12 +92,13 @@ astro-tina-starter/
│ ├── layouts/
│ │ └── Layout.astro
│ ├── pages/
│ │ ── index.astro
│ │ ── index.astro
│ │ └── api/ # API routes (consent, etc.)
│ ├── components/
│ │ └── Header.astro
│ └── content/
│ └── config.ts # Tina content collections
├── Dockerfile
├── Dockerfile # Multi-stage Node.js (not nginx)
└── package.json
```
@@ -85,20 +122,28 @@ The template includes a consent-log table for PDPA compliance:
```ts
// db/config.ts
export const ConsentLog = defineTable({
import { defineDb, defineTable, column } from 'astro:db';
const ConsentLog = defineTable({
columns: {
action: text(),
purpose: text(),
analytics: boolean(),
marketing: boolean(),
functional: boolean(),
userAgent: text(),
ip: text(),
timestamp: text(),
id: column.number({ primaryKey: true }),
action: column.text(),
purpose: column.text(),
analytics: column.boolean({ default: false }),
marketing: column.boolean({ default: false }),
functional: column.boolean({ default: false }),
userAgent: column.text({ optional: true }),
ip: column.text({ optional: true }),
timestamp: column.date(),
sessionId: column.text({ optional: true }),
},
})
});
export default defineDb({ tables: { ConsentLog } });
```
Database file location: `/data/astro.db` (persistent across redeployments)
## License
MIT

View File

@@ -1,6 +1,7 @@
import { defineConfig } from 'astro/config'
import tailwindcss from '@tailwindcss/vite'
import tina from 'tinacms'
import node from '@astrojs/node'
import { fileURLToPath } from 'url'
import path from 'path'
@@ -27,7 +28,10 @@ export default defineConfig({
},
},
},
output: 'static',
output: 'server',
adapter: node({
mode: 'standalone'
}),
build: {
assets: '_assets',
},

View File

@@ -16,6 +16,7 @@
"dependencies": {
"@astrojs/check": "^0.9.4",
"@astrojs/db": "^0.14.3",
"@astrojs/node": "^9.0.0",
"@nanostores/react": "^0.7.3",
"@tailwindcss/typography": "^0.5.15",
"@tailwindcss/vite": "^4.0.0",