Monorepo for Aesthetic.Computer aesthetic.computer
at main 311 lines 16 kB view raw
1# Rebuilt to run SmartPy on Python 3.11 and avoid 3.13 BrokenPipe 2FROM --platform=linux/amd64 fedora:latest 3 4# Preconfigure DNF to minimize footprint and avoid unnecessary optional deps 5RUN set -eux; \ 6 echo 'fastestmirror=True' >> /etc/dnf/dnf.conf; \ 7 echo 'max_parallel_downloads=5' >> /etc/dnf/dnf.conf; \ 8 echo 'keepcache=0' >> /etc/dnf/dnf.conf; \ 9 echo 'install_weak_deps=False' >> /etc/dnf/dnf.conf; \ 10 echo 'tsflags=nodocs' >> /etc/dnf/dnf.conf 11 12ENV NODE_OPTIONS=--max_old_space_size=8192 13ENV DENO_DIR=/home/me/.cache/deno 14ENV NETLIFY_DENO_VERSION=2.4.5 15# Prevent paging for LLM/agentic use 16ENV PAGER=cat 17ENV GIT_PAGER=cat 18ENV SYSTEMD_PAGER=cat 19ENV MANPAGER=cat 20 21# --- Base toolchain & deps ---------------------------------------------------- 22RUN dnf clean all && rm -rf /var/cache/dnf && \ 23 dnf update -y --refresh --setopt=zchunk=false && \ 24 dnf install -y \ 25 awk which tree procps-ng coreutils unzip jq bat ripgrep \ 26 cpio lz4 bc perl mtools dosfstools xorriso ca-certificates \ 27 git gh gcc gcc-c++ clang make cmake \ 28 musl-gcc elfutils-libelf-devel \ 29 python3.11 python3.11-devel python3-pip python3-devel \ 30 emacs-nox fish util-linux-user util-linux-script sshpass \ 31 openssl openssl-devel awscli redis \ 32 dnf-plugins-core lolcat toilet iproute xclip nmap-ncat \ 33 inotify-tools wget curl tar gzip bzip2 \ 34 libsodium libsodium-devel libffi libffi-devel \ 35 gmp gmp-devel \ 36 protobuf-compiler protobuf-devel \ 37 pkg-config autoconf automake libtool \ 38 ocaml opam rsync m4 patch bubblewrap \ 39 libX11 libxkbfile libsecret libxshmfence libXtst \ 40 nss atk pango cups-libs libXcomposite libXcursor \ 41 libXi libXdamage libXrandr alsa-lib gtk3 \ 42 alsa-lib-devel libdrm-devel libpciaccess-devel \ 43 flite-devel \ 44 xorg-x11-server-Xvfb psmisc lsof chromium \ 45 wpa_supplicant dhcp-client iw iwlwifi-mvm-firmware wireless-regdb \ 46 sbcl zeromq-devel redhat-rpm-config \ 47 poppler-utils \ 48 texlive-xetex texlive-collection-fontsrecommended texlive-natbib \ 49 texlive-booktabs texlive-titlesec texlive-fancyhdr texlive-draftwatermark \ 50 texlive-microtype texlive-ragged2e texlive-listings texlive-enumitem \ 51 texlive-collection-latexrecommended \ 52 isync maildir-utils msmtp \ 53 caddy \ 54 texlive-scheme-basic texlive-xetex texlive-bibtex \ 55 texlive-collection-fontsrecommended texlive-collection-latexrecommended \ 56 texlive-natbib texlive-booktabs texlive-enumitem texlive-titlesec \ 57 texlive-fancyhdr texlive-microtype texlive-listings texlive-ragged2e \ 58 texlive-draftwatermark texlive-fontspec texlive-unicode-math \ 59 texlive-collection-mathscience \ 60 texlive-xecjk texlive-tcolorbox texlive-environ \ 61 google-noto-sans-cjk-sc-fonts google-noto-sans-mono-cjk-sc-fonts \ 62 && dnf clean all && rm -rf /var/cache/dnf 63 64# --- FFmpeg from RPM Fusion --------------------------------------------------- 65RUN dnf install -y --setopt=zchunk=false \ 66 https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm \ 67 https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm \ 68 && dnf install -y --allowerasing --skip-unavailable --setopt=zchunk=false ffmpeg ffmpeg-devel \ 69 && dnf clean all && rm -rf /var/cache/dnf 70 71# --- Python 3.11 venv as default "python" ------------------------------------- 72RUN /usr/bin/python3.11 -m venv /opt/py311 && \ 73 /opt/py311/bin/pip install -U pip setuptools wheel && \ 74 ln -s /opt/py311/bin/python /usr/local/bin/python && \ 75 ln -s /opt/py311/bin/pip /usr/local/bin/pip 76ENV PATH="/opt/py311/bin:${PATH}" 77 78# --- SmartPy (pinned) + smoke test ------------------------------------------- 79# Note: SmartPy doesn't support ARM64 architecture (Apple Silicon) 80RUN set -eux; \ 81 if [ "$(uname -m)" = "x86_64" ]; then \ 82 pip install "tezos-smartpy==0.22.0" "pytezos>=3.9.0,<4" requests && \ 83 python -c "import smartpy as sp; print('SmartPy successfully imported')"; \ 84 else \ 85 echo "Skipping SmartPy on $(uname -m) architecture (not supported)"; \ 86 pip install "pytezos>=3.9.0,<4" requests; \ 87 fi 88 89# --- Octez (best-effort binary) ---------------------------------------------- 90# Note: v20.3 doesn't support current Ghostnet protocol (PtSeouLouXkxhg39...) 91# Use Docker method instead: deploy-via-docker.py 92RUN set -eux; \ 93 if curl -fsSL -o /usr/local/bin/octez-client \ 94 https://github.com/serokell/tezos-packaging/releases/download/v20.3-1/octez-client && \ 95 curl -fsSL -o /usr/local/bin/octez-node \ 96 https://github.com/serokell/tezos-packaging/releases/download/v20.3-1/octez-node; then \ 97 chmod +x /usr/local/bin/octez-*; \ 98 else \ 99 echo "Octez binaries unavailable, skipping"; \ 100 fi 101 102# --- Docker CLI (for running latest Octez via Docker) ------------------------ 103# This allows us to use tezos/tezos:master which supports current Ghostnet protocol 104RUN dnf install -y --setopt=zchunk=false docker && dnf clean all && rm -rf /var/cache/dnf 105 106# Pre-pull Tezos & SmartPy Docker images during build (saves time later) 107# Note: This requires BuildKit and may fail in some build environments 108# If it fails, the images will be pulled on first use instead 109RUN --mount=type=cache,target=/var/cache/buildkit \ 110 docker pull tezos/tezos:master 2>/dev/null || echo "Octez image will be pulled on first use" && \ 111 docker pull bakingbad/smartpy-cli:latest 2>/dev/null || echo "SmartPy image will be pulled on first use" 112 113# --- Stripe CLI (architecture-aware) ----------------------------------------- 114RUN set -eux; \ 115 case "$(uname -m)" in \ 116 x86_64) ARCH=x86_64 ;; \ 117 aarch64) ARCH=arm64 ;; \ 118 *) echo "Unsupported architecture: $(uname -m)" && exit 1 ;; \ 119 esac && \ 120 curl -fsSL "https://github.com/stripe/stripe-cli/releases/download/v1.30.0/stripe_1.30.0_linux_${ARCH}.tar.gz" \ 121 | tar xz -C /usr/local/bin 122 123# --- redli (architecture-aware) ---------------------------------------------- 124RUN set -eux; \ 125 case "$(uname -m)" in \ 126 x86_64) ARCH=amd64 ;; \ 127 aarch64) ARCH=arm64 ;; \ 128 *) echo "Unsupported architecture: $(uname -m)" && exit 1 ;; \ 129 esac && \ 130 curl -fsSL "https://github.com/IBM-Cloud/redli/releases/download/v0.15.0/redli_0.15.0_linux_${ARCH}.tar.gz" \ 131 | tar xz -C /usr/local/bin && mv "/usr/local/bin/redli_linux_${ARCH}" /usr/local/bin/redli 132 133# --- mkcert (pre-built binary from GitHub) ----------------------------------- 134RUN set -eux; \ 135 case "$(uname -m)" in \ 136 x86_64) ARCH=amd64 ;; \ 137 aarch64) ARCH=arm64 ;; \ 138 *) echo "Unsupported architecture: $(uname -m)" && exit 1 ;; \ 139 esac && \ 140 curl -fsSL "https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-${ARCH}" -o /usr/local/bin/mkcert && \ 141 chmod +x /usr/local/bin/mkcert 142 143# --- ngrok (architecture-aware) ---------------------------------------------- 144RUN set -eux; \ 145 case "$(uname -m)" in \ 146 x86_64) ARCH=amd64 ;; \ 147 aarch64) ARCH=arm64 ;; \ 148 *) echo "Unsupported architecture: $(uname -m)" && exit 1 ;; \ 149 esac && \ 150 curl -fsSL "https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-${ARCH}.tgz" -o /tmp/ngrok.tgz && \ 151 tar -xzf /tmp/ngrok.tgz -C /usr/local/bin && rm /tmp/ngrok.tgz 152 153# --- Ollama (architecture-aware) --------------------------------------------- 154# RUN set -eux; \ 155# curl -fsSL https://ollama.com/install.sh | sh 156 157# --- doctl (DigitalOcean CLI, architecture-aware) ---------------------------- 158RUN set -eux; \ 159 case "$(uname -m)" in \ 160 x86_64) ARCH=amd64 ;; \ 161 aarch64) ARCH=arm64 ;; \ 162 *) echo "Unsupported architecture: $(uname -m)" && exit 1 ;; \ 163 esac && \ 164 DOCTL_VERSION=1.109.0 && \ 165 curl -fsSL "https://github.com/digitalocean/doctl/releases/download/v${DOCTL_VERSION}/doctl-${DOCTL_VERSION}-linux-${ARCH}.tar.gz" -o /tmp/doctl.tar.gz && \ 166 tar -xzf /tmp/doctl.tar.gz -C /usr/local/bin && rm /tmp/doctl.tar.gz && \ 167 chmod +x /usr/local/bin/doctl 168 169# --- PowerShell (for running Windows scripts on Linux) ----------------------- 170# Install from GitHub releases since Microsoft's repo doesn't have Fedora 43 packages yet 171RUN ARCH=$(uname -m) && \ 172 if [ "$ARCH" = "x86_64" ]; then PS_ARCH="x64"; else PS_ARCH="arm64"; fi && \ 173 PS_VERSION=$(curl -s https://api.github.com/repos/PowerShell/PowerShell/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/') && \ 174 curl -sSL -o /tmp/powershell.tar.gz "https://github.com/PowerShell/PowerShell/releases/download/v${PS_VERSION}/powershell-${PS_VERSION}-linux-${PS_ARCH}.tar.gz" && \ 175 mkdir -p /opt/microsoft/powershell/7 && \ 176 tar -xzf /tmp/powershell.tar.gz -C /opt/microsoft/powershell/7 && \ 177 chmod +x /opt/microsoft/powershell/7/pwsh && \ 178 ln -s /opt/microsoft/powershell/7/pwsh /usr/local/bin/pwsh && \ 179 ln -s /opt/microsoft/powershell/7/pwsh /usr/local/bin/powershell && \ 180 rm /tmp/powershell.tar.gz 181 182# --- s3cmd (for DigitalOcean Spaces management) ------------------------------- 183RUN dnf install -y --setopt=zchunk=false s3cmd && dnf clean all 184 185# --- AC Native OS build dependencies ----------------------------------------- 186# cage: Wayland kiosk compositor for Firefox OAuth popup (tiny: 65KB) 187# qemu: for local QEMU testing of AC OS builds 188RUN dnf install -y --setopt=zchunk=false cage qemu-system-x86-core edk2-ovmf && dnf clean all 189 190# --- Cockpit (web-based system management UI) -------------------------------- 191# Note: service/journal features require systemd; terminal + metrics work without it 192RUN dnf install -y --setopt=zchunk=false cockpit cockpit-ws cockpit-bridge cockpit-system cockpit-networkmanager && dnf clean all 193 194# --- Jupyter bits ------------------------------------------------------------- 195RUN dnf install -y --setopt=zchunk=false python3-notebook python3-nbconvert && dnf clean all 196 197# --- gcloud SDK --------------------------------------------------------------- 198RUN curl -sSL https://sdk.cloud.google.com > /tmp/install_gcloud.sh && \ 199 bash /tmp/install_gcloud.sh --disable-prompts --install-dir=/opt && \ 200 ln -s /opt/google-cloud-sdk/bin/gcloud /usr/local/bin/gcloud && \ 201 ln -s /opt/google-cloud-sdk/bin/gsutil /usr/local/bin/gsutil && \ 202 ln -s /opt/google-cloud-sdk/bin/bq /usr/local/bin/bq && \ 203 rm /tmp/install_gcloud.sh 204 205# --- signal-cli (native binary, no JVM needed) -------------------------------- 206RUN set -eux; \ 207 SIGNAL_CLI_VERSION=0.14.1 && \ 208 curl -fsSL "https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}-Linux-native.tar.gz" \ 209 | tar xz -C /usr/local/bin 210 211# --- User --------------------------------------------------------------------- 212RUN useradd -m me && echo "me ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && chsh -s /usr/bin/fish me 213 214# Fix fish path issue: Fedora installs to /usr/sbin but shebangs expect /usr/bin 215RUN if test ! -f /usr/bin/fish && test -f /usr/sbin/fish; then \ 216 ln -s /usr/sbin/fish /usr/bin/fish; \ 217 fi 218 219USER me 220WORKDIR /home/me 221 222# --- Claude Code native binary (for AC OS initramfs bundling) ----------------- 223RUN curl -fsSL https://claude.ai/install.sh | bash 224 225# --- Rust + websocat (built from source) -------------------------------------- 226RUN curl https://sh.rustup.rs -sSf | sh -s -- -y && \ 227 . "$HOME/.cargo/env" && \ 228 git clone https://github.com/vi/websocat.git && \ 229 cd websocat && cargo build --release && sudo cp target/release/websocat /usr/local/bin/ && \ 230 cd /home/me && cargo install --git https://github.com/boxdot/gurk-rs gurk && \ 231 sudo cp /home/me/.cargo/bin/gurk /usr/local/bin/ 232 233# --- fnm / Node toolchain (PART 1: Create directories with correct ownership FIRST) --- 234RUN mkdir -p /home/me/.config/fish/conf.d /home/me/.config/fish/functions && \ 235 mkdir -p /home/me/.local/share/fish && \ 236 chown -R me:me /home/me/.config && \ 237 chown -R me:me /home/me/.local && \ 238 chmod -R 755 /home/me/.config && \ 239 chmod -R 755 /home/me/.local 240 241# --- fnm / Node toolchain (PART 2: Now install fnm and node) ------------------ 242RUN curl -fsSL https://fnm.vercel.app/install | bash -s -- --install-dir "$HOME/.fnm" --skip-shell 243ENV PATH="/home/me/.fnm:${PATH}" 244RUN echo 'fnm env --use-on-cd --shell fish | source' > /home/me/.config/fish/conf.d/fnm.fish && \ 245 export PATH="/home/me/.fnm:${PATH}" && \ 246 eval "$(/home/me/.fnm/fnm env --use-on-cd)" && \ 247 /home/me/.fnm/fnm install lts-jod && \ 248 /home/me/.fnm/fnm install 20.5.0 && \ 249 /home/me/.fnm/fnm default lts-jod && \ 250 /home/me/.fnm/fnm use lts-jod && \ 251 npm i -g prettier typescript typescript-language-server npm-check-updates @anthropic-ai/claude-code @openai/codex netlify-cli wrangler && \ 252 echo 'fnm use lts-jod' >> /home/me/.config/fish/config.fish && \ 253 chown -R me:me /home/me/.config/fish 254 255# --- ATProto dependencies for /at directory ------------------------------------ 256# Note: These will be available globally for ATProto experiments 257# See /at directory for ATProto/Bluesky exploration tools 258RUN export PATH="/home/me/.fnm:${PATH}" && \ 259 eval "$(/home/me/.fnm/fnm env --use-on-cd)" && \ 260 npm i -g @atproto/api@^0.17.0 @atproto/xrpc@^0.6.5 @atproto/lexicon@^0.4.2 @atproto/identity@^0.4.3 @atproto/syntax@^0.3.1 dotenv@^16.4.5 261 262# --- SBCL / Quicklisp --------------------------------------------------------- 263RUN curl -fsSLO https://beta.quicklisp.org/quicklisp.lisp && \ 264 sbcl --non-interactive \ 265 --load quicklisp.lisp \ 266 --eval '(quicklisp-quickstart:install)' \ 267 --eval '(ql-util:without-prompting (ql:add-to-init-file))' \ 268 --eval '(quit)' 269 270# --- OPS (nanos) -------------------------------------------------------------- 271# RUN curl https://ops.city/get.sh -sSfL | bash || echo "OPS installation failed, skipping..." 272 273# --- uv (fast Python package manager for MCP servers) ------------------------- 274# --- emacs-mcp-server (for VS Code Copilot <-> Emacs integration) ------------- 275# Combined into single RUN to ensure uv is available immediately after install 276RUN curl -LsSf https://astral.sh/uv/install.sh | sh && \ 277 export PATH="$HOME/.local/bin:$PATH" && \ 278 uv --version && \ 279 git clone https://github.com/vivekhaldar/emacs-mcp-server.git /home/me/emacs-mcp-server && \ 280 cd /home/me/emacs-mcp-server && \ 281 uv sync 282ENV PATH="/home/me/.local/bin:${PATH}" 283 284# --- Deno --------------------------------------------------------------------- 285RUN curl -fsSL https://deno.land/install.sh | DENO_INSTALL=/home/me/.deno sh -s v2.4.5 && \ 286 /home/me/.deno/bin/deno --version && \ 287 /home/me/.deno/bin/deno cache https://v2-13-0--edge.netlify.com/bootstrap/index-combined.ts 2>/dev/null || true && \ 288 /home/me/.deno/bin/deno cache https://v2-13-0--edge.netlify.com/bootstrap/handler.ts 2>/dev/null || true && \ 289 /home/me/.deno/bin/deno cache https://v2-13-0--edge.netlify.com/bootstrap/server.ts 2>/dev/null || true 290 291# --- Fish config / entry ------------------------------------------------------ 292# Directories were already created above during fnm setup, now just copy files 293COPY --chown=me:me config.fish /home/me/.config/fish/config.fish 294COPY --chown=me:me entry.fish /entry.fish 295 296# Ensure jupyter directory exists with correct permissions 297RUN mkdir -p /home/me/.jupyter && \ 298 chmod -R u+rw /home/me/.jupyter 299 300# --- IPython preload ---------------------------------------------------------- 301RUN mkdir -p /home/me/.ipython/profile_default/startup && \ 302 echo "import sys; sys.path.append('/workspaces/aesthetic-computer/notebook'); import aesthetic" > /home/me/.ipython/profile_default/startup/00-aesthetic.py && \ 303 sudo chown -R me:me /home/me/.ipython 304 305# --- GYP shim (legacy consumers) --------------------------------------------- 306RUN mkdir -p /home/me/.local/lib/python3.10/site-packages && \ 307 git clone https://chromium.googlesource.com/external/gyp.git /home/me/.local/lib/python3.10/site-packages/gyp || true && \ 308 chown -R me:me /home/me/.local 309 310# Optional: default shell session 311# ENTRYPOINT ["/usr/bin/fish", "/entry.fish"]