406 lines
11 KiB
Markdown
406 lines
11 KiB
Markdown
# Self-hosted Fruix development
|
|
|
|
This guide describes the current human-facing path for:
|
|
|
|
1. building a Fruix installer ISO for the self-hosted development system
|
|
2. installing that system onto a VM or machine
|
|
3. turning the installed node into a practical Fruix development host
|
|
|
|
This path is now validated most strongly in VM workflows, especially the
|
|
current XCP-ng loop, but the same basic process applies to any machine that can
|
|
boot the generated installer ISO.
|
|
|
|
## What this system is for
|
|
|
|
`examples/system/self-hosted-dev.scm` defines a Fruix node intended to:
|
|
|
|
- run Fruix locally
|
|
- expose SSH for operator access
|
|
- provide a development profile with the current editor/runtime tooling
|
|
- provide a sanitized build profile for native base/package work
|
|
- serve as a host for the pi-agent-style development workflow
|
|
|
|
Today that development profile includes the currently recovered developer tools,
|
|
notably:
|
|
|
|
- Clang toolchain
|
|
- GNU make + FreeBSD make files
|
|
- Autotools
|
|
- OpenSSL + zlib
|
|
- sh + bash
|
|
- Node.js + npm
|
|
- ripgrep
|
|
- tmux
|
|
- neovim
|
|
|
|
## Before you build
|
|
|
|
### 1. Prepare a Fruix builder host
|
|
|
|
The commands below assume:
|
|
|
|
- you are on a FreeBSD host
|
|
- `fruix-bootstrap` has already prepared a builder root
|
|
- this repo is checked out locally
|
|
|
|
The checkout entrypoint prefers a prepared builder root at:
|
|
|
|
- `~/.local/opt/fruix-builder`
|
|
|
|
So if that builder exists, you can usually invoke Fruix from the checkout with:
|
|
|
|
```sh
|
|
./bin/fruix ...
|
|
```
|
|
|
|
### 2. Copy the example declaration and customize it
|
|
|
|
Start from the example:
|
|
|
|
```sh
|
|
cp examples/system/self-hosted-dev.scm my-self-hosted-dev.scm
|
|
```
|
|
|
|
At minimum, edit:
|
|
|
|
- `#:host-name`
|
|
- `#:root-authorized-keys` for remote SSH access
|
|
- any user/account details you want to change
|
|
|
|
A minimal customization usually looks like:
|
|
|
|
```scheme
|
|
(use-modules (fruix system freebsd)
|
|
(fruix packages freebsd))
|
|
|
|
(define self-hosted-development-operating-system
|
|
(operating-system
|
|
#:host-name "fruix-dev-1"
|
|
#:rc-conf-entries '(("clear_tmp_enable" . "YES")
|
|
("sendmail_enable" . "NONE")
|
|
("sshd_enable" . "YES"))
|
|
#:root-authorized-keys
|
|
'("ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... you@example")
|
|
#:development-packages %freebsd-development-profile-packages
|
|
#:build-packages %freebsd-development-profile-packages))
|
|
```
|
|
|
|
If you skip `#:root-authorized-keys`, the installed node may still be usable
|
|
from the console, but it will not be ready for the normal remote development
|
|
loop.
|
|
|
|
### 3. Pick a store directory with real space
|
|
|
|
Image and installer builds can be large. Prefer a store directory with plenty of
|
|
space, for example:
|
|
|
|
```sh
|
|
mkdir -p /var/tmp/fruix-selfhosted-store
|
|
```
|
|
|
|
## Build the installer ISO
|
|
|
|
Run:
|
|
|
|
```sh
|
|
./bin/fruix system installer-iso ./my-self-hosted-dev.scm \
|
|
--system self-hosted-development-operating-system \
|
|
--store /var/tmp/fruix-selfhosted-store \
|
|
> /tmp/self-hosted-installer-iso.out
|
|
```
|
|
|
|
The command prints metadata rather than just one path. Recover the ISO path
|
|
from the output like this:
|
|
|
|
```sh
|
|
iso=$(sed -n 's/^iso_image=//p' /tmp/self-hosted-installer-iso.out | sed -n '$p')
|
|
printf 'ISO: %s\n' "$iso"
|
|
```
|
|
|
|
Other useful fields in that output are:
|
|
|
|
- `iso_store_path=`
|
|
- `installer_closure_path=`
|
|
- `target_closure_path=`
|
|
- `installer_state_path=`
|
|
|
|
If you want to inspect the whole result later, keep the metadata file:
|
|
|
|
```sh
|
|
less /tmp/self-hosted-installer-iso.out
|
|
```
|
|
|
|
## Boot and install
|
|
|
|
### 1. Boot the ISO
|
|
|
|
Use the generated `installer.iso` in whichever way is convenient for your
|
|
hardware or VM platform:
|
|
|
|
- attach it as virtual media in a VM
|
|
- boot it as a CD/DVD image
|
|
- or write it to removable media using your usual FreeBSD workflow
|
|
|
|
For development use, give the target disk enough headroom. In practice,
|
|
something in the **20-40 GiB** range is a much better starting point than a
|
|
minimal test disk.
|
|
|
|
### 2. Use the installer
|
|
|
|
The current intended human path from the booted installer is:
|
|
|
|
```sh
|
|
/usr/local/bin/fruix system installer-tui
|
|
```
|
|
|
|
That starts the current experimental Newt-based installer flow.
|
|
|
|
Notes:
|
|
|
|
- this is still marked experimental
|
|
- the ISO was built from your declaration, so this is the path to try first
|
|
- if you are installing in a VM, use the VM console for the TUI
|
|
|
|
### 3. If you need the direct CLI install path
|
|
|
|
If you want an explicit non-interactive install from the booted installer
|
|
environment, use `fruix system install` and pass the declaration file
|
|
explicitly.
|
|
|
|
Direct installs to `/dev/...` targets are intentionally gated. In the installer
|
|
shell, when you are already root, the simplest current pattern is:
|
|
|
|
```sh
|
|
export FRUIX_ASSEMBLY_PRIVILEGED_COMMAND=env
|
|
export FRUIX_ASSEMBLY_ALLOW_BLOCK_DEVICE_TARGETS=1
|
|
|
|
/usr/local/bin/fruix system install /run/current-system/metadata/system-declaration.scm \
|
|
--system self-hosted-development-operating-system \
|
|
--target /dev/vtbd0
|
|
```
|
|
|
|
Adjust `/dev/vtbd0` to the real target device.
|
|
|
|
If you use this path, remember:
|
|
|
|
- it is destructive for the selected target
|
|
- block-device installs are opt-in on purpose
|
|
- the TUI path is the friendlier default for humans
|
|
|
|
## First boot after installation
|
|
|
|
Once the installed system boots, log in on the console or over SSH and do a
|
|
quick sanity check:
|
|
|
|
```sh
|
|
/usr/local/bin/fruix system status
|
|
```
|
|
|
|
You should see metadata describing the current generation, closure, and default
|
|
declaration paths.
|
|
|
|
If you added root SSH keys in the declaration, verify remote access from your
|
|
operator machine.
|
|
|
|
## Development environment on the installed node
|
|
|
|
The installed self-hosted system already includes two important helper scripts.
|
|
|
|
### 1. General development shell
|
|
|
|
For editor/runtime/package-development work:
|
|
|
|
```sh
|
|
eval "$(/usr/local/bin/fruix-development-environment)"
|
|
```
|
|
|
|
That exports a development-oriented environment pointing at:
|
|
|
|
- `/run/current-system/development-profile`
|
|
- compiler/toolchain paths
|
|
- Node/npm paths
|
|
- runtime library paths
|
|
- man pages and other tool metadata
|
|
|
|
After enabling it, useful smoke checks are:
|
|
|
|
```sh
|
|
cc --version
|
|
node --version
|
|
npm --version
|
|
rg --version
|
|
tmux -V
|
|
nvim --version | sed -n '1p'
|
|
```
|
|
|
|
### 2. Sanitized build shell
|
|
|
|
For native FreeBSD base rebuild work and stricter build testing:
|
|
|
|
```sh
|
|
eval "$(/usr/local/bin/fruix-build-environment)"
|
|
```
|
|
|
|
That switches to the build-profile-oriented environment and drops the normal
|
|
development-shell overrides that would interfere with more controlled builds.
|
|
|
|
Useful quick checks:
|
|
|
|
```sh
|
|
echo "$FRUIX_BUILD_PROFILE"
|
|
make -V .CURDIR >/dev/null
|
|
```
|
|
|
|
### 3. Optional native base rebuild helper
|
|
|
|
The self-hosted system also installs:
|
|
|
|
- `/usr/local/bin/fruix-self-hosted-native-build`
|
|
|
|
and exposes it through:
|
|
|
|
```sh
|
|
/usr/local/bin/fruix system build-base
|
|
```
|
|
|
|
That is the current node-local helper for rebuilding FreeBSD world/kernel
|
|
artifacts from the staged source tree. It is useful, but it is a heavier,
|
|
longer-running workflow than ordinary declaration or package iteration.
|
|
|
|
## Working on Fruix itself from the installed node
|
|
|
|
There are two different Fruix entrypoints on an installed self-hosted node, and
|
|
it helps to use the right one.
|
|
|
|
### 1. The installed node CLI
|
|
|
|
```sh
|
|
/usr/local/bin/fruix
|
|
```
|
|
|
|
Use this for node-local lifecycle operations such as:
|
|
|
|
- `fruix system status`
|
|
- `fruix system reconfigure`
|
|
- `fruix system rollback`
|
|
- `fruix system switch`
|
|
|
|
This CLI is bundled into the installed system closure and is the right tool for
|
|
managing the node you are currently running.
|
|
|
|
### 2. The checkout CLI
|
|
|
|
If you are editing Fruix source code in a working tree, use the checkout
|
|
entrypoint from that tree:
|
|
|
|
```sh
|
|
/path/to/fruix/bin/fruix
|
|
```
|
|
|
|
That path evaluates the Fruix source in your checkout and is what you want when
|
|
changing:
|
|
|
|
- Fruix modules
|
|
- package definitions
|
|
- system render logic
|
|
- installer logic
|
|
- build/materialization code
|
|
|
|
### 3. Getting a checkout onto the node
|
|
|
|
The current self-hosted development profile does **not** yet provide a packaged
|
|
`git`, so the easiest current options are:
|
|
|
|
- copy an existing checkout onto the node with `scp`/`rsync`
|
|
- mount or share a dataset that contains the checkout
|
|
- or add your own temporary host-side transfer step
|
|
|
|
### 4. Preparing the checkout environment
|
|
|
|
For checkout-based work, prepare the node the same way as any other Fruix build
|
|
host:
|
|
|
|
- create or copy in a Fruix checkout
|
|
- prepare `~/.local/opt/fruix-builder` using `fruix-bootstrap`
|
|
- run the checkout via `./bin/fruix`
|
|
|
|
The checkout entrypoint already prefers `~/.local/opt/fruix-builder` when it is
|
|
present.
|
|
|
|
## A practical day-to-day loop
|
|
|
|
### Declaration-only changes
|
|
|
|
If you are only changing the system declaration used by the running node:
|
|
|
|
```sh
|
|
/usr/local/bin/fruix system reconfigure /path/to/my-self-hosted-dev.scm \
|
|
--system self-hosted-development-operating-system
|
|
```
|
|
|
|
That builds a new closure using the node's bundled Fruix payload and switches
|
|
node metadata to the new generation.
|
|
|
|
After a successful reconfigure, plan on a reboot.
|
|
|
|
If you need to undo it:
|
|
|
|
```sh
|
|
/usr/local/bin/fruix system rollback
|
|
```
|
|
|
|
### Fruix source-tree changes
|
|
|
|
If you changed Fruix code in a checkout, build with that checkout:
|
|
|
|
```sh
|
|
/path/to/fruix/bin/fruix system build /path/to/my-self-hosted-dev.scm \
|
|
--system self-hosted-development-operating-system \
|
|
--store /var/tmp/fruix-dev-store \
|
|
> /tmp/fruix-build.out
|
|
```
|
|
|
|
Recover the closure path:
|
|
|
|
```sh
|
|
closure=$(sed -n 's/^closure_path=//p' /tmp/fruix-build.out | sed -n '$p')
|
|
printf 'closure: %s\n' "$closure"
|
|
```
|
|
|
|
Then switch the running node to that closure:
|
|
|
|
```sh
|
|
/usr/local/bin/fruix system switch "$closure"
|
|
```
|
|
|
|
Again, plan on a reboot after switching.
|
|
|
|
## Recommended post-install checklist
|
|
|
|
For a node that should serve as a real self-hosted Fruix development box, the
|
|
useful immediate checklist is:
|
|
|
|
- [ ] confirm SSH access works with your real operator key
|
|
- [ ] run `/usr/local/bin/fruix system status`
|
|
- [ ] enable the development environment and check `cc`, `node`, `npm`, `tmux`, and `nvim`
|
|
- [ ] copy a Fruix checkout onto the machine
|
|
- [ ] prepare `~/.local/opt/fruix-builder` on the node
|
|
- [ ] verify the checkout entrypoint works: `./bin/fruix --help`
|
|
- [ ] keep a scratch store directory for checkout builds, e.g. `/var/tmp/fruix-dev-store`
|
|
- [ ] do one full `reconfigure` and one `rollback` before treating the node as a daily driver
|
|
|
|
## Current limitations and expectations
|
|
|
|
This workflow is useful now, but it is still an actively developing path.
|
|
|
|
Important current expectations:
|
|
|
|
- the self-hosted path is real and usable, but not yet the final polished Fruix
|
|
product workflow
|
|
- the installed-node lifecycle is farther along than the broader deploy/upgrade
|
|
story
|
|
- the development profile is practical, but still intentionally small and
|
|
transitional
|
|
- some rough edges remain; treat the current system as a serious development
|
|
environment, not yet a finished distribution experience
|