414 lines
9.9 KiB
Markdown
414 lines
9.9 KiB
Markdown
# Rabbi Gerzi
|
|
|
|
Rabbi Gerzi is the public website and Torah media application for Rabbi
|
|
Yehoshua Gerzi. The site presents Rabbi Gerzi's work, projects, and Torah
|
|
media, with an authenticated admin area for managing media sets, nested
|
|
elements, rich text, YouTube links, icons, and PDF uploads.
|
|
|
|
The application is split into:
|
|
|
|
- `backend/`: Laravel 13, PHP 8.3, PostgreSQL, PHPUnit.
|
|
- `frontend/rabbi_gerzi/`: Vue 3, Vite, TypeScript, Pinia, Cypress.
|
|
- `nix/`: Nix packages, checks, upload limits, and the NixOS service module.
|
|
|
|
Production assumptions:
|
|
|
|
- Website: `https://rabbigerzi.com`
|
|
- API: `https://api.rabbigerzi.com`
|
|
|
|
All local and deployment workflows are Nix-first. Run commands from
|
|
`nix develop`, or use direnv with the checked-in `.envrc`.
|
|
|
|
## Required Secrets and Environment
|
|
|
|
Do not commit real secret values. Local examples can live in ignored `.env`
|
|
files, and production secrets should live outside the Nix store.
|
|
|
|
### Required Production Secrets
|
|
|
|
The NixOS module requires
|
|
`services.rabbi-gerzi.backend.environmentFile`. That file must contain:
|
|
|
|
```dotenv
|
|
APP_KEY=base64:replace-with-laravel-app-key
|
|
RABBI_GERZI_INITIAL_ADMIN_EMAIL=admin@example.com
|
|
RABBI_GERZI_INITIAL_ADMIN_PASSWORD=replace-with-a-long-random-password
|
|
```
|
|
|
|
- `APP_KEY` encrypts and signs Laravel application data.
|
|
- `RABBI_GERZI_INITIAL_ADMIN_EMAIL` is the first admin login email.
|
|
- `RABBI_GERZI_INITIAL_ADMIN_PASSWORD` is used only to create that admin if
|
|
it does not already exist.
|
|
|
|
Generate an app key inside the dev shell:
|
|
|
|
```sh
|
|
cd backend
|
|
php artisan key:generate --show
|
|
```
|
|
|
|
### Public Frontend Config
|
|
|
|
The frontend build needs the public API origin:
|
|
|
|
```dotenv
|
|
VITE_API_BASE_URL=https://api.rabbigerzi.com
|
|
```
|
|
|
|
For NixOS deployment this is handled by
|
|
`services.rabbi-gerzi.frontend.apiBaseUrl`, which defaults to the backend
|
|
public URL.
|
|
|
|
### NixOS Runtime Config
|
|
|
|
The NixOS module supplies these non-secret runtime values:
|
|
|
|
| Setting | Production value |
|
|
|---|---|
|
|
| `APP_ENV` | `production` |
|
|
| `APP_DEBUG` | `false` |
|
|
| `APP_URL` | `https://api.rabbigerzi.com` |
|
|
| `CORS_ALLOWED_ORIGINS` | `https://rabbigerzi.com` by default |
|
|
| `DB_CONNECTION` | `pgsql` |
|
|
| `DB_HOST` | `/run/postgresql` |
|
|
| `DB_DATABASE` | `rabbi-gerzi` by default |
|
|
| `DB_USERNAME` | `rabbi-gerzi` by default |
|
|
| `FILESYSTEM_DISK` | `public` |
|
|
| `LARAVEL_STORAGE_PATH` | `/var/lib/rabbi-gerzi/storage` by default |
|
|
| `SESSION_DRIVER` | `database` |
|
|
| `SESSION_DOMAIN` | empty by default, meaning host-only cookies |
|
|
| `SESSION_SAME_SITE` | `none` by default |
|
|
| `SESSION_SECURE_COOKIE` | `true` by default |
|
|
| `CACHE_STORE` | `file` |
|
|
| `QUEUE_CONNECTION` | `sync` |
|
|
| `MAIL_MAILER` | `log` |
|
|
|
|
The module also manages PostgreSQL, php-fpm, nginx, writable storage/cache
|
|
directories, and the 6 MB upload limit for nginx and PHP.
|
|
|
|
### Local Environment Files
|
|
|
|
Backend local configuration starts from:
|
|
|
|
```sh
|
|
cd backend
|
|
cp .env.example .env
|
|
php artisan key:generate
|
|
```
|
|
|
|
The checked-in example already targets the Nix dev PostgreSQL socket through
|
|
`PGHOST`, and uses the `postgres` local database/user.
|
|
|
|
Frontend local configuration should point Vite at the local backend:
|
|
|
|
```sh
|
|
cd frontend/rabbi_gerzi
|
|
printf '%s\n' 'VITE_API_BASE_URL=http://127.0.0.1:8000' > .env.local
|
|
```
|
|
|
|
## Local Development
|
|
|
|
Enter the Nix dev shell before running local development commands:
|
|
|
|
```sh
|
|
nix develop
|
|
```
|
|
|
|
If direnv is installed:
|
|
|
|
```sh
|
|
direnv allow
|
|
```
|
|
|
|
The dev shell provides PHP, Composer, Node, PostgreSQL, Cypress,
|
|
process-compose, TypeScript tooling, formatters, linters, and Nix formatters.
|
|
It also initializes a local PostgreSQL cluster in `.postgres` when needed.
|
|
|
|
Install dependencies:
|
|
|
|
```sh
|
|
cd backend
|
|
composer install
|
|
|
|
cd ../frontend/rabbi_gerzi
|
|
npm install --legacy-peer-deps
|
|
```
|
|
|
|
Create local environment files:
|
|
|
|
```sh
|
|
cd ../../backend
|
|
cp .env.example .env
|
|
php artisan key:generate
|
|
|
|
cd ../frontend/rabbi_gerzi
|
|
printf '%s\n' 'VITE_API_BASE_URL=http://127.0.0.1:8000' > .env.local
|
|
```
|
|
|
|
Start the local services from the repo root:
|
|
|
|
```sh
|
|
process-compose up
|
|
```
|
|
|
|
This starts:
|
|
|
|
- PostgreSQL on the local Unix socket under `.postgres`.
|
|
- Laravel at `http://127.0.0.1:8000`.
|
|
- Vite at `http://localhost:5173`.
|
|
|
|
In another dev-shell terminal, prepare the database:
|
|
|
|
```sh
|
|
cd backend
|
|
php artisan migrate:fresh --seed
|
|
```
|
|
|
|
The seed admin login is:
|
|
|
|
```text
|
|
admin@rabbigerzi.test
|
|
password123!@#
|
|
```
|
|
|
|
## Testing
|
|
|
|
Run local tests from `nix develop`. To run the entire local test suite, keep
|
|
the app stack running in one dev-shell terminal:
|
|
|
|
```sh
|
|
nix develop
|
|
process-compose up
|
|
```
|
|
|
|
Then run backend, frontend, and Cypress checks from another dev-shell
|
|
terminal. `process-compose` provides the PostgreSQL database, Laravel backend,
|
|
and Vite frontend needed by the full suite.
|
|
|
|
Backend tests live under `backend/tests`.
|
|
|
|
- Unit tests exercise domain entities, use cases, middleware, controllers, and
|
|
fake repositories without requiring PostgreSQL.
|
|
- Feature tests exercise HTTP endpoints, Laravel routing, migrations, seed
|
|
data, and real framework integration.
|
|
- PHPUnit is configured to use an in-memory SQLite database for test runs.
|
|
|
|
Run backend tests:
|
|
|
|
```sh
|
|
cd backend
|
|
./vendor/bin/phpunit tests
|
|
```
|
|
|
|
Run backend style checks:
|
|
|
|
```sh
|
|
cd backend
|
|
phpcs app tests routes database
|
|
```
|
|
|
|
Frontend quality checks live under `frontend/rabbi_gerzi`.
|
|
|
|
- `npm run format` checks and formats Vue and TypeScript source with oxfmt.
|
|
- `npm run lint` runs oxlint and eslint.
|
|
- `npm run type-check` runs vue-tsc against the Vite application.
|
|
|
|
Run frontend checks:
|
|
|
|
```sh
|
|
cd frontend/rabbi_gerzi
|
|
npm run format
|
|
npm run lint
|
|
npm run type-check
|
|
```
|
|
|
|
Cypress E2E tests live under `frontend/rabbi_gerzi/cypress/e2e`.
|
|
|
|
- Specs drive the UI through the Vite frontend at `http://localhost:5173`.
|
|
- The Laravel backend must be running at `http://127.0.0.1:8000`.
|
|
- The Cypress config creates a seeded PostgreSQL template database before the
|
|
run and resets the app database between specs with the `db:reset` task.
|
|
- Seeded media assets are copied into `backend/storage/app/public` for each
|
|
reset.
|
|
|
|
Run E2E tests after `process-compose up` is healthy:
|
|
|
|
```sh
|
|
cd frontend/rabbi_gerzi
|
|
npm run test:e2e
|
|
```
|
|
|
|
Open the Cypress runner:
|
|
|
|
```sh
|
|
cd frontend/rabbi_gerzi
|
|
npm run test:e2e:open
|
|
```
|
|
|
|
## Verification
|
|
|
|
Run the full local suite from a second dev-shell terminal while
|
|
`process-compose up` is running:
|
|
|
|
```sh
|
|
cd backend
|
|
phpcs app tests routes database
|
|
./vendor/bin/phpunit tests
|
|
|
|
cd ../frontend/rabbi_gerzi
|
|
npm run format
|
|
npm run lint
|
|
npm run type-check
|
|
npm run test:e2e
|
|
```
|
|
|
|
Run the full Nix package and module checks:
|
|
|
|
```sh
|
|
nix flake check
|
|
```
|
|
|
|
## Deployment
|
|
|
|
Deploy through the flake's NixOS module. The module builds the frontend with
|
|
`VITE_API_BASE_URL=https://api.rabbigerzi.com`, serves it from nginx, runs the
|
|
Laravel backend with php-fpm, provisions PostgreSQL, creates writable storage
|
|
and cache directories, runs migrations, and ensures the initial admin exists.
|
|
|
|
Example host configuration:
|
|
|
|
```nix
|
|
{
|
|
inputs = {
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
rabbi-gerzi.url = "git+ssh://git@example.com/rabbi-gerzi.git";
|
|
|
|
sops-nix = {
|
|
url = "github:Mic92/sops-nix";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
};
|
|
};
|
|
|
|
outputs =
|
|
{
|
|
nixpkgs,
|
|
rabbi-gerzi,
|
|
sops-nix,
|
|
...
|
|
}:
|
|
{
|
|
nixosConfigurations.rabbigerzi = nixpkgs.lib.nixosSystem {
|
|
system = "x86_64-linux";
|
|
modules = [
|
|
rabbi-gerzi.nixosModules.default
|
|
sops-nix.nixosModules.sops
|
|
(
|
|
{ config, ... }:
|
|
let
|
|
appKey = config.sops.placeholder."app-key";
|
|
initialAdminEmail =
|
|
config.sops.placeholder."admin-email";
|
|
initialAdminPassword =
|
|
config.sops.placeholder."admin-password";
|
|
in
|
|
{
|
|
sops = {
|
|
defaultSopsFile = ./secrets/rabbi-gerzi.yaml;
|
|
age.sshKeyPaths = [
|
|
"/etc/ssh/ssh_host_ed25519_key"
|
|
];
|
|
|
|
secrets = {
|
|
"app-key" = { };
|
|
"admin-email" = { };
|
|
"admin-password" = { };
|
|
};
|
|
|
|
templates."rabbi-gerzi.env".content = ''
|
|
APP_KEY=${appKey}
|
|
RABBI_GERZI_INITIAL_ADMIN_EMAIL=${initialAdminEmail}
|
|
RABBI_GERZI_INITIAL_ADMIN_PASSWORD=${initialAdminPassword}
|
|
'';
|
|
};
|
|
|
|
services.rabbi-gerzi = {
|
|
enable = true;
|
|
|
|
frontend.hostName = "rabbigerzi.com";
|
|
|
|
backend = {
|
|
hostName = "api.rabbigerzi.com";
|
|
environmentFile =
|
|
config.sops.templates."rabbi-gerzi.env".path;
|
|
};
|
|
};
|
|
}
|
|
)
|
|
];
|
|
};
|
|
};
|
|
}
|
|
```
|
|
|
|
If the API origin must be set explicitly, use:
|
|
|
|
```nix
|
|
services.rabbi-gerzi.frontend.apiBaseUrl =
|
|
"https://api.rabbigerzi.com";
|
|
```
|
|
|
|
Configure `.sops.yaml` with age recipients for each administrator and the
|
|
server's SSH Ed25519 host key. Then create the encrypted secrets file:
|
|
|
|
```sh
|
|
sops secrets/rabbi-gerzi.yaml
|
|
```
|
|
|
|
Add these values in the editor opened by `sops`:
|
|
|
|
```yaml
|
|
app-key: base64:replace-with-laravel-app-key
|
|
admin-email: admin@example.com
|
|
admin-password: replace-with-a-long-random-password
|
|
```
|
|
|
|
Commit only the encrypted file written by `sops`. At activation time,
|
|
`sops-nix` decrypts these values and renders the runtime environment file
|
|
outside the Nix store.
|
|
|
|
Then rebuild the host with the deployment method used by the server, for
|
|
example:
|
|
|
|
```sh
|
|
sudo nixos-rebuild switch --flake .#rabbigerzi
|
|
```
|
|
|
|
During activation, `rabbi-gerzi-setup` runs:
|
|
|
|
```sh
|
|
php artisan migrate --force
|
|
php artisan rabbi-gerzi:ensure-initial-admin
|
|
```
|
|
|
|
The initial admin command is idempotent. If the configured admin email already
|
|
exists, it leaves the user unchanged.
|
|
|
|
## Useful Nix Outputs
|
|
|
|
Build the frontend package:
|
|
|
|
```sh
|
|
nix build .#frontend
|
|
```
|
|
|
|
Build the backend package:
|
|
|
|
```sh
|
|
nix build .#backend
|
|
```
|
|
|
|
Evaluate all checks:
|
|
|
|
```sh
|
|
nix flake check
|
|
```
|