Skip to main content

Installation

Sunschool is fully open-source and can be self-hosted on your own infrastructure. This guide walks you through setting up a production-ready instance.
Prefer a hosted solution? Visit sunschool.xyz for a managed instance with automatic updates and backups.

Prerequisites

Before you begin, ensure you have:

Node.js v20+

Runtime for the server and client. v22 recommended for best performance.

PostgreSQL

Relational database for storing users, lessons, and analytics.

npm

Package manager included with Node.js.

Git

Version control for cloning the repository.

System Requirements

AI lesson generation requires external API calls. Ensure your server has outbound internet access to OpenRouter, Perplexity, or Bittensor endpoints.

Step 1: Clone the Repository

Clone the Sunschool repository from GitHub:

Repository Structure


Step 2: Install Dependencies

Install all required packages:

What Gets Installed

Key dependencies from package.json:

Step 3: Configure Environment Variables

Create a .env file in the root directory:

Required Variables

Edit .env and set the following:
string
required
PostgreSQL connection string
string
required
Secret key for signing JWT tokens (minimum 32 characters recommended)
string
required
Secret key for session management
string
required
API key for OpenRouter (primary AI provider)
Get your key at openrouter.ai

Optional Variables

string
API key for Perplexity AI (alternative provider)
number
default:"5000"
Port for the Express server
boolean
default:"true"
Enable SSL for database connections

Example Configuration

Never commit .env to version control. The .gitignore file excludes it by default.

Step 4: Set Up the Database

Create the Database

If you haven’t already, create a PostgreSQL database:

Run Migrations

Sunschool uses Drizzle ORM for database migrations. Migrations run automatically on server startup, but you can run them manually:

Verify Schema

Check that tables were created:
Expected tables:
  • users — All accounts (admins, parents, learners)
  • learner_profiles — Grade levels, subjects, knowledge graphs
  • lessons — Generated lessons with content and status
  • achievements — Milestones and badges
  • rewards — Parent-defined redemption goals
  • points_ledger — Transaction log for earned/spent points
  • sync_configs — External database sync settings

Seed Test Data (Optional)

Populate the database with sample users and lessons:
Seeding creates test accounts. Do not use in production — it includes weak passwords.

Step 5: Build the Frontend

Compile the React client:
This runs Vite to bundle the frontend:
Output is written to client/dist/ and served by Express in production.

Step 6: Start the Server

Development Mode

Run with hot-reloading:
This starts:
  • Backend: Express server on http://localhost:5000
  • Frontend: Vite dev server on http://localhost:5173 (proxies API requests)

Production Mode

Build and run the production server:
This uses the deploy script from package.json:10:
The server:
  1. Runs auto-migrations on startup
  2. Serves the built frontend from client/dist/
  3. Exposes the API at /api/*
  4. Provides health checks at /api/healthcheck

Verify It’s Running

Check the health endpoint:
Expected response:

Step 7: Create the First Admin Account

Navigate to http://localhost:5000 in your browser.

Auto-Promotion to Admin

The first user to register is automatically promoted to Admin, regardless of the role selected during registration.
From server/routes.ts:87-92:

Registration Steps

  1. Click Sign Up
  2. Fill in:
    • Username: admin
    • Email: admin@example.com
    • Name: Admin User
    • Password: <secure-password>
    • Role: PARENT (will be overridden to ADMIN)
  3. Accept the age disclaimer
  4. Submit
You’re now logged in as Admin with full system access.

Step 8: Deploy to Production

Sunschool is designed to deploy seamlessly to platforms like Railway, Render, or Heroku.

Railway Deployment

Sunschool auto-deploys on push to main:
  1. Connect your GitHub repository to Railway
  2. Set environment variables in the Railway dashboard
  3. Railway detects the NIXPACKS buildpack automatically
  4. Push to main triggers deployment
Health checks run at /api/healthcheck (from README.md:152).

Environment Variables in Railway

Set these in the Railway dashboard (do not use .env in production):

Manual Deployment

For other platforms:
  1. Build: npm run build
  2. Set env vars: Configure DATABASE_URL, JWT_SECRET, etc.
  3. Run: npm start
  4. Expose port: Ensure port 5000 (or $PORT) is accessible

Post-Installation

Security Checklist

1

Generate Strong Secrets

Use openssl rand -base64 32 to generate JWT_SECRET and SESSION_SECRET
2

Enable HTTPS

Use a reverse proxy (nginx, Caddy) or platform SSL (Railway, Render)
3

Restrict Database Access

Use firewall rules to allow only your server’s IP
4

Rotate API Keys

Regularly rotate OPENROUTER_API_KEY and other third-party credentials

Backup Strategy

Sunschool does not include built-in backups. Configure external backups for production.

PostgreSQL Backups

Database Sync Feature

Sunschool includes an optional external sync feature:
  1. Parents configure a second PostgreSQL connection at /database-sync
  2. Data is pushed to the external database on-demand or continuously
  3. Use this for redundancy or data portability
See server/sync-utils.ts for implementation.

Next Steps

Configuration

Configure AI providers, feature flags, and advanced settings

First Steps

Navigate the interface and create your first learners

Quickstart

Walk through the full user experience

API Reference

Integrate with the Sunschool API

Troubleshooting

Symptoms: Error: connect ECONNREFUSED or FATAL: password authentication failedSolutions:
  • Verify DATABASE_URL format: postgresql://user:password@host:port/database
  • Check PostgreSQL is running: systemctl status postgresql
  • Test connection: psql $DATABASE_URL
  • Ensure user has CREATE and SELECT permissions
Symptoms: Tables don’t exist, server crashes on startupSolutions:
  • Run migrations manually: npm run migrate
  • Check server logs for Drizzle errors
  • Verify database user has schema modification permissions
  • Delete and recreate the database if schema is corrupted
Symptoms: Blank page, 404 errorsSolutions:
  • Run npm run build to compile the frontend
  • Check client/dist/ exists and contains index.html
  • Verify the server is serving static files (see server/index.ts)
  • Clear browser cache and reload
Symptoms: Failed to generate lesson content, 503 errorsSolutions:
  • Verify OPENROUTER_API_KEY is valid
  • Check OpenRouter account has credits
  • Test API key: curl https://openrouter.ai/api/v1/models -H "Authorization: Bearer $OPENROUTER_API_KEY"
  • Check server logs for rate limiting or quota errors
  • Set USE_AI=0 in .env to disable AI features for testing
Symptoms: EADDRINUSE: address already in use :::5000Solutions:
  • Change PORT in .env to an available port (e.g., 5001)
  • Kill the process using port 5000: lsof -ti:5000 | xargs kill
  • Use a different port in Railway/platform settings