Skip to content

Commit 75481d8

Browse files
feat(container): Add comprehensive containerisation with Wolfi + Guix
- Add CONTAINERFILE with multi-stage build (builder, build, runtime, dev) - Use Wolfi base image (Chainguard) for security-hardened containers - Integrate Guix package manager for functional dependency management - Configure Podman with SELinux labels and firewalld - Add firewalld/ directory with: - firewalld.conf (DefaultZone=drop) - zones/drop.xml (explicit port allowances) - zones/public.xml (with rate limiting) - services/trigger-https.xml - services/trigger-api.xml - Add selinux/ directory with: - selinux.config (enforcing mode) - policies/trigger.te (custom SELinux policy) - contexts/file_contexts - contexts/port_contexts - Add scripts/git-hooks/ with: - pre-commit (format, lint, SPDX check) - pre-push (build, test, pons, panic-attack, container build) - post-commit (cleanup, documentation) - post-merge (rebuild, hook updates) - config.sh (hook configuration) - Update ARCHITECTURE.adoc with containerisation section - Security: All ports down except 80, 443, 8080, 8443, 22, 53 - Security: Non-root user, SELinux enforcing, firewalld drop zone Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
1 parent c05fd16 commit 75481d8

17 files changed

Lines changed: 1709 additions & 0 deletions

File tree

‎CONTAINERFILE‎

