From 97df5aac8dfdbb0486c01b74c75c0c4ee1cadbcc Mon Sep 17 00:00:00 2001 From: Kunthawat Greethong Date: Fri, 17 Apr 2026 22:54:12 +0700 Subject: [PATCH] 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 --- .../templates/astro-tina-starter/.env.example | 17 ++++ .../templates/astro-tina-starter/Dockerfile | 20 +++-- .../templates/astro-tina-starter/README.md | 83 ++++++++++++++----- .../astro-tina-starter/astro.config.mjs | 6 +- .../templates/astro-tina-starter/package.json | 1 + 5 files changed, 100 insertions(+), 27 deletions(-) create mode 100644 skills/website-creator/templates/astro-tina-starter/.env.example diff --git a/skills/website-creator/templates/astro-tina-starter/.env.example b/skills/website-creator/templates/astro-tina-starter/.env.example new file mode 100644 index 0000000..82bf356 --- /dev/null +++ b/skills/website-creator/templates/astro-tina-starter/.env.example @@ -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 diff --git a/skills/website-creator/templates/astro-tina-starter/Dockerfile b/skills/website-creator/templates/astro-tina-starter/Dockerfile index 6e7980d..f9488a2 100644 --- a/skills/website-creator/templates/astro-tina-starter/Dockerfile +++ b/skills/website-creator/templates/astro-tina-starter/Dockerfile @@ -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;"] \ No newline at end of file +ENV HOST=0.0.0.0 +ENV PORT=4321 +ENV NODE_ENV=production + +EXPOSE 4321 + +CMD ["node", "dist/server/entry.mjs"] \ No newline at end of file diff --git a/skills/website-creator/templates/astro-tina-starter/README.md b/skills/website-creator/templates/astro-tina-starter/README.md index 6fc684d..13fc516 100644 --- a/skills/website-creator/templates/astro-tina-starter/README.md +++ b/skills/website-creator/templates/astro-tina-starter/README.md @@ -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,28 +41,64 @@ 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 ``` astro-tina-starter/ ├── .tina/ -│ ├── config.ts # Tina CMS configuration +│ ├── config.ts # Tina CMS configuration │ └── schema.ts # Content schema definitions ├── db/ │ ├── config.ts # Astro DB schema (consent logs) -│ └── seed.ts # Database seed script +│ └── seed.ts # Database seed script ├── src/ │ ├── styles/ │ │ └── global.css # Tailwind v4 styles │ ├── 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 +MIT \ No newline at end of file diff --git a/skills/website-creator/templates/astro-tina-starter/astro.config.mjs b/skills/website-creator/templates/astro-tina-starter/astro.config.mjs index f8210ce..8fd2915 100644 --- a/skills/website-creator/templates/astro-tina-starter/astro.config.mjs +++ b/skills/website-creator/templates/astro-tina-starter/astro.config.mjs @@ -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', }, diff --git a/skills/website-creator/templates/astro-tina-starter/package.json b/skills/website-creator/templates/astro-tina-starter/package.json index 37a94de..6dd9860 100644 --- a/skills/website-creator/templates/astro-tina-starter/package.json +++ b/skills/website-creator/templates/astro-tina-starter/package.json @@ -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",