Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rebase to 3.21 #526

Merged
merged 7 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 25 additions & 8 deletions .github/workflows/external_trigger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,30 @@ jobs:
--header "Accept: application/vnd.oci.image.index.v1+json" \
--header "Authorization: Bearer ${token}" \
"https://ghcr.io/v2/${image}/manifests/${tag}")
multidigest=$(jq -r ".manifests[] | select(.platform.architecture == \"amd64\").digest?" <<< "${multidigest}")
digest=$(curl -s \
--header "Accept: application/vnd.docker.distribution.manifest.v2+json" \
--header "Accept: application/vnd.oci.image.manifest.v1+json" \
--header "Authorization: Bearer ${token}" \
"https://ghcr.io/v2/${image}/manifests/${multidigest}" \
| jq -r '.config.digest')
if jq -e '.layers // empty' <<< "${multidigest}" >/dev/null 2>&1; then
# If there's a layer element it's a single-arch manifest so just get that digest
digest=$(jq -r '.config.digest' <<< "${multidigest}")
else
# Otherwise it's multi-arch or has manifest annotations
if jq -e '.manifests[]?.annotations // empty' <<< "${multidigest}" >/dev/null 2>&1; then
# Check for manifest annotations and delete if found
multidigest=$(jq 'del(.manifests[] | select(.annotations))' <<< "${multidigest}")
fi
if [[ $(jq '.manifests | length' <<< "${multidigest}") -gt 1 ]]; then
# If there's still more than one digest, it's multi-arch
multidigest=$(jq -r ".manifests[] | select(.platform.architecture == \"amd64\").digest?" <<< "${multidigest}")
else
# Otherwise it's single arch
multidigest=$(jq -r ".manifests[].digest?" <<< "${multidigest}")
fi
if digest=$(curl -s \
--header "Accept: application/vnd.docker.distribution.manifest.v2+json" \
--header "Accept: application/vnd.oci.image.manifest.v1+json" \
--header "Authorization: Bearer ${token}" \
"https://ghcr.io/v2/${image}/manifests/${multidigest}"); then
digest=$(jq -r '.config.digest' <<< "${digest}");
fi
fi
image_info=$(curl -sL \
--header "Authorization: Bearer ${token}" \
"https://ghcr.io/v2/${image}/blobs/${digest}")
Expand Down Expand Up @@ -92,7 +109,7 @@ jobs:
else
printf "\n## Trigger new build\n\n" >> $GITHUB_STEP_SUMMARY
echo "New version \`${EXT_RELEASE}\` found; old version was \`${IMAGE_VERSION}\`. Triggering new build" >> $GITHUB_STEP_SUMMARY
if "${artifacts_found}" == "true" ]]; then
if [[ "${artifacts_found}" == "true" ]]; then
echo "All artifacts seem to be uploaded." >> $GITHUB_STEP_SUMMARY
fi
response=$(curl -iX POST \
Expand Down
27 changes: 22 additions & 5 deletions .github/workflows/package_trigger_scheduler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,26 @@ jobs:
fi
printf "\n## Evaluating \`%s\`\n\n" ${br} >> $GITHUB_STEP_SUMMARY
JENKINS_VARS=$(curl -sX GET https://raw.githubusercontent.com/linuxserver/docker-swag/${br}/jenkins-vars.yml)
if [[ "${br}" == $(yq -r '.ls_branch' <<< "${JENKINS_VARS}") ]]; then
if ! curl -sfX GET https://raw.githubusercontent.com/linuxserver/docker-swag/${br}/Jenkinsfile >/dev/null 2>&1; then
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
echo "> No Jenkinsfile found. Branch is either deprecated or is an early dev branch." >> $GITHUB_STEP_SUMMARY
skipped_branches="${skipped_branches}${br} "
elif [[ "${br}" == $(yq -r '.ls_branch' <<< "${JENKINS_VARS}") ]]; then
echo "Branch appears to be live; checking workflow." >> $GITHUB_STEP_SUMMARY
if [[ $(yq -r '.skip_package_check' <<< "${JENKINS_VARS}") == "true" ]]; then
README_VARS=$(curl -sX GET https://raw.githubusercontent.com/linuxserver/docker-swag/${br}/readme-vars.yml)
if [[ $(yq -r '.project_deprecation_status' <<< "${README_VARS}") == "true" ]]; then
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
echo "> Branch appears to be deprecated; skipping trigger." >> $GITHUB_STEP_SUMMARY
skipped_branches="${skipped_branches}${br} "
elif [[ $(yq -r '.skip_package_check' <<< "${JENKINS_VARS}") == "true" ]]; then
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
echo "> Skipping branch ${br} due to \`skip_package_check\` being set in \`jenkins-vars.yml\`." >> $GITHUB_STEP_SUMMARY
skipped_branches="${skipped_branches}${br} "
elif grep -q "^swag_${br}" <<< "${SKIP_PACKAGE_TRIGGER}"; then
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
echo "> Github organizational variable \`SKIP_PACKAGE_TRIGGER\` contains \`swag_${br}\`; skipping trigger." >> $GITHUB_STEP_SUMMARY
skipped_branches="${skipped_branches}${br} "
elif [ $(curl -s https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-swag/job/${br}/lastBuild/api/json | jq -r '.building') == "true" ]; then
elif [ $(curl -s https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-swag/job/${br}/lastBuild/api/json | jq -r '.building' 2>/dev/null) == "true" ]; then
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
echo "> There already seems to be an active build on Jenkins; skipping package trigger for ${br}" >> $GITHUB_STEP_SUMMARY
skipped_branches="${skipped_branches}${br} "
Expand All @@ -49,18 +58,26 @@ jobs:
response=$(curl -iX POST \
https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-swag/job/${br}/buildWithParameters?PACKAGE_CHECK=true \
--user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} | grep -i location | sed "s|^[L|l]ocation: \(.*\)|\1|")
if [[ -z "${response}" ]]; then
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
echo "> Jenkins build could not be triggered. Skipping branch."
continue
fi
echo "Jenkins [job queue url](${response%$'\r'})" >> $GITHUB_STEP_SUMMARY
echo "Sleeping 10 seconds until job starts" >> $GITHUB_STEP_SUMMARY
sleep 10
buildurl=$(curl -s "${response%$'\r'}api/json" | jq -r '.executable.url')
buildurl="${buildurl%$'\r'}"
echo "Jenkins job [build url](${buildurl})" >> $GITHUB_STEP_SUMMARY
echo "Attempting to change the Jenkins job description" >> $GITHUB_STEP_SUMMARY
curl -iX POST \
if ! curl -ifX POST \
"${buildurl}submitDescription" \
--user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} \
--data-urlencode "description=GHA package trigger https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
--data-urlencode "Submit=Submit"
--data-urlencode "Submit=Submit"; then
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
echo "> Unable to change the Jenkins job description."
fi
sleep 20
fi
else
Expand Down
8 changes: 4 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1

FROM ghcr.io/linuxserver/baseimage-alpine-nginx:3.20
FROM ghcr.io/linuxserver/baseimage-alpine-nginx:3.21

# set version label
ARG BUILD_DATE
Expand Down Expand Up @@ -88,7 +88,7 @@ RUN \
pip install -U --no-cache-dir \
pip \
wheel && \
pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.20/ \
pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.21/ \
certbot==${CERTBOT_VERSION} \
certbot-dns-acmedns \
certbot-dns-aliyun \
Expand Down Expand Up @@ -150,9 +150,9 @@ RUN \
rm -f /etc/nginx/conf.d/stream.conf && \
echo "**** correct ip6tables legacy issue ****" && \
rm \
/sbin/ip6tables && \
/usr/sbin/ip6tables && \
ln -s \
/sbin/ip6tables-nft /sbin/ip6tables && \
/usr/sbin/ip6tables-nft /usr/sbin/ip6tables && \
echo "**** remove unnecessary fail2ban filters ****" && \
rm \
/etc/fail2ban/jail.d/alpine-ssh.conf && \
Expand Down
8 changes: 4 additions & 4 deletions Dockerfile.aarch64
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1

FROM ghcr.io/linuxserver/baseimage-alpine-nginx:arm64v8-3.20
FROM ghcr.io/linuxserver/baseimage-alpine-nginx:arm64v8-3.21

# set version label
ARG BUILD_DATE
Expand Down Expand Up @@ -88,7 +88,7 @@ RUN \
pip install -U --no-cache-dir \
pip \
wheel && \
pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.20/ \
pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.21/ \
certbot==${CERTBOT_VERSION} \
certbot-dns-acmedns \
certbot-dns-aliyun \
Expand Down Expand Up @@ -150,9 +150,9 @@ RUN \
rm -f /etc/nginx/conf.d/stream.conf && \
echo "**** correct ip6tables legacy issue ****" && \
rm \
/sbin/ip6tables && \
/usr/sbin/ip6tables && \
ln -s \
/sbin/ip6tables-nft /sbin/ip6tables && \
/usr/sbin/ip6tables-nft /usr/sbin/ip6tables && \
echo "**** remove unnecessary fail2ban filters ****" && \
rm \
/etc/fail2ban/jail.d/alpine-ssh.conf && \
Expand Down
20 changes: 13 additions & 7 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ pipeline {
--label \"org.opencontainers.image.title=Swag\" \
--label \"org.opencontainers.image.description=SWAG - Secure Web Application Gateway (formerly known as letsencrypt, no relation to Let's Encrypt™) sets up an Nginx webserver and reverse proxy with php support and a built-in certbot client that automates free SSL server certificate generation and renewal processes (Let's Encrypt and ZeroSSL). It also contains fail2ban for intrusion prevention.\" \
--no-cache --pull -t ${IMAGE}:${META_TAG} --platform=linux/amd64 \
--provenance=false --sbom=false --builder=container --load \
--provenance=true --sbom=true --builder=container --load \
--build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ."
sh '''#! /bin/bash
set -e
Expand Down Expand Up @@ -604,7 +604,9 @@ pipeline {
for i in "${CACHE[@]}"; do
docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} &
done
wait
for p in $(jobs -p); do
wait "$p" || { echo "job $p failed" >&2; exit 1; }
done
fi
'''
}
Expand Down Expand Up @@ -639,7 +641,7 @@ pipeline {
--label \"org.opencontainers.image.title=Swag\" \
--label \"org.opencontainers.image.description=SWAG - Secure Web Application Gateway (formerly known as letsencrypt, no relation to Let's Encrypt™) sets up an Nginx webserver and reverse proxy with php support and a built-in certbot client that automates free SSL server certificate generation and renewal processes (Let's Encrypt and ZeroSSL). It also contains fail2ban for intrusion prevention.\" \
--no-cache --pull -t ${IMAGE}:amd64-${META_TAG} --platform=linux/amd64 \
--provenance=false --sbom=false --builder=container --load \
--provenance=true --sbom=true --builder=container --load \
--build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ."
sh '''#! /bin/bash
set -e
Expand Down Expand Up @@ -668,7 +670,9 @@ pipeline {
for i in "${CACHE[@]}"; do
docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} &
done
wait
for p in $(jobs -p); do
wait "$p" || { echo "job $p failed" >&2; exit 1; }
done
fi
'''
}
Expand Down Expand Up @@ -696,7 +700,7 @@ pipeline {
--label \"org.opencontainers.image.title=Swag\" \
--label \"org.opencontainers.image.description=SWAG - Secure Web Application Gateway (formerly known as letsencrypt, no relation to Let's Encrypt™) sets up an Nginx webserver and reverse proxy with php support and a built-in certbot client that automates free SSL server certificate generation and renewal processes (Let's Encrypt and ZeroSSL). It also contains fail2ban for intrusion prevention.\" \
--no-cache --pull -f Dockerfile.aarch64 -t ${IMAGE}:arm64v8-${META_TAG} --platform=linux/arm64 \
--provenance=false --sbom=false --builder=container --load \
--provenance=true --sbom=true --builder=container --load \
--build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ."
sh '''#! /bin/bash
set -e
Expand Down Expand Up @@ -725,7 +729,9 @@ pipeline {
for i in "${CACHE[@]}"; do
docker push ${i}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} &
done
wait
for p in $(jobs -p); do
wait "$p" || { echo "job $p failed" >&2; exit 1; }
done
fi
'''
}
Expand Down Expand Up @@ -968,7 +974,7 @@ pipeline {
echo '{"tag_name":"'${META_TAG}'",\
"target_commitish": "master",\
"name": "'${META_TAG}'",\
"body": "**CI Report:**\\n\\n'${CI_URL:-N/A}'\\n\\n**LinuxServer Changes:**\\n\\n'${LS_RELEASE_NOTES}'\\n\\n**PIP Changes:**\\n\\n' > start
"body": "**CI Report:**\\n\\n'${CI_URL:-N/A}'\\n\\n**LinuxServer Changes:**\\n\\n'${LS_RELEASE_NOTES}'\\n\\n**Remote Changes:**\\n\\n' > start
printf '","draft": false,"prerelease": false}' >> releasebody.json
paste -d'\\0' start releasebody.json > releasebody.json.done
curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/releases -d @releasebody.json.done'''
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,15 @@ This will *ask* Google et al not to index and list your site. Be careful with th

Please follow the instructions [on this blog post](https://www.linuxserver.io/blog/2020-08-21-introducing-swag#migrate).

## Read-Only Operation

This image can be run with a read-only container filesystem. For details please [read the docs](https://docs.linuxserver.io/misc/read-only/).

### Caveats

* `/tmp` must be mounted to tmpfs
* fail2ban will not be available

## Usage

To help you get started creating a container from this image you can either use docker-compose or the docker cli.
Expand Down Expand Up @@ -180,6 +189,7 @@ services:
- ONLY_SUBDOMAINS=false #optional
- EXTRA_DOMAINS= #optional
- STAGING=false #optional
- DISABLE_F2B= #optional
volumes:
- /path/to/swag/config:/config
ports:
Expand Down Expand Up @@ -207,6 +217,7 @@ docker run -d \
-e ONLY_SUBDOMAINS=false `#optional` \
-e EXTRA_DOMAINS= `#optional` \
-e STAGING=false `#optional` \
-e DISABLE_F2B= `#optional` \
-p 443:443 \
-p 80:80 `#optional` \
-v /path/to/swag/config:/config \
Expand Down Expand Up @@ -235,7 +246,9 @@ Containers are configured using parameters passed at runtime (such as those abov
| `-e ONLY_SUBDOMAINS=false` | If you wish to get certs only for certain subdomains, but not the main domain (main domain may be hosted on another machine and cannot be validated), set this to `true` |
| `-e EXTRA_DOMAINS=` | Additional fully qualified domain names (comma separated, no spaces) ie. `example.net,subdomain.example.net,*.example.org` |
| `-e STAGING=false` | Set to `true` to retrieve certs in staging mode. Rate limits will be much higher, but the resulting cert will not pass the browser's security test. Only to be used for testing purposes. |
| `-e DISABLE_F2B=` | Set to `true` to disable the Fail2ban service in the container, if you're already running it elsewhere or using a different IPS. |
| `-v /config` | Persistent config files |
| `--read-only=true` | Run container with a read-only filesystem. Please [read the docs](https://docs.linuxserver.io/misc/read-only/). |
| `--cap-add=NET_ADMIN` | Required for fail2Ban to be able to modify iptables rules. |

### Portainer notice
Expand Down Expand Up @@ -404,6 +417,7 @@ Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64

## Versions

* **17.12.24:** - Rebase to Alpine 3.21.
* **21.10.24:** - Fix naming issue with Dynu plugin. If you are using Dynu, please make sure your credentials are set in /config/dns-conf/dynu.ini and your DNSPLUGIN variable is set to dynu (not dynudns).
* **30.08.24:** - Fix zerossl cert revocation.
* **24.07.14:** - Rebase to Alpine 3.20. Remove deprecated Google Domains certbot plugin. Existing users should update their nginx confs to avoid http2 deprecation warnings.
Expand Down
6 changes: 6 additions & 0 deletions readme-vars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,14 @@ opt_param_env_vars:
- {env_var: "ONLY_SUBDOMAINS", env_value: "false", desc: "If you wish to get certs only for certain subdomains, but not the main domain (main domain may be hosted on another machine and cannot be validated), set this to `true`"}
- {env_var: "EXTRA_DOMAINS", env_value: "", desc: "Additional fully qualified domain names (comma separated, no spaces) ie. `example.net,subdomain.example.net,*.example.org`"}
- {env_var: "STAGING", env_value: "false", desc: "Set to `true` to retrieve certs in staging mode. Rate limits will be much higher, but the resulting cert will not pass the browser's security test. Only to be used for testing purposes."}
- {env_var: "DISABLE_F2B", env_value: "", desc: "Set to `true` to disable the Fail2ban service in the container, if you're already running it elsewhere or using a different IPS."}
opt_param_usage_include_ports: true
opt_param_ports:
- {external_port: "80", internal_port: "80", port_desc: "HTTP port (required for HTTP validation and HTTP -> HTTPS redirect)"}
readonly_supported: true
readonly_message: |
* `/tmp` must be mounted to tmpfs
* fail2ban will not be available
# application setup block
app_setup_block_enabled: true
app_setup_block: |
Expand Down Expand Up @@ -200,6 +205,7 @@ init_diagram: |
"swag:latest" <- Base Images
# changelog
changelogs:
- {date: "17.12.24:", desc: "Rebase to Alpine 3.21."}
- {date: "21.10.24:", desc: "Fix naming issue with Dynu plugin. If you are using Dynu, please make sure your credentials are set in /config/dns-conf/dynu.ini and your DNSPLUGIN variable is set to dynu (not dynudns)."}
- {date: "30.08.24:", desc: "Fix zerossl cert revocation."}
- {date: "24.07.14:", desc: "Rebase to Alpine 3.20. Remove deprecated Google Domains certbot plugin. Existing users should update their nginx confs to avoid http2 deprecation warnings."}
Expand Down
2 changes: 1 addition & 1 deletion root/app/le-renew.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ echo
echo "<------------------------------------------------->"
echo "cronjob running on $(date)"
echo "Running certbot renew"
certbot renew --non-interactive
certbot renew --non-interactive --config-dir /config/etc/letsencrypt --logs-dir /config/log/letsencrypt --work-dir /tmp/letsencrypt --config /config/etc/letsencrypt/cli.ini
Empty file modified root/defaults/etc/letsencrypt/renewal-hooks/deploy/10-default
100644 → 100755
Empty file.
Empty file modified root/defaults/etc/letsencrypt/renewal-hooks/post/10-nginx
100644 → 100755
Empty file.
Empty file modified root/defaults/etc/letsencrypt/renewal-hooks/pre/10-nginx
100644 → 100755
Empty file.
4 changes: 1 addition & 3 deletions root/defaults/nginx/site-confs/default.conf.sample
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Version 2024/07/16 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/site-confs/default.conf.sample
## Version 2024/12/17 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/site-confs/default.conf.sample

# redirect all traffic to https
server {
Expand Down Expand Up @@ -80,5 +80,3 @@ server {

# enable subdomain method reverse proxy confs
include /config/nginx/proxy-confs/*.subdomain.conf;
# enable proxy cache for auth
proxy_cache_path cache/ keys_zone=auth_cache:10m;
2 changes: 1 addition & 1 deletion root/etc/crontabs/root
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
0 3 * * 6 run-parts /etc/periodic/weekly
0 5 1 * * run-parts /etc/periodic/monthly

8 2 * * * /app/le-renew.sh >> /config/log/letsencrypt/letsencrypt.log 2>&1
8 2 * * * /app/le-renew.sh >> /config/log/letsencrypt/renewal.log 2>&1
Loading
Loading