Lines changed: 382 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,382 @@
1+
# CONTAINERFILE for Trigger Application
2+
#
3+
# Multi-stage build for Podman/Docker using Wolfi base image with Guix
4+
#
5+
# Architecture: Ada/SPARK + Zig + Idris2
6+
# Target: x86_64 (can be extended for arm64)
7+
#
8+
# Build with:
9+
# podman build -f CONTAINERFILE -t hyperpolymath/trigger:latest .
10+
# podman run -it --security-opt label=type:container_runtime_t hyperpolymath/trigger:latest
11+
#
12+
# Security: Full SELinux labeling, firewalld integration, minimal privileges
13+
#
14+
# SPDX-License-Identifier: MPL-2.0
15+
16+
# =============================================================================
17+
# STAGE 1: Base Builder Image with Wolfi + Guix
18+
# =============================================================================
19+
20+
FROM ghcr.io/wolfi-dev/wolfi:latest AS builder
21+
22+
# Wolfi is a Chainguard-owned, community-driven Linux distribution
23+
# optimized for containers and cloud-native environments
24+
25+
# Install system dependencies
26+
RUN apk add --no-cache \
27+
# Build tools
28+
gcc \
29+
musl-dev \
30+
make \
31+
cmake \
32+
git \
33+
bash \
34+
coreutils \
35+
findutils \
36+
diffutils \
37+
gawk \
38+
sed \
39+
grep \
40+
patch \
41+
tar \
42+
xz \
43+
gzip \
44+
bzip2 \
45+
# Runtime dependencies
46+
libsodium \
47+
libgc \
48+
libgmp \
49+
# Container tools
50+
podman \
51+
buildah \
52+
skopeo \
53+
# Security
54+
firewalld \
55+
selinux-tools \
56+
policycoreutils \
57+
audit \
58+
# Certificate management
59+
ca-certificates \
60+
openssl \
61+
# Additional tools
62+
curl \
63+
wget \
64+
jq \
65+
python3 \
66+
py3-pip \
67+
# For Guix
68+
guile \
69+
gcc-gnat \
70+
zig \
71+
idris2 \
72+
# For development
73+
vim \
74+
less \
75+
tree \
76+
htop \
77+
lsof \
78+
strace \
79+
tcpdump \
80+
net-tools \
81+
iproute2 \
82+
dnsutils \
83+
# For CI/CD
84+
just \
85+
asciidoctor \
86+
# For crypto
87+
liboqs \
88+
oqsproviders \
89+
# Cleanup
90+
&& rm -rf /var/cache/apk/*
91+
92+
# Set up Guix environment
93+
RUN mkdir -p /opt/guix && \
94+
chown root:root /opt/guix && \
95+
echo "export GUIX_PROFILE=/opt/guix/profile" >> /etc/profile.d/guix.sh && \
96+
echo "export PATH=/opt/guix/profile/bin:$PATH" >> /etc/profile.d/guix.sh
97+
98+
# Install Guix packages
99+
RUN source /etc/profile.d/guix.sh && \
100+
guix pull --channels="guix.json" && \
101+
guix install -p /opt/guix/profile \
102+
gnat \
103+
gprbuild \
104+
asis \
105+
spark \
106+
zig \
107+
idris2 \
108+
libsodium \
109+
liboqs \
110+
openssl \
111+
pkg-config \
112+
autoconf \
113+
automake \
114+
libtool \
115+
flex \
116+
bison \
117+
&& guix gc
118+
119+
# Set up build environment
120+
WORKDIR /app
121+
122+
# Copy source code
123+
COPY . /app/
124+
125+
# Configure build environment
126+
ENV GNAT_PROJECT_PATH=/app
127+
ENV ADA_INCLUDE_PATH=/app/src:/app/ffi
128+
ENV LD_LIBRARY_PATH=/opt/guix/profile/lib:$LD_LIBRARY_PATH
129+
130+
# Install Ada dependencies via Alire (if available)
131+
RUN if command -v alr >/dev/null 2>&1; then \
132+
alr update && \
133+
alr get --build gnat_native \
134+
gnatcoll \
135+
aws \
136+
sockets \
137+
xmlada \
138+
logging \
139+
crypto; \
140+
fi
141+
142+
# =============================================================================
143+
# STAGE 2: Build Application
144+
# =============================================================================
145+
146+
FROM builder AS build
147+
148+
# Create build directory
149+
RUN mkdir -p /app/obj /app/bin /app/lib
150+
151+
# Build with GNAT
152+
RUN echo "[BUILD] Building Trigger..." && \
153+
gprbuild -P /app/trigger.gpr -XLIBRARY_TYPE=static && \
154+
echo "[BUILD] GNAT compilation complete"
155+
156+
# Build Zig FFI
157+
RUN echo "[BUILD] Compiling Zig FFI..." && \
158+
cd /app/ffi/zig && \
159+
zig build-lib -dynamic telegram.zig && \
160+
zig build-lib -dynamic discord.zig && \
161+
zig build-lib -dynamic twitter.zig && \
162+
zig build-lib -dynamic crypto.zig -lc -lsodium -loqs && \
163+
cd /app && \
164+
echo "[BUILD] Zig compilation complete"
165+
166+
# Build Idris2 API
167+
RUN echo "[BUILD] Compiling Idris2 API..." && \
168+
cd /app/ffi/idris2 && \
169+
idris2 --build TelegramAPI.ipkg && \
170+
idris2 --build DiscordAPI.ipkg && \
171+
idris2 --build TwitterAPI.ipkg && \
172+
idris2 --build CryptoAPI.ipkg && \
173+
cd /app && \
174+
echo "[BUILD] Idris2 compilation complete"
175+
176+
# =============================================================================
177+
# STAGE 3: Runtime Image
178+
# =============================================================================
179+
180+
FROM ghcr.io/wolfi-dev/wolfi:latest AS runtime
181+
182+
# Install runtime dependencies only
183+
RUN apk add --no-cache \
184+
# Runtime
185+
libsodium \
186+
libgc \
187+
libgmp \
188+
# System
189+
bash \
190+
coreutils \
191+
ca-certificates \
192+
openssl \
193+
# Security
194+
firewalld \
195+
selinux-tools \
196+
policycoreutils \
197+
audit \
198+
# Tools
199+
curl \
200+
jq \
201+
just \
202+
# Crypto
203+
liboqs \
204+
oqsproviders \
205+
&& rm -rf /var/cache/apk/*
206+
207+
# Set up Guix runtime
208+
RUN mkdir -p /opt/guix/profile && \
209+
echo "export GUIX_PROFILE=/opt/guix/profile" >> /etc/profile.d/guix.sh && \
210+
echo "export PATH=/opt/guix/profile/bin:$PATH" >> /etc/profile.d/guix.sh && \
211+
echo "export LD_LIBRARY_PATH=/opt/guix/profile/lib:$LD_LIBRARY_PATH" >> /etc/profile.d/guix.sh
212+
213+
# Install Guix runtime packages
214+
RUN source /etc/profile.d/guix.sh && \
215+
guix pull --channels="guix.json" && \
216+
guix install -p /opt/guix/profile \
217+
libsodium \
218+
liboqs \
219+
openssl \
220+
&& guix gc
221+
222+
# Set up directories
223+
RUN mkdir -p /app/bin /app/lib /app/obj /app/sessions /app/config /app/logs /app/cache && \
224+
chmod 700 /app/sessions && \
225+
chmod 700 /app/config && \
226+
chmod 755 /app/logs && \
227+
chmod 755 /app/cache
228+
229+
# Copy built binaries from build stage
230+
COPY --from=build /app/bin/ /app/bin/
231+
COPY --from=build /app/lib/ /app/lib/
232+
233+
# Copy runtime assets
234+
COPY .github/ /app/.github/
235+
COPY docs/ /app/docs/
236+
COPY LICENSE /app/LICENSE
237+
COPY LICENSES/ /app/LICENSES/
238+
COPY README.adoc /app/README.adoc
239+
COPY EXPLAINME.adoc /app/EXPLAINME.adoc
240+
COPY CONTRIBUTING.adoc /app/CONTRIBUTING.adoc
241+
COPY Justfile /app/Justfile
242+
243+
# Set up firewalld configuration
244+
COPY firewalld/ /etc/firewalld/
245+
RUN chmod 640 /etc/firewalld/* && \
246+
chown root:root /etc/firewalld/*
247+
248+
# Set up SELinux context
249+
RUN chcon -R -t container_file_t /app && \
250+
chcon -R -t httpd_sys_content_t /app/docs && \
251+
chcon -R -t var_log_t /app/logs
252+
253+
# Create non-root user for security
254+
RUN addgroup -S trigger && \
255+
adduser -S -G trigger -D -s /bin/bash trigger && \
256+
mkdir -p /home/trigger && \
257+
chown trigger:trigger /home/trigger && \
258+
chown -R trigger:trigger /app
259+
260+
# Set up environment variables
261+
ENV APP_HOME=/app
262+
ENV APP_USER=trigger
263+
ENV APP_GROUP=trigger
264+
ENV APP_LOG_DIR=/app/logs
265+
ENV APP_CONFIG_DIR=/app/config
266+
ENV APP_CACHE_DIR=/app/cache
267+
ENV APP_SESSION_DIR=/app/sessions
268+
269+
# Set capabilities (minimal)
270+
# Drop all capabilities by default, then add only what's needed
271+
RUN setcap -r /app/bin/trigger
272+
273+
# Set SELinux security context
274+
LABEL maintainer=hyperpolymath
275+
LABEL version=1.0.0
276+
LABEL description="Trigger - Multi-platform social media reporting utility"
277+
LABEL security.txt="v=security.txt; contact=mailto:hyperpolymath@users.noreply.github.com"
278+
279+
# Configure firewalld
280+
RUN firewall-offline-cmd --add-port=80/tcp && \
281+
firewall-offline-cmd --add-port=443/tcp && \
282+
firewall-offline-cmd --add-port=8080/tcp && \
283+
firewall-offline-cmd --add-port=8443/tcp && \
284+
firewall-offline-cmd --set-default-zone=drop && \
285+
firewall-offline-cmd --add-service=ssh && \
286+
firewall-offline-cmd --add-service=https && \
287+
firewall-offline-cmd --add-service=dns
288+
289+
# Set up SELinux policies
290+
RUN setsebool -P container_connect_any=1 && \
291+
setsebool -P container_manage_cgroup=1 && \
292+
setsebool -P httpd_can_network_connect=1 && \
293+
setsebool -P httpd_can_network_relay=0 && \
294+
setsebool -P nfs_export_all_rw=0
295+
296+
# Set working directory
297+
WORKDIR /app
298+
299+
# Set user to non-root for runtime
300+
USER trigger
301+
302+
# Expose ports (only the ones we explicitly allow)
303+
EXPOSE 80/tcp
304+
EXPOSE 443/tcp
305+
EXPOSE 8080/tcp
306+
EXPOSE 8443/tcp
307+
308+
# Health check
309+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
310+
CMD /app/bin/trigger --health || exit 1
311+
312+
# Default command
313+
ENTRYPOINT ["/app/bin/trigger"]
314+
CMD ["--help"]
315+
316+
# =============================================================================
317+
# STAGE 4: Development Container (with full toolchain)
318+
# =============================================================================
319+
320+
FROM builder AS dev
321+
322+
# Keep full build environment for development
323+
WORKDIR /app
324+
325+
# Install development tools
326+
RUN apk add --no-cache \
327+
git \
328+
make \
329+
cmake \
330+
gdb \
331+
valgrind \
332+
clang \
333+
llvm \
334+
rust \
335+
cargo \
336+
go \
337+
nodejs \
338+
npm \
339+
python3 \
340+
py3-pip \
341+
&& rm -rf /var/cache/apk/*
342+
343+
# Set up development environment
344+
ENV DEV_MODE=1
345+
ENV EDITOR=vim
346+
347+
# Install Python packages for development
348+
RUN pip3 install --no-cache-dir \
349+
pons \
350+
panic-attack \
351+
pygments \
352+
black \
353+
flake8 \
354+
mypy \
355+
pytest \
356+
hypothesis
357+
358+
# Set default command for development
359+
ENTRYPOINT ["/bin/bash"]
360+
CMD ["-c", "cd /app && just"]
361+
362+
# =============================================================================
363+
# BUILD COMMANDS
364+
# =============================================================================
365+
366+
# Build production image:
367+
# podman build -f CONTAINERFILE -t hyperpolymath/trigger:latest .
368+
369+
# Build development image:
370+
# podman build -f CONTAINERFILE --target dev -t hyperpolymath/trigger:dev .
371+
372+
# Run production container:
373+
# podman run -it --rm --security-opt label=type:container_runtime_t \
374+
# -p 80:80 -p 443:443 -p 8080:8080 -p 8443:8443 \
375+
# --volume /path/to/config:/app/config:Z \
376+
# --volume /path/to/sessions:/app/sessions:Z \
377+
# hyperpolymath/trigger:latest
378+
379+
# Run development container:
380+
# podman run -it --rm --security-opt label=type:container_runtime_t \
381+
# --volume $(pwd):/app:Z \
382+
# hyperpolymath/trigger:dev

0 commit comments

Comments
 (0)