Skip to content

Commit

Permalink
ci: Build deb/rpm packages (#649)
Browse files Browse the repository at this point in the history
* embed ui into the binary

* make sure all required files are embedded

* make the packaging actually work

* add newlines

* prepare workflow file for testing

* add packaging step for .deb

* defguard-core -> defguard

* place the binary in /usr/bin

* try without path interpolation

* try without cross compilation

* try with env passthrough

* env -> conf

* add frontend building step

* set node version

* add cache dependency path

* remove node version from matrix

* fix path

* frozen lockfile

* build rpm

* cleanup and fix docker

* fix .env file

* remove possibly unnecessary step

* cleanup

* cleanup 2

* sort cargo toml

* add new lines

* change dockerfile

* sort whole file

* remove unused file
  • Loading branch information
t-aleksander authored Jun 25, 2024
1 parent 9ae4a62 commit 6eddd52
Show file tree
Hide file tree
Showing 12 changed files with 207 additions and 53 deletions.
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ DEFGUARD_DEFAULT_ADMIN_PASSWORD=pass123

### Proxy configuration ###
# Optional. URL of proxy gRPC server
# DEFGUARD_PROXY_URL: http://localhost:50051
# DEFGUARD_PROXY_URL=http://localhost:50051

### LDAP configuration ###
DEFGUARD_LDAP_URL=ldap://localhost:389
Expand Down
6 changes: 6 additions & 0 deletions .fpm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-s dir
--name defguard
--architecture x86_64
--description "defguard core service"
--url "https://defguard.net/"
--maintainer "teonite"
56 changes: 56 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,26 @@ jobs:
[registry."docker.io"]
mirrors = ["dockerhub-proxy.teonite.net"]
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 9

- name: Use Node.js 20
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
cache-dependency-path: ./web/pnpm-lock.yaml

- name: Install frontend dependencies
run: pnpm install --ignore-scripts --frozen-lockfile
working-directory: web

- name: Build frontend
run: pnpm build
working-directory: web

- name: Build release binary
uses: actions-rs/cargo@v1
with:
Expand Down Expand Up @@ -139,3 +159,39 @@ jobs:
asset_path: defguard-${{ github.ref_name }}-${{ matrix.target }}.tar.gz
asset_name: defguard-${{ github.ref_name }}-${{ matrix.target }}.tar.gz
asset_content_type: application/octet-stream

- name: Build DEB package
if: matrix.build == 'linux'
uses: bpicode/github-action-fpm@master
with:
fpm_args: "defguard-${{ github.ref_name }}-${{ matrix.target }}=/usr/bin/defguard defguard.service=/usr/lib/systemd/system/defguard.service .env=/etc/defguard/core.conf"
fpm_opts: "--debug --output-type deb --version ${{ env.VERSION }} --package defguard-${{ env.VERSION }}-${{ matrix.target }}.deb"

- name: Upload DEB
if: matrix.build == 'linux'
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: defguard-${{ env.VERSION }}-${{ matrix.target }}.deb
asset_name: defguard-${{ env.VERSION }}-${{ matrix.target }}.deb
asset_content_type: application/octet-stream

- name: Build RPM package
if: matrix.build == 'linux'
uses: bpicode/github-action-fpm@master
with:
fpm_args: "defguard-${{ github.ref_name }}-${{ matrix.target }}=/usr/bin/defguard defguard.service=/usr/lib/systemd/system/defguard.service .env=/etc/defguard/core.conf"
fpm_opts: "--debug --output-type rpm --version ${{ env.VERSION }} --package defguard-${{ env.VERSION }}-${{ matrix.target }}.rpm"

- name: Upload RPM
if: matrix.build == 'linux'
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: defguard-${{ env.VERSION }}-${{ matrix.target }}.rpm
asset_name: defguard-${{ env.VERSION }}-${{ matrix.target }}.rpm
asset_content_type: application/octet-stream
37 changes: 37 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ repository = "https://github.com/DefGuard/defguard"
[workspace]

[dependencies]
model_derive = { path = "model-derive" }
anyhow = "1.0"
argon2 = { version = "0.5", features = ["std"] }
axum = { version = "0.7" }
Expand All @@ -35,16 +34,19 @@ jsonwebtoken = "9.2"
ldap3 = { version = "0.11", default-features = false, features = ["tls"] }
lettre = { version = "0.11", features = ["tokio1", "tokio1-native-tls"] }
md4 = "0.10"
otpauth = "0.4"
mime_guess = "2.0"
model_derive = { path = "model-derive" }
openidconnect = { version = "3.4", default-features = false, optional = true }
pulldown-cmark = "0.9"
otpauth = "0.4"
prost = "0.12"
pulldown-cmark = "0.9"
rand = "0.8"
rand_core = { version = "0.6", default-features = false, features = [
"getrandom",
] }
reqwest = { version = "0.11", features = ["json"] }
rsa = { version = "0.9", features = ["pem"] }
rust-embed = { version = "8.4", features = ["include-exclude"] }
rust-ini = "0.20"
secp256k1 = { version = "0.28", features = [
"recovery",
Expand Down
8 changes: 4 additions & 4 deletions Cross.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pre-build = [
"apt-get update && apt-get install --assume-yes libssl-dev unzip",
"PB_REL='https://github.com/protocolbuffers/protobuf/releases'",
"PB_VERSION='3.20.0' && curl -LO $PB_REL/download/v$PB_VERSION/protoc-$PB_VERSION-linux-x86_64.zip",
"unzip -o protoc-$PB_VERSION-linux-x86_64.zip bin/protoc include/google/* -d /usr"
"unzip -o protoc-$PB_VERSION-linux-x86_64.zip bin/protoc include/google/* -d /usr",
]

[target.armv7-unknown-linux-gnueabihf]
Expand All @@ -17,7 +17,7 @@ pre-build = [
"apt-get update && apt-get install --assume-yes libssl-dev libssl-dev:$CROSS_DEB_ARCH unzip",
"PB_REL='https://github.com/protocolbuffers/protobuf/releases'",
"PB_VERSION='3.20.0' && curl -LO $PB_REL/download/v$PB_VERSION/protoc-$PB_VERSION-linux-x86_64.zip",
"unzip -o protoc-$PB_VERSION-linux-x86_64.zip bin/protoc include/google/* -d /usr"
"unzip -o protoc-$PB_VERSION-linux-x86_64.zip bin/protoc include/google/* -d /usr",
]

[target.aarch64-unknown-linux-gnu]
Expand All @@ -27,7 +27,7 @@ pre-build = [
"apt-get update && apt-get install --assume-yes libssl-dev libssl-dev:$CROSS_DEB_ARCH unzip",
"PB_REL='https://github.com/protocolbuffers/protobuf/releases'",
"PB_VERSION='3.20.0' && curl -LO $PB_REL/download/v$PB_VERSION/protoc-$PB_VERSION-linux-x86_64.zip",
"unzip -o protoc-$PB_VERSION-linux-x86_64.zip bin/protoc include/google/* -d /usr"
"unzip -o protoc-$PB_VERSION-linux-x86_64.zip bin/protoc include/google/* -d /usr",
]


Expand All @@ -37,5 +37,5 @@ pre-build = [
"apt-get update && apt-get install --assume-yes libssl-dev unzip",
"PB_REL='https://github.com/protocolbuffers/protobuf/releases'",
"PB_VERSION='3.20.0' && curl -LO $PB_REL/download/v$PB_VERSION/protoc-$PB_VERSION-linux-x86_64.zip",
"unzip -o protoc-$PB_VERSION-linux-x86_64.zip bin/protoc include/google/* -d /usr"
"unzip -o protoc-$PB_VERSION-linux-x86_64.zip bin/protoc include/google/* -d /usr",
]
28 changes: 13 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
FROM node:20-alpine as web

WORKDIR /app
COPY web/package.json web/pnpm-lock.yaml web/.npmrc .
RUN npm i -g pnpm
RUN pnpm install --ignore-scripts --frozen-lockfile
COPY web/ .
RUN pnpm run generate-translation-types
RUN pnpm build

FROM rust:1.77 as chef

WORKDIR /build
Expand All @@ -20,6 +30,9 @@ COPY --from=planner /build/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json

# build project
COPY --from=web /app/dist ./web/dist
COPY web/src/shared/images/svg ./web/src/shared/images/svg
COPY user_agent_header_regexes.yaml /build/user_agent_header_regexes.yaml
RUN apt-get update && apt-get -y install protobuf-compiler libprotobuf-dev
COPY Cargo.toml Cargo.lock build.rs ./
COPY .sqlx .sqlx
Expand All @@ -30,26 +43,11 @@ COPY proto proto
COPY migrations migrations
RUN cargo install --locked --path . --root /build

FROM node:20.5-alpine3.17 as web

WORKDIR /app
COPY web/package.json .
COPY web/pnpm-lock.yaml .
COPY web/.npmrc .
RUN npm i -g pnpm
RUN pnpm install --ignore-scripts --frozen-lockfile
COPY web/ .
RUN pnpm run generate-translation-types
RUN pnpm build

# run
FROM debian:bookworm-slim as runtime
RUN apt-get update -y && \
apt-get install --no-install-recommends -y ca-certificates libssl-dev && \
rm -rf /var/lib/apt/lists/*
COPY user_agent_header_regexes.yaml /app/user_agent_header_regexes.yaml
WORKDIR /app
COPY --from=builder /build/bin/defguard .
COPY --from=web /app/dist ./web/dist
COPY web/src/shared/images/svg ./web/src/shared/images/svg
ENTRYPOINT ["./defguard"]
18 changes: 0 additions & 18 deletions Dockerfile.ci

This file was deleted.

23 changes: 23 additions & 0 deletions defguard.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[Unit]
Description=defguard core service
Documentation=https://defguard.gitbook.io/defguard/
Wants=network-online.target
After=network-online.target

[Service]
DynamicUser=yes
User=defguard
ExecReload=/bin/kill -HUP $MAINPID
EnvironmentFile=/etc/defguard/core.conf
ExecStart=/usr/bin/defguard
KillMode=process
KillSignal=SIGINT
LimitNOFILE=65536
LimitNPROC=infinity
Restart=on-failure
RestartSec=2
TasksMax=infinity
OOMScoreAdjust=-1000

[Install]
WantedBy=multi-user.target
48 changes: 48 additions & 0 deletions src/assets.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use axum::{
http::{header, StatusCode, Uri},
response::{IntoResponse, Response},
};
use rust_embed::Embed;

pub async fn web_asset(uri: Uri) -> impl IntoResponse {
let mut path = uri.path().trim_start_matches('/').to_string();
// Rewrite the path to match the structure of the embedded files
path.insert_str(0, "dist/");
StaticFile(path)
}

pub async fn index() -> impl IntoResponse {
web_asset(Uri::from_static("/index.html")).await
}

pub async fn svg(uri: Uri) -> impl IntoResponse {
let mut path = uri.path().trim_start_matches('/').to_string();
// Rewrite the path to match the structure of the embedded files
path.insert_str(0, "src/shared/images/");
StaticFile(path)
}

#[derive(Embed)]
#[folder = "web/"]
#[include = "dist/*"]
#[include = "src/shared/images/*"]
struct WebAsset;

pub struct StaticFile<T>(pub T);

impl<T> IntoResponse for StaticFile<T>
where
T: Into<String>,
{
fn into_response(self) -> Response {
let path = self.0.into();

match WebAsset::get(path.as_str()) {
Some(content) => {
let mime = mime_guess::from_path(path).first_or_octet_stream();
([(header::CONTENT_TYPE, mime.as_ref())], content.data).into_response()
}
None => (StatusCode::NOT_FOUND, "404 Not Found").into_response(),
}
}
}
3 changes: 2 additions & 1 deletion src/headers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ use crate::{

#[must_use]
pub fn create_user_agent_parser() -> Arc<UserAgentParser> {
let regexes = include_bytes!("../user_agent_header_regexes.yaml");
Arc::new(
UserAgentParser::builder()
.build_from_yaml("user_agent_header_regexes.yaml")
.build_from_bytes(regexes)
.expect("Parser creation failed"),
)
}
Expand Down
Loading

0 comments on commit 6eddd52

Please sign in to comment.