218 lines
6.0 KiB
Markdown
218 lines
6.0 KiB
Markdown
# SQLite Migration Summary
|
|
|
|
## Changes Made
|
|
|
|
The backend has been migrated from PostgreSQL to SQLite for both local development and production (Fly.io).
|
|
|
|
### Benefits of SQLite
|
|
|
|
1. **Simplified Deployment** - No separate database service needed
|
|
2. **Lower Cost** - Save ~$15/month (no Postgres hosting)
|
|
3. **Easier Development** - No need to install/run PostgreSQL locally
|
|
4. **Single File Database** - Easy backups and migrations
|
|
5. **Perfect for this use case** - Low concurrent writes, simple queries
|
|
|
|
## Modified Files
|
|
|
|
### Dependencies
|
|
- **package.json**
|
|
- Removed: `pg`, `@types/pg`
|
|
- Added: `better-sqlite3`, `@types/better-sqlite3`
|
|
|
|
### Database Configuration
|
|
- **src/config/database.ts**
|
|
- Changed from `drizzle-orm/node-postgres` to `drizzle-orm/better-sqlite3`
|
|
- Uses `DATABASE_PATH` instead of `DATABASE_URL`
|
|
- Enabled WAL mode for better concurrent access
|
|
|
|
- **src/config/env.ts**
|
|
- Changed `DATABASE_URL` to `DATABASE_PATH`
|
|
- Default: `./data/gallus_cms.db`
|
|
|
|
- **src/db/schema.ts**
|
|
- Changed from `pgTable` to `sqliteTable`
|
|
- Changed `uuid()` to `text()` with `crypto.randomUUID()`
|
|
- Changed `jsonb()` to `text(..., { mode: 'json' })`
|
|
- Changed `timestamp()` to `integer(..., { mode: 'timestamp' })`
|
|
- Changed `boolean()` to `integer(..., { mode: 'boolean' })`
|
|
- Uses `sql\`(unixepoch())\`` for default timestamps
|
|
|
|
- **drizzle.config.ts**
|
|
- Changed dialect from `postgresql` to `sqlite`
|
|
- Uses `DATABASE_PATH` instead of `DATABASE_URL`
|
|
|
|
### Environment Files
|
|
- **.env** and **.env.example**
|
|
- Changed `DATABASE_URL=postgresql://...` to `DATABASE_PATH=./data/gallus_cms.db`
|
|
- Changed `GIT_WORKSPACE_DIR=/tmp/gallus-repo` to `./data/workspace`
|
|
|
|
### Docker Configuration
|
|
- **Dockerfile**
|
|
- Added build tools for `better-sqlite3` native module (python3, make, g++)
|
|
- Added `sqlite` CLI tool
|
|
- Creates `/app/data` directory for database
|
|
- Sets `DATABASE_PATH=/app/data/gallus_cms.db`
|
|
- Proper permissions for non-root user
|
|
|
|
- **fly.toml**
|
|
- Added `DATABASE_PATH` and `GIT_WORKSPACE_DIR` to [env]
|
|
- Changed volume mount from `gallus_repo_workspace` to `gallus_data`
|
|
- Mount destination: `/app/data` (contains both DB and git workspace)
|
|
|
|
### Documentation
|
|
- **README.md** - Updated setup instructions
|
|
- **DEPLOYMENT.md** - Removed Postgres setup, updated volume creation
|
|
- **SQLITE_MIGRATION.md** - This file!
|
|
|
|
## Local Development
|
|
|
|
### Setup
|
|
```bash
|
|
# Dependencies already installed
|
|
pnpm install
|
|
|
|
# Create data directory (done)
|
|
mkdir -p data
|
|
|
|
# Database will be created automatically at ./data/gallus_cms.db
|
|
```
|
|
|
|
### Generate and Run Migrations
|
|
```bash
|
|
# Generate migration files from schema
|
|
pnpm run db:generate
|
|
|
|
# Run migrations to create tables
|
|
pnpm run db:migrate
|
|
```
|
|
|
|
### Start Development Server
|
|
```bash
|
|
pnpm run dev
|
|
```
|
|
|
|
The database file will be created at `./data/gallus_cms.db` on first run.
|
|
|
|
## Production (Fly.io)
|
|
|
|
### Volume Setup
|
|
```bash
|
|
# Create single volume for both database and git workspace
|
|
flyctl volumes create gallus_data --size 2 --region ams
|
|
```
|
|
|
|
### Environment Variables
|
|
Set in fly.toml (non-sensitive):
|
|
- `DATABASE_PATH=/app/data/gallus_cms.db`
|
|
- `GIT_WORKSPACE_DIR=/app/data/workspace`
|
|
|
|
Set as secrets (sensitive):
|
|
- All other env vars (OAuth credentials, tokens, etc.)
|
|
|
|
### Deployment
|
|
```bash
|
|
flyctl deploy
|
|
```
|
|
|
|
Database will be created automatically on first start. No need for separate database service!
|
|
|
|
## Database Location
|
|
|
|
### Local Development
|
|
- **Database:** `./data/gallus_cms.db`
|
|
- **WAL files:** `./data/gallus_cms.db-wal`, `./data/gallus_cms.db-shm`
|
|
- **Git workspace:** `./data/workspace/`
|
|
|
|
### Production (Fly.io)
|
|
- **Database:** `/app/data/gallus_cms.db` (on volume)
|
|
- **Git workspace:** `/app/data/workspace/` (on volume)
|
|
- **Volume name:** `gallus_data` (2GB)
|
|
|
|
## Backup Strategy
|
|
|
|
### Manual Backup
|
|
```bash
|
|
# Local
|
|
cp data/gallus_cms.db data/gallus_cms.backup.db
|
|
|
|
# Production (Fly.io)
|
|
flyctl ssh console
|
|
sqlite3 /app/data/gallus_cms.db ".backup /app/data/backup.db"
|
|
# Then copy back: flyctl ssh sftp get /app/data/backup.db
|
|
```
|
|
|
|
### Automated Backup (Optional)
|
|
Consider setting up a cron job or Fly.io machine to periodically:
|
|
1. Create SQLite backup
|
|
2. Upload to S3/Backblaze/etc.
|
|
|
|
## Performance Notes
|
|
|
|
SQLite is perfect for this use case because:
|
|
- **Low write concurrency** - Single admin user making changes
|
|
- **Read-heavy** - Mostly reading content for publish operations
|
|
- **Small dataset** - Events, gallery images, content sections
|
|
- **Simple queries** - No complex joins or aggregations
|
|
|
|
WAL mode is enabled for:
|
|
- Better concurrent read access
|
|
- Safer writes (crash recovery)
|
|
- Improved performance
|
|
|
|
## Migration from Existing Data
|
|
|
|
If you had PostgreSQL data to migrate:
|
|
|
|
1. Export from Postgres:
|
|
```sql
|
|
\copy events TO 'events.csv' CSV HEADER;
|
|
\copy gallery_images TO 'gallery.csv' CSV HEADER;
|
|
-- etc.
|
|
```
|
|
|
|
2. Import to SQLite:
|
|
```sql
|
|
.mode csv
|
|
.import events.csv events
|
|
.import gallery.csv gallery_images
|
|
-- etc.
|
|
```
|
|
|
|
## Known Limitations
|
|
|
|
1. **No native UUID type** - Using TEXT with UUID format
|
|
2. **No native JSON type** - Using TEXT with JSON serialization (Drizzle handles this)
|
|
3. **No native TIMESTAMP** - Using INTEGER with Unix epoch (Drizzle handles this)
|
|
4. **Single writer** - Only one write transaction at a time (not an issue for this use case)
|
|
|
|
## Troubleshooting
|
|
|
|
### "Database is locked" error
|
|
- WAL mode should prevent this
|
|
- Check if multiple processes are accessing the database
|
|
- Ensure proper file permissions
|
|
|
|
### Native module build errors
|
|
- Make sure build tools are installed: `apt-get install python3 make g++` (Linux)
|
|
- On Alpine: `apk add python3 make g++`
|
|
- Try rebuilding: `pnpm rebuild better-sqlite3`
|
|
|
|
### Database file not found
|
|
- Check `DATABASE_PATH` is set correctly
|
|
- Ensure `data/` directory exists
|
|
- Check file permissions
|
|
|
|
## Next Steps
|
|
|
|
1. ✅ Update dependencies
|
|
2. ✅ Update database configuration
|
|
3. ✅ Update schema
|
|
4. ✅ Update Docker configuration
|
|
5. ⏳ Generate migrations: `pnpm run db:generate`
|
|
6. ⏳ Run migrations: `pnpm run db:migrate`
|
|
7. ⏳ Test development server: `pnpm run dev`
|
|
8. ⏳ Test publish flow
|
|
9. ⏳ Deploy to Fly.io
|
|
|
|
The migration is complete! Just need to generate/run migrations and test.
|