Skip to content

Commit 9a67815

Browse files
committed
feat: Add local desktop installation support with LXD sandboxing
- Add --local/--desktop flag to install.sh for sandboxed installation - Create scripts/lib/sandbox.sh for LXD container management - Create scripts/local/acfs_container.sh (acfs-local CLI) - Create scripts/local/lxd_bootstrap.sh for host preparation - Add is_lxd_container() and is_container() to os_detect.sh - Add onboarding lesson 21_local_desktop.md - Add Local Desktop Installation section to README.md - Add integration test tests/vm/test_local_install.sh The sandbox isolates all invasive ACFS operations (passwordless sudo, SSH config, user creation) inside an LXD system container, allowing safe use on personal Ubuntu desktop machines. Configuration: - Container name: acfs-local - Workspace: ~/acfs-workspace ↔ /data/projects - Dashboard port: 38080
1 parent 2f4aaae commit 9a67815

8 files changed

Lines changed: 1411 additions & 0 deletions

File tree

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,35 @@ The installer is **idempotent**—if interrupted, simply re-run it. It will auto
4141
> ```
4242
> Tagged releases are tested and stable. Setting `ACFS_REF` ensures all fetched scripts use the same version.
4343
44+
### Local Desktop Installation (Sandboxed)
45+
46+
Run ACFS on your personal Ubuntu desktop without modifying your host system:
47+
48+
```bash
49+
git clone https://github.com/Dicklesworthstone/agentic_coding_flywheel_setup.git
50+
cd agentic_coding_flywheel_setup
51+
./install.sh --local --yes
52+
```
53+
54+
This provisions an **LXD system container** that:
55+
- Contains all invasive operations (passwordless sudo, SSH config, etc.)
56+
- Shares a workspace directory at `~/acfs-workspace`
57+
- Forwards dashboard to `localhost:38080`
58+
59+
**Requirements:**
60+
- Ubuntu 22.04+ desktop
61+
- snap installed (default on Ubuntu)
62+
- ~10GB disk space for container
63+
64+
**Access your ACFS environment:**
65+
```bash
66+
acfs-local shell # Enter sandbox shell
67+
acfs-local dashboard # Open dashboard in browser
68+
acfs-local status # View container info
69+
```
70+
71+
> **Why sandbox?** ACFS is designed for fresh VPS instances and intentionally modifies system-level configurations. The sandbox isolates these changes, protecting your personal machine.
72+
4473
---
4574

4675
## TL;DR
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
# Lesson 21: Local Desktop Mode
2+
3+
**Duration:** 5 minutes
4+
5+
## What You'll Learn
6+
7+
- How local desktop mode works
8+
- Entering and exiting your ACFS sandbox
9+
- Managing your workspace
10+
- Accessing the dashboard
11+
12+
---
13+
14+
## What Is Local Desktop Mode?
15+
16+
Unlike the standard VPS installation, **local desktop mode** runs ACFS inside an isolated LXD container on your Ubuntu PC. This means:
17+
18+
- ✅ Your host system is never modified
19+
- ✅ Passwordless sudo and agent permissions are safely sandboxed
20+
- ✅ You can experiment freely without risk
21+
- ✅ Easy cleanup: just destroy the container
22+
23+
> **Think of it like:** A virtual machine, but lighter and faster. Your coding environment lives in its own bubble.
24+
25+
---
26+
27+
## Entering Your ACFS Sandbox
28+
29+
After installation, your ACFS environment lives inside a container. To enter it:
30+
31+
```bash
32+
acfs-local shell
33+
```
34+
35+
You'll see a prompt like:
36+
37+
```
38+
ubuntu@acfs-local:~$
39+
```
40+
41+
This is your sandboxed environment. All your agents and tools are here!
42+
43+
To exit and return to your host:
44+
45+
```bash
46+
exit
47+
```
48+
49+
---
50+
51+
## Your Workspace
52+
53+
Your projects are shared between host and container:
54+
55+
| Location | Description |
56+
|----------|-------------|
57+
| **Host:** `~/acfs-workspace/` | On your regular desktop |
58+
| **Container:** `/data/projects/` | Same files, accessible inside sandbox |
59+
60+
Files you create in either location appear in both places instantly.
61+
62+
**Example:**
63+
64+
```bash
65+
# On host
66+
touch ~/acfs-workspace/hello.txt
67+
68+
# Inside container
69+
ls /data/projects/
70+
# → hello.txt
71+
```
72+
73+
---
74+
75+
## Useful Commands
76+
77+
| Command | What It Does |
78+
|---------|--------------|
79+
| `acfs-local shell` | Enter sandbox shell |
80+
| `acfs-local status` | Show container state and access info |
81+
| `acfs-local start` | Start the container |
82+
| `acfs-local stop` | Stop the container |
83+
| `acfs-local dashboard` | Open dashboard in browser |
84+
| `acfs-local doctor` | Run health check inside container |
85+
| `acfs-local destroy` | Remove container (keeps workspace) |
86+
87+
---
88+
89+
## Accessing the Dashboard
90+
91+
The ACFS dashboard is available at:
92+
93+
```
94+
http://localhost:38080
95+
```
96+
97+
Or run:
98+
99+
```bash
100+
acfs-local dashboard
101+
```
102+
103+
This automatically opens your browser to the dashboard.
104+
105+
---
106+
107+
## Working with Agents
108+
109+
Once inside the sandbox (`acfs-local shell`), all your agents work normally:
110+
111+
```bash
112+
# Claude Code (vibe mode)
113+
cc "Build a hello world API"
114+
115+
# Codex
116+
cod
117+
118+
# Gemini
119+
gmi
120+
```
121+
122+
Remember: These agents have full permissions **inside the sandbox**, but cannot touch your host system.
123+
124+
---
125+
126+
## Container Lifecycle
127+
128+
Your container persists across reboots! But you can manage it:
129+
130+
**Stopping (saves resources):**
131+
```bash
132+
acfs-local stop
133+
```
134+
135+
**Starting back up:**
136+
```bash
137+
acfs-local start
138+
```
139+
140+
**Complete removal:**
141+
```bash
142+
acfs-local destroy
143+
```
144+
145+
> **Note:** Destroying the container keeps your `~/acfs-workspace` files safe. Only the container environment is removed.
146+
147+
---
148+
149+
## Quick Reference
150+
151+
| Task | Command |
152+
|------|---------|
153+
| Enter environment | `acfs-local shell` |
154+
| Check status | `acfs-local status` |
155+
| Run agents | Inside shell: `cc`, `cod`, `gmi` |
156+
| Access projects | Host: `~/acfs-workspace` |
157+
| View dashboard | `acfs-local dashboard` |
158+
| Health check | `acfs-local doctor` |
159+
160+
---
161+
162+
## Troubleshooting
163+
164+
**Container won't start?**
165+
```bash
166+
lxc list # Check container state
167+
lxc info acfs-local # View detailed info
168+
```
169+
170+
**Need to reinstall?**
171+
```bash
172+
acfs-local destroy --force
173+
acfs-local create
174+
```
175+
176+
**Low on disk space?**
177+
The container uses ~5-10GB. Check with:
178+
```bash
179+
df -h ~/snap/lxd/
180+
```
181+
182+
---
183+
184+
## Next Steps
185+
186+
- Run `acfs-local shell` and try `acfs doctor`
187+
- Create a project in `~/acfs-workspace`
188+
- Launch an agent with `cc "describe this project"`
189+
190+
**Congratulations!** You're ready to use ACFS on your desktop safely. 🎉

install.sh

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
# --auto-fix-dry-run Show what auto-fix would do without executing
2727
# --skip-ubuntu-upgrade Skip automatic Ubuntu version upgrade
2828
# --target-ubuntu=VER Set target Ubuntu version (default: 25.10)
29+
# --local / --desktop Run in sandboxed LXD container (for desktop PCs)
2930
# --strict Treat ALL tools as critical (any checksum mismatch aborts)
3031
# --list-modules List available modules and exit
3132
# --print-plan Print execution plan and exit (no installs)
@@ -100,6 +101,10 @@ SKIP_POSTGRES=false
100101
SKIP_VAULT=false
101102
SKIP_CLOUD=false
102103

104+
# Local desktop installation mode (LXD sandboxing)
105+
# When true, ACFS runs inside an LXD container to protect the host
106+
LOCAL_MODE=false
107+
103108
# Manifest-driven selection options (mjt.5.3)
104109
LIST_MODULES=false
105110
PRINT_PLAN_MODE=false
@@ -1002,6 +1007,11 @@ parse_args() {
10021007
SKIP_CLOUD=true
10031008
shift
10041009
;;
1010+
--local|--desktop)
1011+
# Enable local desktop installation mode with LXD sandboxing
1012+
LOCAL_MODE=true
1013+
shift
1014+
;;
10051015
--resume)
10061016
export ACFS_FORCE_RESUME=true
10071017
shift
@@ -5099,6 +5109,53 @@ main() {
50995109
export ACFS_INTERACTIVE=false
51005110
fi
51015111

5112+
# Local Desktop Mode: If --local/--desktop was passed and we're NOT already
5113+
# inside an LXD container, redirect to acfs-local create (sandbox provisioning)
5114+
if [[ "$LOCAL_MODE" == "true" ]]; then
5115+
# Source os_detect to get is_lxd_container function
5116+
local lib_dir
5117+
if [[ -n "${SCRIPT_DIR:-}" ]]; then
5118+
lib_dir="$SCRIPT_DIR/scripts/lib"
5119+
else
5120+
# Fallback: attempt to find the lib directory relative to this script
5121+
lib_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/scripts/lib"
5122+
fi
5123+
5124+
if [[ -f "$lib_dir/os_detect.sh" ]]; then
5125+
# shellcheck source=scripts/lib/os_detect.sh
5126+
source "$lib_dir/os_detect.sh"
5127+
fi
5128+
5129+
# Check if we're inside an LXD container
5130+
if declare -f is_lxd_container &>/dev/null && ! is_lxd_container; then
5131+
# We're on the host - redirect to acfs-local container management
5132+
local local_script
5133+
if [[ -n "${SCRIPT_DIR:-}" ]]; then
5134+
local_script="$SCRIPT_DIR/scripts/local/acfs_container.sh"
5135+
else
5136+
local_script="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/scripts/local/acfs_container.sh"
5137+
fi
5138+
5139+
if [[ -x "$local_script" ]]; then
5140+
echo ""
5141+
echo "╔══════════════════════════════════════════════════════════════╗"
5142+
echo "║ ACFS Local Desktop Mode Detected ║"
5143+
echo "╠══════════════════════════════════════════════════════════════╣"
5144+
echo "║ Redirecting to sandboxed installation... ║"
5145+
echo "║ Your host system will NOT be modified. ║"
5146+
echo "╚══════════════════════════════════════════════════════════════╝"
5147+
echo ""
5148+
exec "$local_script" create
5149+
else
5150+
log_error "Local desktop mode requires scripts/local/acfs_container.sh"
5151+
log_error "Please clone the full ACFS repository first."
5152+
exit 1
5153+
fi
5154+
fi
5155+
# If we're already inside a container, continue normal installation
5156+
log_detail "Inside LXD container - proceeding with normal installation"
5157+
fi
5158+
51025159
# Handle --pin-ref early (before any heavy setup) - just resolve SHA and exit
51035160
if [[ "$PIN_REF_MODE" == "true" ]]; then
51045161
fetch_commit_sha

scripts/lib/os_detect.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,27 @@ is_docker() {
136136
fi
137137
return 1
138138
}
139+
140+
# Check if running inside LXD/LXC container (ACFS local desktop mode)
141+
# Used to detect when we're inside the ACFS sandbox
142+
is_lxd_container() {
143+
# LXD sets container environment variable
144+
if [[ "${container:-}" == "lxc" ]]; then
145+
return 0
146+
fi
147+
# Fallback: check for LXD-specific cgroup markers
148+
if grep -q lxc /proc/1/cgroup 2>/dev/null; then
149+
return 0
150+
fi
151+
# Fallback: check for container-specific boot marker
152+
if [[ -f /dev/.lxc-boot-id ]]; then
153+
return 0
154+
fi
155+
return 1
156+
}
157+
158+
# Check if running in any container (Docker, LXD, etc.)
159+
is_container() {
160+
is_docker || is_lxd_container
161+
}
162+

0 commit comments

Comments
 (0)