SchoolStack

For the person who runs the server

The step-by-step setup instructions are in deploy/README.md in the SchoolStack code. This page is an overview.

Installing and updating

Example: A teacher reports a fix is merged. The owner opens the DigitalOcean console, pastes /opt/schoolstack/bin/schoolstack-update, waits for "Update finished", and opens the site on their phone to check.

Administrators and the Users page

Administrators approve teachers and look after accounts. The first account created on a new server is its administrator. To make an existing account an administrator, paste this in the server's console (the site keeps running):

/opt/schoolstack/bin/schoolstack-make-admin you@example.com

Administrators see Users at the top of every page:

Example: Mr. Ali signs up as a teacher. On Users you see him under "Teachers waiting for approval (1)" and choose Approve as teacher. A student who left school can be turned off. Another day you choose Only students with a class code and add the new science teacher with Add a person (Teacher); you read her the temporary password shown at the top.

Example: At the start of the year you choose Only people an administrator adds, save the student list from the school office's spreadsheet as CSV (Name, Email, Role, Class code), choose it under Add many people from a spreadsheet and Add everyone. Row 14 has a typo in an email, so nobody is added; you fix it, send it again, download the list of temporary passwords and hand them out in class.

With email on, people who forget their password get a link by email ("Forgot your password?" on the Sign in page) instead of asking you. SchoolStack sends through an email service; the steps below are for Brevo (free for up to 300 emails a day). Your site needs its domain first.

  1. In Brevo: Senders, Domains & Dedicated IPs ▸ Domains ▸ Add a domain, type your domain, and add the DNS records Brevo shows at your domain's DNS provider. Wait until Brevo says Authenticated.
  2. In Brevo: SMTP & API ▸ SMTP. Note the Login shown there, and choose Generate a new SMTP key. Keep the key private: don't send it to anyone or paste it into a chat.
  3. In the server's console, run /opt/schoolstack/bin/schoolstack-email-setup. Type the login, then paste the key (it doesn't show as you type) and press Enter. The site restarts with email on, sending as no-reply@ your domain.
  4. On Users ▸ Email, choose Send me a test email. It arrives within a minute or two (look in spam the first time). If it fails, the page says why.

Good to know: SchoolStack uses port 2525, because DigitalOcean blocks the usual email ports on new accounts. Another service works too: /opt/schoolstack/bin/schoolstack-email-setup --host smtp.example.com --port 587. To turn email off: /opt/schoolstack/bin/schoolstack-email-setup --off. The settings live in /etc/schoolstack/schoolstack.env (readable by root only), and re-running the installer keeps them.

Example: After Brevo shows schoolstack.me as authenticated, the owner runs /opt/schoolstack/bin/schoolstack-email-setup, pastes the key, and sends a test email from Users. From then on a student who forgets their password resets it themselves.

Daily summary email

With email on, everyone gets one email a day at 7:00 (the school's time zone) with what's new in their classes: new work, work returned and work due tomorrow for students; work turned in for teachers. People with no news that day get nothing. Users ▸ Email ▸ Choose what each class sends opens Class emails (/admin/emails): every class with its four switches and Save email choices; the class's teachers can change the same switches in the class's Settings. (Commands: class.setEmails; admin.classEmails lists every class's choices.)

Guardian summaries go out at the same time: parents or guardians that teachers (or you) invited on a class's People page get a summary of their student's missing and upcoming work and class news, daily on school days (the school's week minus its last two days) or weekly on the first day of the school's week (Users ▸ First day of the week). You can invite guardians of any student. They count towards the 250 a day.

Example: At the start of the year the school office has a spreadsheet of students and their parents' emails. You save it as CSV with the two columns, choose it under Invite guardians from a spreadsheet, and every parent gets an invitation that morning.

Good to know:

Example: The science department only wants students emailed, so on Class emails the owner turns off "Teachers: work students turned in" for the three science classes and saves each.

Test accounts

For testing (by hand, or by a testing service such as TestSprite), run in the server's console:

sudo /opt/schoolstack/bin/schoolstack-test-accounts

and type a password (it isn't shown). It makes test-admin@schoolstack.test (administrator and teacher), test-teacher@schoolstack.test, test-student1@schoolstack.test and test-student2@schoolstack.test, all with that password; running it again sets the password again. It also makes, once, the class "Test class: returned work" (taught by test-teacher, with both test students in it and a returned essay with a grade, rubric feedback and a private comment), so testers can check what students see after grading. When testing is done, sudo /opt/schoolstack/bin/schoolstack-test-accounts --off turns them off. The .test addresses never receive email. The product requirements for testers are in docs/testing/ in the repository.

Example: Before handing the site to a testing service, the owner runs the command, types a password, and gives the service https://schoolstack.me, test-teacher@schoolstack.test and that password.

Where the data lives

Example: A teacher deleted a class by mistake yesterday. The owner finds last night's backup in /var/backups/schoolstack and follows the restore steps in deploy/README.md.

Server options

Set them in /etc/schoolstack/schoolstack.env as SCHOOLSTACK_FLAGS=…, then systemctl restart schoolstack:

With a domain, www.(your domain) sends people to the address without www (for example www.schoolstack.me → schoolstack.me). It needs its own DNS record: a CNAME to your domain, or an A record to the server. schoolstack-update adds it to servers installed before it existed.

Example: Teachers want to upload longer videos, so the owner sets SCHOOLSTACK_FLAGS=--time-zone Asia/Riyadh --max-upload-mb 50, raises max_size in the Caddyfile to 55 MB and runs systemctl restart schoolstack.

Command-line tool and AI agents

schoolstack-cli runs the same actions as the web pages, as a chosen user. While the site runs, it sends each change to the running server through /var/lib/schoolstack/school.sock (only root and the schoolstack account can use it, so run the tool with sudo), so nothing needs to stop; when the site is stopped, it changes the data files itself.

Every action is listed in the reference.

Example: To make a class for a new teacher without signing in, the owner runs sudo schoolstack-cli --data /var/lib/schoolstack/school.json exec --as tom@school.org class.create '{"name":"Physics"}'; Tom sees "Physics" on his Classes page straight away.