Compare commits
20 commits
v0.5.0-alp
...
main
Author | SHA1 | Date | |
---|---|---|---|
e82e0f5483 | |||
03e8b31f92 | |||
0b96b0244c | |||
a36b98881c | |||
24e034c742 | |||
d8eb763893 | |||
17befe1c17 | |||
ae910514d4 | |||
b68ee94f38 | |||
8a6bb08134 | |||
d1ab413bf3 | |||
26d4c3efe9 | |||
e54432d020 | |||
232a1a04a1 | |||
aebc6ba814 | |||
f43c3948fe | |||
d18a33940f | |||
f123f7d60a | |||
7a862bc8ff | |||
d467dfb2d1 |
20 changed files with 1886 additions and 1318 deletions
421
.drone.yml
421
.drone.yml
|
@ -1,421 +0,0 @@
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: clippy
|
|
||||||
|
|
||||||
platform:
|
|
||||||
arch: amd64
|
|
||||||
|
|
||||||
clone:
|
|
||||||
disable: true
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: clone
|
|
||||||
image: alpine/git:latest
|
|
||||||
user: root
|
|
||||||
commands:
|
|
||||||
- git clone $DRONE_GIT_HTTP_URL .
|
|
||||||
- git checkout $DRONE_COMMIT
|
|
||||||
- chown -R 991:991 .
|
|
||||||
|
|
||||||
- name: clippy
|
|
||||||
image: asonix/rust-builder:latest-linux-amd64
|
|
||||||
pull: always
|
|
||||||
commands:
|
|
||||||
- rustup component add clippy
|
|
||||||
- cargo clippy -- -D warnings
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- push
|
|
||||||
- pull_request
|
|
||||||
- tag
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: tests
|
|
||||||
|
|
||||||
platform:
|
|
||||||
arch: amd64
|
|
||||||
|
|
||||||
clone:
|
|
||||||
disable: true
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: clone
|
|
||||||
image: alpine/git:latest
|
|
||||||
user: root
|
|
||||||
commands:
|
|
||||||
- git clone $DRONE_GIT_HTTP_URL .
|
|
||||||
- git checkout $DRONE_COMMIT
|
|
||||||
- chown -R 991:991 .
|
|
||||||
|
|
||||||
- name: tests
|
|
||||||
image: asonix/rust-builder:latest-linux-amd64
|
|
||||||
pull: always
|
|
||||||
commands:
|
|
||||||
- cargo test
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- push
|
|
||||||
- pull_request
|
|
||||||
- tag
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: check-amd64
|
|
||||||
|
|
||||||
platform:
|
|
||||||
arch: amd64
|
|
||||||
|
|
||||||
clone:
|
|
||||||
disable: true
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: clone
|
|
||||||
image: alpine/git:latest
|
|
||||||
user: root
|
|
||||||
commands:
|
|
||||||
- git clone $DRONE_GIT_HTTP_URL .
|
|
||||||
- git checkout $DRONE_COMMIT
|
|
||||||
- chown -R 991:991 .
|
|
||||||
|
|
||||||
- name: check
|
|
||||||
image: asonix/rust-builder:latest-linux-amd64
|
|
||||||
pull: always
|
|
||||||
commands:
|
|
||||||
- cargo check --target=$TARGET
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- push
|
|
||||||
- pull_request
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: build-amd64
|
|
||||||
|
|
||||||
platform:
|
|
||||||
arch: amd64
|
|
||||||
|
|
||||||
clone:
|
|
||||||
disable: true
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: clone
|
|
||||||
image: alpine/git:latest
|
|
||||||
user: root
|
|
||||||
commands:
|
|
||||||
- git clone $DRONE_GIT_HTTP_URL .
|
|
||||||
- git checkout $DRONE_COMMIT
|
|
||||||
- chown -R 991:991 .
|
|
||||||
|
|
||||||
- name: build
|
|
||||||
image: asonix/rust-builder:latest-linux-amd64
|
|
||||||
pull: always
|
|
||||||
commands:
|
|
||||||
- cargo build --target=$TARGET --release
|
|
||||||
- $TOOL-strip target/$TARGET/release/pict-rs-proxy
|
|
||||||
- cp target/$TARGET/release/pict-rs-proxy .
|
|
||||||
- cp pict-rs-proxy pict-rs-proxy-linux-amd64
|
|
||||||
|
|
||||||
- name: push
|
|
||||||
image: plugins/docker:20
|
|
||||||
settings:
|
|
||||||
username: asonix
|
|
||||||
password:
|
|
||||||
from_secret: dockerhub_token
|
|
||||||
repo: asonix/pictrs-proxy
|
|
||||||
dockerfile: docker/drone/Dockerfile
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: linux-amd64
|
|
||||||
build_args:
|
|
||||||
- REPO_ARCH=amd64
|
|
||||||
|
|
||||||
- name: publish
|
|
||||||
image: plugins/gitea-release:1
|
|
||||||
settings:
|
|
||||||
api_key:
|
|
||||||
from_secret: gitea_token
|
|
||||||
base_url: https://git.asonix.dog
|
|
||||||
files:
|
|
||||||
- pict-rs-proxy-linux-amd64
|
|
||||||
|
|
||||||
depends_on:
|
|
||||||
- clippy
|
|
||||||
- tests
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: check-arm64v8
|
|
||||||
|
|
||||||
platform:
|
|
||||||
arch: amd64
|
|
||||||
|
|
||||||
clone:
|
|
||||||
disable: true
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: clone
|
|
||||||
image: alpine/git:latest
|
|
||||||
user: root
|
|
||||||
commands:
|
|
||||||
- git clone $DRONE_GIT_HTTP_URL .
|
|
||||||
- git checkout $DRONE_COMMIT
|
|
||||||
- chown -R 991:991 .
|
|
||||||
|
|
||||||
- name: check
|
|
||||||
image: asonix/rust-builder:latest-linux-arm64v8
|
|
||||||
pull: always
|
|
||||||
commands:
|
|
||||||
- cargo check --target=$TARGET
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- push
|
|
||||||
- pull_request
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: build-arm64v8
|
|
||||||
|
|
||||||
platform:
|
|
||||||
arch: amd64
|
|
||||||
|
|
||||||
clone:
|
|
||||||
disable: true
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: clone
|
|
||||||
image: alpine/git:latest
|
|
||||||
user: root
|
|
||||||
commands:
|
|
||||||
- git clone $DRONE_GIT_HTTP_URL .
|
|
||||||
- git checkout $DRONE_COMMIT
|
|
||||||
- chown -R 991:991 .
|
|
||||||
|
|
||||||
- name: build
|
|
||||||
image: asonix/rust-builder:latest-linux-arm64v8
|
|
||||||
pull: always
|
|
||||||
commands:
|
|
||||||
- cargo build --target=$TARGET --release
|
|
||||||
- $TOOL-strip target/$TARGET/release/pict-rs-proxy
|
|
||||||
- cp target/$TARGET/release/pict-rs-proxy .
|
|
||||||
- cp pict-rs-proxy pict-rs-proxy-linux-arm64v8
|
|
||||||
|
|
||||||
- name: push
|
|
||||||
image: plugins/docker:20
|
|
||||||
settings:
|
|
||||||
username: asonix
|
|
||||||
password:
|
|
||||||
from_secret: dockerhub_token
|
|
||||||
repo: asonix/pictrs-proxy
|
|
||||||
dockerfile: docker/drone/Dockerfile
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: linux-arm64v8
|
|
||||||
build_args:
|
|
||||||
- REPO_ARCH=arm64v8
|
|
||||||
|
|
||||||
- name: publish
|
|
||||||
image: plugins/gitea-release:1
|
|
||||||
settings:
|
|
||||||
api_key:
|
|
||||||
from_secret: gitea_token
|
|
||||||
base_url: https://git.asonix.dog
|
|
||||||
files:
|
|
||||||
- pict-rs-proxy-linux-arm64v8
|
|
||||||
|
|
||||||
depends_on:
|
|
||||||
- clippy
|
|
||||||
- tests
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: check-arm32v7
|
|
||||||
|
|
||||||
platform:
|
|
||||||
arch: amd64
|
|
||||||
|
|
||||||
clone:
|
|
||||||
disable: true
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: clone
|
|
||||||
image: alpine/git:latest
|
|
||||||
user: root
|
|
||||||
commands:
|
|
||||||
- git clone $DRONE_GIT_HTTP_URL .
|
|
||||||
- git checkout $DRONE_COMMIT
|
|
||||||
- chown -R 991:991 .
|
|
||||||
|
|
||||||
- name: check
|
|
||||||
image: asonix/rust-builder:latest-linux-arm32v7
|
|
||||||
pull: always
|
|
||||||
commands:
|
|
||||||
- cargo check --target=$TARGET
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- push
|
|
||||||
- pull_request
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: build-arm32v7
|
|
||||||
|
|
||||||
platform:
|
|
||||||
arch: amd64
|
|
||||||
|
|
||||||
clone:
|
|
||||||
disable: true
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: clone
|
|
||||||
image: alpine/git:latest
|
|
||||||
user: root
|
|
||||||
commands:
|
|
||||||
- git clone $DRONE_GIT_HTTP_URL .
|
|
||||||
- git checkout $DRONE_COMMIT
|
|
||||||
- chown -R 991:991 .
|
|
||||||
|
|
||||||
- name: build
|
|
||||||
image: asonix/rust-builder:latest-linux-arm32v7
|
|
||||||
pull: always
|
|
||||||
commands:
|
|
||||||
- cargo build --target=$TARGET --release
|
|
||||||
- $TOOL-strip target/$TARGET/release/pict-rs-proxy
|
|
||||||
- cp target/$TARGET/release/pict-rs-proxy .
|
|
||||||
- cp pict-rs-proxy pict-rs-proxy-linux-arm32v7
|
|
||||||
|
|
||||||
- name: push
|
|
||||||
image: plugins/docker:20
|
|
||||||
settings:
|
|
||||||
username: asonix
|
|
||||||
password:
|
|
||||||
from_secret: dockerhub_token
|
|
||||||
repo: asonix/pictrs-proxy
|
|
||||||
dockerfile: docker/drone/Dockerfile
|
|
||||||
auto_tag: true
|
|
||||||
auto_tag_suffix: linux-arm32v7
|
|
||||||
build_args:
|
|
||||||
- REPO_ARCH=arm32v7
|
|
||||||
|
|
||||||
- name: publish
|
|
||||||
image: plugins/gitea-release:1
|
|
||||||
settings:
|
|
||||||
api_key:
|
|
||||||
from_secret: gitea_token
|
|
||||||
base_url: https://git.asonix.dog
|
|
||||||
files:
|
|
||||||
- pict-rs-proxy-linux-arm32v7
|
|
||||||
|
|
||||||
depends_on:
|
|
||||||
- clippy
|
|
||||||
- tests
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: manifest
|
|
||||||
|
|
||||||
platform:
|
|
||||||
arch: amd64
|
|
||||||
|
|
||||||
clone:
|
|
||||||
disable: true
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: clone
|
|
||||||
image: alpine/git:latest
|
|
||||||
user: root
|
|
||||||
commands:
|
|
||||||
- git clone $DRONE_GIT_HTTP_URL .
|
|
||||||
- git checkout $DRONE_COMMIT
|
|
||||||
- chown -R 991:991 .
|
|
||||||
|
|
||||||
- name: manifest
|
|
||||||
image: plugins/manifest:1
|
|
||||||
settings:
|
|
||||||
username: asonix
|
|
||||||
password:
|
|
||||||
from_secret: dockerhub_token
|
|
||||||
dump: true
|
|
||||||
auto_tag: true
|
|
||||||
ignore_missing: true
|
|
||||||
spec: docker/drone/manifest.tmpl
|
|
||||||
|
|
||||||
|
|
||||||
depends_on:
|
|
||||||
- build-amd64
|
|
||||||
- build-arm64v8
|
|
||||||
- build-arm32v7
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: publish-crate
|
|
||||||
|
|
||||||
platform:
|
|
||||||
arch: amd64
|
|
||||||
|
|
||||||
clone:
|
|
||||||
disable: true
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: clone
|
|
||||||
image: alpine/git:latest
|
|
||||||
user: root
|
|
||||||
commands:
|
|
||||||
- git clone $DRONE_GIT_HTTP_URL .
|
|
||||||
- git checkout $DRONE_COMMIT
|
|
||||||
- chown -R 991:991 .
|
|
||||||
|
|
||||||
- name: publish
|
|
||||||
image: asonix/rust-builder:latest-linux-amd64
|
|
||||||
pull: always
|
|
||||||
environment:
|
|
||||||
CRATES_IO_TOKEN:
|
|
||||||
from_secret: crates_io_token
|
|
||||||
commands:
|
|
||||||
- cargo publish --token $CRATES_IO_TOKEN
|
|
||||||
|
|
||||||
depends_on:
|
|
||||||
- build-amd64
|
|
||||||
- build-arm64v8
|
|
||||||
- build-arm32v7
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- tag
|
|
61
.forgejo/workflows/check.yaml
Normal file
61
.forgejo/workflows/check.yaml
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '*'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
clippy:
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: docker.io/asonix/actions-base-image:0.1
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout pict-rs-proxy
|
||||||
|
uses: https://github.com/actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Cargo Cache
|
||||||
|
uses: https://git.asonix.dog/asonix/actions/cache-rust-dependencies@main
|
||||||
|
-
|
||||||
|
name: Clippy
|
||||||
|
run: |
|
||||||
|
cargo clippy --no-default-features -- -D warnings
|
||||||
|
|
||||||
|
tests:
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: docker.io/asonix/actions-base-image:0.1
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout pict-rs-proxy
|
||||||
|
uses: https://github.com/actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Cargo Cache
|
||||||
|
uses: https://git.asonix.dog/asonix/actions/cache-rust-dependencies@main
|
||||||
|
-
|
||||||
|
name: Test
|
||||||
|
run: cargo test
|
||||||
|
|
||||||
|
check:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
target:
|
||||||
|
- x86_64-unknown-linux-musl
|
||||||
|
- armv7-unknown-linux-musleabihf
|
||||||
|
- aarch64-unknown-linux-musl
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: docker.io/asonix/actions-base-image:0.1
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout pict-rs-proxy
|
||||||
|
uses: https://github.com/actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Cargo Cache
|
||||||
|
uses: https://git.asonix.dog/asonix/actions/cache-rust-dependencies@main
|
||||||
|
-
|
||||||
|
name: Debug builds
|
||||||
|
run: cargo zigbuild --target ${{ matrix.target }}
|
225
.forgejo/workflows/publish.yaml
Normal file
225
.forgejo/workflows/publish.yaml
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*.*.*'
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY_IMAGE: asonix/pictrs-proxy
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
clippy:
|
||||||
|
runs-on: base-image
|
||||||
|
container:
|
||||||
|
image: docker.io/asonix/actions-base-image:0.1
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout pict-rs-proxy
|
||||||
|
uses: https://github.com/actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Cargo Cache
|
||||||
|
uses: https://git.asonix.dog/asonix/actions/cache-rust-dependencies@main
|
||||||
|
-
|
||||||
|
name: Clippy
|
||||||
|
run: |
|
||||||
|
cargo clippy --no-default-features -- -D warnings
|
||||||
|
|
||||||
|
tests:
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: docker.io/asonix/actions-base-image:0.1
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout pict-rs-proxy
|
||||||
|
uses: https://github.com/actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Cargo Cache
|
||||||
|
uses: https://git.asonix.dog/asonix/actions/cache-rust-dependencies@main
|
||||||
|
-
|
||||||
|
name: Test
|
||||||
|
run: cargo test
|
||||||
|
|
||||||
|
build:
|
||||||
|
needs:
|
||||||
|
- clippy
|
||||||
|
- tests
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: docker.io/asonix/actions-base-image:0.1
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
info:
|
||||||
|
- target: x86_64-unknown-linux-musl
|
||||||
|
artifact: linux-amd64
|
||||||
|
platform: linux/amd64
|
||||||
|
- target: armv7-unknown-linux-musleabihf
|
||||||
|
artifact: linux-arm32v7
|
||||||
|
platform: linux/arm/v7
|
||||||
|
- target: aarch64-unknown-linux-musl
|
||||||
|
artifact: linux-arm64v8
|
||||||
|
platform: linux/arm64
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout pict-rs-proxy
|
||||||
|
uses: https://github.com/actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Cargo Cache
|
||||||
|
uses: https://git.asonix.dog/asonix/actions/cache-rust-dependencies@main
|
||||||
|
-
|
||||||
|
name: Prepare Platform
|
||||||
|
run: |
|
||||||
|
platform=${{ matrix.info.platform }}
|
||||||
|
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||||
|
shell: bash
|
||||||
|
-
|
||||||
|
name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: https://github.com/docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: ${{ env.REGISTRY_IMAGE }}
|
||||||
|
flavor: |
|
||||||
|
latest=auto
|
||||||
|
suffix=-${{ matrix.info.artifact }}
|
||||||
|
tags: |
|
||||||
|
type=raw,value=latest,enable={{ is_default_branch }}
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
type=semver,pattern={{major}}
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: https://github.com/docker/setup-qemu-action@v3
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: https://github.com/docker/setup-buildx-action@v3
|
||||||
|
-
|
||||||
|
name: Docker login
|
||||||
|
uses: https://github.com/docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Compile pict-rs-proxy
|
||||||
|
run: cargo zigbuild --target ${{ matrix.info.target }} --release
|
||||||
|
-
|
||||||
|
name: Prepare artifacts
|
||||||
|
run: |
|
||||||
|
mkdir artifacts
|
||||||
|
cp target/${{ matrix.info.target }}/release/pict-rs-proxy artifacts/pict-rs-proxy-${{ matrix.info.artifact }}
|
||||||
|
-
|
||||||
|
uses: https://github.com/actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: binaries
|
||||||
|
path: artifacts/
|
||||||
|
-
|
||||||
|
name: Prepare binary
|
||||||
|
run: |
|
||||||
|
cp target/${{ matrix.info.target }}/release/pict-rs-proxy docker/forgejo/pict-rs-proxy
|
||||||
|
-
|
||||||
|
name: Build and push ${{ matrix.info.platform }} docker image
|
||||||
|
id: build
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: ./docker/forgejo
|
||||||
|
platforms: ${{ matrix.info.platform }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},name-canonical=true,push=true
|
||||||
|
-
|
||||||
|
name: Export digest
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/digests
|
||||||
|
digest="${{ steps.build.outputs.digest }}"
|
||||||
|
touch "/tmp/digests/${digest#sha256:}"
|
||||||
|
echo "Created /tmp/digests/${digest#sha256:}"
|
||||||
|
shell: bash
|
||||||
|
-
|
||||||
|
name: Upload ${{ matrix.info.platform }} digest
|
||||||
|
uses: https://github.com/actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: digests
|
||||||
|
path: /tmp/digests/*
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 1
|
||||||
|
|
||||||
|
publish-docker:
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: docker.io/asonix/actions-base-image:0.1
|
||||||
|
needs: [build]
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Download digests
|
||||||
|
uses: https://github.com/actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: digests
|
||||||
|
path: /tmp/digests
|
||||||
|
pattern: digests-*
|
||||||
|
merge-multiple: true
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
-
|
||||||
|
name: Docker login
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: https://github.com/docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: ${{ env.REGISTRY_IMAGE }}
|
||||||
|
flavor: |
|
||||||
|
latest=auto
|
||||||
|
tags: |
|
||||||
|
type=raw,value=latest,enable={{ is_default_branch }}
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
type=semver,pattern={{major}}
|
||||||
|
-
|
||||||
|
name: Create manifest list and push
|
||||||
|
working-directory: /tmp/digests
|
||||||
|
run: |
|
||||||
|
tags=$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "${DOCKER_METADATA_OUTPUT_JSON}")
|
||||||
|
images=$(printf "${{ env.REGISTRY_IMAGE }}@sha256:%s " *)
|
||||||
|
echo "Running 'docker buildx imagetools create ${tags[@]} ${images[@]}'"
|
||||||
|
docker buildx imagetools create ${tags[@]} ${images[@]}
|
||||||
|
shell: bash
|
||||||
|
-
|
||||||
|
name: Inspect Image
|
||||||
|
run: |
|
||||||
|
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }}
|
||||||
|
|
||||||
|
publish-forgejo:
|
||||||
|
needs: [build]
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: docker.io/asonix/actions-base-image:0.1
|
||||||
|
steps:
|
||||||
|
- uses: https://github.com/actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: binaries
|
||||||
|
path: artifacts/
|
||||||
|
merge-multiple: true
|
||||||
|
- uses: actions/forgejo-release@v1
|
||||||
|
with:
|
||||||
|
direction: upload
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
release-dir: artifacts/
|
||||||
|
|
||||||
|
publish-crate:
|
||||||
|
needs: [build]
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: docker.io/asonix/actions-base-image:0.1
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout pict-rs-proxy
|
||||||
|
uses: https://github.com/actions/checkout@v4
|
||||||
|
-
|
||||||
|
name: Cargo Cache
|
||||||
|
uses: https://git.asonix.dog/asonix/actions/cache-rust-dependencies@main
|
||||||
|
-
|
||||||
|
name: Publish Crate
|
||||||
|
run: cargo publish --token ${{ secrets.CRATES_IO_TOKEN }}
|
1890
Cargo.lock
generated
1890
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
38
Cargo.toml
38
Cargo.toml
|
@ -1,7 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "pict-rs-proxy"
|
name = "pict-rs-proxy"
|
||||||
description = "A simple web frontend for pict-rs"
|
description = "A simple web frontend for pict-rs"
|
||||||
version = "0.5.0-alpha.1"
|
version = "0.5.0"
|
||||||
authors = ["asonix <asonix@asonix.dog>"]
|
authors = ["asonix <asonix@asonix.dog>"]
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -10,6 +10,9 @@ edition = "2021"
|
||||||
|
|
||||||
build = "src/build.rs"
|
build = "src/build.rs"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
strip = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
|
||||||
|
@ -17,43 +20,48 @@ default = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = "2.7.0"
|
actix-rt = "2.7.0"
|
||||||
actix-web = { version = "4.0.0", default-features = false }
|
actix-web = { version = "4.0.0", default-features = false, features = ["rustls-0_21"] }
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
awc = { version = "3.0.0", default-features = false }
|
awc = { version = "3.0.0", default-features = false, features = ["rustls-0_21"] }
|
||||||
clap = { version = "4.0.2", features = ["derive", "env"] }
|
clap = { version = "4.0.2", features = ["derive", "env"] }
|
||||||
console-subscriber = "0.1"
|
console-subscriber = "0.2"
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
mime = "0.3"
|
mime = "0.3"
|
||||||
minify-html = "0.11.1"
|
minify-html = "0.15.0"
|
||||||
once_cell = "1.4"
|
opentelemetry = "0.21"
|
||||||
opentelemetry = { version = "0.19", features = ["rt-tokio"] }
|
opentelemetry_sdk = { version = "0.21", features = ["rt-tokio"] }
|
||||||
opentelemetry-otlp = "0.12"
|
opentelemetry-otlp = "0.14"
|
||||||
|
rustls = "0.21"
|
||||||
|
rustls-pemfile = "2.0.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_qs = { version = "0.12", features = ["actix4"] }
|
serde_qs = { version = "0.12", features = ["actix4"] }
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
tokio = { version = "1", features = ["fs"] }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-error = "0.2"
|
tracing-error = "0.2"
|
||||||
tracing-futures = "0.2"
|
tracing-futures = "0.2"
|
||||||
tracing-log = "0.1"
|
tracing-log = "0.2"
|
||||||
tracing-opentelemetry = "0.19"
|
tracing-opentelemetry = "0.22"
|
||||||
tracing-subscriber = { version = "0.3", features = [
|
tracing-subscriber = { version = "0.3", features = [
|
||||||
"ansi",
|
"ansi",
|
||||||
"env-filter",
|
"env-filter",
|
||||||
"fmt",
|
"fmt",
|
||||||
] }
|
] }
|
||||||
url = "2.1"
|
url = "2.1"
|
||||||
|
webpki-roots = "0.26"
|
||||||
|
rustls-channel-resolver = "0.1.0"
|
||||||
|
|
||||||
[dependencies.tracing-actix-web]
|
[dependencies.tracing-actix-web]
|
||||||
version = "0.7.5"
|
version = "0.7.9"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["emit_event_on_error", "opentelemetry_0_19"]
|
features = ["emit_event_on_error", "opentelemetry_0_21"]
|
||||||
|
|
||||||
[dependencies.tracing-awc]
|
[dependencies.tracing-awc]
|
||||||
version = "0.1.7"
|
version = "0.1.9"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["emit_event_on_error", "opentelemetry_0_19"]
|
features = ["emit_event_on_error", "opentelemetry_0_21"]
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
ructe = { version = "0.16.1", features = ["sass", "mime03"] }
|
ructe = { version = "0.17.0", features = ["sass", "mime03"] }
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
ARG REPO_ARCH
|
|
||||||
|
|
||||||
FROM asonix/rust-runner:latest-linux-$REPO_ARCH
|
|
||||||
|
|
||||||
COPY pict-rs-proxy /usr/local/bin/pict-rs-proxy
|
|
||||||
|
|
||||||
USER app
|
|
||||||
EXPOSE 8080
|
|
||||||
EXPOSE 6669
|
|
||||||
VOLUME /mnt
|
|
||||||
ENTRYPOINT ["/sbin/tini", "--"]
|
|
||||||
CMD ["/usr/local/bin/pict-rs-proxy"]
|
|
|
@ -1,25 +0,0 @@
|
||||||
image: asonix/pictrs-proxy:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
|
||||||
{{#if build.tags}}
|
|
||||||
tags:
|
|
||||||
{{#each build.tags}}
|
|
||||||
- {{this}}
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
manifests:
|
|
||||||
-
|
|
||||||
image: asonix/pictrs-proxy:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
|
||||||
platform:
|
|
||||||
architecture: amd64
|
|
||||||
os: linux
|
|
||||||
-
|
|
||||||
image: asonix/pictrs-proxy:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64v8
|
|
||||||
platform:
|
|
||||||
architecture: arm64
|
|
||||||
os: linux
|
|
||||||
variant: v8
|
|
||||||
-
|
|
||||||
image: asonix/pictrs-proxy:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm32v7
|
|
||||||
platform:
|
|
||||||
architecture: arm
|
|
||||||
os: linux
|
|
||||||
variant: v7
|
|
24
docker/forgejo/Dockerfile
Normal file
24
docker/forgejo/Dockerfile
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
FROM alpine:3.19
|
||||||
|
|
||||||
|
ARG UID=991
|
||||||
|
ARG GID=991
|
||||||
|
|
||||||
|
ENV \
|
||||||
|
UID=${UID} \
|
||||||
|
GID=${GID}
|
||||||
|
|
||||||
|
USER root
|
||||||
|
RUN \
|
||||||
|
addgroup -g "${GID}" app && \
|
||||||
|
adduser -D -G app -u "${UID}" -g "" -h /opt/app app && \
|
||||||
|
apk add tini && \
|
||||||
|
chown -R app:app /mnt
|
||||||
|
|
||||||
|
COPY pict-rs-proxy /usr/local/bin/pict-rs-proxy
|
||||||
|
|
||||||
|
USER app
|
||||||
|
EXPOSE 6669
|
||||||
|
EXPOSE 8080
|
||||||
|
VOLUME /mnt
|
||||||
|
ENTRYPOINT ["/sbin/tini", "--"]
|
||||||
|
CMD ["/usr/local/bin/pict-rs-proxy"]
|
|
@ -1,41 +0,0 @@
|
||||||
ARG REPO_ARCH=amd64
|
|
||||||
|
|
||||||
# cross-build environment
|
|
||||||
FROM asonix/rust-builder:$REPO_ARCH-latest AS builder
|
|
||||||
|
|
||||||
ARG TAG=main
|
|
||||||
ARG BINARY=pict-rs-proxy
|
|
||||||
ARG PROJECT=pict-rs-proxy
|
|
||||||
ARG GIT_REPOSITORY=https://git.asonix.dog/asonix/$PROJECT
|
|
||||||
|
|
||||||
ENV \
|
|
||||||
BINARY=${BINARY}
|
|
||||||
|
|
||||||
ADD \
|
|
||||||
--chown=build:build \
|
|
||||||
$GIT_REPOSITORY/archive/$TAG.tar.gz \
|
|
||||||
/opt/build/repo.tar.gz
|
|
||||||
|
|
||||||
RUN \
|
|
||||||
tar zxf repo.tar.gz
|
|
||||||
|
|
||||||
WORKDIR /opt/build/$PROJECT
|
|
||||||
|
|
||||||
RUN \
|
|
||||||
build
|
|
||||||
|
|
||||||
# production environment
|
|
||||||
FROM asonix/rust-runner:$REPO_ARCH-latest
|
|
||||||
|
|
||||||
ARG BINARY=pict-rs-proxy
|
|
||||||
|
|
||||||
ENV \
|
|
||||||
BINARY=${BINARY}
|
|
||||||
|
|
||||||
COPY \
|
|
||||||
--from=builder \
|
|
||||||
/opt/build/binary \
|
|
||||||
/usr/bin/${BINARY}
|
|
||||||
|
|
||||||
ENTRYPOINT ["/sbin/tini", "--"]
|
|
||||||
CMD /usr/bin/${BINARY}
|
|
|
@ -1,37 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
function require() {
|
|
||||||
if [ "$1" = "" ]; then
|
|
||||||
echo "input '$2' required"
|
|
||||||
print_help
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function print_help() {
|
|
||||||
echo "deploy.sh"
|
|
||||||
echo ""
|
|
||||||
echo "Usage:"
|
|
||||||
echo " deploy.sh [repo] [tag] [arch]"
|
|
||||||
echo ""
|
|
||||||
echo "Args:"
|
|
||||||
echo " repo: The docker repository to publish the image"
|
|
||||||
echo " tag: The tag applied to the docker image"
|
|
||||||
echo " arch: The architecuture of the doker image"
|
|
||||||
}
|
|
||||||
|
|
||||||
REPO=$1
|
|
||||||
TAG=$2
|
|
||||||
ARCH=$3
|
|
||||||
|
|
||||||
require "$REPO" repo
|
|
||||||
require "$TAG" tag
|
|
||||||
require "$ARCH" arch
|
|
||||||
|
|
||||||
sudo docker build \
|
|
||||||
--pull \
|
|
||||||
--build-arg TAG=$TAG \
|
|
||||||
--build-arg REPO_ARCH=$ARCH \
|
|
||||||
-t $REPO:$ARCH-$TAG \
|
|
||||||
-f Dockerfile \
|
|
||||||
.
|
|
|
@ -1,87 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
function require() {
|
|
||||||
if [ "$1" = "" ]; then
|
|
||||||
echo "input '$2' required"
|
|
||||||
print_help
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function print_help() {
|
|
||||||
echo "deploy.sh"
|
|
||||||
echo ""
|
|
||||||
echo "Usage:"
|
|
||||||
echo " deploy.sh [tag] [branch] [push]"
|
|
||||||
echo ""
|
|
||||||
echo "Args:"
|
|
||||||
echo " tag: The git tag to be applied to the repository and docker build"
|
|
||||||
echo " branch: The git branch to use for tagging and publishing"
|
|
||||||
echo " push: Whether or not to push the image"
|
|
||||||
echo ""
|
|
||||||
echo "Examples:"
|
|
||||||
echo " ./deploy.sh v0.3.0-alpha.13 main true"
|
|
||||||
echo " ./deploy.sh v0.3.0-alpha.13-shell-out asonix/shell-out false"
|
|
||||||
}
|
|
||||||
|
|
||||||
function build_image() {
|
|
||||||
tag=$1
|
|
||||||
arch=$2
|
|
||||||
push=$3
|
|
||||||
|
|
||||||
./build-image.sh asonix/pictrs-proxy $tag $arch
|
|
||||||
|
|
||||||
sudo docker tag asonix/pictrs-proxy:$arch-$tag asonix/pictrs-proxy:$arch-latest
|
|
||||||
|
|
||||||
if [ "$push" == "true" ]; then
|
|
||||||
sudo docker push asonix/pictrs-proxy:$arch-$tag
|
|
||||||
sudo docker push asonix/pictrs-proxy:$arch-latest
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Creating the new tag
|
|
||||||
new_tag="$1"
|
|
||||||
branch="$2"
|
|
||||||
push=$3
|
|
||||||
|
|
||||||
require "$new_tag" "tag"
|
|
||||||
require "$branch" "branch"
|
|
||||||
require "$push" "push"
|
|
||||||
|
|
||||||
if ! sudo docker run --rm -it arm64v8/alpine:3.11 /bin/sh -c 'echo "docker is configured correctly"'
|
|
||||||
then
|
|
||||||
echo "docker is not configured to run on qemu-emulated architectures, fixing will require sudo"
|
|
||||||
sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
|
||||||
fi
|
|
||||||
|
|
||||||
set -xe
|
|
||||||
|
|
||||||
git checkout $branch
|
|
||||||
|
|
||||||
# Changing the docker-compose prod
|
|
||||||
sed -i "s/asonix\/pictrs-proxy:.*/asonix\/pictrs-proxy:$new_tag/" docker-compose.yml
|
|
||||||
git add ../prod/docker-compose.yml
|
|
||||||
# The commit
|
|
||||||
git commit -m"Version $new_tag"
|
|
||||||
git tag $new_tag
|
|
||||||
|
|
||||||
# Push
|
|
||||||
git push origin $new_tag
|
|
||||||
git push
|
|
||||||
|
|
||||||
# Build for arm64v8, arm32v7 and amd64
|
|
||||||
build_image $new_tag arm64v8 $push
|
|
||||||
build_image $new_tag arm32v7 $push
|
|
||||||
build_image $new_tag amd64 $push
|
|
||||||
|
|
||||||
# Build for other archs
|
|
||||||
# TODO
|
|
||||||
|
|
||||||
if [ "$push" == "true" ]; then
|
|
||||||
./manifest.sh pictrs-proxy $new_tag
|
|
||||||
./manifest.sh pictrs-proxy latest
|
|
||||||
|
|
||||||
pushd ../../
|
|
||||||
cargo publish
|
|
||||||
popd
|
|
||||||
fi
|
|
|
@ -8,7 +8,7 @@ services:
|
||||||
- ./volumes/pictrs:/mnt
|
- ./volumes/pictrs:/mnt
|
||||||
|
|
||||||
pictrs-proxy:
|
pictrs-proxy:
|
||||||
image: asonix/pictrs-proxy:v0.3.0-beta.1
|
image: asonix/pictrs-proxy:0.3
|
||||||
ports:
|
ports:
|
||||||
- "8081:8081"
|
- "8081:8081"
|
||||||
restart: always
|
restart: always
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
function require() {
|
|
||||||
if [ "$1" = "" ]; then
|
|
||||||
echo "input '$2' required"
|
|
||||||
print_help
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
function print_help() {
|
|
||||||
echo "deploy.sh"
|
|
||||||
echo ""
|
|
||||||
echo "Usage:"
|
|
||||||
echo " manifest.sh [repo] [tag]"
|
|
||||||
echo ""
|
|
||||||
echo "Args:"
|
|
||||||
echo " repo: The docker repository to update"
|
|
||||||
echo " tag: The git tag to be applied to the image manifest"
|
|
||||||
}
|
|
||||||
|
|
||||||
REPO=$1
|
|
||||||
TAG=$2
|
|
||||||
|
|
||||||
require "$REPO" "repo"
|
|
||||||
require "$TAG" "tag"
|
|
||||||
|
|
||||||
set -xe
|
|
||||||
|
|
||||||
sudo docker manifest create asonix/$REPO:$TAG \
|
|
||||||
-a asonix/$REPO:arm64v8-$TAG \
|
|
||||||
-a asonix/$REPO:arm32v7-$TAG \
|
|
||||||
-a asonix/$REPO:amd64-$TAG
|
|
||||||
|
|
||||||
sudo docker manifest annotate asonix/$REPO:$TAG \
|
|
||||||
asonix/$REPO:arm64v8-$TAG --os linux --arch arm64 --variant v8
|
|
||||||
|
|
||||||
sudo docker manifest annotate asonix/$REPO:$TAG \
|
|
||||||
asonix/$REPO:arm32v7-$TAG --os linux --arch arm --variant v7
|
|
||||||
|
|
||||||
sudo docker manifest annotate asonix/$REPO:$TAG \
|
|
||||||
asonix/$REPO:amd64-$TAG --os linux --arch amd64
|
|
||||||
|
|
||||||
sudo docker manifest push asonix/$REPO:$TAG --purge
|
|
12
flake.lock
12
flake.lock
|
@ -5,11 +5,11 @@
|
||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1689068808,
|
"lastModified": 1705309234,
|
||||||
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
|
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
|
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -20,11 +20,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1689192006,
|
"lastModified": 1706550542,
|
||||||
"narHash": "sha256-QM0f0d8oPphOTYJebsHioR9+FzJcy1QNIzREyubB91U=",
|
"narHash": "sha256-UcsnCG6wx++23yeER4Hg18CXWbgNpqNXcHIo5/1Y+hc=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "2de8efefb6ce7f5e4e75bdf57376a96555986841",
|
"rev": "97b17f32362e475016f942bbdfda4a4a72a8a652",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
devShell = with pkgs; mkShell {
|
devShell = with pkgs; mkShell {
|
||||||
nativeBuildInputs = [ cargo cargo-outdated cargo-zigbuild clippy gcc protobuf rust-analyzer rustc rustfmt ];
|
nativeBuildInputs = [ cargo cargo-outdated clippy gcc rust-analyzer rustc rustfmt ];
|
||||||
|
|
||||||
RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";
|
RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,18 +1,14 @@
|
||||||
{ lib
|
{ lib
|
||||||
, nixosTests
|
, nixosTests
|
||||||
, protobuf
|
|
||||||
, rustPlatform
|
, rustPlatform
|
||||||
}:
|
}:
|
||||||
|
|
||||||
rustPlatform.buildRustPackage {
|
rustPlatform.buildRustPackage {
|
||||||
pname = "pict-rs-proxy";
|
pname = "pict-rs-proxy";
|
||||||
version = "0.5.0-alpha.1";
|
version = "0.5.0";
|
||||||
src = ./.;
|
src = ./.;
|
||||||
cargoLock.lockFile = ./Cargo.lock;
|
cargoLock.lockFile = ./Cargo.lock;
|
||||||
|
|
||||||
PROTOC = "${protobuf}/bin/protoc";
|
|
||||||
PROTOC_INCLUDE = "${protobuf}/include";
|
|
||||||
|
|
||||||
nativeBuildInputs = [ ];
|
nativeBuildInputs = [ ];
|
||||||
|
|
||||||
passthru.tests = { inherit (nixosTests) pict-rs-proxy; };
|
passthru.tests = { inherit (nixosTests) pict-rs-proxy; };
|
||||||
|
|
268
src/main.rs
268
src/main.rs
|
@ -10,18 +10,22 @@ use actix_web::{
|
||||||
middleware::NormalizePath,
|
middleware::NormalizePath,
|
||||||
web, App, HttpRequest, HttpResponse, HttpResponseBuilder, HttpServer, ResponseError,
|
web, App, HttpRequest, HttpResponse, HttpResponseBuilder, HttpServer, ResponseError,
|
||||||
};
|
};
|
||||||
use awc::Client;
|
use anyhow::Context;
|
||||||
|
use awc::{Client, Connector};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use console_subscriber::ConsoleLayer;
|
use console_subscriber::ConsoleLayer;
|
||||||
use once_cell::sync::Lazy;
|
use opentelemetry::KeyValue;
|
||||||
use opentelemetry::{
|
|
||||||
sdk::{propagation::TraceContextPropagator, Resource},
|
|
||||||
KeyValue,
|
|
||||||
};
|
|
||||||
use opentelemetry_otlp::WithExportConfig;
|
use opentelemetry_otlp::WithExportConfig;
|
||||||
|
use opentelemetry_sdk::{propagation::TraceContextPropagator, Resource};
|
||||||
|
use rustls::{
|
||||||
|
sign::CertifiedKey, Certificate, ClientConfig, OwnedTrustAnchor, PrivateKey, RootCertStore,
|
||||||
|
ServerConfig,
|
||||||
|
};
|
||||||
use std::{
|
use std::{
|
||||||
io::Cursor,
|
io::Cursor,
|
||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
|
path::PathBuf,
|
||||||
|
sync::{Arc, OnceLock},
|
||||||
time::{Duration, SystemTime},
|
time::{Duration, SystemTime},
|
||||||
};
|
};
|
||||||
use tracing_actix_web::TracingLogger;
|
use tracing_actix_web::TracingLogger;
|
||||||
|
@ -29,8 +33,7 @@ use tracing_awc::Tracing;
|
||||||
use tracing_error::{ErrorLayer, SpanTrace};
|
use tracing_error::{ErrorLayer, SpanTrace};
|
||||||
use tracing_log::LogTracer;
|
use tracing_log::LogTracer;
|
||||||
use tracing_subscriber::{
|
use tracing_subscriber::{
|
||||||
filter::Targets, fmt::format::FmtSpan, layer::SubscriberExt, registry::LookupSpan, Layer,
|
filter::Targets, layer::SubscriberExt, registry::LookupSpan, Layer, Registry,
|
||||||
Registry,
|
|
||||||
};
|
};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -47,7 +50,7 @@ struct Config {
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
env = "PICTRS_PROXY_ADDR",
|
env = "PICTRS_PROXY_ADDR",
|
||||||
default_value = "0.0.0.0:8081",
|
default_value = "[::]:8081",
|
||||||
help = "The address and port the server binds to"
|
help = "The address and port the server binds to"
|
||||||
)]
|
)]
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
|
@ -73,10 +76,17 @@ struct Config {
|
||||||
#[arg(
|
#[arg(
|
||||||
long,
|
long,
|
||||||
env = "PICTRS_PROXY_CONSOLE_BUFFER_SIZE",
|
env = "PICTRS_PROXY_CONSOLE_BUFFER_SIZE",
|
||||||
help = "Number of events to buffer for the console subscriber. When unset, console will be disabled"
|
help = "Number of events to buffer for the console subscriber"
|
||||||
)]
|
)]
|
||||||
console_event_buffer_size: Option<usize>,
|
console_event_buffer_size: Option<usize>,
|
||||||
|
|
||||||
|
#[arg(
|
||||||
|
long,
|
||||||
|
env = "PICTRS_PROXY_CONSOLE",
|
||||||
|
help = "Enable the tokio-console at the specified address"
|
||||||
|
)]
|
||||||
|
console_addr: Option<SocketAddr>,
|
||||||
|
|
||||||
#[arg(
|
#[arg(
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
|
@ -84,11 +94,33 @@ struct Config {
|
||||||
help = "URL of OpenTelemetry Collector"
|
help = "URL of OpenTelemetry Collector"
|
||||||
)]
|
)]
|
||||||
opentelemetry_url: Option<Url>,
|
opentelemetry_url: Option<Url>,
|
||||||
|
|
||||||
|
#[arg(
|
||||||
|
short,
|
||||||
|
long,
|
||||||
|
env = "PICTRS_PROXY_CERTIFICATE",
|
||||||
|
help = "Path to the certificate file to connect to pict-rs over TLS"
|
||||||
|
)]
|
||||||
|
certificate: Option<PathBuf>,
|
||||||
|
|
||||||
|
#[arg(
|
||||||
|
long,
|
||||||
|
env = "PICTRS_PROXY_SERVER_CERTIFICATE",
|
||||||
|
help = "Path to the certificate file to serve pict-rs-proxy over TLS"
|
||||||
|
)]
|
||||||
|
server_certificate: Option<PathBuf>,
|
||||||
|
|
||||||
|
#[arg(
|
||||||
|
long,
|
||||||
|
env = "PICTRS_PROXY_SERVER_PRIVATE_KEY",
|
||||||
|
help = "Path to the private key file to serve pict-rs-proxy over TLS"
|
||||||
|
)]
|
||||||
|
server_private_key: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
fn domain(&self) -> Option<&str> {
|
fn domain(&self) -> Option<&str> {
|
||||||
CONFIG.domain.domain()
|
config().domain.domain()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn upstream_upload_url(&self) -> String {
|
fn upstream_upload_url(&self) -> String {
|
||||||
|
@ -185,7 +217,11 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static CONFIG: Lazy<Config> = Lazy::new(Config::parse);
|
static CONFIG: OnceLock<Config> = OnceLock::new();
|
||||||
|
|
||||||
|
fn config() -> &'static Config {
|
||||||
|
CONFIG.get_or_init(Config::parse)
|
||||||
|
}
|
||||||
|
|
||||||
pub enum UploadResult<'a> {
|
pub enum UploadResult<'a> {
|
||||||
Image(Image),
|
Image(Image),
|
||||||
|
@ -311,27 +347,27 @@ impl Image {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn link(&self) -> String {
|
fn link(&self) -> String {
|
||||||
CONFIG.image_url(&self.file)
|
config().image_url(&self.file)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn thumbnails(&self) -> String {
|
fn thumbnails(&self) -> String {
|
||||||
CONFIG.thumbnails_url(&self.file)
|
config().thumbnails_url(&self.file)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view(&self, size: Option<u64>) -> String {
|
fn view(&self, size: Option<u64>) -> String {
|
||||||
CONFIG.view_url(size, &self.file)
|
config().view_url(size, &self.file)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn thumb(&self, size: u64, filetype: FileType) -> String {
|
fn thumb(&self, size: u64, filetype: FileType) -> String {
|
||||||
CONFIG.thumbnail_url(size, &self.file, filetype)
|
config().thumbnail_url(size, &self.file, filetype)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete(&self) -> String {
|
fn delete(&self) -> String {
|
||||||
CONFIG.delete_url(&self.delete_token, &self.file)
|
config().delete_url(&self.delete_token, &self.file)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm_delete(&self) -> String {
|
fn confirm_delete(&self) -> String {
|
||||||
CONFIG.confirm_delete_url(&self.delete_token, &self.file)
|
config().confirm_delete_url(&self.delete_token, &self.file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,6 +381,15 @@ pub struct Error {
|
||||||
kind: ErrorKind,
|
kind: ErrorKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Error {
|
||||||
|
pub(crate) fn upstream_error(&self) -> Option<&str> {
|
||||||
|
match self.kind {
|
||||||
|
ErrorKind::UploadFailed(ref msg) => Some(msg),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> From<T> for Error
|
impl<T> From<T> for Error
|
||||||
where
|
where
|
||||||
ErrorKind: From<T>,
|
ErrorKind: From<T>,
|
||||||
|
@ -431,7 +476,7 @@ async fn list_uploads(
|
||||||
let mut details_handles = Vec::new();
|
let mut details_handles = Vec::new();
|
||||||
|
|
||||||
for upload_id in &query.uploads {
|
for upload_id in &query.uploads {
|
||||||
let claim_url = CONFIG.upstream_claim_url(upload_id.as_str());
|
let claim_url = config().upstream_claim_url(upload_id.as_str());
|
||||||
let client = client.clone();
|
let client = client.clone();
|
||||||
|
|
||||||
upload_handles.push(actix_rt::spawn(async move {
|
upload_handles.push(actix_rt::spawn(async move {
|
||||||
|
@ -452,7 +497,7 @@ async fn list_uploads(
|
||||||
}
|
}
|
||||||
|
|
||||||
for (file, delete_token) in &query.files {
|
for (file, delete_token) in &query.files {
|
||||||
let details_url = CONFIG.upstream_details_url(file);
|
let details_url = config().upstream_details_url(file);
|
||||||
|
|
||||||
let file = file.clone();
|
let file = file.clone();
|
||||||
let delete_token = delete_token.clone();
|
let delete_token = delete_token.clone();
|
||||||
|
@ -544,7 +589,7 @@ async fn upload(
|
||||||
body: web::Payload,
|
body: web::Payload,
|
||||||
client: web::Data<Client>,
|
client: web::Data<Client>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let client_request = client.request_from(CONFIG.upstream_upload_url(), req.head());
|
let client_request = client.request_from(config().upstream_upload_url(), req.head());
|
||||||
|
|
||||||
let client_request = if let Some(addr) = req.head().peer_addr {
|
let client_request = if let Some(addr) = req.head().peer_addr {
|
||||||
client_request.append_header(("X-Forwarded-For", addr.to_string()))
|
client_request.append_header(("X-Forwarded-For", addr.to_string()))
|
||||||
|
@ -579,7 +624,7 @@ async fn thumbs(
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let file = query.into_inner().image;
|
let file = query.into_inner().image;
|
||||||
|
|
||||||
let url = CONFIG.upstream_details_url(&file);
|
let url = config().upstream_details_url(&file);
|
||||||
let mut res = client.get(url).send().await?;
|
let mut res = client.get(url).send().await?;
|
||||||
|
|
||||||
if res.status() == StatusCode::NOT_FOUND {
|
if res.status() == StatusCode::NOT_FOUND {
|
||||||
|
@ -634,7 +679,7 @@ async fn view_original(
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let file = file.into_inner();
|
let file = file.into_inner();
|
||||||
|
|
||||||
let url = CONFIG.upstream_details_url(&file);
|
let url = config().upstream_details_url(&file);
|
||||||
let mut res = client.get(url).send().await?;
|
let mut res = client.get(url).send().await?;
|
||||||
|
|
||||||
if res.status() == StatusCode::NOT_FOUND {
|
if res.status() == StatusCode::NOT_FOUND {
|
||||||
|
@ -665,7 +710,7 @@ async fn view(
|
||||||
return Ok(to_404());
|
return Ok(to_404());
|
||||||
}
|
}
|
||||||
|
|
||||||
let url = CONFIG.upstream_details_url(&file);
|
let url = config().upstream_details_url(&file);
|
||||||
let mut res = client.get(url).send().await?;
|
let mut res = client.get(url).send().await?;
|
||||||
|
|
||||||
if res.status() == StatusCode::NOT_FOUND {
|
if res.status() == StatusCode::NOT_FOUND {
|
||||||
|
@ -694,7 +739,7 @@ async fn thumbnail(
|
||||||
let (size, filetype, file) = parts.into_inner();
|
let (size, filetype, file) = parts.into_inner();
|
||||||
|
|
||||||
if valid_thumbnail_size(size) {
|
if valid_thumbnail_size(size) {
|
||||||
let url = CONFIG.upstream_thumbnail_url(size, &file, filetype);
|
let url = config().upstream_thumbnail_url(size, &file, filetype);
|
||||||
|
|
||||||
return image(url, req, client).await;
|
return image(url, req, client).await;
|
||||||
}
|
}
|
||||||
|
@ -712,7 +757,7 @@ async fn full_res(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
client: web::Data<Client>,
|
client: web::Data<Client>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let url = CONFIG.upstream_image_url(&filename.into_inner());
|
let url = config().upstream_image_url(&filename.into_inner());
|
||||||
|
|
||||||
image(url, req, client).await
|
image(url, req, client).await
|
||||||
}
|
}
|
||||||
|
@ -757,7 +802,7 @@ async fn delete(
|
||||||
confirm,
|
confirm,
|
||||||
} = query.into_inner();
|
} = query.into_inner();
|
||||||
|
|
||||||
let url = CONFIG.upstream_details_url(&file);
|
let url = config().upstream_details_url(&file);
|
||||||
let mut res = client.get(url).send().await?;
|
let mut res = client.get(url).send().await?;
|
||||||
|
|
||||||
if res.status() == StatusCode::NOT_FOUND {
|
if res.status() == StatusCode::NOT_FOUND {
|
||||||
|
@ -765,7 +810,7 @@ async fn delete(
|
||||||
}
|
}
|
||||||
|
|
||||||
if confirm {
|
if confirm {
|
||||||
let url = CONFIG.upstream_delete_url(&token, &file);
|
let url = config().upstream_delete_url(&token, &file);
|
||||||
client.delete(url).send().await?;
|
client.delete(url).send().await?;
|
||||||
|
|
||||||
render(HttpResponse::Ok(), |cursor| {
|
render(HttpResponse::Ok(), |cursor| {
|
||||||
|
@ -825,6 +870,7 @@ fn render(
|
||||||
fn init_tracing(
|
fn init_tracing(
|
||||||
service_name: &'static str,
|
service_name: &'static str,
|
||||||
opentelemetry_url: Option<&Url>,
|
opentelemetry_url: Option<&Url>,
|
||||||
|
console_addr: Option<SocketAddr>,
|
||||||
console_event_buffer_size: Option<usize>,
|
console_event_buffer_size: Option<usize>,
|
||||||
) -> Result<(), anyhow::Error> {
|
) -> Result<(), anyhow::Error> {
|
||||||
opentelemetry::global::set_text_map_propagator(TraceContextPropagator::new());
|
opentelemetry::global::set_text_map_propagator(TraceContextPropagator::new());
|
||||||
|
@ -835,27 +881,32 @@ fn init_tracing(
|
||||||
.unwrap_or_else(|_| "info".into())
|
.unwrap_or_else(|_| "info".into())
|
||||||
.parse()?;
|
.parse()?;
|
||||||
|
|
||||||
let format_layer = tracing_subscriber::fmt::layer()
|
let format_layer = tracing_subscriber::fmt::layer().with_filter(targets.clone());
|
||||||
.with_span_events(FmtSpan::NEW | FmtSpan::CLOSE)
|
|
||||||
.with_filter(targets.clone());
|
|
||||||
|
|
||||||
let subscriber = Registry::default()
|
let subscriber = Registry::default()
|
||||||
.with(format_layer)
|
.with(format_layer)
|
||||||
.with(ErrorLayer::default());
|
.with(ErrorLayer::default());
|
||||||
|
|
||||||
if let Some(buffer_size) = console_event_buffer_size {
|
if let Some(console_addr) = console_addr {
|
||||||
let console_layer = ConsoleLayer::builder()
|
let console_builder = ConsoleLayer::builder()
|
||||||
.with_default_env()
|
.with_default_env()
|
||||||
.server_addr(([0, 0, 0, 0], 6669))
|
.server_addr(console_addr);
|
||||||
.event_buffer_capacity(buffer_size)
|
|
||||||
.spawn();
|
let console_layer = if let Some(buffer_size) = console_event_buffer_size {
|
||||||
|
console_builder.event_buffer_capacity(buffer_size).spawn()
|
||||||
|
} else {
|
||||||
|
console_builder.spawn()
|
||||||
|
};
|
||||||
|
|
||||||
let subscriber = subscriber.with(console_layer);
|
let subscriber = subscriber.with(console_layer);
|
||||||
|
|
||||||
init_subscriber(subscriber, targets, opentelemetry_url, service_name)
|
init_subscriber(subscriber, targets, opentelemetry_url, service_name)?;
|
||||||
|
tracing::info!("Serving tokio-console endpoint on {console_addr}");
|
||||||
} else {
|
} else {
|
||||||
init_subscriber(subscriber, targets, opentelemetry_url, service_name)
|
init_subscriber(subscriber, targets, opentelemetry_url, service_name)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_subscriber<S>(
|
fn init_subscriber<S>(
|
||||||
|
@ -869,18 +920,19 @@ where
|
||||||
for<'a> S: LookupSpan<'a>,
|
for<'a> S: LookupSpan<'a>,
|
||||||
{
|
{
|
||||||
if let Some(url) = opentelemetry_url {
|
if let Some(url) = opentelemetry_url {
|
||||||
let tracer =
|
let tracer = opentelemetry_otlp::new_pipeline()
|
||||||
opentelemetry_otlp::new_pipeline()
|
.tracing()
|
||||||
.tracing()
|
.with_trace_config(
|
||||||
.with_trace_config(opentelemetry::sdk::trace::config().with_resource(
|
opentelemetry_sdk::trace::config().with_resource(Resource::new(vec![
|
||||||
Resource::new(vec![KeyValue::new("service.name", service_name)]),
|
KeyValue::new("service.name", service_name),
|
||||||
))
|
])),
|
||||||
.with_exporter(
|
)
|
||||||
opentelemetry_otlp::new_exporter()
|
.with_exporter(
|
||||||
.tonic()
|
opentelemetry_otlp::new_exporter()
|
||||||
.with_endpoint(url.as_str()),
|
.tonic()
|
||||||
)
|
.with_endpoint(url.as_str()),
|
||||||
.install_batch(opentelemetry::runtime::Tokio)?;
|
)
|
||||||
|
.install_batch(opentelemetry_sdk::runtime::Tokio)?;
|
||||||
|
|
||||||
let otel_layer = tracing_opentelemetry::layer()
|
let otel_layer = tracing_opentelemetry::layer()
|
||||||
.with_tracer(tracer)
|
.with_tracer(tracer)
|
||||||
|
@ -896,22 +948,85 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn rustls_client_config() -> anyhow::Result<ClientConfig> {
|
||||||
|
let mut cert_store = RootCertStore {
|
||||||
|
roots: webpki_roots::TLS_SERVER_ROOTS
|
||||||
|
.iter()
|
||||||
|
.map(|anchor| {
|
||||||
|
OwnedTrustAnchor::from_subject_spki_name_constraints(
|
||||||
|
anchor.subject.to_vec(),
|
||||||
|
anchor.subject_public_key_info.to_vec(),
|
||||||
|
anchor.name_constraints.as_ref().map(|d| d.to_vec()),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(cert) = config().certificate.as_ref() {
|
||||||
|
let cert_bytes = tokio::fs::read(&cert).await?;
|
||||||
|
|
||||||
|
for res in rustls_pemfile::certs(&mut cert_bytes.as_slice()) {
|
||||||
|
cert_store.add(&Certificate(res?.to_vec()))?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(ClientConfig::builder()
|
||||||
|
.with_safe_defaults()
|
||||||
|
.with_root_certificates(cert_store)
|
||||||
|
.with_no_client_auth())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn rustls_server_key() -> anyhow::Result<Option<CertifiedKey>> {
|
||||||
|
let certificate_path = if let Some(c) = &config().server_certificate {
|
||||||
|
c
|
||||||
|
} else {
|
||||||
|
tracing::info!("No server certificate");
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
let private_key_path = if let Some(p) = &config().server_private_key {
|
||||||
|
p
|
||||||
|
} else {
|
||||||
|
tracing::info!("No server private_key");
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
|
let cert_bytes = tokio::fs::read(certificate_path).await?;
|
||||||
|
|
||||||
|
let certs = rustls_pemfile::certs(&mut cert_bytes.as_slice())
|
||||||
|
.map(|res| res.map(|c| Certificate(c.to_vec())))
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
|
let key_bytes = tokio::fs::read(private_key_path).await?;
|
||||||
|
|
||||||
|
let key =
|
||||||
|
rustls_pemfile::private_key(&mut key_bytes.as_slice())?.context("No key in keyfile")?;
|
||||||
|
|
||||||
|
let signing_key = rustls::sign::any_supported_type(&PrivateKey(Vec::from(key.secret_der())))?;
|
||||||
|
|
||||||
|
Ok(Some(CertifiedKey::new(certs, signing_key)))
|
||||||
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_rt::main]
|
||||||
async fn main() -> Result<(), anyhow::Error> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
dotenv::dotenv().ok();
|
dotenv::dotenv().ok();
|
||||||
|
|
||||||
init_tracing(
|
init_tracing(
|
||||||
"pict-rs-proxy",
|
"pict-rs-proxy",
|
||||||
CONFIG.opentelemetry_url.as_ref(),
|
config().opentelemetry_url.as_ref(),
|
||||||
CONFIG.console_event_buffer_size,
|
config().console_addr,
|
||||||
|
config().console_event_buffer_size,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
HttpServer::new(move || {
|
let client_config = rustls_client_config().await?;
|
||||||
|
|
||||||
|
let server = HttpServer::new(move || {
|
||||||
let client = Client::builder()
|
let client = Client::builder()
|
||||||
.wrap(Tracing)
|
.wrap(Tracing)
|
||||||
.add_default_header(("User-Agent", "pict-rs-frontend, v0.5.0-alpha.1"))
|
.add_default_header(("User-Agent", "pict-rs-frontend, v0.5.0"))
|
||||||
.timeout(Duration::from_secs(30))
|
.timeout(Duration::from_secs(30))
|
||||||
.disable_redirects()
|
.disable_redirects()
|
||||||
|
.connector(Connector::new().rustls_021(Arc::new(client_config.clone())))
|
||||||
.finish();
|
.finish();
|
||||||
|
|
||||||
App::new()
|
App::new()
|
||||||
|
@ -936,10 +1051,45 @@ async fn main() -> Result<(), anyhow::Error> {
|
||||||
.service(web::resource("/delete").route(web::get().to(delete)))
|
.service(web::resource("/delete").route(web::get().to(delete)))
|
||||||
.service(web::resource("/404").route(web::get().to(not_found)))
|
.service(web::resource("/404").route(web::get().to(not_found)))
|
||||||
.default_service(web::get().to(go_home))
|
.default_service(web::get().to(go_home))
|
||||||
})
|
});
|
||||||
.bind(CONFIG.addr)?
|
|
||||||
.run()
|
if let Some(key) = rustls_server_key().await? {
|
||||||
.await?;
|
tracing::info!("Serving pict-rs-proxy over TLS on {}", config().addr);
|
||||||
|
|
||||||
|
let (tx, rx) = rustls_channel_resolver::channel::<32>(key);
|
||||||
|
|
||||||
|
let handle = actix_rt::spawn(async move {
|
||||||
|
let mut interval = actix_rt::time::interval(Duration::from_secs(30));
|
||||||
|
interval.tick().await;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
interval.tick().await;
|
||||||
|
|
||||||
|
match rustls_server_key().await {
|
||||||
|
Ok(Some(key)) => tx.update(key),
|
||||||
|
Ok(None) => tracing::warn!("Missing server certificates"),
|
||||||
|
Err(e) => tracing::error!("Failed to read server certificates {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let server_config = ServerConfig::builder()
|
||||||
|
.with_safe_defaults()
|
||||||
|
.with_no_client_auth()
|
||||||
|
.with_cert_resolver(rx);
|
||||||
|
|
||||||
|
server
|
||||||
|
.bind_rustls_021(config().addr, server_config)?
|
||||||
|
.run()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
handle.abort();
|
||||||
|
let _ = handle.await;
|
||||||
|
} else {
|
||||||
|
tracing::info!("Serving pict-rs-proxy on {}", config().addr);
|
||||||
|
|
||||||
|
server.bind(config().addr)?.run().await?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,11 @@
|
||||||
UploadResult::Error(error) => {
|
UploadResult::Error(error) => {
|
||||||
<p>
|
<p>
|
||||||
Error:<br />
|
Error:<br />
|
||||||
|
@if let Some(msg) = error.upstream_error() {
|
||||||
|
@msg
|
||||||
|
} else {
|
||||||
@error.to_string()
|
@error.to_string()
|
||||||
|
}
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
UploadResult::UploadId(_) => {
|
UploadResult::UploadId(_) => {
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<div class="button plain">
|
<div class="button plain">
|
||||||
<span id="file-upload-text">Select Files</span>
|
<span id="file-upload-text">Select Files</span>
|
||||||
<input id="file-upload-input" type="file" name="@name"
|
<input id="file-upload-input" type="file" name="@name"
|
||||||
accept="image/apng,image/avif,image/png,image/gif,image/jpeg,image/jxl,image/webp,video/mp4,video/quicktime,video/webm,.apng,.avif,.jpg,.jpeg,.jxl,.png,.gif,.webp,.m4v,.mp4,.webm"
|
accept="image/apng,image/avif,image/png,image/gif,image/jpeg,image/jxl,image/webp,video/mp4,video/quicktime,video/webm,.apng,.avif,.jpg,.jpeg,.jxl,.png,.gif,.webp,.m4v,.mov,.mp4,.webm"
|
||||||
multiple />
|
multiple />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
@use super::statics::{layout_css, favicon_ico};
|
@use super::statics::{layout_css, favicon_ico};
|
||||||
@use crate::CONFIG;
|
@use crate::config;
|
||||||
|
|
||||||
@(title: &str, description: Option<&str>, head: Content, body: Content)
|
@(title: &str, description: Option<&str>, head: Content, body: Content)
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
<meta property="og:description" content="Upload and share image files" />
|
<meta property="og:description" content="Upload and share image files" />
|
||||||
<meta property="twitter:description" content="Upload and share image files" />
|
<meta property="twitter:description" content="Upload and share image files" />
|
||||||
}
|
}
|
||||||
@if let Some(domain) = CONFIG.domain() {
|
@if let Some(domain) = config().domain() {
|
||||||
<meta property="twitter:domain" content="@domain" />
|
<meta property="twitter:domain" content="@domain" />
|
||||||
}
|
}
|
||||||
<link rel="stylesheet" href="@crate::statics(layout_css.name)" type="text/css" />
|
<link rel="stylesheet" href="@crate::statics(layout_css.name)" type="text/css" />
|
||||||
|
|
Loading…
Reference in a new issue