Skip to content

Commit 0c48e2f

Browse files
authored
DNF5, AI, AI agents, docs update (#2)
1 parent 7c67883 commit 0c48e2f

17 files changed

Lines changed: 1670 additions & 208 deletions

File tree

README.md

Lines changed: 43 additions & 197 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,25 @@
22

33
Keep your friends close, your supply chain in a VM.
44

5-
DVM, short for dev VM, is a small open source command-line wrapper around Lima for
6-
Fedora project VMs.
5+
DVM, short for dev VM, is a small Bash wrapper around Lima for Fedora project VMs. It
6+
keeps project code off the host, creates per-VM SSH keys, supports per-VM GPG signing
7+
subkeys, syncs opt-in host dotfiles as snapshots, and provides an isolated `dvm-agent`
8+
user for hosted AI coding tools.
79

8-
The repository contains the reusable core. User-specific VM behavior lives outside the
9-
repo in `~/.config/dvm`, so local configuration can be kept in a separate dotfiles or
10-
project configuration repository.
11-
12-
DVM is intentionally small. It creates similar Lima VMs, reruns user setup scripts,
13-
manages per-VM SSH keys, helps with GPG signing subkeys, and refuses to delete a VM
14-
when repositories have uncommitted changes.
15-
16-
## Install
17-
18-
Requirements:
10+
## Requirements
1911

2012
- macOS
2113
- Bash
2214
- Lima
2315
- GPG for `dvm gpg ...`
2416

17+
Guest support target:
18+
19+
- Lima `template:fedora`
20+
- `dnf5` available in the guest
21+
22+
## Install
23+
2524
For stable installations, use a signed release tag:
2625

2726
```bash
@@ -33,18 +32,12 @@ git checkout --detach vX.Y.Z
3332
./install.sh --init
3433
```
3534

36-
Replace `vX.Y.Z` with the release version to install. The `main` branch is for
37-
development and testing.
38-
3935
This symlinks:
4036

4137
```text
4238
~/.local/bin/dvm -> <repo>/bin/dvm
4339
```
4440

45-
The scripts are written in Bash (`#!/usr/bin/env bash`). This is independent of your
46-
interactive shell; using Zsh as the default macOS shell is fine.
47-
4841
Update the core by moving to a newer signed release tag:
4942

5043
```bash
@@ -57,50 +50,30 @@ git checkout --detach vX.Y.Z
5750

5851
Development checkouts may track `main` and update with `git pull --ff-only`.
5952

60-
## Config
53+
## Quick Start
6154

62-
`dvm init` creates:
63-
64-
```text
65-
~/.config/dvm/config.sh
66-
~/.config/dvm/setup.d/fedora.sh
67-
~/.local/share/dvm/
55+
```bash
56+
dvm init
57+
dvm new myapp
58+
dvm myapp
59+
git clone git@github.com:example/myapp.git ~/code/myapp
6860
```
6961

70-
User configuration is shell code by design and is the extension point.
71-
72-
Common config:
62+
Rerun setup in one VM or every VM:
7363

7464
```bash
75-
DVM_PREFIX="dvm"
76-
DVM_CPUS="4"
77-
DVM_MEMORY="8GiB"
78-
DVM_DISK="80GiB"
79-
80-
DVM_PACKAGES="git openssh-clients gpg helix ripgrep fd-find jq"
81-
DVM_SETUP_SCRIPTS="$DVM_CONFIG/setup.d/fedora.sh"
82-
DVM_DOTFILES_DIR="$HOME/.dotfiles"
65+
dvm setup myapp
66+
dvm setup-all
8367
```
8468

85-
Put package-independent setup, shell config, and tool config in `setup.d/fedora.sh`.
86-
If `DVM_DOTFILES_DIR` is set, DVM copies a snapshot of that host directory into the VM
87-
before user setup scripts run. It does not mount the host directory live. User setup
88-
scripts run inside the VM as the guest user with:
69+
Run hosted AI tools through the restricted agent user:
8970

90-
```text
91-
DVM_NAME
92-
DVM_VM_NAME
93-
DVM_CODE_DIR
94-
DVM_DOTFILES_TARGET
71+
```bash
72+
dvm agent setup myapp
73+
dvm agent install myapp codex
74+
dvm agent myapp -- codex
9575
```
9676

97-
Dotfiles sync is opt-in. By default DVM excludes `.git`, `.ssh`, `.gnupg`, `.env`, and
98-
`secrets`, refuses dangerous source paths such as `/`, `$HOME`, `~/.ssh`, and
99-
`~/.gnupg`, and keeps the target under the guest home directory.
100-
101-
The default workflow keeps source code inside the VM under `~/code`. No host project
102-
directory is mounted.
103-
10477
## Commands
10578

10679
```text
@@ -113,165 +86,38 @@ dvm ssh <name> [command...]
11386
dvm key <name>
11487
dvm list
11588
dvm rm <name> [--force]
116-
dvm gpg create <name> <primary-key> [--expire 1y]
117-
dvm gpg install <name> [secret-subkey.asc] [--signing-key fpr]
118-
dvm gpg revoke <name>
89+
dvm ai create|setup|pull|models|use|status|host ...
90+
dvm agent setup|install|<name> ...
91+
dvm gpg create|install|revoke ...
11992
dvm doctor
12093
dvm completion zsh
12194
```
12295

12396
`dvm <name>` is a shortcut for `dvm enter <name>`.
12497

125-
## Create A VM
98+
## Docs
12699

127-
```bash
128-
dvm new myapp
129-
```
130-
131-
This creates `dvm-myapp`, starts it, runs core setup, runs user setup scripts, creates
132-
`~/.ssh/id_ed25519_myapp` inside the VM, and prints the public key.
133-
134-
Enter it:
135-
136-
```bash
137-
dvm myapp
138-
git clone git@github.com:example/myapp.git ~/code/myapp
139-
```
140-
141-
Rerun setup in one or all VMs:
142-
143-
```bash
144-
dvm setup myapp
145-
dvm setup-all
146-
```
147-
148-
This is the intended way to add packages everywhere or refresh dotfiles snapshots. The
149-
script does not try to remove packages automatically; removals should be explicit and
150-
manual.
151-
152-
## Delete Safety
153-
154-
```bash
155-
dvm rm myapp
156-
```
157-
158-
Before deleting, DVM searches Git repositories under `~/code` in the VM. If any repo
159-
has unstaged changes, staged changes, or untracked files, deletion is refused.
160-
161-
Force deletion:
162-
163-
```bash
164-
dvm rm myapp --force
165-
```
166-
167-
If a GPG signing subkey was created for the VM, `rm` prints the recorded subkey
168-
fingerprint and the revoke command. Deleting a VM does not revoke GPG keys
169-
automatically.
170-
171-
## GPG
172-
173-
Create a signing subkey on the host and export a secret-subkey bundle:
174-
175-
```bash
176-
dvm gpg create myapp <primary-key-id> --expire 1y
177-
```
178-
179-
Files are written under:
180-
181-
```text
182-
~/.local/share/dvm/gpg/
183-
```
184-
185-
Install the subkey into the VM and configure Git commit signing:
186-
187-
```bash
188-
dvm gpg install myapp
189-
```
190-
191-
Revoke the VM subkey on the host:
192-
193-
```bash
194-
dvm gpg revoke myapp
195-
```
196-
197-
Revocation only updates the local GPG keyring and exports the updated public key. It
198-
does not update GitHub/GitLab, remove old public keys from remote services, delete the
199-
secret bundle from disk, or change anything inside an already-deleted VM. Upload the
200-
updated public key wherever the old public key was trusted. Depending on the local GPG
201-
setup, revoke/create commands may open pinentry.
202-
203-
## Doctor
204-
205-
Check local requirements and paths:
206-
207-
```bash
208-
dvm doctor
209-
```
210-
211-
## Completion
212-
213-
Zsh:
214-
215-
```bash
216-
source <(dvm completion zsh)
217-
```
218-
219-
Add that line to a shell startup file to enable completion automatically.
100+
- [Docs index](docs/README.md)
101+
- [VM lifecycle](docs/vms.md)
102+
- [Config and dotfiles](docs/config.md)
103+
- [GPG signing subkeys](docs/gpg.md)
104+
- [Local llama.cpp AI VM](docs/ai-vm.md)
105+
- [Hosted AI tools through `dvm agent`](docs/ai-tools.md)
106+
- [Security policy and model](SECURITY.md)
107+
- [Contributing](CONTRIBUTING.md)
108+
- [Maintainer release process](docs/release.md)
109+
- [GitHub security settings](docs/github-security.md)
220110

221111
## Security
222112

223-
Read [SECURITY.md](SECURITY.md) before installing DVM for stable use. The short
224-
version:
113+
Read [SECURITY.md](SECURITY.md) before installing DVM for stable use. Short version:
225114

226115
- install and update from signed release tags
227116
- keep `main` for development and testing
228117
- do not run remote install scripts directly
229-
- keep VM setup scripts in user-controlled config or dotfiles
230-
- review setup scripts before running `dvm setup` or `dvm setup-all`
231-
232-
Repository maintainer settings are documented in
233-
[docs/github-security.md](docs/github-security.md).
118+
- keep setup scripts in user-controlled config or dotfiles
119+
- run hosted AI tools through `dvm agent`, not the normal VM user
234120

235121
## License
236122

237123
DVM is released under the [MIT License](LICENSE).
238-
239-
## Contributing
240-
241-
Contributions are welcome when they keep the project small, auditable, and focused on
242-
VM lifecycle, SSH, GPG, and user-controlled setup. See
243-
[CONTRIBUTING.md](CONTRIBUTING.md).
244-
245-
## Maintainer Release Process
246-
247-
Maintainer checklist:
248-
249-
```bash
250-
bash scripts/check.sh
251-
git tag -s vX.Y.Z -m "dvm vX.Y.Z"
252-
git push origin main
253-
git push origin vX.Y.Z
254-
```
255-
256-
Create the GitHub release from the signed `v*` tag. Published releases and tags should
257-
not be moved or replaced; publish a new fixed release instead.
258-
259-
## LLaMA VM
260-
261-
llama.cpp can be configured as a normal named VM:
262-
263-
```bash
264-
dvm new ai
265-
```
266-
267-
Place llama-specific package and service setup in `setup.d/fedora.sh` behind a name
268-
check:
269-
270-
```bash
271-
if [ "$DVM_NAME" = "ai" ]; then
272-
sudo dnf5 install -y llama-cpp
273-
# configure a systemd service here
274-
fi
275-
```
276-
277-
This keeps the core small while still making the AI VM reproducible.

SECURITY.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ Useful report details:
2323
## Security Model
2424

2525
DVM is a small wrapper around Lima. It helps isolate project work into separate Fedora
26-
VMs and keeps user-controlled setup outside the core repository. It is not a sandbox
27-
that can provide stronger guarantees than Lima, QEMU, macOS virtualization, SSH, GPG,
28-
or the packages and scripts that users choose to run.
26+
VMs and keeps user-controlled setup outside the core repository. The core targets Lima
27+
`template:fedora` and assumes `dnf5` in the guest. It is not a sandbox that can
28+
provide stronger guarantees than Lima, QEMU, macOS virtualization, SSH, GPG, or the
29+
packages and scripts that users choose to run.
2930

3031
Security-sensitive behavior in scope:
3132

@@ -43,6 +44,11 @@ DVM does not mount host dotfiles into VMs by default. If dotfiles sync is enable
4344
copies a filtered snapshot during setup so project code in the VM does not retain a
4445
persistent read path back to the host.
4546

47+
Hosted AI tools should run through `dvm agent`, which uses a separate VM user and
48+
bubblewrap to hide the normal VM user's home while exposing project code. This limits
49+
access to per-VM SSH keys, GPG subkeys, dotfiles, and secret-manager config, but it
50+
does not make AI-executed project code safe.
51+
4652
## Safe Installation
4753

4854
Install from a signed release tag, not from an arbitrary branch. Before running

bin/dvm

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ source "$DVM_CORE/lib/config.sh"
2626
# shellcheck disable=SC1091
2727
source "$DVM_CORE/lib/vm.sh"
2828
# shellcheck disable=SC1091
29+
source "$DVM_CORE/lib/ai.sh"
30+
# shellcheck disable=SC1091
31+
source "$DVM_CORE/lib/agent.sh"
32+
# shellcheck disable=SC1091
2933
source "$DVM_CORE/lib/gpg.sh"
3034
# shellcheck disable=SC1091
3135
source "$DVM_CORE/lib/doctor.sh"
@@ -44,6 +48,8 @@ usage:
4448
dvm key <name>
4549
dvm list
4650
dvm rm <name> [--force]
51+
dvm ai create|setup|pull|models|use|status|host ...
52+
dvm agent setup|install|<name> ...
4753
dvm gpg create|install|revoke ...
4854
dvm doctor
4955
dvm completion zsh
@@ -67,6 +73,8 @@ dvm_main() {
6773
key) dvm_key "$@" ;;
6874
list | ls) dvm_list_names "$@" ;;
6975
rm | delete) dvm_rm "$@" ;;
76+
ai) dvm_ai_cmd "$@" ;;
77+
agent) dvm_agent_cmd "$@" ;;
7078
gpg) dvm_gpg_cmd "$@" ;;
7179
doctor) dvm_doctor "$@" ;;
7280
completion) dvm_completion "$@" ;;

defaults/config.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,23 @@ DVM_DOTFILES_DIR="${DVM_DOTFILES_DIR:-}"
2929
DVM_DOTFILES_TARGET="${DVM_DOTFILES_TARGET:-$DVM_GUEST_HOME/.dotfiles}"
3030
DVM_DOTFILES_EXCLUDES="${DVM_DOTFILES_EXCLUDES:-.git .ssh .gnupg .env secrets}"
3131

32+
# Optional llama.cpp VM helper config. `dvm ai create` uses these values.
33+
DVM_AI_NAME="${DVM_AI_NAME:-ai}"
34+
DVM_AI_PACKAGES="${DVM_AI_PACKAGES:-llama-cpp curl}"
35+
DVM_AI_SERVER_CMD="${DVM_AI_SERVER_CMD:-llama-server}"
36+
DVM_AI_SERVICE_NAME="${DVM_AI_SERVICE_NAME:-dvm-llama.service}"
37+
DVM_AI_HOST="${DVM_AI_HOST:-0.0.0.0}"
38+
DVM_AI_PORT="${DVM_AI_PORT:-8080}"
39+
DVM_AI_MODELS_DIR="${DVM_AI_MODELS_DIR:-$DVM_GUEST_HOME/models}"
40+
DVM_AI_DEFAULT_MODEL="${DVM_AI_DEFAULT_MODEL:-qwen25-coder-7b-q4}"
41+
# Space-separated alias=url entries. Aliases become model filenames in the VM.
42+
DVM_AI_MODELS="${DVM_AI_MODELS:-qwen25-coder-7b-q4=https://huggingface.co/bartowski/Qwen2.5-Coder-7B-Instruct-GGUF/resolve/main/Qwen2.5-Coder-7B-Instruct-Q4_K_M.gguf?download=true}"
43+
DVM_AI_EXTRA_ARGS="${DVM_AI_EXTRA_ARGS:-}"
44+
45+
# Hosted AI tools should run through `dvm agent`, not the normal VM user.
46+
DVM_AGENT_USER="${DVM_AGENT_USER:-dvm-agent}"
47+
DVM_AGENT_HOME="${DVM_AGENT_HOME:-/home/$DVM_AGENT_USER}"
48+
DVM_AGENT_PACKAGES="${DVM_AGENT_PACKAGES:-bubblewrap acl shadow-utils}"
49+
DVM_AGENT_CLAUDE_CHANNEL="${DVM_AGENT_CLAUDE_CHANNEL:-stable}"
50+
3251
DVM_GPG_DIR="${DVM_GPG_DIR:-$DVM_STATE/gpg}"

0 commit comments

Comments
 (0)