No description
  • TypeScript 90.2%
  • Svelte 6.4%
  • Nix 1.8%
  • JavaScript 1.3%
  • HTML 0.2%
Find a file
NeilClack 1c93aa3abc
Some checks failed
Deploy / deploy (push) Has been cancelled
Update path of do-ca-certificate.crt
2026-03-10 12:37:18 -05:00
.forgejo/workflows Move to a Nix derivation 2026-03-04 21:32:26 -06:00
nixos Update path of do-ca-certificate.crt 2026-03-10 12:37:18 -05:00
prisma Init project 2026-02-20 15:24:44 -06:00
src Run prisma generate 2026-02-21 10:47:26 -06:00
static Init project 2026-02-20 15:24:44 -06:00
.example.env Remove unused environment variables 2026-02-21 10:47:02 -06:00
.gitignore Init project 2026-02-20 15:24:44 -06:00
.npmrc Init project 2026-02-20 15:24:44 -06:00
.prettierignore Init project 2026-02-20 15:24:44 -06:00
.prettierrc Init project 2026-02-20 15:24:44 -06:00
eslint.config.js Init project 2026-02-20 15:24:44 -06:00
flake.lock Create nix flake 2026-03-10 10:23:11 -05:00
flake.nix Fix flake/module 2026-03-10 11:31:41 -05:00
package-lock.json add package-lock 2026-02-21 10:47:41 -06:00
package.json Init project 2026-02-20 15:24:44 -06:00
prisma.config.ts Init project 2026-02-20 15:24:44 -06:00
README.md Create nix flake 2026-03-10 10:23:11 -05:00
svelte.config.js Init project 2026-02-20 15:24:44 -06:00
tsconfig.json Init project 2026-02-20 15:24:44 -06:00
vite.config.ts Init project 2026-02-20 15:24:44 -06:00

Signup.RhemaWaveTech.com

Referral signup site for RhemaWave. Built with SvelteKit (adapter-node), Prisma, and Tailwind CSS. Generates referral links and QR codes for new signups and sends data to MailerLite.

Local development

  1. Copy .example.env to .env and fill in your values:

    cp .example.env .env
    # Edit .env -- you need at minimum a DATABASE_URL
    
  2. Install dependencies and generate the Prisma client:

    npm install
    npx prisma generate
    
  3. Start the dev server:

    npm run dev
    

    The site will be at http://localhost:5173. Changes hot-reload automatically.

The .env file is only for local development. On the server, environment variables are injected by the systemd service defined in this repo's NixOS module.

Building with Nix

The project has a flake.nix that packages the entire app into a Nix derivation. This is what gets deployed to the server -- you don't rsync files or run npm install on the server.

What nix build does

  1. Installs all npm dependencies from package-lock.json (pinned by hash)
  2. Runs svelte-kit sync to generate SvelteKit's type scaffolding
  3. Runs prisma generate to create the Prisma client (uses nixpkgs' prisma-engines so it works in the Nix sandbox without network access)
  4. Runs npm run build (SvelteKit build via Vite)
  5. Copies build/, production-only node_modules/, package.json, and prisma/ into a Nix store path

The output is a self-contained directory in /nix/store/ that has everything needed to run the app with node build.

Building locally

nix build

This creates a ./result symlink pointing to the store path. You can run it locally to test:

DATABASE_URL="your-connection-string" \
ORIGIN="http://localhost:3000" \
HOST=0.0.0.0 \
PORT=3000 \
node ./result/build

If nix build succeeds on your machine, it will succeed on the server too.

When you change dependencies

If you add, remove, or update packages in package.json / package-lock.json, the npmDepsHash in flake.nix will be wrong and nix build will fail. To fix it:

nix run nixpkgs#prefetch-npm-deps -- package-lock.json

Paste the new hash into the npmDepsHash field in flake.nix.

NixOS module

This flake exports a NixOS module at nixosModules.default. It defines everything the server needs to run the signup service:

  • signup user and group
  • systemd service (runs node build from /var/lib/signup/current)
  • tmpfiles rule for /var/lib/signup
  • sudo rules for the forgejo-runner user to deploy and restart

Module options

Option Type Description
services.signup.enable bool Enable the signup service
services.signup.databaseUrlFile path Path to a file containing the DATABASE_URL

Environment variables set by the service

Variable Value
DATABASE_URL Read from databaseUrlFile
ORIGIN https://signup.rhemawavetech.com
HOST 0.0.0.0
PORT 3000
DO_CA_CERTIFICATE /etc/ssl/certs/do-ca-certificate.crt

Adding to a server config for the first time

In your server's flake.nix, add the input and module:

# flake.nix
{
  inputs = {
    signup.url = "git+https://git.rhemawavetech.com/NeilClack/Signup.RhemaWaveTech.com";
    signup.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = { nixpkgs, signup, ... }: {
    nixosConfigurations.my-server = nixpkgs.lib.nixosSystem {
      modules = [
        signup.nixosModules.default
        ./configuration.nix
      ];
    };
  };
}

Then in configuration.nix:

services.signup = {
  enable = true;
  databaseUrlFile = config.sops.secrets."signup/database-url".path;
};

After adding, run nixos-rebuild switch on the server.

When you change the service config

If you modify the NixOS module (e.g. add an environment variable, change the port), you need to update the flake input on the server and rebuild:

# In Webserver-Infra
nix flake update signup
nixos-rebuild switch

This is separate from app deployments -- changing the module changes the systemd service definition, not the app code.

Deployment (CI/CD)

Every push to main triggers .forgejo/workflows/deploy.yml. The self-hosted runner on the server:

  1. nix build -- builds the derivation on the server. Output lands in /nix/store/.
  2. sudo nix-env -p /var/lib/signup/current --set ./result -- atomically swaps the profile symlink to the new build.
  3. sudo systemctl restart signup -- restarts the service to pick up the new build.

What "atomic" means

/var/lib/signup/current is a Nix profile (a symlink chain). nix-env --set creates the new store path first, then swaps the symlink in one atomic filesystem operation. The old build stays in /nix/store/ until garbage collected.

  • If nix build fails, nothing changes.
  • If you need to roll back, the old build is still in the store.

Day-to-day workflow

  1. Edit code locally, test with npm run dev
  2. Run nix build to verify the production build
  3. Commit and push to main
  4. Forgejo Actions builds and deploys automatically
  5. Check https://signup.rhemawavetech.com

Rolling back

SSH into the server:

sudo nix-env -p /var/lib/signup/current --rollback
sudo systemctl restart signup

To see profile history:

nix-env -p /var/lib/signup/current --list-generations

Database migrations

Prisma manages the schema. Migrations are not run automatically during deployment -- you run them manually.

# Create a new migration (local dev)
npx prisma migrate dev

# Apply pending migrations to production
DATABASE_URL="your-production-url" npx prisma migrate deploy

The Prisma schema is at prisma/schema.prisma.