34 Commits

Author SHA1 Message Date
c7f9d5c036 ci: fix binary path in image (/usr/local/bin/nora) 2026-02-24 14:03:16 +00:00
b41bfd9a88 ci: pin build job to nora runner label to avoid wrong runner 2026-02-24 13:18:11 +00:00
3e3070a401 docs: use logo.jpg in README 2026-02-24 12:47:07 +00:00
3868b16ea4 docs: replace text title with SVG logo, O styled in blue-600 2026-02-24 12:29:07 +00:00
3a6d3eeb9a feat: add binary + sha256 to GitHub Release artifacts 2026-02-24 12:14:29 +00:00
dd29707395 ci: ignore RUSTSEC-2025-0119 (number_prefix unmaintained, transitive via indicatif) 2026-02-24 12:06:34 +00:00
e7a6a652af ci: allow CDLA-Permissive-2.0 license (webpki-roots) 2026-02-24 11:54:19 +00:00
4ad802ce2f fix: bump prometheus 0.13->0.14 and bytes 1.11.0->1.11.1 (CVE-2025-53605, CVE-2026-25541) 2026-02-24 11:36:07 +00:00
dependabot[bot]
04c806b659 chore(deps): bump chrono from 0.4.43 to 0.4.44 (#10)
Bumps [chrono](https://github.com/chronotope/chrono) from 0.4.43 to 0.4.44.
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.43...v0.4.44)

---
updated-dependencies:
- dependency-name: chrono
  dependency-version: 0.4.44
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-24 12:23:06 +01:00
dependabot[bot]
50a5395a87 chore(deps): bump quick-xml from 0.31.0 to 0.39.2 (#9)
Bumps [quick-xml](https://github.com/tafia/quick-xml) from 0.31.0 to 0.39.2.
- [Release notes](https://github.com/tafia/quick-xml/releases)
- [Changelog](https://github.com/tafia/quick-xml/blob/master/Changelog.md)
- [Commits](https://github.com/tafia/quick-xml/compare/v0.31.0...v0.39.2)

---
updated-dependencies:
- dependency-name: quick-xml
  dependency-version: 0.39.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-24 12:22:58 +01:00
dependabot[bot]
bcd172f23f chore(deps): bump toml from 0.8.23 to 1.0.3+spec-1.1.0 (#7)
Bumps [toml](https://github.com/toml-rs/toml) from 0.8.23 to 1.0.3+spec-1.1.0.
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.23...toml-v1.0.3)

---
updated-dependencies:
- dependency-name: toml
  dependency-version: 1.0.3+spec-1.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-24 12:22:52 +01:00
dependabot[bot]
a5a7c4f8be chore(deps): bump flate2 from 1.1.8 to 1.1.9 (#6)
Bumps [flate2](https://github.com/rust-lang/flate2-rs) from 1.1.8 to 1.1.9.
- [Release notes](https://github.com/rust-lang/flate2-rs/releases)
- [Commits](https://github.com/rust-lang/flate2-rs/compare/1.1.8...1.1.9)

---
updated-dependencies:
- dependency-name: flate2
  dependency-version: 1.1.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-24 12:22:46 +01:00
dependabot[bot]
2c7c497c30 chore(deps): bump softprops/action-gh-release from 1 to 2 (#5)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 1 to 2.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v1...v2)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: '2'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-24 12:20:23 +01:00
dependabot[bot]
6b6f88ab9c chore(deps): bump actions/checkout from 4 to 6 (#4)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-24 12:20:19 +01:00
dependabot[bot]
1255e3227b chore(deps): bump docker/build-push-action from 5 to 6 (#3)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5 to 6.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-24 12:20:16 +01:00
dependabot[bot]
aabd0b76fb chore(deps): bump aquasecurity/trivy-action from 0.30.0 to 0.34.1 (#2)
Bumps [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action) from 0.30.0 to 0.34.1.
- [Release notes](https://github.com/aquasecurity/trivy-action/releases)
- [Commits](https://github.com/aquasecurity/trivy-action/compare/0.30.0...0.34.1)

---
updated-dependencies:
- dependency-name: aquasecurity/trivy-action
  dependency-version: 0.34.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-24 12:20:12 +01:00
ac14405af3 ci: restore scan gate on release, block on HIGH/CRITICAL CVE 2026-02-24 10:53:28 +00:00
5f385dce45 ci: add dependabot, pin trivy-action@0.30.0, release no longer waits on scan 2026-02-24 10:48:06 +00:00
761e08f168 ci: upgrade codeql-action v3 -> v4 2026-02-24 10:41:37 +00:00
eb4f82df07 ci: fix deny.toml deprecated keys (copyleft, unlicensed removed in cargo-deny) 2026-02-24 10:26:58 +00:00
9784ad1813 chore: bump version to 0.2.22 2026-02-24 09:20:52 +00:00
fc1288820d ci: remove astra build for now 2026-02-24 00:39:16 +00:00
a17a75161b ci: consolidate all docker builds into single job to fix runner network issues 2026-02-24 00:07:44 +00:00
0b3ef3ab96 ci: use shared runner filesystem instead of artifact API to avoid network upload 2026-02-23 23:41:41 +00:00
99e290d30c ci: fix SBOM image tag and registry credentials 2026-02-23 18:53:17 +00:00
f74b781d1f ci: build musl static binary, fix cargo path (hardcode github-runner home) 2026-02-23 18:08:57 +00:00
05c765627f ci: fix trivy image tag (strip v prefix) 2026-02-23 16:47:18 +00:00
1813546bee ci: move trivy image scan to separate ubuntu-latest job to avoid self-hosted timeout 2026-02-23 16:15:03 +00:00
196c313f20 ci: add cargo cache to build-binary job, remove nora proxy (no sparse protocol) 2026-02-23 14:17:39 +00:00
aece2d739d ci: add registry credentials to trivy image scan 2026-02-23 14:01:31 +00:00
b7e11da2da ci: replace gitleaks action with CLI to avoid license requirement 2026-02-23 13:59:12 +00:00
dd3813edff ci: use github-runner own rust toolchain instead of ai-user path 2026-02-23 13:54:23 +00:00
adade10c67 chore: bump version to 0.2.21 2026-02-23 12:05:19 +00:00
6ad710ff32 ci: add security scanning and SBOM to release pipeline
- ci.yml: add security job (gitleaks, cargo-audit, cargo-deny, trivy fs)
- release.yml: restructure into build-binary + build-docker matrix + release
  - build binary once on self-hosted, reuse across all Docker builds
  - trivy image scan per matrix variant, results to GitHub Security tab
  - SBOM generation in SPDX and CycloneDX formats attached to release
- deny.toml: cargo-deny policy (allowed licenses, banned openssl, crates.io only)
- Dockerfile: remove Rust build stage, use pre-built binary
- Dockerfile.astra, Dockerfile.redos: FROM scratch for Russian certified OS support
2026-02-23 11:37:27 +00:00
15 changed files with 373 additions and 234 deletions

16
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
version: 2
updates:
# GitHub Actions — обновляет версии actions в workflows
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
labels: [dependencies, ci]
# Cargo — только security-апдейты, без шума от minor/patch
- package-ecosystem: cargo
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5
labels: [dependencies, rust]

View File

@@ -11,7 +11,7 @@ jobs:
name: Test name: Test
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v6
- name: Install Rust - name: Install Rust
uses: dtolnay/rust-toolchain@stable uses: dtolnay/rust-toolchain@stable
@@ -27,3 +27,63 @@ jobs:
- name: Run tests - name: Run tests
run: cargo test --package nora-registry run: cargo test --package nora-registry
security:
name: Security
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write # for uploading SARIF to GitHub Security tab
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0 # full history required for gitleaks
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo
uses: Swatinem/rust-cache@v2
# ── Secrets ────────────────────────────────────────────────────────────
- name: Gitleaks — scan for hardcoded secrets
run: |
curl -sL https://github.com/gitleaks/gitleaks/releases/download/v8.21.2/gitleaks_8.21.2_linux_x64.tar.gz \
| tar xz -C /usr/local/bin gitleaks
gitleaks detect --source . --exit-code 1 --report-format sarif --report-path gitleaks.sarif || true
continue-on-error: true # findings are reported, do not block the pipeline
# ── CVE in Rust dependencies ────────────────────────────────────────────
- name: Install cargo-audit
run: cargo install cargo-audit --locked
- name: cargo audit — RustSec advisory database
run: cargo audit
continue-on-error: true # warn only; known CVEs should not block CI until triaged
# ── Licenses, banned crates, supply chain policy ────────────────────────
- name: cargo deny — licenses and banned crates
uses: EmbarkStudios/cargo-deny-action@v2
with:
command: check
arguments: --all-features
# ── CVE scan of source tree and Cargo.lock ──────────────────────────────
- name: Trivy — filesystem scan (Cargo.lock + source)
if: always()
uses: aquasecurity/trivy-action@0.34.1
with:
scan-type: fs
scan-ref: .
format: sarif
output: trivy-fs.sarif
severity: HIGH,CRITICAL
exit-code: 0 # warn only; change to 1 to block the pipeline
- name: Upload Trivy fs results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v4
if: always()
with:
sarif_file: trivy-fs.sarif
category: trivy-fs

View File

@@ -10,29 +10,26 @@ env:
jobs: jobs:
build: build:
name: Build & Push (${{ matrix.name }}) name: Build & Push
runs-on: self-hosted runs-on: [self-hosted, nora]
permissions: permissions:
contents: read contents: read
packages: write packages: write
strategy:
fail-fast: false
matrix:
include:
- name: alpine
dockerfile: Dockerfile
suffix: ""
- name: astra
dockerfile: Dockerfile.astra
suffix: "-astra"
- name: redos
dockerfile: Dockerfile.redos
suffix: "-redos"
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Set up Rust
run: |
echo "/home/github-runner/.cargo/bin" >> $GITHUB_PATH
echo "RUSTUP_HOME=/home/github-runner/.rustup" >> $GITHUB_ENV
echo "CARGO_HOME=/home/github-runner/.cargo" >> $GITHUB_ENV
- name: Build release binary (musl static)
run: |
cargo build --release --target x86_64-unknown-linux-musl --package nora-registry
cp target/x86_64-unknown-linux-musl/release/nora ./nora
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
@@ -43,46 +40,179 @@ jobs:
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata # ── Alpine (standard) ────────────────────────────────────────────────────
id: meta - name: Extract metadata (alpine)
id: meta-alpine
uses: docker/metadata-action@v5 uses: docker/metadata-action@v5
with: with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
flavor: |
suffix=${{ matrix.suffix }},onlatest=true
tags: | tags: |
type=semver,pattern={{version}} type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable=${{ matrix.suffix == '' }} type=raw,value=latest
type=raw,value=${{ matrix.name }},enable=${{ matrix.suffix != '' }}
- name: Build and push - name: Build and push (alpine)
uses: docker/build-push-action@v5 uses: docker/build-push-action@v5
with: with:
context: . context: .
file: ${{ matrix.dockerfile }} file: Dockerfile
platforms: linux/amd64 platforms: linux/amd64
push: true push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta-alpine.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta-alpine.outputs.labels }}
cache-from: type=gha,scope=${{ matrix.name }} cache-from: type=gha,scope=alpine
cache-to: type=gha,mode=max,scope=${{ matrix.name }} cache-to: type=gha,mode=max,scope=alpine
# ── RED OS ───────────────────────────────────────────────────────────────
- name: Extract metadata (redos)
id: meta-redos
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
flavor: suffix=-redos,onlatest=true
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=redos
- name: Build and push (redos)
uses: docker/build-push-action@v5
with:
context: .
file: Dockerfile.redos
platforms: linux/amd64
push: true
tags: ${{ steps.meta-redos.outputs.tags }}
labels: ${{ steps.meta-redos.outputs.labels }}
cache-from: type=gha,scope=redos
cache-to: type=gha,mode=max,scope=redos
scan:
name: Scan (${{ matrix.name }})
runs-on: ubuntu-latest
needs: build
permissions:
contents: read
packages: read
security-events: write
strategy:
fail-fast: false
matrix:
include:
- name: alpine
suffix: ""
- name: redos
suffix: "-redos"
steps:
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set version tag (strip leading v)
id: ver
run: echo "tag=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT
# ── CVE scan of the pushed image ────────────────────────────────────────
# Images are FROM scratch — no OS packages, only binary CVE scan
- name: Trivy — image scan (${{ matrix.name }})
uses: aquasecurity/trivy-action@0.30.0
with:
scan-type: image
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.ver.outputs.tag }}${{ matrix.suffix }}
format: sarif
output: trivy-image-${{ matrix.name }}.sarif
severity: HIGH,CRITICAL
exit-code: 1 # block release on HIGH/CRITICAL vulnerabilities
- name: Upload Trivy image results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v4
if: always()
with:
sarif_file: trivy-image-${{ matrix.name }}.sarif
category: trivy-image-${{ matrix.name }}
release: release:
name: GitHub Release name: GitHub Release
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: [build, scan]
permissions: permissions:
contents: write contents: write
packages: read # to pull image for SBOM generation
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set version tag (strip leading v)
id: ver
run: echo "tag=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT
# ── Binary — extract from Docker image ──────────────────────────────────
- name: Extract binary from image
run: |
docker create --name nora-extract \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.ver.outputs.tag }}
docker cp nora-extract:/usr/local/bin/nora ./nora-linux-amd64
docker rm nora-extract
chmod +x ./nora-linux-amd64
sha256sum ./nora-linux-amd64 > nora-linux-amd64.sha256
echo "Binary size: $(du -sh nora-linux-amd64 | cut -f1)"
cat nora-linux-amd64.sha256
# ── SBOM — Software Bill of Materials ───────────────────────────────────
- name: Generate SBOM (SPDX)
uses: anchore/sbom-action@v0
with:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.ver.outputs.tag }}
format: spdx-json
output-file: nora-${{ github.ref_name }}.sbom.spdx.json
registry-username: ${{ github.actor }}
registry-password: ${{ secrets.GITHUB_TOKEN }}
- name: Generate SBOM (CycloneDX)
uses: anchore/sbom-action@v0
with:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.ver.outputs.tag }}
format: cyclonedx-json
output-file: nora-${{ github.ref_name }}.sbom.cdx.json
registry-username: ${{ github.actor }}
registry-password: ${{ secrets.GITHUB_TOKEN }}
- name: Create Release - name: Create Release
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
with: with:
generate_release_notes: true generate_release_notes: true
files: |
nora-linux-amd64
nora-linux-amd64.sha256
nora-${{ github.ref_name }}.sbom.spdx.json
nora-${{ github.ref_name }}.sbom.cdx.json
body: | body: |
## Install
```bash
curl -fsSL https://getnora.io/install.sh | sh
```
Or download the binary directly:
```bash
curl -LO https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/nora-linux-amd64
chmod +x nora-linux-amd64
sudo mv nora-linux-amd64 /usr/local/bin/nora
```
## Docker ## Docker
**Alpine (standard):** **Alpine (standard):**
@@ -90,11 +220,6 @@ jobs:
docker pull ghcr.io/${{ github.repository }}:${{ github.ref_name }} docker pull ghcr.io/${{ github.repository }}:${{ github.ref_name }}
``` ```
**Astra Linux SE:**
```bash
docker pull ghcr.io/${{ github.repository }}:${{ github.ref_name }}-astra
```
**RED OS:** **RED OS:**
```bash ```bash
docker pull ghcr.io/${{ github.repository }}:${{ github.ref_name }}-redos docker pull ghcr.io/${{ github.repository }}:${{ github.ref_name }}-redos

113
Cargo.lock generated
View File

@@ -234,9 +234,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.11.0" version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
[[package]] [[package]]
name = "cc" name = "cc"
@@ -262,9 +262,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.43" version = "0.4.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
dependencies = [ dependencies = [
"iana-time-zone", "iana-time-zone",
"js-sys", "js-sys",
@@ -495,9 +495,9 @@ checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]] [[package]]
name = "flate2" name = "flate2"
version = "1.1.8" version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369" checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
dependencies = [ dependencies = [
"crc32fast", "crc32fast",
"miniz_oxide", "miniz_oxide",
@@ -1201,7 +1201,7 @@ checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21"
[[package]] [[package]]
name = "nora-cli" name = "nora-cli"
version = "0.2.20" version = "0.2.22"
dependencies = [ dependencies = [
"clap", "clap",
"flate2", "flate2",
@@ -1215,7 +1215,7 @@ dependencies = [
[[package]] [[package]]
name = "nora-registry" name = "nora-registry"
version = "0.2.20" version = "0.2.22"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"axum", "axum",
@@ -1253,7 +1253,7 @@ dependencies = [
[[package]] [[package]]
name = "nora-storage" name = "nora-storage"
version = "0.2.20" version = "0.2.22"
dependencies = [ dependencies = [
"axum", "axum",
"base64", "base64",
@@ -1412,9 +1412,9 @@ dependencies = [
[[package]] [[package]]
name = "prometheus" name = "prometheus"
version = "0.13.4" version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" checksum = "3ca5326d8d0b950a9acd87e6a3f94745394f62e4dae1b1ee22b2bc0c394af43a"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"fnv", "fnv",
@@ -1422,14 +1422,28 @@ dependencies = [
"memchr", "memchr",
"parking_lot", "parking_lot",
"protobuf", "protobuf",
"thiserror 1.0.69", "thiserror 2.0.18",
] ]
[[package]] [[package]]
name = "protobuf" name = "protobuf"
version = "2.28.0" version = "3.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" checksum = "d65a1d4ddae7d8b5de68153b48f6aa3bba8cb002b243dbdbc55a5afbc98f99f4"
dependencies = [
"once_cell",
"protobuf-support",
"thiserror 1.0.69",
]
[[package]]
name = "protobuf-support"
version = "3.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e36c2f31e0a47f9280fb347ef5e461ffcd2c52dd520d8e216b52f93b0b0d7d6"
dependencies = [
"thiserror 1.0.69",
]
[[package]] [[package]]
name = "quanta" name = "quanta"
@@ -1448,9 +1462,9 @@ dependencies = [
[[package]] [[package]]
name = "quick-xml" name = "quick-xml"
version = "0.31.0" version = "0.39.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" checksum = "958f21e8e7ceb5a1aa7fa87fab28e7c75976e0bfe7e23ff069e0a260f894067d"
dependencies = [ dependencies = [
"memchr", "memchr",
"serde", "serde",
@@ -1836,11 +1850,11 @@ dependencies = [
[[package]] [[package]]
name = "serde_spanned" name = "serde_spanned"
version = "0.6.9" version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776"
dependencies = [ dependencies = [
"serde", "serde_core",
] ]
[[package]] [[package]]
@@ -2139,44 +2153,42 @@ dependencies = [
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.8.23" version = "1.0.3+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" checksum = "c7614eaf19ad818347db24addfa201729cf2a9b6fdfd9eb0ab870fcacc606c0c"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.22.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"serde", "serde_core",
"serde_spanned", "serde_spanned",
"toml_datetime", "toml_datetime",
"toml_write", "toml_parser",
"toml_writer",
"winnow", "winnow",
] ]
[[package]] [[package]]
name = "toml_write" name = "toml_datetime"
version = "0.1.2" version = "1.0.0+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e"
dependencies = [
"serde_core",
]
[[package]]
name = "toml_parser"
version = "1.0.9+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4"
dependencies = [
"winnow",
]
[[package]]
name = "toml_writer"
version = "1.0.6+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607"
[[package]] [[package]]
name = "tonic" name = "tonic"
@@ -2856,9 +2868,6 @@ name = "winnow"
version = "0.7.14" version = "0.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "wiremock" name = "wiremock"
@@ -3038,9 +3047,9 @@ dependencies = [
[[package]] [[package]]
name = "zlib-rs" name = "zlib-rs"
version = "0.5.5" version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" checksum = "c745c48e1007337ed136dc99df34128b9faa6ed542d80a1c673cf55a6d7236c8"
[[package]] [[package]]
name = "zmij" name = "zmij"

View File

@@ -7,7 +7,7 @@ members = [
] ]
[workspace.package] [workspace.package]
version = "0.2.20" version = "0.2.23"
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"
authors = ["DevITWay <devitway@gmail.com>"] authors = ["DevITWay <devitway@gmail.com>"]

View File

@@ -1,58 +1,11 @@
# syntax=docker/dockerfile:1.4 # syntax=docker/dockerfile:1.4
# Binary is pre-built by CI (cargo build --release) and passed via context
# Build stage
FROM rust:1.83-alpine AS builder
RUN apk add --no-cache musl-dev curl
WORKDIR /app
# Copy manifests
COPY Cargo.toml Cargo.lock ./
COPY nora-registry/Cargo.toml nora-registry/
COPY nora-storage/Cargo.toml nora-storage/
COPY nora-cli/Cargo.toml nora-cli/
# Create dummy sources for dependency caching
RUN mkdir -p nora-registry/src nora-storage/src nora-cli/src && \
echo "fn main() {}" > nora-registry/src/main.rs && \
echo "fn main() {}" > nora-storage/src/main.rs && \
echo "fn main() {}" > nora-cli/src/main.rs
# Build dependencies only (with cache)
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/usr/local/cargo/git \
--mount=type=cache,target=/app/target \
cargo build --release --package nora-registry && \
rm -rf nora-registry/src nora-storage/src nora-cli/src
# Copy real sources
COPY nora-registry/src nora-registry/src
COPY nora-storage/src nora-storage/src
COPY nora-cli/src nora-cli/src
# Build release binary (with cache)
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/usr/local/cargo/git \
--mount=type=cache,target=/app/target \
touch nora-registry/src/main.rs && \
cargo build --release --package nora-registry && \
cp /app/target/release/nora /usr/local/bin/nora
# Runtime stage
FROM alpine:3.20 FROM alpine:3.20
RUN apk add --no-cache ca-certificates RUN apk add --no-cache ca-certificates && mkdir -p /data
WORKDIR /app COPY nora /usr/local/bin/nora
# Copy binary
COPY --from=builder /usr/local/bin/nora /usr/local/bin/nora
# Create data directory
RUN mkdir -p /data
# Default environment
ENV RUST_LOG=info ENV RUST_LOG=info
ENV NORA_HOST=0.0.0.0 ENV NORA_HOST=0.0.0.0
ENV NORA_PORT=4000 ENV NORA_PORT=4000
@@ -64,5 +17,5 @@ EXPOSE 4000
VOLUME ["/data"] VOLUME ["/data"]
ENTRYPOINT ["nora"] ENTRYPOINT ["/usr/local/bin/nora"]
CMD ["serve"] CMD ["serve"]

View File

@@ -1,52 +1,17 @@
# syntax=docker/dockerfile:1.4 # syntax=docker/dockerfile:1.4
# Binary is pre-built by CI (cargo build --release) and passed via context
# Runtime: scratch — compatible with Astra Linux SE (FSTEC certified)
# To switch to official base: replace FROM scratch with
# FROM registry.astralinux.ru/library/alse:latest
# RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates && rm -rf /var/lib/apt/lists/*
# Build stage — static binary via musl (runs on any Linux) FROM alpine:3.20 AS certs
FROM rust:1.83-alpine AS builder RUN apk add --no-cache ca-certificates
RUN apk add --no-cache musl-dev curl
WORKDIR /app
# Copy manifests
COPY Cargo.toml Cargo.lock ./
COPY nora-registry/Cargo.toml nora-registry/
COPY nora-storage/Cargo.toml nora-storage/
COPY nora-cli/Cargo.toml nora-cli/
# Create dummy sources for dependency caching
RUN mkdir -p nora-registry/src nora-storage/src nora-cli/src && \
echo "fn main() {}" > nora-registry/src/main.rs && \
echo "fn main() {}" > nora-storage/src/main.rs && \
echo "fn main() {}" > nora-cli/src/main.rs
# Build dependencies only (with cache)
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/usr/local/cargo/git \
--mount=type=cache,target=/app/target \
cargo build --release --package nora-registry && \
rm -rf nora-registry/src nora-storage/src nora-cli/src
# Copy real sources
COPY nora-registry/src nora-registry/src
COPY nora-storage/src nora-storage/src
COPY nora-cli/src nora-cli/src
# Build release binary (with cache)
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/usr/local/cargo/git \
--mount=type=cache,target=/app/target \
touch nora-registry/src/main.rs && \
cargo build --release --package nora-registry && \
cp /app/target/release/nora /usr/local/bin/nora
# Runtime stage — scratch (compatible with Astra Linux SE, no foreign OS components)
# Switch FROM to registry.astralinux.ru/library/alse once registry access is configured
FROM scratch FROM scratch
# CA certificates for TLS COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt COPY nora /usr/local/bin/nora
COPY --from=builder /usr/local/bin/nora /usr/local/bin/nora
ENV RUST_LOG=info ENV RUST_LOG=info
ENV NORA_HOST=0.0.0.0 ENV NORA_HOST=0.0.0.0

View File

@@ -1,52 +1,17 @@
# syntax=docker/dockerfile:1.4 # syntax=docker/dockerfile:1.4
# Binary is pre-built by CI (cargo build --release) and passed via context
# Runtime: scratch — compatible with RED OS (FSTEC certified)
# To switch to official base: replace FROM scratch with
# FROM registry.red-soft.ru/redos/redos:8
# RUN dnf install -y ca-certificates && dnf clean all
# Build stage — static binary via musl (runs on any Linux) FROM alpine:3.20 AS certs
FROM rust:1.83-alpine AS builder RUN apk add --no-cache ca-certificates
RUN apk add --no-cache musl-dev curl
WORKDIR /app
# Copy manifests
COPY Cargo.toml Cargo.lock ./
COPY nora-registry/Cargo.toml nora-registry/
COPY nora-storage/Cargo.toml nora-storage/
COPY nora-cli/Cargo.toml nora-cli/
# Create dummy sources for dependency caching
RUN mkdir -p nora-registry/src nora-storage/src nora-cli/src && \
echo "fn main() {}" > nora-registry/src/main.rs && \
echo "fn main() {}" > nora-storage/src/main.rs && \
echo "fn main() {}" > nora-cli/src/main.rs
# Build dependencies only (with cache)
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/usr/local/cargo/git \
--mount=type=cache,target=/app/target \
cargo build --release --package nora-registry && \
rm -rf nora-registry/src nora-storage/src nora-cli/src
# Copy real sources
COPY nora-registry/src nora-registry/src
COPY nora-storage/src nora-storage/src
COPY nora-cli/src nora-cli/src
# Build release binary (with cache)
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/usr/local/cargo/git \
--mount=type=cache,target=/app/target \
touch nora-registry/src/main.rs && \
cargo build --release --package nora-registry && \
cp /app/target/release/nora /usr/local/bin/nora
# Runtime stage — scratch (compatible with RED OS, no foreign OS components)
# Switch FROM to registry.red-soft.ru/redos once registry access is configured
FROM scratch FROM scratch
# CA certificates for TLS COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt COPY nora /usr/local/bin/nora
COPY --from=builder /usr/local/bin/nora /usr/local/bin/nora
ENV RUST_LOG=info ENV RUST_LOG=info
ENV NORA_HOST=0.0.0.0 ENV NORA_HOST=0.0.0.0

View File

@@ -1,4 +1,5 @@
# 🐿️ N○RA <img src="logo.jpg" alt="NORA" height="120" />
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![Release](https://img.shields.io/github/v/release/getnora-io/nora)](https://github.com/getnora-io/nora/releases) [![Release](https://img.shields.io/github/v/release/getnora-io/nora)](https://github.com/getnora-io/nora/releases)

40
deny.toml Normal file
View File

@@ -0,0 +1,40 @@
# cargo-deny configuration
# https://embarkstudios.github.io/cargo-deny/
[advisories]
# Vulnerability database (RustSec)
db-urls = ["https://github.com/rustsec/advisory-db"]
ignore = [
"RUSTSEC-2025-0119", # number_prefix unmaintained, transitive via indicatif; no fix available
]
[licenses]
# Allowed open-source licenses
allow = [
"MIT",
"Apache-2.0",
"Apache-2.0 WITH LLVM-exception",
"BSD-2-Clause",
"BSD-3-Clause",
"ISC",
"Unicode-DFS-2016",
"Unicode-3.0",
"CC0-1.0",
"OpenSSL",
"Zlib",
"CDLA-Permissive-2.0", # webpki-roots (CA certificates bundle)
"MPL-2.0",
]
[bans]
multiple-versions = "warn"
deny = [
{ name = "openssl-sys" },
{ name = "openssl" },
]
skip = []
[sources]
unknown-registry = "warn"
unknown-git = "warn"
allow-registry = ["https://github.com/rust-lang/crates.io-index"]

BIN
logo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

5
logo.svg Normal file
View File

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 72" width="300" height="72">
<text font-family="'SF Mono', 'Fira Code', 'Cascadia Code', monospace" font-weight="800" fill="#0f172a" letter-spacing="1">
<tspan x="8" y="58" font-size="52">N</tspan><tspan font-size="68" dy="-10" fill="#2563EB">O</tspan><tspan font-size="52" dy="10">RA</tspan>
</text>
</svg>

After

Width:  |  Height:  |  Size: 373 B

View File

@@ -20,4 +20,4 @@ serde_json.workspace = true
clap = { version = "4", features = ["derive"] } clap = { version = "4", features = ["derive"] }
indicatif = "0.17" indicatif = "0.17"
tar = "0.4" tar = "0.4"
flate2 = "1.0" flate2 = "1.1"

View File

@@ -26,18 +26,18 @@ sha2.workspace = true
async-trait.workspace = true async-trait.workspace = true
hmac.workspace = true hmac.workspace = true
hex.workspace = true hex.workspace = true
toml = "0.8" toml = "1.0"
uuid = { version = "1", features = ["v4"] } uuid = { version = "1", features = ["v4"] }
bcrypt = "0.17" bcrypt = "0.17"
base64 = "0.22" base64 = "0.22"
prometheus = "0.13" prometheus = "0.14"
lazy_static = "1.5" lazy_static = "1.5"
httpdate = "1" httpdate = "1"
utoipa = { version = "5", features = ["axum_extras"] } utoipa = { version = "5", features = ["axum_extras"] }
utoipa-swagger-ui = { version = "9", features = ["axum", "reqwest"] } utoipa-swagger-ui = { version = "9", features = ["axum", "reqwest"] }
clap = { version = "4", features = ["derive"] } clap = { version = "4", features = ["derive"] }
tar = "0.4" tar = "0.4"
flate2 = "1.0" flate2 = "1.1"
indicatif = "0.17" indicatif = "0.17"
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }
thiserror = "2" thiserror = "2"

View File

@@ -19,10 +19,10 @@ serde.workspace = true
serde_json.workspace = true serde_json.workspace = true
tracing.workspace = true tracing.workspace = true
tracing-subscriber.workspace = true tracing-subscriber.workspace = true
toml = "0.8" toml = "1.0"
uuid = { version = "1", features = ["v4"] } uuid = { version = "1", features = ["v4"] }
sha2 = "0.10" sha2 = "0.10"
base64 = "0.22" base64 = "0.22"
httpdate = "1" httpdate = "1"
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }
quick-xml = { version = "0.31", features = ["serialize"] } quick-xml = { version = "0.39", features = ["serialize"] }