-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathContainerfile.base
More file actions
175 lines (151 loc) · 7.71 KB
/
Containerfile.base
File metadata and controls
175 lines (151 loc) · 7.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
FROM archlinux:latest
ARG BUILD_DATE=unknown
ARG BUILD_SHA=unknown
RUN pacman-key --init && \
pacman-key --populate archlinux && \
pacman -Syu --noconfirm
# Pacman packages, grouped by purpose (one group per line below):
# Build toolchain + core utils: base-devel glib2 git openssh sudo ...
# Node.js runtime + npm: explicit dep for sandbox-runtime (see npm install below)
# Shell & terminal: zsh tmux btop
# Editors: nano vim (vi-vim-symlink from AUR aliases vi -> vim)
# Python + polyglot runtime: python (also needed host-side for box.toml compiler), uv, mise (usage is a mise dep)
# IaC: terraform
# Container mgmt: docker docker-compose (talks to host podman socket)
# Audio passthrough: pipewire libpipewire pipewire-alsa pipewire-pulse (client libs + ALSA/PA bridges for host PipeWire)
# Git ecosystem: github-cli, git-absorb (auto-fixup), diff-so-fancy
# Claude Code sandbox: bubblewrap (process isolation), socat (socket proxy),
# libseccomp (BPF seccomp filters)
# VPN: tailscale (client for per-box tailnets)
# KDE integration: breeze-gtk (Breeze theme for GTK apps like Chrome), xdg-desktop-portal-kde (KDE notifications + file dialogs)
RUN pacman -S --noconfirm --needed \
base-devel glib2 git openssh sudo ca-certificates curl wget gnupg inetutils \
nodejs npm \
man-db man-pages \
zsh tmux btop less \
jq tree ripgrep fd unzip zip \
nano vim \
python uv mise usage \
terraform \
docker docker-compose \
pipewire libpipewire pipewire-alsa pipewire-pulse \
github-cli git-absorb diff-so-fancy \
bubblewrap socat libseccomp \
tailscale \
breeze-gtk xdg-desktop-portal-kde && \
mandb
# Switch iptables/ip6tables to nftables backend (host kernel lacks ip_tables module)
RUN ln -sf /usr/bin/xtables-nft-multi /usr/bin/iptables && \
ln -sf /usr/bin/xtables-nft-multi /usr/bin/iptables-restore && \
ln -sf /usr/bin/xtables-nft-multi /usr/bin/iptables-save && \
ln -sf /usr/bin/xtables-nft-multi /usr/sbin/iptables && \
ln -sf /usr/bin/xtables-nft-multi /usr/sbin/iptables-restore && \
ln -sf /usr/bin/xtables-nft-multi /usr/sbin/iptables-save && \
ln -sf /usr/bin/xtables-nft-multi /usr/bin/ip6tables && \
ln -sf /usr/bin/xtables-nft-multi /usr/bin/ip6tables-restore && \
ln -sf /usr/bin/xtables-nft-multi /usr/bin/ip6tables-save && \
ln -sf /usr/bin/xtables-nft-multi /usr/sbin/ip6tables && \
ln -sf /usr/bin/xtables-nft-multi /usr/sbin/ip6tables-restore && \
ln -sf /usr/bin/xtables-nft-multi /usr/sbin/ip6tables-save
# makepkg cannot run as root
RUN useradd -m -G wheel builduser && \
printf 'builduser ALL=(ALL) NOPASSWD: ALL\n' > /etc/sudoers.d/builduser
USER builduser
WORKDIR /tmp/yay-build
RUN git clone https://aur.archlinux.org/yay.git . && \
makepkg -s --noconfirm --needed && \
sudo pacman -U --noconfirm ./*.pkg.tar*
# AUR packages, grouped by purpose:
# IDEs / editors: visual-studio-code-bin, cursor-bin
# Zsh framework: oh-my-zsh-git
# Browser (exported via distrobox): google-chrome (desktop file patched later by chrome-wrapper)
# Database CLI tools (mongodump, mongorestore, etc.): mongodb-tools
# GCP CLI + GKE auth plugin for kubectl: google-cloud-cli, gke-gcloud-auth-plugin
# AI coding assistant (Node.js CLI): claude-code
RUN yay -S --noconfirm --needed \
visual-studio-code-bin cursor-bin \
oh-my-zsh-git \
google-chrome \
mongodb-tools \
google-cloud-cli google-cloud-cli-component-gke-gcloud-auth-plugin \
claude-code
USER root
WORKDIR /
# vi -> vim symlink (vi-vim-symlink AUR package no longer exists)
RUN ln -sf /usr/bin/vim /usr/bin/vi
# Claude Code seccomp sandbox: provides BPF filters to block unix domain sockets
RUN npm install -g @anthropic-ai/sandbox-runtime
# Pre-install Cursor extensions to a system-wide directory.
# Uses /usr/bin/cursor directly (before wrapper is created).
RUN mkdir -p /opt/cursor-extensions && \
for ext in \
anysphere.cursorpyright \
buenon.scratchpads \
charliermarsh.ruff \
eamodio.gitlens \
hashicorp.terraform \
k--kato.intellij-idea-keybindings \
mads-hartmann.bash-ide-vscode \
ms-python.debugpy \
ms-python.python \
redhat.vscode-yaml \
rust-lang.rust-analyzer \
tamasfe.even-better-toml \
astral-sh.ty \
DavidAnson.vscode-markdownlint \
anthropic.claude-code \
bierner.markdown-mermaid; \
do \
/usr/bin/cursor --no-sandbox --extensions-dir /opt/cursor-extensions \
--install-extension "$ext" || true; \
done
# Allow runtime users to write temp files inside extension directories (e.g. debugpy)
RUN chmod -R a+w /opt/cursor-extensions
# Wrapper so both CLI and .desktop launch use the pre-installed extensions
RUN printf '#!/bin/sh\nexec /usr/bin/cursor --extensions-dir /opt/cursor-extensions "$@"\n' \
> /usr/local/bin/cursor && \
chmod +x /usr/local/bin/cursor
RUN desktop_file=$(find /usr/share/applications -iname '*cursor*' 2>/dev/null | head -1) && \
if [ -n "$desktop_file" ]; then \
sed -i 's|\(Exec=.*cursor[^ ]*\)|\1 --extensions-dir /opt/cursor-extensions|' "$desktop_file"; \
fi
RUN chmod u+s /usr/bin/newuidmap /usr/bin/newgidmap
# Container-local xdg-open so links open in the container browser
RUN printf '#!/bin/sh\nexec gio open "$@"\n' > /usr/local/bin/xdg-open && \
chmod +x /usr/local/bin/xdg-open
# Chrome wrapper: desktop-launched apps (distrobox-export) bypass shell init
# and PAM, so DBUS_SESSION_BUS_ADDRESS from /etc/environment is never set.
# This wrapper sources /etc/environment before exec'ing Chrome so screen
# sharing and notifications work via the host's xdg-desktop-portal.
# Depends on: google-chrome AUR package (installed above)
RUN printf '#!/bin/bash\nif [[ -f /etc/environment ]]; then\n set -a; source /etc/environment; set +a\nfi\nexec /usr/bin/google-chrome-stable "$@"\n' \
> /usr/local/bin/chrome-wrapper && \
chmod +x /usr/local/bin/chrome-wrapper && \
sed -i 's|/usr/bin/google-chrome-stable|/usr/local/bin/chrome-wrapper|g' \
/usr/share/applications/google-chrome.desktop
RUN printf 'export ZSH=/usr/share/oh-my-zsh\nZSH_THEME="robbyrussell"\nplugins=(git)\nsource "$ZSH/oh-my-zsh.sh"\n' \
> /etc/skel/.zshrc
# Tailscale systemd override: use a custom socket path so distrobox-enter
# can't overwrite it with a host symlink on every entry.
RUN mkdir -p /etc/systemd/system/tailscaled.service.d && \
printf '[Service]\nExecStart=\nExecStart=/usr/bin/tailscaled --state=/var/lib/tailscale/tailscaled.state --socket=/var/run/tailscale/box.sock --port 41641\n' \
> /etc/systemd/system/tailscaled.service.d/socket-path.conf && \
systemctl enable tailscaled.service && \
systemctl enable sshd.service
# Mask the user-session D-Bus so the container's systemd --user never starts its
# own bus. All apps (terminal and desktop-launched) use the host bus instead,
# which is required for xdg-desktop-portal (screen sharing) and keyring access.
RUN systemctl --global mask dbus-daemon.service dbus-broker.service
COPY scripts/init-root.sh /usr/local/share/box-init/init-root.sh
COPY scripts/init-user.sh /usr/local/share/box-init/init-user.sh
COPY scripts/shell-init.sh /usr/local/share/box-init/shell-init.sh
RUN chmod +x /usr/local/share/box-init/init-root.sh /usr/local/share/box-init/init-user.sh /usr/local/share/box-init/shell-init.sh
COPY local-bin/ /usr/local/bin/
RUN chmod +x /usr/local/bin/* 2>/dev/null || true
RUN printf 'build_date=%s\nbuild_sha=%s\nimage=box-base\n' \
"$BUILD_DATE" "$BUILD_SHA" > /etc/box-build-info
RUN rm -rf /tmp/* && \
rm -f /etc/sudoers.d/builduser && \
userdel -r builduser 2>/dev/null || true && \
pacman -Scc --noconfirm && \
rm -rf /var/cache/pacman/pkg/*