Make 'nix run' spin up the whole stack in one command

This commit is contained in:
kurogeek committed 2026-10-15 07:36:56 +00:00
1 parent c8b08fe258
commit 4d77464988
3 files changed
+56 -26

No files matched your search

+15 -5
View File
@@ -8,15 +8,25 @@ Two Laravel 10 apps sharing one MySQL database (`greaterc_db2024`):
## Local development
Requires [Nix](https://nixos.org) with flakes (direnv optional: `.envrc` → `use flake`).
Requires [Nix](https://nixos.org) with flakes.
```sh
nix develop # php 8.3 + composer + mariadb + node on PATH
dev setup # composer install both apps, init MariaDB under .dev/
dev db import dump.sql # load a production dump — the article/category schema only exists in prod
dev up # http://127.0.0.1:8000 (site), http://127.0.0.1:8001 (CMS); Ctrl-C stops all
nix run # installs vendors on first run, starts MariaDB, serves both apps; Ctrl-C stops all
```
- site: http://127.0.0.1:8000
- CMS: http://127.0.0.1:8001
The site's article pages need the production schema, which only exists in the prod DB:
```sh
mysqldump greaterc_db2024 > dump.sql # on the server
nix run . -- db import dump.sql
```
`nix run . -- <cmd>` forwards to the `dev` script; `nix develop` drops you into a shell with
`dev`, `php`, `composer`, `mariadb`, `node` on PATH (direnv: `.envrc` → `use flake`).
Other commands: `dev db start|stop|status|shell`, `dev serve frontend|backend`,
`dev artisan <app> ...`, `dev down`. See `dev help`.
+14 -3
View File
@@ -65,8 +65,9 @@ db_start() {
echo "db: already running (pid $(cat "$MYSQL_PID"))"
return
fi
mariadbd --datadir="$MYSQL_DATA" --socket="$MYSQL_SOCK" --pid-file="$MYSQL_PID" \
--port="$DB_PORT" --bind-address=127.0.0.1 --skip-name-resolve \
# Ignore terminal Ctrl-C in the DB so `up` can shut it down cleanly after the app servers.
(trap '' INT; exec mariadbd --datadir="$MYSQL_DATA" --socket="$MYSQL_SOCK" --pid-file="$MYSQL_PID" \
--port="$DB_PORT" --bind-address=127.0.0.1 --skip-name-resolve) \
>"$MYSQL_LOG" 2>&1 &
for _ in $(seq 1 50); do
mariadb-admin --socket="$MYSQL_SOCK" -uroot ping >/dev/null 2>&1 && break
@@ -121,9 +122,19 @@ serve() {
}
up() {
for app in "$FRONTEND" "$BACKEND"; do
[ -f "$app/vendor/autoload.php" ] || composer_install
done
db_start
local pids=()
trap 'kill "${pids[@]}" 2>/dev/null; wait; db_stop' EXIT INT TERM
cleanup() {
trap - EXIT INT TERM
set +e
kill "${pids[@]}" 2>/dev/null
wait "${pids[@]}" 2>/dev/null
db_stop
}
trap cleanup EXIT INT TERM
(cd "$FRONTEND" && php artisan serve --host=127.0.0.1 --port="$FRONTEND_PORT") & pids+=($!)
(cd "$BACKEND" && php artisan serve --host=127.0.0.1 --port="$BACKEND_PORT") & pids+=($!)
echo "frontend: http://127.0.0.1:$FRONTEND_PORT"
+27 -18
View File
@@ -7,27 +7,36 @@
let
systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
forAll = f: nixpkgs.lib.genAttrs systems (system: f nixpkgs.legacyPackages.${system});
toolchain = pkgs:
let php = pkgs.php83; in
[ php php.packages.composer pkgs.mariadb pkgs.nodejs_22 ];
in
{
devShells = forAll (pkgs:
let
php = pkgs.php83;
in
{
default = pkgs.mkShell {
packages = [
php
php.packages.composer
pkgs.mariadb
pkgs.nodejs_22
];
devShells = forAll (pkgs: {
default = pkgs.mkShell {
packages = toolchain pkgs;
shellHook = ''
export DEV_ROOT="$PWD"
export PATH="$DEV_ROOT/dev:$PATH"
echo "think-greaterchiangmai dev shell — run 'dev help'"
'';
};
});
shellHook = ''
export DEV_ROOT="$PWD"
export PATH="$DEV_ROOT/dev:$PATH"
echo "think-greaterchiangmai dev shell — run 'dev help'"
# `nix run` = `dev up` with the toolchain on PATH, no `nix develop` needed.
# Runs the checked-out dev/dev (not a store copy) so state lands in the working tree.
apps = forAll (pkgs: {
default = {
type = "app";
program = toString (pkgs.writeShellApplication {
name = "dev";
runtimeInputs = toolchain pkgs;
text = ''
[ -x "$PWD/dev/dev" ] || { echo "run from the repo root (dev/dev not found in $PWD)" >&2; exit 1; }
DEV_ROOT="$PWD" exec "$PWD/dev/dev" "''${@:-up}"
'';
};
});
}) + "/bin/dev";
};
});
};
}