Compare commits

...

16 Commits

Author SHA1 Message Date
Vladimir Dubrovin
da99424eac Fix rpm signing: hand the built packages back to the runner user
The rpm build runs in a container as root, so the packages arrived in the
workspace owned by root. Renaming them still worked, since that only needs
write permission on the directory, but rpm --addsign rewrites the file in
place and failed:

    error: 3proxy-0.9.9.0.el9.x86_64.rpm: open failed: Permission denied

Restore the invoking user's ownership before leaving the container, falling
back to a mode change where the container cannot chown, as under a rootless
container runtime.
2026-08-22 12:09:25 +03:00
Vladimir Dubrovin
95eb9f2a9f README: widen the documented deb coverage to Debian 12 and Ubuntu 22.04 2026-08-22 11:31:11 +03:00
Vladimir Dubrovin
8fba7ffc40 Build deb packages in an Ubuntu 22.04 container
dpkg-buildpackage ran on the runner itself, so the packages inherited its ABI.
On ubuntu-latest that means glibc 2.38 and libssl3t64, which restricts the
packages to Ubuntu 24.04 and newer - Debian 12, Debian 13 and Ubuntu 22.04
cannot install them.

Nothing in the source needs glibc 2.38. The floor comes from the build host:
gcc 13 with glibc 2.38 redirects sscanf and strtol to __isoc23_ variants, and
arc4random arrived in glibc 2.36.

Build in an Ubuntu 22.04 container instead. That lowers the dependencies to
libc6 (>= 2.34) and libssl3, and libssl3t64 declares Provides: libssl3, so one
package covers Ubuntu 22.04 and later as well as Debian 12 and later. Verified
by installing on all four.

The armhf cross build moves into the same container, keeping the cross
toolchain on PATH so that install -s uses the ARM strip rather than the host
one.
2026-08-22 11:30:37 +03:00
Vladimir Dubrovin
b19e310956 Document the package repository in README 2026-08-22 11:13:20 +03:00
Vladimir Dubrovin
34722c031f Drop the Ed25519 release key
No published release was ever signed with it - signing was introduced after
0.9.9 - so it verifies nothing and only adds a second key for users to reason
about.
2026-08-22 10:39:06 +03:00
Vladimir Dubrovin
6c9c4d51aa Build rpm packages against Enterprise Linux, not Ubuntu
rpmbuild ran directly on the Ubuntu runner, so the packages carried Ubuntu's
ABI: glibc 2.38, libssl.so.3 and libpcre2-8. No RPM distribution can satisfy
that - RHEL 9 has glibc 2.34, RHEL 8 has 2.28 and OpenSSL 1.1 - so the rpms
were installable nowhere.

Build them in AlmaLinux 8, 9 and 10 containers instead, covering supported
AlmaLinux and CentOS Stream releases. Release: 1%{?dist} already in the spec
now expands, so the packages are named el8, el9 and el10 and can coexist.

Two spec changes are needed for a build outside Ubuntu:

debug_package is disabled. Enterprise Linux enables debuginfo extraction by
default while Ubuntu's rpm does not; the build produces no debug sources, so
rpmbuild aborted on an empty debugsourcefiles.list.

/bin/3proxy is excluded from automatic requires. The installed configuration
file is executable and begins with #!/bin/3proxy, so rpm generates a
dependency on it. rpm 4.16 and later canonicalise that to /usr/bin/3proxy
while %files declares /bin/3proxy, leaving a dependency that can never be
satisfied and making the package uninstallable on el9 and el10.

Enterprise Linux has no 32-bit ARM, so the armhf workflow now builds only the
deb package.
2026-08-22 10:39:05 +03:00
Vladimir Dubrovin
a3605b8289 Fix library detection under shells whose echo does not expand escapes
The OpenSSL, wolfSSL, PCRE2 and PAM probes built their test program with
echo "...\n...". make runs recipes through /bin/sh, which is dash on Debian
and Ubuntu, where the builtin echo expands \n. On distributions where /bin/sh
is bash - every RPM based distribution, and macOS - it does not, so the probe
compiled

    #include <openssl/ssl.h>n int main(){return 0;}

which is not valid C. Every probe therefore failed and the build silently
dropped TLS, PCRE2 and PAM support with no diagnostic.

Use printf, which expands escapes the same way everywhere.
2026-08-22 10:39:05 +03:00
Vladimir Dubrovin
39bc8b065c Switch release signing to an RSA-4096 key
rpm 4.14 (RHEL/CentOS/Rocky 8) cannot import an Ed25519 public key at all:
the import fails and package verification reports SIGNATURES NOT OK. RHEL 8
is supported until 2029 and is a realistic target for a signed package repo,
so the Ed25519 key excludes a large part of the rpm audience.

Publish an RSA-4096 signing key as 3proxy-release-key.asc and keep the old
Ed25519 key as 3proxy-release-key-ed25519.asc so artifacts up to 0.9.9 stay
verifiable. Workflows derive the key id from the imported secret key, so no
workflow change is needed.
2026-08-21 17:45:09 +03:00
Vladimir Dubrovin
63cc737b62 rpm signing: accept non-RSA signature headers
The release key is ed25519, so rpm stores the header signature in
DSAHEADER (EdDSA/SHA256) and RSAHEADER is empty. The verification only
looked at RSAHEADER and failed correctly signed packages.
2026-08-21 15:33:58 +03:00
Vladimir Dubrovin
aeee37998e rpm signing: pass the passphrase explicitly, add diagnostics on failure
Do not rely on the gpg-agent passphrase cache surviving between steps:
the signing command gets the passphrase from a file. A test signature is
made first, so a wrong passphrase or a key which can not sign fails with
a clear gpg error instead of an rpm which is silently left unsigned.
On failure the rpm version, the sign command and the key capabilities are
printed.
2026-08-21 13:13:24 +03:00
Vladimir Dubrovin
a830104238 Fix rpm signing: point %__gpg at the real gpg binary
rpm on Debian/Ubuntu defaults %__gpg to /usr/bin/gpg2, which does not exist,
so rpm --addsign failed with 'Could not exec gpg' and packages were left
unsigned.
2026-08-21 13:01:47 +03:00
Vladimir Dubrovin
b5e75daee4 Publish release key 2026-08-21 11:25:32 +03:00
Vladimir Dubrovin
db2f57fdd2 Sign packages, publish checksums, attest before upload, narrow permissions
GPG signing of rpm packages and detached signatures for deb packages and
for the SHA256SUMS files, using GPG_PRIVATE_KEY / GPG_PASSPHRASE secrets.
Checksums are published as release assets.

Build provenance is attested before the assets are uploaded, so a failed
attestation does not leave unattested files published.

Workflow permissions are read-only, write permissions are requested per
job only where they are used.
2026-08-21 11:08:20 +03:00
Vladimir Dubrovin
d53fdbc536 publish as 0.9 branch (0.9.9.0) 2026-08-20 20:10:47 +03:00
Vladimir Dubrovin
3dfd9052be Rework docker workflow, add build provenance attestations
Docker: single workflow, one job per image per platform instead of one
workflow per registry. Platforms are built in parallel and pushed by
digest, then combined into a manifest list pushed to Docker Hub and GHCR
at once, so both registries get identical digests. arm64 and arm/v7 build
on native arm runners, ppc64le is dropped.

Registry provenance/sbom attestations are disabled (they were shown as
unknown/unknown entries in the registries), build provenance is attested
with actions/attest-build-provenance instead and is verifiable with
'gh attestation verify oci://...'. Release binaries (rpm, deb, zip) are
attested the same way. cosign version is pinned and images are signed by
digest.
2026-08-20 20:04:00 +03:00
Vladimir Dubrovin
8e2732b323 Use lts docker tags in 0.9 branch
Release images built from the 0.9 branch are tagged lts / lts-busybox /
lts-minimal instead of latest / busybox / minimal, so master keeps the
latest tags. Version tags are unchanged.
2026-08-20 19:04:48 +03:00
21 changed files with 731 additions and 321 deletions

View File

