Skip to content

Latest commit

 

History

42 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ward

Ward is a disposable Arch Linux environment for pi and its shared tmux server. It runs as a rootless Podman container under the user systemd instance. It exists to give a coding agent an exact, always-current toolchain that can be rebuilt and discarded at any time, without touching host state.

The image builds from archlinux:latest and installs the full package set in one transaction at build time; a daily rebuild keeps it current. The container runs with dropped capabilities and private namespaces; its writable root is discarded on stop, and only declared bind mounts — projects, selected configuration, and agent state — persist. The tmux server runs in the container and exposes its socket, so sessions are driven by host clients. Networking is shared with the host; Ward isolates state, not the network.

Host setup

sudo pacman --needed -S github-cli openssh podman tmux
systemctl --user enable --now ssh-agent.socket podman.socket

The ward unit syncs the ward-github-token podman secret from gh auth token at every start and exposes it in the container as GH_TOKEN. The start fails when gh is not authenticated on the host. Create the Brave secret before starting Ward; it is exposed in the container as BRAVE_API_KEY:

printf %s "$BRAVE_API_KEY" | \
    podman secret create --replace ward-brave-api-key -

Deploy

From the repository root:

install -d -m 0700 "$HOME/.config/containers/systemd" "$HOME/.config/systemd/user"
ln -sT "$PWD" "$HOME/.config/containers/systemd/ward"
ln -sT "$PWD/ward-build.timer" "$HOME/.config/systemd/user/ward-build.timer"
systemctl --user daemon-reload
systemctl --user start ward-build.service
systemctl --user start ward.service
systemctl --user enable --now ward-build.timer

Updates

ward-build.timer builds daily in the background (Persistent=true catches up after downtime). Every run pulls archlinux:latest; when the digest is unchanged, every layer is a cache hit and the build installs nothing. Real rebuilds happen only when Arch publishes a new base image or the Containerfile changes — the single pacman -Syu transaction then runs against current mirrors. Package state advances when the base image moves, not at each build.

A build never restarts the running container: it keeps its current root, and the new image is used the next time ward.service starts — after a reboot, or when applied manually below. Updates land when you choose, not mid-session. Superseded builds remain in storage as dangling images; podman image prune -f removes all dangling images, spares the live build cache (images with children), and never removes an image in use by a container.

ward-build.timer is a plain systemd unit, not a quadlet file, so it installs under ~/.config/systemd/user/.

Apply

systemctl --user daemon-reload
systemctl --user restart ward-build.service &&
systemctl --user restart ward.service

The container is restarted only after a successful build; sessions in it end at that moment.

Start a session

tmux -S "$XDG_RUNTIME_DIR/ward/tmux.sock"

Remove

systemctl --user disable --now ward-build.timer
systemctl --user stop ward.service ward-build.service
rm -- "$HOME/.config/containers/systemd/ward" \
      "$HOME/.config/systemd/user/ward-build.timer"
systemctl --user daemon-reload
podman image rm localhost/ward:latest
podman image prune -f
podman secret rm ward-github-token ward-brave-api-key

About

Magical barrier

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages