Skip to content

Commit 98e4b37

Browse files
author
Nicolas Pernoud
committed
feat: integrated fail2ban style jail & standalone binary
1 parent 376570a commit 98e4b37

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1328
-371
lines changed

.github/workflows/build.yml

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,56 @@ jobs:
1919
- name: Test
2020
run: cargo test --release
2121

22+
build-standalone-binary:
23+
name: Build standalone binary for ${{ matrix.suffix }}
24+
runs-on: ubuntu-latest
25+
strategy:
26+
matrix:
27+
include:
28+
- target: x86_64-unknown-linux-gnu
29+
platform: linux/amd64
30+
suffix: amd64
31+
- target: aarch64-unknown-linux-gnu
32+
platform: linux/arm64
33+
suffix: arm64
34+
- target: armv7-unknown-linux-gnueabihf
35+
platform: linux/arm/v7
36+
suffix: armv7
37+
- target: arm-unknown-linux-musleabihf
38+
platform: linux/arm/v6
39+
suffix: armv6
40+
steps:
41+
- name: Free Disk Space (Ubuntu)
42+
uses: jlumbroso/free-disk-space@main
43+
with:
44+
tool-cache: false
45+
android: false
46+
docker-images: false
47+
- uses: actions/checkout@v3
48+
- name: Dotenv Action
49+
id: dotenv
50+
uses: falti/dotenv-action@v1.1.4
51+
with:
52+
path: versions.env
53+
- name: Set up QEMU
54+
uses: docker/setup-qemu-action@v2
55+
- name: Set up Docker Buildx
56+
uses: docker/setup-buildx-action@v2
57+
- name: Build binary using Docker
58+
run: |
59+
docker buildx build \
60+
--platform ${{ matrix.platform }} \
61+
--target binary-exporter \
62+
--output type=local,dest=. \
63+
--build-arg RUST_VERSION=${{ steps.dotenv.outputs.rust_version }} \
64+
--build-arg FLUTTER_VERSION=${{ steps.dotenv.outputs.flutter_version }} \
65+
.
66+
- name: Upload binary
67+
uses: actions/upload-artifact@v4
68+
with:
69+
name: atrium-${{ matrix.suffix }}
70+
path: ./atrium-${{ matrix.suffix }}
71+
2272
docker-build:
2373
name: Build backend with web frontend as docker image and push to docker hub
2474
runs-on: ubuntu-latest
@@ -31,6 +81,11 @@ jobs:
3181
docker-images: false
3282
- name: Code Checkout
3383
uses: actions/checkout@v3
84+
- name: Dotenv Action
85+
id: dotenv
86+
uses: falti/dotenv-action@v1.1.4
87+
with:
88+
path: versions.env
3489
- name: Set up QEMU
3590
uses: docker/setup-qemu-action@v2
3691
- name: Set up Docker Buildx
@@ -42,7 +97,8 @@ jobs:
4297
docker buildx build --push \
4398
--tag nicolaspernoud/atrium:"$([[ ${GITHUB_REF##*/} = main ]] && echo "latest" || echo "${GITHUB_REF##*/}")" \
4499
--platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64 \
45-
$(cat versions.env | grep -v '^#' | xargs -I {} echo --build-arg {}) \
100+
--build-arg RUST_VERSION=${{ steps.dotenv.outputs.rust_version }} \
101+
--build-arg FLUTTER_VERSION=${{ steps.dotenv.outputs.flutter_version }} \
46102
.
47103
48104
app-build:
@@ -59,8 +115,6 @@ jobs:
59115
uses: falti/dotenv-action@v1.1.4
60116
with:
61117
path: versions.env
62-
- name: Export Release Timestamp
63-
run: echo "APP_VERSION=$(date +'%Y-%m-%d_%H-%m-%S')" >> $GITHUB_ENV
64118
- name: Set up Java
65119
uses: actions/setup-java@v4
66120
with:
@@ -77,17 +131,39 @@ jobs:
77131
run: echo "${{ secrets.KEY_PROPERTIES }}" | base64 --decode > android/key.properties
78132
- name: Install pub Dependencies
79133
run: flutter pub get
80-
# - name: Run Tests
81-
# run: flutter test
82134
- name: Build Android App
83135
run: flutter build apk --split-per-abi
136+
- name: Upload APKs
137+
uses: actions/upload-artifact@v4
138+
with:
139+
name: apks
140+
path: frontend/build/app/outputs/flutter-apk/*.apk
141+
142+
release:
143+
name: Release App
144+
runs-on: ubuntu-latest
145+
needs: [build-standalone-binary, app-build]
146+
if: github.ref == 'refs/heads/main'
147+
steps:
148+
- name: Export Release Timestamp
149+
run: echo "APP_VERSION=$(date +'%Y-%m-%d_%H-%m-%S')" >> $GITHUB_ENV
150+
- name: Download all binaries
151+
uses: actions/download-artifact@v4
152+
with:
153+
pattern: atrium-*
154+
merge-multiple: true
155+
- name: Download APKs
156+
uses: actions/download-artifact@v4
157+
with:
158+
name: apks
159+
path: apks
84160
- name: Release Apps
85161
uses: ncipollo/release-action@v1
86162
with:
87163
tag: ${{ env.APP_VERSION }}
88164
name: ${{ env.APP_VERSION }}
89165
token: ${{ secrets.GITHUB_TOKEN }}
90-
artifacts: "frontend/build/app/outputs/flutter-apk/*.apk"
166+
artifacts: "atrium-*,apks/*.apk"
91167
- name: Delete old releases
92168
uses: dev-drprasad/delete-older-releases@v0.2.0
93169
with:

.github/workflows/nosetcap-image.yml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ jobs:
1717
docker-images: false
1818
- name: Code Checkout
1919
uses: actions/checkout@v3
20+
- name: Dotenv Action
21+
id: dotenv
22+
uses: falti/dotenv-action@v1.1.4
23+
with:
24+
path: versions.env
2025
- name: Set up QEMU
2126
uses: docker/setup-qemu-action@v2
2227
- name: Set up Docker Buildx
@@ -27,7 +32,8 @@ jobs:
2732
run: |
2833
sed -i '/^RUN setcap/d' Dockerfile && \
2934
docker buildx build --push \
30-
--tag nicolaspernoud/atrium:nosetcap \
31-
--platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64 \
32-
$(cat versions.env | grep -v '^#' | xargs -I {} echo --build-arg {}) \
33-
.
35+
--tag nicolaspernoud/atrium:nosetcap \
36+
--platform linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64 \
37+
--build-arg RUST_VERSION=${{ steps.dotenv.outputs.rust_version }} \
38+
--build-arg FLUTTER_VERSION=${{ steps.dotenv.outputs.flutter_version }} \
39+
.

Dockerfile

Lines changed: 90 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,87 @@
1-
###########################
2-
# Stage 1 : Backend build #
3-
###########################
1+
# syntax=docker/dockerfile:1
42

5-
# Versions
6-
ARG RUST_VERSION
7-
ARG FLUTTER_VERSION
3+
# Default versions (can be overridden with --build-arg)
4+
ARG RUST_VERSION=1.93
5+
ARG FLUTTER_VERSION=3.41.2
86

9-
# Set up an environnement to cross-compile the app for musl to create a statically-linked binary
10-
FROM --platform=$BUILDPLATFORM rust:${RUST_VERSION}-trixie AS backend-builder
7+
# --- Frontend Builder ---
8+
# Use the Flutter image to build the web assets
9+
FROM --platform=$BUILDPLATFORM ghcr.io/cirruslabs/flutter:${FLUTTER_VERSION} AS frontend-builder
10+
WORKDIR /src
11+
# Build the Flutter web app
12+
COPY --exclude=.dart_tool frontend .
13+
RUN flutter build web --release
14+
# Add the static web assets
15+
COPY --exclude=index.html backend/web/. build/web/
16+
# Gzip assets for the backend to serve gzipped files
17+
RUN find build/web -type f ! -name "*.gz" ! -name "*.tmpl" -exec gzip -9 {} +
18+
19+
# --- Backend Builder ---
20+
FROM --platform=$BUILDPLATFORM rust:${RUST_VERSION}-bookworm AS backend-builder
1121
ARG TARGETPLATFORM
12-
RUN case "$TARGETPLATFORM" in \
13-
"linux/amd64") echo x86_64-unknown-linux-gnu > /rust_target.txt ;; \
14-
"linux/arm64") echo aarch64-unknown-linux-gnu > /rust_target.txt ;; \
15-
"linux/arm/v7") echo armv7-unknown-linux-gnueabihf > /rust_target.txt ;; \
16-
"linux/arm/v6") wget https://github.com/cross-tools/musl-cross/releases/download/20250929/arm-unknown-linux-musleabihf.tar.xz -O - | tar -xJf - -C /opt && echo arm-unknown-linux-musleabihf > /rust_target.txt ;; \
17-
*) exit 1 ;; \
18-
esac
19-
ENV PATH="/opt/arm-unknown-linux-musleabihf/bin:$PATH"
20-
RUN rustup target add $(cat /rust_target.txt)
21-
RUN apt update && apt install -y clang cmake gcc-aarch64-linux-gnu gcc-arm-linux-gnueabihf libc6-dev-i386 libcap2-bin libclang-dev musl-dev musl-tools
22+
23+
# Install cross-compilation dependencies
24+
RUN apt-get update && apt-get install -y \
25+
clang \
26+
cmake \
27+
gcc-aarch64-linux-gnu \
28+
gcc-arm-linux-gnueabihf \
29+
libc6-dev-i386 \
30+
libcap2-bin \
31+
libclang-dev \
32+
musl-dev \
33+
musl-tools \
34+
wget \
35+
xz-utils \
36+
&& rm -rf /var/lib/apt/lists/*
37+
2238
RUN ln -s /usr/include/asm-generic /usr/include/asm
2339

40+
# Handle armv6 musl toolchain if needed
41+
RUN if [ "$TARGETPLATFORM" = "linux/arm/v6" ]; then \
42+
wget https://github.com/cross-tools/musl-cross/releases/download/20250929/arm-unknown-linux-musleabihf.tar.xz -O - | tar -xJf - -C /opt; \
43+
fi
44+
ENV PATH="/opt/arm-unknown-linux-musleabihf/bin:$PATH"
45+
46+
WORKDIR /app
47+
48+
# Determine the rust target
49+
RUN case "$TARGETPLATFORM" in \
50+
"linux/amd64") RUST_TARGET="x86_64-unknown-linux-gnu" ;; \
51+
"linux/arm64") RUST_TARGET="aarch64-unknown-linux-gnu" ;; \
52+
"linux/arm/v7") RUST_TARGET="armv7-unknown-linux-gnueabihf" ;; \
53+
"linux/arm/v6") RUST_TARGET="arm-unknown-linux-musleabihf" ;; \
54+
*) RUST_TARGET="x86_64-unknown-linux-gnu" ;; \
55+
esac; \
56+
echo "$RUST_TARGET" > /rust_target_name && \
57+
rustup target add "$RUST_TARGET"
58+
59+
# Copy frontend assets from frontend-builder
60+
# We copy them to backend/dist because backend/src/web.rs uses #[folder = "dist/"]
61+
COPY --from=frontend-builder /src/build/web ./backend/dist
62+
63+
# Copy backend source
64+
COPY backend/Cargo.toml ./backend/
65+
COPY backend/.cargo ./backend/.cargo
66+
COPY backend/src ./backend/src
67+
68+
WORKDIR /app/backend
69+
RUN RUST_TARGET=$(cat /rust_target_name) && \
70+
cargo build --profile release_optimized --target "$RUST_TARGET" && \
71+
cp target/"$RUST_TARGET"/release_optimized/atrium /atrium
72+
73+
# --- Binary Exporter ---
74+
# This stage is used to extract the binary locally
75+
FROM scratch AS binary-exporter
76+
ARG TARGETARCH
77+
ARG TARGETVARIANT
78+
COPY --from=backend-builder /atrium /atrium-${TARGETARCH}${TARGETVARIANT}
79+
80+
# --- Final Prep ---
81+
# Prepare the binary and environment in a temporary stage
82+
FROM --platform=$BUILDPLATFORM debian:trixie-slim AS prep
83+
ARG TARGETPLATFORM
84+
RUN apt-get update && apt-get install -y adduser libcap2-bin && rm -rf /var/lib/apt/lists/*
2485
# Create appuser
2586
ENV USER=appuser
2687
ENV UID=1000
@@ -33,54 +94,25 @@ RUN adduser \
3394
--uid "${UID}" \
3495
"${USER}"
3596

36-
WORKDIR /build
37-
38-
COPY ./backend/.cargo ./.cargo
39-
COPY ./backend/Cargo.toml ./
40-
COPY ./backend/src ./src
41-
COPY ./backend/tests ./tests
42-
43-
#RUN cargo test --release --target $(cat /rust_target.txt)
44-
RUN cargo build --profile release_optimized --target $(cat /rust_target.txt)
45-
RUN cp target/$(cat /rust_target.txt)/release_optimized/atrium .
46-
RUN chown -f "${UID}":"${UID}" ./atrium
47-
# Allow running on ports < 1000
48-
RUN setcap cap_net_bind_service=+ep ./atrium
49-
5097
RUN mkdir -p /myapp/app
51-
COPY ./backend/atrium.yaml /myapp/app
52-
COPY ./backend/web/onlyoffice/ /myapp/app/web/onlyoffice/
53-
COPY ./backend/web/oauth2/ /myapp/app/web/oauth2/
54-
RUN chown -Rf "${UID}":"${UID}" /myapp
55-
56-
############################
57-
# Stage 2 : Frontend build #
58-
############################
59-
60-
FROM --platform=$BUILDPLATFORM ghcr.io/cirruslabs/flutter:${FLUTTER_VERSION} AS frontend-builder
61-
WORKDIR /build
62-
COPY ./frontend .
63-
RUN flutter pub get
64-
RUN flutter build web
65-
66-
#########################
67-
# Stage 3 : Final image #
68-
#########################
98+
COPY --from=backend-builder /atrium /myapp/app/atrium
99+
RUN chown -Rf "${UID}":"${UID}" /myapp/app/
100+
# Allow running on ports < 1000
101+
RUN setcap cap_net_bind_service=+ep /myapp/app/atrium
69102

103+
# --- Final Image ---
70104
FROM --platform=linux/amd64 gcr.io/distroless/cc-debian13 AS base-amd64
71105
FROM --platform=linux/arm64 gcr.io/distroless/cc-debian13 AS base-arm64
72106
FROM --platform=linux/arm/v7 gcr.io/distroless/cc-debian13 AS base-armv7
73107
FROM --platform=linux/arm/v6 scratch AS base-armv6
74108

109+
ARG TARGETARCH
110+
ARG TARGETVARIANT
75111
FROM base-${TARGETARCH}${TARGETVARIANT}
112+
COPY --from=prep /etc/passwd /etc/passwd
113+
COPY --from=prep /etc/group /etc/group
114+
COPY --from=prep --chown=appuser:appuser /myapp /
76115

77-
COPY --from=backend-builder /etc/passwd /etc/passwd
78-
COPY --from=backend-builder /etc/group /etc/group
79-
80-
COPY --from=backend-builder /myapp /
81116
WORKDIR /app
82-
COPY --from=backend-builder /build/atrium ./
83-
COPY --chown=appuser:appuser --from=frontend-builder /build/build/web/ /app/web/
84-
85117
USER appuser:appuser
86-
ENTRYPOINT ["./atrium"]
118+
ENTRYPOINT ["./atrium"]

0 commit comments

Comments
 (0)