@ -6,10 +6,14 @@ on:
workflow_dispatch: workflow_dispatch:
permissions: permissions:
contents: write contents: read
jobs: jobs:
ci: ci:
permissions:
contents: write
id-token: write
attestations: write
name: "${{ matrix.target }}" name: "${{ matrix.target }}"
strategy: strategy:
matrix: matrix:
@ -39,45 +43,136 @@ jobs:
cp ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/debian/3proxy_$RELEASE.orig.tar.gz cp ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/debian/3proxy_$RELEASE.orig.tar.gz
- name: rpmbuild - name: rpmbuild
run: | run: |
ret=`pwd` mkdir -p rpmout
cd ~/rpmbuild/SPECS for EL in 8 9 10; do
rpmbuild -ba 3proxy-$RELEASE.spec docker run --rm \
cd $ret -v "$HOME/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz:/src.tar.gz:ro" \
mv ~/rpmbuild/RPMS/aarch64/3proxy-$RELEASE-1.aarch64.rpm 3proxy-$RELEASE.arm64.rpm -v "$PWD/scripts/rh/3proxy.spec:/3proxy.spec:ro" \
-v "$PWD/rpmout:/out" \
-e RELEASE="$RELEASE" -e HOSTUID="$(id -u)" -e HOSTGID="$(id -g)" \
"almalinux:$EL" bash -c '
set -e
dnf -y install rpm-build gcc make openssl-devel pcre2-devel pam-devel tar gzip
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
cp /src.tar.gz ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz
ln -sf ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/rpmbuild/SOURCES/$RELEASE.tar.gz
cp /3proxy.spec ~/rpmbuild/SPECS/3proxy-$RELEASE.spec
cd ~/rpmbuild/SPECS
rpmbuild -ba 3proxy-$RELEASE.spec
cp ~/rpmbuild/RPMS/*/*.rpm /out/
chown "$HOSTUID:$HOSTGID" /out/*.rpm || chmod 0666 /out/*.rpm'
done
for f in rpmout/*.rpm; do
dist=$(rpm -qp --qf '%{RELEASE}' "$f" | sed 's/^1\.//')
arch=$(rpm -qp --qf '%{ARCH}' "$f")
mv "$f" "3proxy-$RELEASE.$dist.$arch.rpm"
done
rmdir rpmout
ls -l *.rpm
- name: Get artifact rpm - name: Get artifact rpm
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v7
with: with:
name: "3proxy-${{ env.RELEASE }}-arm64.rpm" name: "3proxy-${{ env.RELEASE }}-arm64.rpm"
path: "*.rpm" path: "*.rpm"
- name: Upload rpm to release
if: github.event_name == 'release'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name }}
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}.arm64.rpm
- name: debbuild - name: debbuild
run: | run: |
ret=`pwd` docker run --rm \
cd ~/debian/ -v "$HOME/debian:/debian" \
tar xzf 3proxy_$RELEASE.orig.tar.gz -e RELEASE="$RELEASE" -e VERSION="$VERSION" \
cd 3proxy-$RELEASE ubuntu:22.04 bash -c '
echo "3proxy ($RELEASE-$VERSION) buster; urgency=medium" >debian/changelog set -e
echo " " >>debian/changelog export DEBIAN_FRONTEND=noninteractive
echo " *3proxy $RELEASE build" >>debian/changelog apt-get update
echo " " >>debian/changelog apt-get install -y build-essential debhelper fakeroot libssl-dev libpcre2-dev libpam0g-dev
echo " -- z3APA3A <3apa3a@3proxy.org> "`date "+%a, %d %b %Y %H:%M:%S %z"` >>debian/changelog cd /debian
echo "">>debian/changelog tar xzf 3proxy_$RELEASE.orig.tar.gz
dpkg-buildpackage cd 3proxy-$RELEASE
cd $ret { echo "3proxy ($RELEASE-$VERSION) buster; urgency=medium"
echo " "
echo " *3proxy $RELEASE build"
echo " "
echo " -- z3APA3A <3apa3a@3proxy.org> $(date "+%a, %d %b %Y %H:%M:%S %z")"
echo ""
} > debian/changelog
dpkg-buildpackage'
cp ~/debian/3proxy_$RELEASE-"$VERSION"_arm64.deb ./3proxy-$RELEASE.arm64.deb cp ~/debian/3proxy_$RELEASE-"$VERSION"_arm64.deb ./3proxy-$RELEASE.arm64.deb
- name: Get artifact deb - name: Get artifact deb
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v7
with: with:
name: "3proxy-${{ env.RELEASE }}-arm64.deb" name: "3proxy-${{ env.RELEASE }}-arm64.deb"
path: "*.deb" path: "*.deb"
- name: Upload deb to release - name: Import signing key
if: github.event_name == 'release'
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
if [ -z "$GPG_PRIVATE_KEY" ]; then echo "GPG_PRIVATE_KEY is not set"; exit 1; fi
mkdir -p ~/.gnupg && chmod 700 ~/.gnupg
printf 'allow-loopback-pinentry\ndefault-cache-ttl 7200\nmax-cache-ttl 7200\n' > ~/.gnupg/gpg-agent.conf
gpgconf --kill gpg-agent || true
printf '%s' "$GPG_PRIVATE_KEY" | gpg --batch --import
KEYID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/{print $5; exit}')
echo "GPG_KEYID=$KEYID" >> $GITHUB_ENV
echo prime > /tmp/prime.txt
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
-u "$KEYID" --detach-sign -o /dev/null /tmp/prime.txt
rm -f /tmp/prime.txt
- name: Sign rpm
if: github.event_name == 'release'
env:
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
GPGBIN=$(command -v gpg)
if [ -z "$GPGBIN" ]; then echo "gpg not found"; exit 1; fi
umask 077
printf '%s' "$GPG_PASSPHRASE" > /tmp/gpgpass
echo test > /tmp/signtest
gpg --batch --yes --pinentry-mode loopback --passphrase-file /tmp/gpgpass \
-u "$GPG_KEYID" --detach-sign -o /tmp/signtest.sig /tmp/signtest
echo "key can sign"
{ echo "%_gpg_name $GPG_KEYID"
echo "%__gpg $GPGBIN"
echo '%__gpg_sign_cmd %{__gpg} gpg --batch --no-armor --pinentry-mode loopback --passphrase-file /tmp/gpgpass --no-secmem-warning --digest-algo sha256 -u "%{_gpg_name}" -sbo %{__signature_filename} %{__plaintext_filename}'
} > ~/.rpmmacros
rpm --addsign *.rpm
rm -f /tmp/gpgpass /tmp/signtest /tmp/signtest.sig
for f in *.rpm; do
sig=$(rpm -qp --qf '%{RSAHEADER:pgpsig}' "$f" 2>/dev/null)
case "$sig" in ""|"(none)")
sig=$(rpm -qp --qf '%{DSAHEADER:pgpsig}' "$f" 2>/dev/null) ;;
esac
case "$sig" in ""|"(none)")
echo "$f is not signed"
echo "--- rpm version ---"; rpm --version
echo "--- sign cmd ---"; rpm --eval '%{__gpg_sign_cmd}'
echo "--- secret keys ---"; gpg --list-secret-keys --with-colons | grep -E '^(sec|ssb):' || true
exit 1 ;;
esac
echo "$f: $sig"
done
- name: Checksums and detached signatures
if: github.event_name == 'release'
env:
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
sha256sum *.rpm *.deb > SHA256SUMS-arm64
for f in *.deb SHA256SUMS-arm64; do
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
-u "$GPG_KEYID" --armor --detach-sign "$f"
done
sha256sum -c SHA256SUMS-arm64
gpg --verify SHA256SUMS-arm64.asc SHA256SUMS-arm64
- name: Attest build provenance
if: github.event_name == 'release'
uses: actions/attest-build-provenance@v2
with:
subject-path: |
*.rpm
*.deb
- name: Upload to release
if: github.event_name == 'release' if: github.event_name == 'release'
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name }} TAG: ${{ github.event.release.tag_name }}
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}.arm64.deb run: gh release upload "$TAG" *.rpm *.deb *.deb.asc SHA256SUMS-arm64 SHA256SUMS-arm64.asc

View File

@ -1,4 +1,4 @@
name: RPM/DEB build armhf name: DEB build armhf
on: on:
release: release:
@ -6,10 +6,14 @@ on:
workflow_dispatch: workflow_dispatch:
permissions: permissions:
contents: write contents: read
jobs: jobs:
ci: ci:
permissions:
contents: write
id-token: write
attestations: write
name: "${{ matrix.target }}" name: "${{ matrix.target }}"
strategy: strategy:
matrix: matrix:
@ -23,34 +27,7 @@ jobs:
pwd pwd
echo "RELEASE=$(cat RELEASE)" >> $GITHUB_ENV echo "RELEASE=$(cat RELEASE)" >> $GITHUB_ENV
echo "VERSION=$(date +%y%m%d%H%M%S)" >> $GITHUB_ENV echo "VERSION=$(date +%y%m%d%H%M%S)" >> $GITHUB_ENV
- name: Linux libraries - name: configure deb env
run: |
sudo apt update
sudo dpkg --add-architecture armhf
echo "Types: deb" > ~/ubuntu.sources
echo "URIs: http://archive.ubuntu.com/ubuntu/" >> ~/ubuntu.sources
echo "Suites: noble noble-updates noble-backports" >> ~/ubuntu.sources
echo "Components: main restricted universe multiverse" >> ~/ubuntu.sources
echo "Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg" >> ~/ubuntu.sources
echo "Architectures: amd64" >> ~/ubuntu.sources
echo "" >> ~/ubuntu.sources
echo "Types: deb" >> ~/ubuntu.sources
echo "URIs: http://security.ubuntu.com/ubuntu/" >> ~/ubuntu.sources
echo "Suites: noble-security" >> ~/ubuntu.sources
echo "Components: main restricted universe multiverse" >> ~/ubuntu.sources
echo "Architectures: amd64" >> ~/ubuntu.sources
echo "Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg" >> ~/ubuntu.sources
echo "" >> ~/ubuntu.sources
echo "Types: deb" >>~/ubuntu.sources
echo "URIs: http://ports.ubuntu.com/ubuntu-ports/" >>~/ubuntu.sources
echo "Suites: noble noble-updates" >>~/ubuntu.sources
echo "Components: main restricted universe multiverse" >>~/ubuntu.sources
echo "Architectures: armhf" >>~/ubuntu.sources
echo "Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg" >>~/ubuntu.sources
sudo cp ~/ubuntu.sources /etc/apt/sources.list.d/ubuntu.sources
sudo apt update
sudo apt install libssl3t64:armhf openssl:armhf libssl-dev:armhf libpam0g:armhf libpam0g-dev:armhf libpcre2-dev:armhf rpm crossbuild-essential-armhf build-essential debhelper
- name: configure rpm env
run: | run: |
mkdir ~/debian mkdir ~/debian
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS} mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
@ -58,59 +35,80 @@ jobs:
ln -s ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/rpmbuild/SOURCES/$RELEASE.tar.gz ln -s ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/rpmbuild/SOURCES/$RELEASE.tar.gz
cp scripts/rh/3proxy.spec ~/rpmbuild/SPECS/3proxy-$RELEASE.spec cp scripts/rh/3proxy.spec ~/rpmbuild/SPECS/3proxy-$RELEASE.spec
cp ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/debian/3proxy_$RELEASE.orig.tar.gz cp ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/debian/3proxy_$RELEASE.orig.tar.gz
- name: rpmbuild
run: |
ret=`pwd`
cd ~/rpmbuild/SPECS
PATH=/usr/arm-linux-gnueabihf/bin:$PATH
export PATH=$PATH
CC=arm-linux-gnueabihf-gcc
export CC=$CC
export RPATH=/usr/arm-linux-gnueabihf/lib:$RPATH
export LD_LIBRARY_PATH=/usr/arm-linux-gnueabihf/lib:$LD_LIBRARY_PATH
rpmbuild -ba --define "PAMLIB pam0g" --define "_arch arm" --define "cross yes" --target=arm-linux-gnueabihf 3proxy-$RELEASE.spec
cd $ret
mv ~/rpmbuild/RPMS/arm/3proxy-$RELEASE-1.arm.rpm 3proxy-$RELEASE.arm.rpm
- name: Get artifact rpm
uses: actions/upload-artifact@v7
with:
name: "3proxy-${{ env.RELEASE }}-arm.rpm"
path: "*.rpm"
- name: Upload rpm to release
if: github.event_name == 'release'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name }}
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}.arm.rpm
- name: debbuild - name: debbuild
run: | run: |
ret=`pwd` docker run --rm \
cd ~/debian/ -v "$HOME/debian:/debian" \
tar xzf 3proxy_$RELEASE.orig.tar.gz -e RELEASE="$RELEASE" -e VERSION="$VERSION" \
cd 3proxy-$RELEASE ubuntu:22.04 bash -c '
echo "3proxy ($RELEASE-$VERSION) buster; urgency=medium" >debian/changelog set -e
echo " " >>debian/changelog export DEBIAN_FRONTEND=noninteractive
echo " *3proxy $RELEASE build" >>debian/changelog dpkg --add-architecture armhf
echo " " >>debian/changelog sed -i "s|^deb |deb [arch=amd64] |" /etc/apt/sources.list
echo " -- z3APA3A <3apa3a@3proxy.org> "`date "+%a, %d %b %Y %H:%M:%S %z"` >>debian/changelog { echo "deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports jammy main restricted universe multiverse"
echo "">>debian/changelog echo "deb [arch=armhf] http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted universe multiverse"
PATH=/usr/arm-linux-gnueabihf/bin:$PATH } >> /etc/apt/sources.list
export PATH=$PATH apt-get update
CC=arm-linux-gnueabihf-gcc apt-get install -y crossbuild-essential-armhf build-essential debhelper fakeroot \
export CC=$CC libssl-dev:armhf libpcre2-dev:armhf libpam0g-dev:armhf
export RPATH=/usr/arm-linux-gnueabihf/lib:$RPATH cd /debian
export LD_LIBRARY_PATH=/usr/arm-linux-gnueabihf/lib:$LD_LIBRARY_PATH tar xzf 3proxy_$RELEASE.orig.tar.gz
dpkg-buildpackage cd 3proxy-$RELEASE
cd $ret { echo "3proxy ($RELEASE-$VERSION) buster; urgency=medium"
echo " "
echo " *3proxy $RELEASE build"
echo " "
echo " -- z3APA3A <3apa3a@3proxy.org> $(date "+%a, %d %b %Y %H:%M:%S %z")"
echo ""
} > debian/changelog
export PATH=/usr/arm-linux-gnueabihf/bin:$PATH
export CC=arm-linux-gnueabihf-gcc
export LD_LIBRARY_PATH=/usr/arm-linux-gnueabihf/lib:$LD_LIBRARY_PATH
dpkg-buildpackage'
cp ~/debian/3proxy_$RELEASE-"$VERSION"_armhf.deb ./3proxy-$RELEASE.arm.deb cp ~/debian/3proxy_$RELEASE-"$VERSION"_armhf.deb ./3proxy-$RELEASE.arm.deb
- name: Get artifact deb - name: Get artifact deb
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v7
with: with:
name: "3proxy-${{ env.RELEASE }}-arm.deb" name: "3proxy-${{ env.RELEASE }}-arm.deb"
path: "*.deb" path: "*.deb"
- name: Upload deb to release - name: Import signing key
if: github.event_name == 'release'
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
if [ -z "$GPG_PRIVATE_KEY" ]; then echo "GPG_PRIVATE_KEY is not set"; exit 1; fi
mkdir -p ~/.gnupg && chmod 700 ~/.gnupg
printf 'allow-loopback-pinentry\ndefault-cache-ttl 7200\nmax-cache-ttl 7200\n' > ~/.gnupg/gpg-agent.conf
gpgconf --kill gpg-agent || true
printf '%s' "$GPG_PRIVATE_KEY" | gpg --batch --import
KEYID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/{print $5; exit}')
echo "GPG_KEYID=$KEYID" >> $GITHUB_ENV
echo prime > /tmp/prime.txt
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
-u "$KEYID" --detach-sign -o /dev/null /tmp/prime.txt
rm -f /tmp/prime.txt
- name: Checksums and detached signatures
if: github.event_name == 'release'
env:
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
sha256sum *.deb > SHA256SUMS-arm
for f in *.deb SHA256SUMS-arm; do
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
-u "$GPG_KEYID" --armor --detach-sign "$f"
done
sha256sum -c SHA256SUMS-arm
gpg --verify SHA256SUMS-arm.asc SHA256SUMS-arm
- name: Attest build provenance
if: github.event_name == 'release'
uses: actions/attest-build-provenance@v2
with:
subject-path: |
*.deb
- name: Upload to release
if: github.event_name == 'release' if: github.event_name == 'release'
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name }} TAG: ${{ github.event.release.tag_name }}
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}.arm.deb run: gh release upload "$TAG" *.deb *.deb.asc SHA256SUMS-arm SHA256SUMS-arm.asc

View File

@ -6,10 +6,14 @@ on:
workflow_dispatch: workflow_dispatch:
permissions: permissions:
contents: write contents: read
jobs: jobs:
ci: ci:
permissions:
contents: write
id-token: write
attestations: write
name: "${{ matrix.target }}" name: "${{ matrix.target }}"
strategy: strategy:
matrix: matrix:
@ -39,46 +43,137 @@ jobs:
cp ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/debian/3proxy_$RELEASE.orig.tar.gz cp ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/debian/3proxy_$RELEASE.orig.tar.gz
- name: rpmbuild - name: rpmbuild
run: | run: |
ret=`pwd` mkdir -p rpmout
cd ~/rpmbuild/SPECS for EL in 8 9 10; do
rpmbuild -ba 3proxy-$RELEASE.spec docker run --rm \
cd $ret -v "$HOME/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz:/src.tar.gz:ro" \
mv ~/rpmbuild/RPMS/x86_64/3proxy-$RELEASE-1.x86_64.rpm 3proxy-$RELEASE.x86_64.rpm -v "$PWD/scripts/rh/3proxy.spec:/3proxy.spec:ro" \
-v "$PWD/rpmout:/out" \
-e RELEASE="$RELEASE" -e HOSTUID="$(id -u)" -e HOSTGID="$(id -g)" \
"almalinux:$EL" bash -c '
set -e
dnf -y install rpm-build gcc make openssl-devel pcre2-devel pam-devel tar gzip
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
cp /src.tar.gz ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz
ln -sf ~/rpmbuild/SOURCES/3proxy-$RELEASE.tar.gz ~/rpmbuild/SOURCES/$RELEASE.tar.gz
cp /3proxy.spec ~/rpmbuild/SPECS/3proxy-$RELEASE.spec
cd ~/rpmbuild/SPECS
rpmbuild -ba 3proxy-$RELEASE.spec
cp ~/rpmbuild/RPMS/*/*.rpm /out/
chown "$HOSTUID:$HOSTGID" /out/*.rpm || chmod 0666 /out/*.rpm'
done
for f in rpmout/*.rpm; do
dist=$(rpm -qp --qf '%{RELEASE}' "$f" | sed 's/^1\.//')
arch=$(rpm -qp --qf '%{ARCH}' "$f")
mv "$f" "3proxy-$RELEASE.$dist.$arch.rpm"
done
rmdir rpmout
ls -l *.rpm
- name: Get artifact rpm - name: Get artifact rpm
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v7
with: with:
name: "3proxy-${{ env.RELEASE }}-x86_64.rpm" name: "3proxy-${{ env.RELEASE }}-x86_64.rpm"
path: "*.rpm" path: "*.rpm"
- name: Upload rpm to release
if: github.event_name == 'release'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name }}
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}.x86_64.rpm
- name: debbuild - name: debbuild
run: | run: |
ret=`pwd` docker run --rm \
cd ~/debian/ -v "$HOME/debian:/debian" \
tar xzf 3proxy_$RELEASE.orig.tar.gz -e RELEASE="$RELEASE" -e VERSION="$VERSION" \
cd 3proxy-$RELEASE ubuntu:22.04 bash -c '
echo "3proxy ($RELEASE-$VERSION) buster; urgency=medium" >debian/changelog set -e
echo " " >>debian/changelog export DEBIAN_FRONTEND=noninteractive
echo " *3proxy $RELEASE build" >>debian/changelog apt-get update
echo " " >>debian/changelog apt-get install -y build-essential debhelper fakeroot libssl-dev libpcre2-dev libpam0g-dev
echo " -- z3APA3A <3apa3a@3proxy.org> "`date "+%a, %d %b %Y %H:%M:%S %z"` >>debian/changelog cd /debian
echo "">>debian/changelog tar xzf 3proxy_$RELEASE.orig.tar.gz
dpkg-buildpackage cd 3proxy-$RELEASE
cd $ret { echo "3proxy ($RELEASE-$VERSION) buster; urgency=medium"
echo " "
echo " *3proxy $RELEASE build"
echo " "
echo " -- z3APA3A <3apa3a@3proxy.org> $(date "+%a, %d %b %Y %H:%M:%S %z")"
echo ""
} > debian/changelog
dpkg-buildpackage'
cp ~/debian/3proxy_$RELEASE-"$VERSION"_amd64.deb ./3proxy-$RELEASE.x86_64.deb cp ~/debian/3proxy_$RELEASE-"$VERSION"_amd64.deb ./3proxy-$RELEASE.x86_64.deb
- name: Get artifact deb - name: Get artifact deb
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v7
with: with:
name: "3proxy-${{ env.RELEASE }}-x86_64.deb" name: "3proxy-${{ env.RELEASE }}-x86_64.deb"
path: "*.deb" path: "*.deb"
- name: Upload deb to release
- name: Import signing key
if: github.event_name == 'release'
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
if [ -z "$GPG_PRIVATE_KEY" ]; then echo "GPG_PRIVATE_KEY is not set"; exit 1; fi
mkdir -p ~/.gnupg && chmod 700 ~/.gnupg
printf 'allow-loopback-pinentry\ndefault-cache-ttl 7200\nmax-cache-ttl 7200\n' > ~/.gnupg/gpg-agent.conf
gpgconf --kill gpg-agent || true
printf '%s' "$GPG_PRIVATE_KEY" | gpg --batch --import
KEYID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/{print $5; exit}')
echo "GPG_KEYID=$KEYID" >> $GITHUB_ENV
echo prime > /tmp/prime.txt
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
-u "$KEYID" --detach-sign -o /dev/null /tmp/prime.txt
rm -f /tmp/prime.txt
- name: Sign rpm
if: github.event_name == 'release'
env:
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
GPGBIN=$(command -v gpg)
if [ -z "$GPGBIN" ]; then echo "gpg not found"; exit 1; fi
umask 077
printf '%s' "$GPG_PASSPHRASE" > /tmp/gpgpass
echo test > /tmp/signtest
gpg --batch --yes --pinentry-mode loopback --passphrase-file /tmp/gpgpass \
-u "$GPG_KEYID" --detach-sign -o /tmp/signtest.sig /tmp/signtest
echo "key can sign"
{ echo "%_gpg_name $GPG_KEYID"
echo "%__gpg $GPGBIN"
echo '%__gpg_sign_cmd %{__gpg} gpg --batch --no-armor --pinentry-mode loopback --passphrase-file /tmp/gpgpass --no-secmem-warning --digest-algo sha256 -u "%{_gpg_name}" -sbo %{__signature_filename} %{__plaintext_filename}'
} > ~/.rpmmacros
rpm --addsign *.rpm
rm -f /tmp/gpgpass /tmp/signtest /tmp/signtest.sig
for f in *.rpm; do
sig=$(rpm -qp --qf '%{RSAHEADER:pgpsig}' "$f" 2>/dev/null)
case "$sig" in ""|"(none)")
sig=$(rpm -qp --qf '%{DSAHEADER:pgpsig}' "$f" 2>/dev/null) ;;
esac
case "$sig" in ""|"(none)")
echo "$f is not signed"
echo "--- rpm version ---"; rpm --version
echo "--- sign cmd ---"; rpm --eval '%{__gpg_sign_cmd}'
echo "--- secret keys ---"; gpg --list-secret-keys --with-colons | grep -E '^(sec|ssb):' || true
exit 1 ;;
esac
echo "$f: $sig"
done
- name: Checksums and detached signatures
if: github.event_name == 'release'
env:
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
sha256sum *.rpm *.deb > SHA256SUMS-x86_64
for f in *.deb SHA256SUMS-x86_64; do
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
-u "$GPG_KEYID" --armor --detach-sign "$f"
done
sha256sum -c SHA256SUMS-x86_64
gpg --verify SHA256SUMS-x86_64.asc SHA256SUMS-x86_64
- name: Attest build provenance
if: github.event_name == 'release'
uses: actions/attest-build-provenance@v2
with:
subject-path: |
*.rpm
*.deb
- name: Upload to release
if: github.event_name == 'release' if: github.event_name == 'release'
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name }} TAG: ${{ github.event.release.tag_name }}
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}.x86_64.deb run: gh release upload "$TAG" *.rpm *.deb *.deb.asc SHA256SUMS-x86_64 SHA256SUMS-x86_64.asc

View File

@ -6,10 +6,14 @@ on:
workflow_dispatch: workflow_dispatch:
permissions: permissions:
contents: write contents: read
jobs: jobs:
ci: ci:
permissions:
contents: write
id-token: write
attestations: write
name: "${{ matrix.target }}" name: "${{ matrix.target }}"
strategy: strategy:
matrix: matrix:
@ -86,10 +90,30 @@ jobs:
if: github.event_name == 'release' if: github.event_name == 'release'
shell: pwsh shell: pwsh
run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-lite.zip run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-lite.zip
- name: Checksums and detached signature
if: github.event_name == 'release'
shell: bash
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
if [ -z "$GPG_PRIVATE_KEY" ]; then echo "GPG_PRIVATE_KEY is not set"; exit 1; fi
printf '%s' "$GPG_PRIVATE_KEY" | gpg --batch --import
KEYID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/{print $5; exit}')
sha256sum *.zip > SHA256SUMS-win-lite
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
-u "$KEYID" --armor --detach-sign SHA256SUMS-win-lite
sha256sum -c SHA256SUMS-win-lite
- name: Attest build provenance
if: github.event_name == 'release'
uses: actions/attest-build-provenance@v2
with:
subject-path: |
*.zip
- name: Upload to release - name: Upload to release
if: github.event_name == 'release' if: github.event_name == 'release'
shell: bash shell: bash
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name }} TAG: ${{ github.event.release.tag_name }}
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}-lite.zip run: gh release upload "$TAG" *.zip SHA256SUMS-win-lite SHA256SUMS-win-lite.asc

View File

@ -6,10 +6,14 @@ on:
workflow_dispatch: workflow_dispatch:
permissions: permissions:
contents: write contents: read
jobs: jobs:
ci: ci:
permissions:
contents: write
id-token: write
attestations: write
name: "${{ matrix.target }}" name: "${{ matrix.target }}"
strategy: strategy:
matrix: matrix:
@ -101,10 +105,30 @@ jobs:
if: github.event_name == 'release' if: github.event_name == 'release'
shell: pwsh shell: pwsh
run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-x86.zip run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-x86.zip
- name: Checksums and detached signature
if: github.event_name == 'release'
shell: bash
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
if [ -z "$GPG_PRIVATE_KEY" ]; then echo "GPG_PRIVATE_KEY is not set"; exit 1; fi
printf '%s' "$GPG_PRIVATE_KEY" | gpg --batch --import
KEYID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/{print $5; exit}')
sha256sum *.zip > SHA256SUMS-win-x86
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
-u "$KEYID" --armor --detach-sign SHA256SUMS-win-x86
sha256sum -c SHA256SUMS-win-x86
- name: Attest build provenance
if: github.event_name == 'release'
uses: actions/attest-build-provenance@v2
with:
subject-path: |
*.zip
- name: Upload to release - name: Upload to release
if: github.event_name == 'release' if: github.event_name == 'release'
shell: bash shell: bash
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name }} TAG: ${{ github.event.release.tag_name }}
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}-x86.zip run: gh release upload "$TAG" *.zip SHA256SUMS-win-x86 SHA256SUMS-win-x86.asc

View File

@ -6,10 +6,14 @@ on:
workflow_dispatch: workflow_dispatch:
permissions: permissions:
contents: write contents: read
jobs: jobs:
ci: ci:
permissions:
contents: write
id-token: write
attestations: write
name: "${{ matrix.target }}" name: "${{ matrix.target }}"
strategy: strategy:
matrix: matrix:
@ -102,10 +106,30 @@ jobs:
if: github.event_name == 'release' if: github.event_name == 'release'
shell: pwsh shell: pwsh
run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-x64.zip run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-x64.zip
- name: Checksums and detached signature
if: github.event_name == 'release'
shell: bash
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
if [ -z "$GPG_PRIVATE_KEY" ]; then echo "GPG_PRIVATE_KEY is not set"; exit 1; fi
printf '%s' "$GPG_PRIVATE_KEY" | gpg --batch --import
KEYID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/{print $5; exit}')
sha256sum *.zip > SHA256SUMS-win-x64
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
-u "$KEYID" --armor --detach-sign SHA256SUMS-win-x64
sha256sum -c SHA256SUMS-win-x64
- name: Attest build provenance
if: github.event_name == 'release'
uses: actions/attest-build-provenance@v2
with:
subject-path: |
*.zip
- name: Upload to release - name: Upload to release
if: github.event_name == 'release' if: github.event_name == 'release'
shell: bash shell: bash
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name }} TAG: ${{ github.event.release.tag_name }}
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}-x64.zip run: gh release upload "$TAG" *.zip SHA256SUMS-win-x64 SHA256SUMS-win-x64.asc

View File

@ -6,10 +6,14 @@ on:
workflow_dispatch: workflow_dispatch:
permissions: permissions:
contents: write contents: read
jobs: jobs:
ci: ci:
permissions:
contents: write
id-token: write
attestations: write
name: "${{ matrix.target }}" name: "${{ matrix.target }}"
strategy: strategy:
matrix: matrix:
@ -101,10 +105,30 @@ jobs:
if: github.event_name == 'release' if: github.event_name == 'release'
shell: pwsh shell: pwsh
run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-arm64.zip run: Compress-Archive -Path dist/* -DestinationPath 3proxy-${{ env.RELEASE }}-arm64.zip
- name: Checksums and detached signature
if: github.event_name == 'release'
shell: bash
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
if [ -z "$GPG_PRIVATE_KEY" ]; then echo "GPG_PRIVATE_KEY is not set"; exit 1; fi
printf '%s' "$GPG_PRIVATE_KEY" | gpg --batch --import
KEYID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/{print $5; exit}')
sha256sum *.zip > SHA256SUMS-win-arm64
gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \
-u "$KEYID" --armor --detach-sign SHA256SUMS-win-arm64
sha256sum -c SHA256SUMS-win-arm64
- name: Attest build provenance
if: github.event_name == 'release'
uses: actions/attest-build-provenance@v2
with:
subject-path: |
*.zip
- name: Upload to release - name: Upload to release
if: github.event_name == 'release' if: github.event_name == 'release'
shell: bash shell: bash
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
TAG: ${{ github.event.release.tag_name }} TAG: ${{ github.event.release.tag_name }}
run: gh release upload "$TAG" 3proxy-${{ env.RELEASE }}-arm64.zip run: gh release upload "$TAG" *.zip SHA256SUMS-win-arm64 SHA256SUMS-win-arm64.asc

View File

@ -1,99 +0,0 @@
name: Build Docker images (GHCR)
on:
release:
types: [published]
workflow_dispatch:
permissions:
contents: read
packages: write
id-token: write
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
name: Build and push Docker images
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Determine tags
id: tags
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
run: |
if [[ "$RELEASE_TAG" != "" ]]; then
RELEASE="${RELEASE_TAG#v}"
echo "minimal=${IMAGE}:${RELEASE}.minimal,${IMAGE}:minimal" >> "$GITHUB_OUTPUT"
echo "busybox=${IMAGE}:${RELEASE}.busybox,${IMAGE}:busybox" >> "$GITHUB_OUTPUT"
echo "full=${IMAGE}:${RELEASE},${IMAGE}:latest" >> "$GITHUB_OUTPUT"
else
DATETIME=$(date +%d%m%y%H%M%S)
BRANCH=$(echo "${GITHUB_REF#refs/heads/}" | tr "/" "-")
echo "minimal=${IMAGE}:${DATETIME}-${BRANCH}.minimal,${IMAGE}:${BRANCH}.minimal" >> "$GITHUB_OUTPUT"
echo "busybox=${IMAGE}:${DATETIME}-${BRANCH}.busybox,${IMAGE}:${BRANCH}.busybox" >> "$GITHUB_OUTPUT"
echo "full=${IMAGE}:${DATETIME}-${BRANCH},${IMAGE}:${BRANCH}" >> "$GITHUB_OUTPUT"
fi
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Install cosign
uses: sigstore/cosign-installer@v3
- name: Login to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push minimal
uses: docker/build-push-action@v7
with:
context: .
file: Dockerfile.minimal
platforms: linux/amd64,linux/arm64,linux/arm/v7,ppc64le
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.tags.outputs.minimal }}
- name: Build and push busybox
uses: docker/build-push-action@v7
with:
context: .
file: Dockerfile.busybox
platforms: linux/amd64,linux/arm64,linux/arm/v7,ppc64le
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.tags.outputs.busybox }}
- name: Build and push full
uses: docker/build-push-action@v7
with:
context: .
file: Dockerfile.full
platforms: linux/amd64,linux/arm64,linux/arm/v7,ppc64le
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.tags.outputs.full }}
- name: Sign images
if: github.event_name != 'pull_request'
env:
TAGS_MINIMAL: ${{ steps.tags.outputs.minimal }}
TAGS_BUSYBOX: ${{ steps.tags.outputs.busybox }}
TAGS_FULL: ${{ steps.tags.outputs.full }}
run: |
IFS=',' read -ra TAGS <<< "$TAGS_MINIMAL,$TAGS_BUSYBOX,$TAGS_FULL"
for tag in "${TAGS[@]}"; do
cosign sign --yes "$tag"
done

View File

@ -1,4 +1,4 @@
name: Build Docker images (Docker Hub) name: Build Docker images
on: on:
release: release:
@ -7,89 +7,187 @@ on:
permissions: permissions:
contents: read contents: read
id-token: write
env: env:
REGISTRY: docker.io DOCKERHUB_IMAGE: docker.io/3proxy/3proxy
IMAGE_NAME: 3proxy/3proxy GHCR_IMAGE: ghcr.io/3proxy/3proxy
jobs: jobs:
build: build:
name: Build and push Docker images name: ${{ matrix.image }} ${{ matrix.platform }}
runs-on: ubuntu-latest permissions:
contents: read
packages: write
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
image: [full, busybox, minimal]
platform: [linux/amd64, linux/arm64, linux/arm/v7]
include:
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm
- platform: linux/arm/v7
runner: ubuntu-24.04-arm
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v7 uses: actions/checkout@v7
- name: Determine tags - name: Platform name
id: tags id: platform
env: run: echo "pair=$(echo '${{ matrix.platform }}' | tr / -)" >> "$GITHUB_OUTPUT"
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
if [[ "$RELEASE_TAG" != "" ]]; then
RELEASE="${RELEASE_TAG#v}"
echo "minimal=${REGISTRY}/${IMAGE_NAME}:${RELEASE}.minimal,${REGISTRY}/${IMAGE_NAME}:minimal" >> "$GITHUB_OUTPUT"
echo "busybox=${REGISTRY}/${IMAGE_NAME}:${RELEASE}.busybox,${REGISTRY}/${IMAGE_NAME}:busybox" >> "$GITHUB_OUTPUT"
echo "full=${REGISTRY}/${IMAGE_NAME}:${RELEASE},${REGISTRY}/${IMAGE_NAME}:latest" >> "$GITHUB_OUTPUT"
else
DATETIME=$(date +%d%m%y%H%M%S)
BRANCH=$(echo "${GITHUB_REF#refs/heads/}" | tr "/" "-")
echo "minimal=${REGISTRY}/${IMAGE_NAME}:${DATETIME}-${BRANCH}.minimal,${REGISTRY}/${IMAGE_NAME}:${BRANCH}.minimal" >> "$GITHUB_OUTPUT"
echo "busybox=${REGISTRY}/${IMAGE_NAME}:${DATETIME}-${BRANCH}.busybox,${REGISTRY}/${IMAGE_NAME}:${BRANCH}.busybox" >> "$GITHUB_OUTPUT"
echo "full=${REGISTRY}/${IMAGE_NAME}:${DATETIME}-${BRANCH},${REGISTRY}/${IMAGE_NAME}:${BRANCH}" >> "$GITHUB_OUTPUT"
fi
- name: Set up QEMU - name: Set up QEMU
if: matrix.platform == 'linux/arm/v7'
uses: docker/setup-qemu-action@v4 uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4 uses: docker/setup-buildx-action@v4
- name: Login to GHCR
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push by digest
id: build
uses: docker/build-push-action@v7
with:
context: .
file: Dockerfile.${{ matrix.image }}
platforms: ${{ matrix.platform }}
provenance: false
sbom: false
outputs: type=image,name=${{ env.GHCR_IMAGE }},push-by-digest=true,name-canonical=true,push=true
- name: Export digest
env:
DIGEST: ${{ steps.build.outputs.digest }}
run: |
mkdir -p /tmp/digests
touch "/tmp/digests/${DIGEST#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v7
with:
name: digests-${{ matrix.image }}-${{ steps.platform.outputs.pair }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
publish:
name: Publish ${{ matrix.image }}
permissions:
contents: read
packages: write
id-token: write
attestations: write
runs-on: ubuntu-latest
needs: build
strategy:
fail-fast: false
matrix:
include:
- image: full
suffix: ''
floating: lts
- image: busybox
suffix: .busybox
floating: lts-busybox
- image: minimal
suffix: .minimal
floating: lts-minimal
steps:
- name: Download digests
uses: actions/download-artifact@v7
with:
path: /tmp/digests
pattern: digests-${{ matrix.image }}-*
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Install cosign - name: Install cosign
uses: sigstore/cosign-installer@v3 uses: sigstore/cosign-installer@v3
with:
cosign-release: v2.4.3
- name: Login to Docker Hub - name: Login to Docker Hub
if: github.event_name != 'pull_request'
uses: docker/login-action@v4 uses: docker/login-action@v4
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push minimal - name: Login to GHCR
uses: docker/build-push-action@v7 uses: docker/login-action@v4
with: with:
context: . registry: ghcr.io
file: Dockerfile.minimal username: ${{ github.actor }}
platforms: linux/amd64,linux/arm64,linux/arm/v7,ppc64le password: ${{ secrets.GITHUB_TOKEN }}
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.tags.outputs.minimal }}
- name: Build and push busybox - name: Determine tags
uses: docker/build-push-action@v7 id: tags
with: env:
context: . RELEASE_TAG: ${{ github.event.release.tag_name }}
file: Dockerfile.busybox SUFFIX: ${{ matrix.suffix }}
platforms: linux/amd64,linux/arm64,linux/arm/v7,ppc64le FLOATING: ${{ matrix.floating }}
push: ${{ github.event_name != 'pull_request' }} run: |
tags: ${{ steps.tags.outputs.busybox }} if [[ "$RELEASE_TAG" != "" ]]; then
RELEASE="${RELEASE_TAG#v}"
echo "versioned=${RELEASE}${SUFFIX}" >> "$GITHUB_OUTPUT"
echo "moving=${FLOATING}" >> "$GITHUB_OUTPUT"
else
DATETIME=$(date +%d%m%y%H%M%S)
BRANCH=$(echo "${GITHUB_REF#refs/heads/}" | tr "/" "-")
echo "versioned=${DATETIME}-${BRANCH}${SUFFIX}" >> "$GITHUB_OUTPUT"
echo "moving=${BRANCH}${SUFFIX}" >> "$GITHUB_OUTPUT"
fi
- name: Build and push full - name: Create manifest list and push
uses: docker/build-push-action@v7 working-directory: /tmp/digests
env:
VERSIONED: ${{ steps.tags.outputs.versioned }}
MOVING: ${{ steps.tags.outputs.moving }}
run: |
docker buildx imagetools create \
-t "${DOCKERHUB_IMAGE}:${VERSIONED}" \
-t "${DOCKERHUB_IMAGE}:${MOVING}" \
-t "${GHCR_IMAGE}:${VERSIONED}" \
-t "${GHCR_IMAGE}:${MOVING}" \
$(printf "${GHCR_IMAGE}@sha256:%s " *)
- name: Get pushed digest
id: digest
env:
VERSIONED: ${{ steps.tags.outputs.versioned }}
run: |
DIGEST=$(docker buildx imagetools inspect "${DOCKERHUB_IMAGE}:${VERSIONED}" \
--format '{{json .Manifest}}' | jq -r .digest)
echo "digest=${DIGEST}" >> "$GITHUB_OUTPUT"
- name: Attest Docker Hub image
uses: actions/attest-build-provenance@v2
with: with:
context: . subject-name: ${{ env.DOCKERHUB_IMAGE }}
file: Dockerfile.full subject-digest: ${{ steps.digest.outputs.digest }}
platforms: linux/amd64,linux/arm64,linux/arm/v7,ppc64le push-to-registry: false
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.tags.outputs.full }} - name: Attest GHCR image
uses: actions/attest-build-provenance@v2
with:
subject-name: ${{ env.GHCR_IMAGE }}
subject-digest: ${{ steps.digest.outputs.digest }}
push-to-registry: false
- name: Sign images - name: Sign images
if: github.event_name != 'pull_request'
env: env:
TAGS_MINIMAL: ${{ steps.tags.outputs.minimal }} DIGEST: ${{ steps.digest.outputs.digest }}
TAGS_BUSYBOX: ${{ steps.tags.outputs.busybox }}
TAGS_FULL: ${{ steps.tags.outputs.full }}
run: | run: |
IFS=',' read -ra TAGS <<< "$TAGS_MINIMAL,$TAGS_BUSYBOX,$TAGS_FULL" cosign sign --yes "${DOCKERHUB_IMAGE}@${DIGEST}"
for tag in "${TAGS[@]}"; do cosign sign --yes "${GHCR_IMAGE}@${DIGEST}"
cosign sign --yes "$tag"
done

29
3proxy-release-key.asc Normal file
View File

@ -0,0 +1,29 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGqIZCIBEADF3zxdMo2dvUGAlQm3aIcQiqmpLMHucvLfSK3fHtwagO8f03CO
bEx9EfIK/U6BzLwEJ0CxyClzfvgo9COVpi5EjES9sI2LXzcgc4hGaYO0Q4Unj//0
W/G8aarDaLF2NRKMLf07eaYGBRJjqHnmeHgOHdr+SnN0JtMSadWMHoliB8esnabz
5CO4JabTrhwoez3DMLSgJNIod7wL6PJJv/2BeRahwNr2CjaXmzZKr/j7fc1MKLij
bsvJ5OmLmngZr6CHDa9cBhVhiH+7RgWLCsRlEGxEv7w0afp/T0xDwNAPkGzk5ObC
BrdXvypTAbNyUoVT8qSVJwkneZ4S0Ts4rRRNfNpaus4tsCmgyGKzsrbxvbiBOTPW
jB/fjkgr6X9M/AQ3yGpXrwXRJrM/nSfjUyOEHXttTC9HpGt41NH/mpC4mDWa1Kxi
FMxuo1+dw2kpDKl0Bp78IGdCo5akHwftFr8aHgmfZoGXAGJRHPAWbJGjC2ARy8yp
QOpxba0S3VlCU6bs8MDKl6cpWItnlXcl/GD/Qc55bjLXjFv1pbn2RUSYZS+n9wDX
64syZf3dZ/N5U4ydmybWfiLFUXqKQLtdO8QAWQGt4TSwKptTmI581/MMCTQ8qWZL
zgFj6C/8K0SZ4lMOv+5zfc2+QOoWw7E2Ws3stEKTyWjOMm/QMJAGumqvqwARAQAB
tCozcHJveHkgcmVsZWFzZSBzaWduaW5nIDwzcHJveHlAM3Byb3h5Lm9yZz6JAm0E
EwEIAFcWIQT8EiFEmfzHuhz/bNwDEjhOOnOUCwUCaohkIhsUgAAAAAAEAA5tYW51
MiwyLjUrMS4xMiwwLDMCGwMFCwkIBwICIgIGFQoJCAsCBBYCAwECHgcCF4AACgkQ
AxI4TjpzlAsCwRAAtH3OO42yCd2B8Od4yS1yBDkaIFwEm8hF68eou6uaSDkKG8YZ
C3DUH7qk0nXEMQu/5J6RWZKlW1C8D3AkUR9A1g54o6mUg4IL5196XsrQRdVu64YF
nLCk17Piku1lMk+Re6bZ6uJv5UlSv8d0dvxmAYzjusyPyBC2VXy7B0CoDif6AmXt
aw2/V6m0dRrfFo4W9mJKUqTAJcdBOKzEiQb7qLnzuwy4CB5qsvnEQTqymoCXFXzg
VDCSKRLXnbDPbIs0TvsCmthn/w1hCgftPq4W0s7EUJBOhbrjF59+AuTb+U1wIXNR
1+DPF+V+5RlwWjOWMlsOVGk2jaxjVY8wuaD3rE6ISJkt1pRv/WVdY984rT7Eu94J
ZHnxPjFrb2ohFKjoBCt60kbgZbuQ6yvEma5lAF9K63gwMNNyGZvq6QWl58iouzuS
3B9t7EwGwFstJfaXVhn/rnIHoExgxVZMbbsmXiGJyE2KcfVmlZcEi0MIyqEeBSDD
gjpE4yVO6StBtJKfXra8rMwtsbWBw9MptPhcLvdWtN6TG0CxDyTHhdL1pSLNcwX1
CTVpwi6+WmGogcv0WFNn5caQUpu9le/v/5qLRK08KWOH8inMJmTfpJg/9869YJuF
vDKdzJd6jug5YQRfV/7YVC2hdSOBLvBuDpRINePrj9CKJ34qG+jRSJ5xwYk=
=IS3Y
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -52,14 +52,14 @@ ifeq ($(LIBSTATIC), true)
STATIC_SUFFIX = -Wl,-Bdynamic STATIC_SUFFIX = -Wl,-Bdynamic
ZLIB = -lz -lzstd ZLIB = -lz -lzstd
endif endif
WOLFSSL_CHECK ?= $(shell echo "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestwssl testwssl.o $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) 2>/dev/null && rm testwssl testwssl.o && echo true||echo false) WOLFSSL_CHECK ?= $(shell printf "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestwssl testwssl.o $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) 2>/dev/null && rm testwssl testwssl.o && echo true||echo false)
ifeq ($(WOLFSSL_CHECK), true) ifeq ($(WOLFSSL_CHECK), true)
LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX)
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS) SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
ZLIB := ZLIB :=
else else
OPENSSL_CHECK ?= $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false) OPENSSL_CHECK ?= $(shell printf "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false)
ifeq ($(OPENSSL_CHECK), true) ifeq ($(OPENSSL_CHECK), true)
LIBS += $(STATIC_PREFIX) $(ZLIB) -l crypto -l ssl $(STATIC_SUFFIX) LIBS += $(STATIC_PREFIX) $(ZLIB) -l crypto -l ssl $(STATIC_SUFFIX)
CFLAGS += -DWITH_SSL CFLAGS += -DWITH_SSL
@ -68,13 +68,13 @@ else
ZLIB := ZLIB :=
endif endif
endif endif
PCRE_CHECK ?= $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -lpcre2-8 2>/dev/null && rm testpcre testpcre.o && echo true||echo false) PCRE_CHECK ?= $(shell printf "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -lpcre2-8 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
ifeq ($(PCRE_CHECK), true) ifeq ($(PCRE_CHECK), true)
CFLAGS += -DWITH_PCRE CFLAGS += -DWITH_PCRE
PCRE_OBJS = pcre$(OBJSUFFICS) PCRE_OBJS = pcre$(OBJSUFFICS)
PCRE_LIBS = $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) PCRE_LIBS = $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX)
endif endif
PAM_CHECK ?= $(shell echo "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false) PAM_CHECK ?= $(shell printf "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false)
ifeq ($(PAM_CHECK), true) ifeq ($(PAM_CHECK), true)
PLUGINS += PamAuth PLUGINS += PamAuth
endif endif

View File

@ -60,14 +60,14 @@ ifeq ($(LIBSTATIC), true)
ZLIB = -lz -lzstd ZLIB = -lz -lzstd
endif endif
WOLFSSL_CHECK ?= $(shell echo "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestwssl testwssl.o $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) 2>/dev/null && rm testwssl testwssl.o && echo true||echo false) WOLFSSL_CHECK ?= $(shell printf "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestwssl testwssl.o $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) 2>/dev/null && rm testwssl testwssl.o && echo true||echo false)
ifeq ($(WOLFSSL_CHECK), true) ifeq ($(WOLFSSL_CHECK), true)
LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX)
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS) SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
ZLIB := ZLIB :=
else else
OPENSSL_CHECK ?= $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false) OPENSSL_CHECK ?= $(shell printf "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false)
ifeq ($(OPENSSL_CHECK), true) ifeq ($(OPENSSL_CHECK), true)
LIBS += $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) LIBS += $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX)
CFLAGS += -DWITH_SSL CFLAGS += -DWITH_SSL
@ -76,13 +76,13 @@ else
ZLIB := ZLIB :=
endif endif
endif endif
PCRE_CHECK ?= $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) 2>/dev/null && rm testpcre testpcre.o && echo true||echo false) PCRE_CHECK ?= $(shell printf "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
ifeq ($(PCRE_CHECK), true) ifeq ($(PCRE_CHECK), true)
CFLAGS += -DWITH_PCRE CFLAGS += -DWITH_PCRE
PCRE_OBJS = pcre$(OBJSUFFICS) PCRE_OBJS = pcre$(OBJSUFFICS)
PCRE_LIBS = $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) PCRE_LIBS = $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX)
endif endif
PAM_CHECK ?= $(shell echo "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false) PAM_CHECK ?= $(shell printf "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false)
ifeq ($(PAM_CHECK), true) ifeq ($(PAM_CHECK), true)
PLUGINS += PamAuth PLUGINS += PamAuth
endif endif

View File

@ -31,20 +31,20 @@ COMPATLIBS =
MAKEFILE = Makefile.Solaris MAKEFILE = Makefile.Solaris
PLUGINS = StringsPlugin TrafficPlugin TransparentPlugin FilePlugin PLUGINS = StringsPlugin TrafficPlugin TransparentPlugin FilePlugin
WOLFSSL_CHECK = $(shell echo "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testwssl testwssl.o -lwolfssl 2>/dev/null && rm testwssl testwssl.o && echo true||echo false) WOLFSSL_CHECK = $(shell printf "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testwssl testwssl.o -lwolfssl 2>/dev/null && rm testwssl testwssl.o && echo true||echo false)
ifeq ($(WOLFSSL_CHECK), true) ifeq ($(WOLFSSL_CHECK), true)
LIBS += -lwolfssl LIBS += -lwolfssl
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS) SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
else else
OPENSSL_CHECK = $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testssl testssl.o -lcrypto -lssl 2>/dev/null && rm testssl testssl.o && echo true||echo false) OPENSSL_CHECK = $(shell printf "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testssl testssl.o -lcrypto -lssl 2>/dev/null && rm testssl testssl.o && echo true||echo false)
ifeq ($(OPENSSL_CHECK), true) ifeq ($(OPENSSL_CHECK), true)
LIBS += -l crypto -l ssl LIBS += -l crypto -l ssl
CFLAGS += -DWITH_SSL CFLAGS += -DWITH_SSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS) SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
endif endif
endif endif
PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -Wl,-Bstatic -lpcre2-8 -Wl,-Bdynamic 2>/dev/null && rm testpcre testpcre.o && echo true||echo false) PCRE_CHECK = $(shell printf "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) -Wl,-Bstatic -lpcre2-8 -Wl,-Bdynamic 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
ifeq ($(PCRE_CHECK), true) ifeq ($(PCRE_CHECK), true)
CFLAGS += -DWITH_PCRE CFLAGS += -DWITH_PCRE
PCRE_OBJS = pcre$(OBJSUFFICS) PCRE_OBJS = pcre$(OBJSUFFICS)

View File

@ -54,14 +54,14 @@ ifeq ($(LIBSTATIC), true)
STATIC_SUFFIX = -Wl,-Bdynamic STATIC_SUFFIX = -Wl,-Bdynamic
ZLIB = -lz -lzstd ZLIB = -lz -lzstd
endif endif
WOLFSSL_CHECK ?= $(shell echo "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestwssl testwssl.o $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) 2>/dev/null && rm testwssl testwssl.o && echo true||echo false) WOLFSSL_CHECK ?= $(shell printf "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testwssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestwssl testwssl.o $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) 2>/dev/null && rm testwssl testwssl.o && echo true||echo false)
ifeq ($(WOLFSSL_CHECK), true) ifeq ($(WOLFSSL_CHECK), true)
LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX)
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS) SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
ZLIB := ZLIB :=
else else
OPENSSL_CHECK ?= $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false) OPENSSL_CHECK ?= $(shell printf "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testssl.o - 2>/dev/null && $(CC) $(LDFLAGS) -otestssl testssl.o $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) 2>/dev/null && rm testssl testssl.o && echo true||echo false)
ifeq ($(OPENSSL_CHECK), true) ifeq ($(OPENSSL_CHECK), true)
LIBS += $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX) LIBS += $(STATIC_PREFIX) $(ZLIB) -lcrypto -lssl $(STATIC_SUFFIX)
CFLAGS += -DWITH_SSL CFLAGS += -DWITH_SSL
@ -70,13 +70,13 @@ else
ZLIB := ZLIB :=
endif endif
endif endif
PCRE_CHECK ?= $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) 2>/dev/null && rm testpcre testpcre.o && echo true||echo false) PCRE_CHECK ?= $(shell printf "\#define PCRE2_CODE_UNIT_WIDTH 8\\n\#include <pcre2.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpcre.o - 2>/dev/null && $(CC) -o testpcre testpcre.o $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) 2>/dev/null && rm testpcre testpcre.o && echo true||echo false)
ifeq ($(PCRE_CHECK), true) ifeq ($(PCRE_CHECK), true)
CFLAGS += -DWITH_PCRE CFLAGS += -DWITH_PCRE
PCRE_OBJS = pcre$(OBJSUFFICS) PCRE_OBJS = pcre$(OBJSUFFICS)
PCRE_LIBS = $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) PCRE_LIBS = $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX)
endif endif
PAM_CHECK ?= $(shell echo "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false) PAM_CHECK ?= $(shell printf "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d \\\\ | $(CC) -x c $(CFLAGS) -o testpam.o - 2>/dev/null && $(CC) $(LDFLAGS) -o testpam testpam.o -lpam 2>/dev/null && rm testpam testpam.o && echo true||echo false)
ifeq ($(PAM_CHECK), true) ifeq ($(PAM_CHECK), true)
PLUGINS += PamAuth PLUGINS += PamAuth
endif endif

View File

@ -47,14 +47,14 @@ ifeq ($(LIBSTATIC), true)
STATIC_SUFFIX = -Wl,-Bdynamic STATIC_SUFFIX = -Wl,-Bdynamic
ZLIB = -lz ZLIB = -lz
endif endif
WOLFSSL_CHECK = $(shell echo "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) -o testwssl - 2>/dev/null && rm testwssl && echo true||echo false) WOLFSSL_CHECK = $(shell printf "\#include <wolfssl/options.h>\\n\#include <wolfssl/openssl/ssl.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) -o testwssl - 2>/dev/null && rm testwssl && echo true||echo false)
ifeq ($(WOLFSSL_CHECK), true) ifeq ($(WOLFSSL_CHECK), true)
LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) -lws2_32 LIBS += $(STATIC_PREFIX) -lwolfssl $(STATIC_SUFFIX) -lws2_32
CFLAGS += -DWITH_SSL -DWITH_WOLFSSL CFLAGS += -DWITH_SSL -DWITH_WOLFSSL
SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS) SSL_OBJS = ssllib$(OBJSUFFICS) ssl$(OBJSUFFICS)
ZLIB := ZLIB :=
else else
OPENSSL_CHECK = $(shell echo "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) $(STATIC_PREFIX) $(ZLIB) -l crypto -l ssl $(STATIC_SUFFIX) -o testssl - 2>/dev/null && rm testssl && echo true||echo false) OPENSSL_CHECK = $(shell printf "\#include <openssl/ssl.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) $(STATIC_PREFIX) $(ZLIB) -l crypto -l ssl $(STATIC_SUFFIX) -o testssl - 2>/dev/null && rm testssl && echo true||echo false)
ifeq ($(OPENSSL_CHECK), true) ifeq ($(OPENSSL_CHECK), true)
LIBS += $(STATIC_PREFIX) $(ZLIB) -l crypto -l ssl $(STATIC_SUFFIX) -lcrypt32 LIBS += $(STATIC_PREFIX) $(ZLIB) -l crypto -l ssl $(STATIC_SUFFIX) -lcrypt32
CFLAGS += -DWITH_SSL CFLAGS += -DWITH_SSL
@ -63,11 +63,11 @@ else
ZLIB := ZLIB :=
endif endif
endif endif
PAM_CHECK = $(shell echo "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) -l pam -o testpam - 2>/dev/null && rm testpam && echo true||echo false) PAM_CHECK = $(shell printf "\#include <security/pam_appl.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) -l pam -o testpam - 2>/dev/null && rm testpam && echo true||echo false)
ifeq ($(PAM_CHECK), true) ifeq ($(PAM_CHECK), true)
PLUGINS += PamAuth PLUGINS += PamAuth
endif endif
PCRE_CHECK = $(shell echo "\#define PCRE2_CODE_UNIT_WIDTH 8\\n#include <pcre2.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) -o testpcre - 2>/dev/null && rm testpcre && echo true||echo false) PCRE_CHECK = $(shell printf "\#define PCRE2_CODE_UNIT_WIDTH 8\\n#include <pcre2.h>\\n int main(){return 0;}" | tr -d '\\\\' | $(CC) -x c $(CFLAGS) $(LDFLAGS) $(STATIC_PREFIX) -lpcre2-8 $(STATIC_SUFFIX) -o testpcre - 2>/dev/null && rm testpcre && echo true||echo false)
ifeq ($(PCRE_CHECK), true) ifeq ($(PCRE_CHECK), true)
CFLAGS += -DWITH_PCRE CFLAGS += -DWITH_PCRE
PCRE_OBJS = pcre$(OBJSUFFICS) PCRE_OBJS = pcre$(OBJSUFFICS)

View File

@ -6,13 +6,52 @@
### Branches ### Branches
- **Master** (stable) branch - 3proxy 0.9 - **Master** (stable) branch - 3proxy 1.0
- **Devel** branch - 3proxy 10 (don't use it) - **0.9** (LTS) branch - 3proxy 0.9 maintenance branch, this branch
- **Devel** branch - 3proxy 2.0-devel (don't use it)
### Binaries (deb / rpm / Windows zip) ### Binaries (deb / rpm / Windows zip)
https://github.com/3proxy/3proxy/releases https://github.com/3proxy/3proxy/releases
### Package repository (apt / dnf)
Signed apt and dnf repositories are published at https://3proxy.org/repo/ in
two channels: `lts` (0.9 branch) and `current` (master).
Debian 12 and Ubuntu 22.04 or newer:
```
sudo curl -fsSL https://3proxy.org/repo/3proxy-release-key.asc \
-o /usr/share/keyrings/3proxy.asc
sudo tee /etc/apt/sources.list.d/3proxy.sources <<EOF
Types: deb
URIs: https://3proxy.org/repo/deb
Suites: lts
Components: main
Signed-By: /usr/share/keyrings/3proxy.asc
EOF
sudo apt update && sudo apt install 3proxy
```
AlmaLinux, RHEL, Rocky and CentOS Stream 8, 9 and 10:
```
sudo tee /etc/yum.repos.d/3proxy.repo <<EOF
[3proxy]
name=3proxy
baseurl=https://3proxy.org/repo/rpm/lts/el\$releasever/\$basearch/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://3proxy.org/repo/3proxy-release-key.asc
EOF
sudo dnf install 3proxy
```
Both the packages and the repository metadata are signed. See
https://3proxy.org/repo/ for the `current` channel and for release key details.
### Docker images ### Docker images
https://hub.docker.com/r/3proxy/3proxy https://hub.docker.com/r/3proxy/3proxy
@ -29,9 +68,9 @@ Documentation (man pages and HTML) available with download, on https://3proxy.or
## Docker images ## Docker images
3 docker configurations are provided, default (full) also tagged as `:latest`, `:busybox` and `:minimal`, all refer to newest stable version. Except busybox, images are distroless and contain only binaries, you can not sh inside the container. `:busybox` contains busybox shell. 3 docker configurations are provided, default (full) also tagged as `:lts`, `:lts-busybox` and `:lts-minimal`, all refer to newest 0.9 LTS version. Images built from this branch use the `lts` tags, images built from the master branch use `:latest`, `:busybox` and `:minimal`. Use the `lts` tags to stay on the 0.9 branch, use a version tag (e.g. `:0.9.9`) to pin an exact version. Except busybox, images are distroless and contain only binaries, you can not sh inside the container. `:lts-busybox` contains busybox shell.
### Default image (`:latest`): ### Default image (`:lts`):
Full installation requires to mount /etc/3proxy/3proxy.cfg files. Full installation requires to mount /etc/3proxy/3proxy.cfg files.
@ -42,7 +81,7 @@ echo "log
nserver 8.8.8.8 nserver 8.8.8.8
nscache 65536 nscache 65536
proxy -p3129" | docker config create 3proxy proxy -p3129" | docker config create 3proxy
docker run --read-only -p 3129:3129 --config source=3proxy,target=/etc/3proxy/3proxy.cfg --name 3proxy.full docker.io/3proxy/3proxy docker run --read-only -p 3129:3129 --config source=3proxy,target=/etc/3proxy/3proxy.cfg --name 3proxy.full docker.io/3proxy/3proxy:lts
``` ```
`podman` does not support `config` as above. `podman` does not support `config` as above.
@ -60,13 +99,13 @@ podman run --read-only -p 3129:3129 -v /path/to/local/config/directory/3proxy.cf
use `log` without pathname in config to log to stdout. use `log` without pathname in config to log to stdout.
plugins are located in /usr/local/3proxy/libexec (/libexec for chroot config) and since 0.9.6 symlinked by /lib and /lib64 in both chroot and non-chroot configurations, so no full path is required in `plugin` command. Use e.g. `plugin SSLPlugin.ls.so ssl_plugin`. SSLPlugin is supported since 0.9.6. Some proxy types (e.g. SOCKSv5 UDPASSCOC, SOCKSv5 BIND functionality, ftp proxy) require access to ephemeral port, you may use e.g. -`-network host` mode or `-P` for `docker run`. plugins are located in /usr/local/3proxy/libexec (/libexec for chroot config) and since 0.9.6 symlinked by /lib and /lib64 in both chroot and non-chroot configurations, so no full path is required in `plugin` command. Use e.g. `plugin SSLPlugin.ls.so ssl_plugin`. SSLPlugin is supported since 0.9.6. Some proxy types (e.g. SOCKSv5 UDPASSCOC, SOCKSv5 BIND functionality, ftp proxy) require access to ephemeral port, you may use e.g. -`-network host` mode or `-P` for `docker run`.
since 0.9.6 images are distroless (except :busybox) it's recommended to use with read only file system, there are no benefits from chroot. For compatibility, you still can use chroot installation by mounting directory with 3proxy.cfg to /usr/local/3proxy/config. since 0.9.6 images are distroless (except :lts-busybox) it's recommended to use with read only file system, there are no benefits from chroot. For compatibility, you still can use chroot installation by mounting directory with 3proxy.cfg to /usr/local/3proxy/config.
### Busybox image (`:busybox`): ### Busybox image (`:lts-busybox`):
`full` with busybox added, to allow `sh` and few more commands like `sed` inside container. All libraries are in /lib, so chroot configuration can not use plugins. `full` with busybox added, to allow `sh` and few more commands like `sed` inside container. All libraries are in /lib, so chroot configuration can not use plugins.
### Interactive `:minimal` image: ### Interactive `:lts-minimal` image:
Dockerfile for "interactive" minimal 3proxy execution, no configuration mounting is required, configuration Dockerfile for "interactive" minimal 3proxy execution, no configuration mounting is required, configuration
is accepted from stdin. Use `end` command to indicate the end of configuration. Use `log` for stdout logging. is accepted from stdin. Use `end` command to indicate the end of configuration. Use `log` for stdout logging.
@ -76,7 +115,7 @@ since 0.9.6 images are distroless (except :busybox) it's recommended to use with
Run example: Run example:
`docker run --read-only -i -p 3129:3129 --name 3proxy docker.io/3proxy/3proxy:minimal` `docker run --read-only -i -p 3129:3129 --name 3proxy docker.io/3proxy/3proxy:lts-minimal`
or or
`docker start -ai 3proxy` to start existing container `docker start -ai 3proxy` to start existing container
@ -92,7 +131,7 @@ end
Some proxy types (e.g. SOCKSv5 UDPASSCOC, SOCKSv5 BIND functionality, ftp proxy) require access to ephemeral port, you may use e.g. `--network host` mode or `-P` to `docker run`. Some proxy types (e.g. SOCKSv5 UDPASSCOC, SOCKSv5 BIND functionality, ftp proxy) require access to ephemeral port, you may use e.g. `--network host` mode or `-P` to `docker run`.
`:minimal` without version specified uses current stable version. `:lts-minimal` without version specified uses current 0.9 LTS version.
## Building and installation ## Building and installation

View File

@ -1 +1 @@
0.9.9 0.9.9.0

View File

@ -12,3 +12,53 @@
Report to 3proxy@3proxy.org or via [GitHub security reporting](https://github.com/3proxy/3proxy/security) Report to 3proxy@3proxy.org or via [GitHub security reporting](https://github.com/3proxy/3proxy/security)
For High/Critical patched version is released within 2 weeks For High/Critical patched version is released within 2 weeks
## Verifying downloads
Release binaries are published with SHA256 checksums, an OpenPGP signature and
a GitHub build provenance attestation.
The release signing key is `3proxy-release-key.asc` in the root of this
repository, an RSA-4096 key:
```
pub rsa4096 2026-08-21 [SC]
FC12 2144 99FC C7BA 1CFF 6CDC 0312 384E 3A73 940B
uid 3proxy release signing <3proxy@3proxy.org>
```
Import it once:
```
gpg --import 3proxy-release-key.asc
```
Checksums and the checksum file signature:
```
gpg --verify SHA256SUMS-x86_64.asc SHA256SUMS-x86_64
sha256sum -c SHA256SUMS-x86_64
```
RPM packages are signed, the signature is checked by rpm itself:
```
sudo rpm --import 3proxy-release-key.asc
rpm -K 3proxy-0.9.9.x86_64.rpm
```
DEB packages are published with a detached signature:
```
gpg --verify 3proxy-0.9.9.x86_64.deb.asc 3proxy-0.9.9.x86_64.deb
```
Build provenance (which workflow, commit and runner produced the file) is
verified with the GitHub CLI:
```
gh attestation verify 3proxy-0.9.9.x86_64.rpm --owner 3proxy
gh attestation verify oci://docker.io/3proxy/3proxy:lts --owner 3proxy
```
Windows binaries are Authenticode signed in addition to the above.

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
3proxy (0.9.9.0-1) buster; urgency=medium
*3proxy 0.9.9.0 initial build
-- z3APA3A <3apa3a@3proxy.org> Thu, 20 Aug 2026 19:12:35 +0300
3proxy (0.9.9-1) buster; urgency=medium 3proxy (0.9.9-1) buster; urgency=medium
*3proxy 0.9.9 initial build *3proxy 0.9.9 initial build

View File

@ -1,5 +1,5 @@
Name: 3proxy Name: 3proxy
Version: 0.9.9 Version: 0.9.9.0
Release: 1%{?dist} Release: 1%{?dist}
Summary: 3proxy tiny proxy server Summary: 3proxy tiny proxy server
License: GPL/LGPL/Apache/BSD License: GPL/LGPL/Apache/BSD
@ -9,6 +9,9 @@ Prefix: %{_prefix}
Packager: z3APA3A Packager: z3APA3A
Source: https://github.com/%{packager}/%{name}/archive/%{version}.tar.gz Source: https://github.com/%{packager}/%{name}/archive/%{version}.tar.gz
%global debug_package %{nil}
%global __requires_exclude ^/(usr/)?bin/3proxy$
%description %description
3proxy is lightweight yet powerful proxy server 3proxy is lightweight yet powerful proxy server

View File

@ -1,5 +1,5 @@
#ifndef VERSION #ifndef VERSION
#define VERSION "3proxy-0.9.9" #define VERSION "3proxy-0.9.9.0"
#endif #endif
#ifndef BUILDDATE #ifndef BUILDDATE
#define BUILDDATE "" #define BUILDDATE ""
@ -8,7 +8,7 @@
#define SUBMAJOR3PROXY 9 #define SUBMAJOR3PROXY 9
#define MINOR3PROXY 9 #define MINOR3PROXY 9
#define SUBMINOR3PROXY 0 #define SUBMINOR3PROXY 0
#define RELEASE3PROXY "3proxy-0.9.9(" BUILDDATE ")\0" #define RELEASE3PROXY "3proxy-0.9.9.0(" BUILDDATE ")\0"
#ifndef YEAR3PROXY #ifndef YEAR3PROXY
#define YEAR3PROXY "2026" #define YEAR3PROXY "2026"
#endif #endif