Skip to content

Commit e56ade7

Browse files
committed
Rebase to 3.21
1 parent 584ca67 commit e56ade7

File tree

17 files changed

+144
-84
lines changed

17 files changed

+144
-84
lines changed

.github/workflows/external_trigger.yml

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,30 @@ jobs:
4848
--header "Accept: application/vnd.oci.image.index.v1+json" \
4949
--header "Authorization: Bearer ${token}" \
5050
"https://ghcr.io/v2/${image}/manifests/${tag}")
51-
multidigest=$(jq -r ".manifests[] | select(.platform.architecture == \"amd64\").digest?" <<< "${multidigest}")
52-
digest=$(curl -s \
53-
--header "Accept: application/vnd.docker.distribution.manifest.v2+json" \
54-
--header "Accept: application/vnd.oci.image.manifest.v1+json" \
55-
--header "Authorization: Bearer ${token}" \
56-
"https://ghcr.io/v2/${image}/manifests/${multidigest}" \
57-
| jq -r '.config.digest')
51+
if jq -e '.layers // empty' <<< "${multidigest}" >/dev/null 2>&1; then
52+
# If there's a layer element it's a single-arch manifest so just get that digest
53+
digest=$(jq -r '.config.digest' <<< "${multidigest}")
54+
else
55+
# Otherwise it's multi-arch or has manifest annotations
56+
if jq -e '.manifests[]?.annotations // empty' <<< "${multidigest}" >/dev/null 2>&1; then
57+
# Check for manifest annotations and delete if found
58+
multidigest=$(jq 'del(.manifests[] | select(.annotations))' <<< "${multidigest}")
59+
fi
60+
if [[ $(jq '.manifests | length' <<< "${multidigest}") -gt 1 ]]; then
61+
# If there's still more than one digest, it's multi-arch
62+
multidigest=$(jq -r ".manifests[] | select(.platform.architecture == \"amd64\").digest?" <<< "${multidigest}")
63+
else
64+
# Otherwise it's single arch
65+
multidigest=$(jq -r ".manifests[].digest?" <<< "${multidigest}")
66+
fi
67+
if digest=$(curl -s \
68+
--header "Accept: application/vnd.docker.distribution.manifest.v2+json" \
69+
--header "Accept: application/vnd.oci.image.manifest.v1+json" \
70+
--header "Authorization: Bearer ${token}" \
71+
"https://ghcr.io/v2/${image}/manifests/${multidigest}"); then
72+
digest=$(jq -r '.config.digest' <<< "${digest}");
73+
fi
74+
fi
5875
image_info=$(curl -sL \
5976
--header "Authorization: Bearer ${token}" \
6077
"https://ghcr.io/v2/${image}/blobs/${digest}")
@@ -92,7 +109,7 @@ jobs:
92109
else
93110
printf "\n## Trigger new build\n\n" >> $GITHUB_STEP_SUMMARY
94111
echo "New version \`${EXT_RELEASE}\` found; old version was \`${IMAGE_VERSION}\`. Triggering new build" >> $GITHUB_STEP_SUMMARY
95-
if "${artifacts_found}" == "true" ]]; then
112+
if [[ "${artifacts_found}" == "true" ]]; then
96113
echo "All artifacts seem to be uploaded." >> $GITHUB_STEP_SUMMARY
97114
fi
98115
response=$(curl -iX POST \

.github/workflows/package_trigger_scheduler.yml

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,26 @@ jobs:
2727
fi
2828
printf "\n## Evaluating \`%s\`\n\n" ${br} >> $GITHUB_STEP_SUMMARY
2929
JENKINS_VARS=$(curl -sX GET https://raw.githubusercontent.com/linuxserver/docker-swag/${br}/jenkins-vars.yml)
30-
if [[ "${br}" == $(yq -r '.ls_branch' <<< "${JENKINS_VARS}") ]]; then
30+
if ! curl -sfX GET https://raw.githubusercontent.com/linuxserver/docker-swag/${br}/Jenkinsfile >/dev/null 2>&1; then
31+
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
32+
echo "> No Jenkinsfile found. Branch is either deprecated or is an early dev branch." >> $GITHUB_STEP_SUMMARY
33+
skipped_branches="${skipped_branches}${br} "
34+
elif [[ "${br}" == $(yq -r '.ls_branch' <<< "${JENKINS_VARS}") ]]; then
3135
echo "Branch appears to be live; checking workflow." >> $GITHUB_STEP_SUMMARY
32-
if [[ $(yq -r '.skip_package_check' <<< "${JENKINS_VARS}") == "true" ]]; then
36+
README_VARS=$(curl -sX GET https://raw.githubusercontent.com/linuxserver/docker-swag/${br}/readme-vars.yml)
37+
if [[ $(yq -r '.project_deprecation_status' <<< "${README_VARS}") == "true" ]]; then
38+
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
39+
echo "> Branch appears to be deprecated; skipping trigger." >> $GITHUB_STEP_SUMMARY
40+
skipped_branches="${skipped_branches}${br} "
41+
elif [[ $(yq -r '.skip_package_check' <<< "${JENKINS_VARS}") == "true" ]]; then
3342
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
3443
echo "> Skipping branch ${br} due to \`skip_package_check\` being set in \`jenkins-vars.yml\`." >> $GITHUB_STEP_SUMMARY
3544
skipped_branches="${skipped_branches}${br} "
3645
elif grep -q "^swag_${br}" <<< "${SKIP_PACKAGE_TRIGGER}"; then
3746
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
3847
echo "> Github organizational variable \`SKIP_PACKAGE_TRIGGER\` contains \`swag_${br}\`; skipping trigger." >> $GITHUB_STEP_SUMMARY
3948
skipped_branches="${skipped_branches}${br} "
40-
elif [ $(curl -s https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-swag/job/${br}/lastBuild/api/json | jq -r '.building') == "true" ]; then
49+
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
4150
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
4251
echo "> There already seems to be an active build on Jenkins; skipping package trigger for ${br}" >> $GITHUB_STEP_SUMMARY
4352
skipped_branches="${skipped_branches}${br} "
@@ -49,18 +58,26 @@ jobs:
4958
response=$(curl -iX POST \
5059
https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-swag/job/${br}/buildWithParameters?PACKAGE_CHECK=true \
5160
--user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} | grep -i location | sed "s|^[L|l]ocation: \(.*\)|\1|")
61+
if [[ -z "${response}" ]]; then
62+
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
63+
echo "> Jenkins build could not be triggered. Skipping branch."
64+
continue
65+
fi
5266
echo "Jenkins [job queue url](${response%$'\r'})" >> $GITHUB_STEP_SUMMARY
5367
echo "Sleeping 10 seconds until job starts" >> $GITHUB_STEP_SUMMARY
5468
sleep 10
5569
buildurl=$(curl -s "${response%$'\r'}api/json" | jq -r '.executable.url')
5670
buildurl="${buildurl%$'\r'}"
5771
echo "Jenkins job [build url](${buildurl})" >> $GITHUB_STEP_SUMMARY
5872
echo "Attempting to change the Jenkins job description" >> $GITHUB_STEP_SUMMARY
59-
curl -iX POST \
73+
if ! curl -ifX POST \
6074
"${buildurl}submitDescription" \
6175
--user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} \
6276
--data-urlencode "description=GHA package trigger https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
63-
--data-urlencode "Submit=Submit"
77+
--data-urlencode "Submit=Submit"; then
78+
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
79+
echo "> Unable to change the Jenkins job description."
80+
fi
6481
sleep 20
6582
fi
6683
else

Dockerfile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# syntax=docker/dockerfile:1
22

3-
FROM ghcr.io/linuxserver/baseimage-alpine-nginx:3.20
3+
FROM cr.spad.uk/linuxserver/baseimage-alpine-nginx:3.21
44

55
# set version label
66
ARG BUILD_DATE
@@ -88,7 +88,7 @@ RUN \
8888
pip install -U --no-cache-dir \
8989
pip \
9090
wheel && \
91-
pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.20/ \
91+
pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.21/ \
9292
certbot==${CERTBOT_VERSION} \
9393
certbot-dns-acmedns \
9494
certbot-dns-aliyun \
@@ -150,9 +150,9 @@ RUN \
150150
rm -f /etc/nginx/conf.d/stream.conf && \
151151
echo "**** correct ip6tables legacy issue ****" && \
152152
rm \
153-
/sbin/ip6tables && \
153+
/usr/sbin/ip6tables && \
154154
ln -s \
155-
/sbin/ip6tables-nft /sbin/ip6tables && \
155+
/usr/sbin/ip6tables-nft /usr/sbin/ip6tables && \
156156
echo "**** remove unnecessary fail2ban filters ****" && \
157157
rm \
158158
/etc/fail2ban/jail.d/alpine-ssh.conf && \

Dockerfile.aarch64

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# syntax=docker/dockerfile:1
22

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

55
# set version label
66
ARG BUILD_DATE
@@ -88,7 +88,7 @@ RUN \
8888
pip install -U --no-cache-dir \
8989
pip \
9090
wheel && \
91-
pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.20/ \
91+
pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.21/ \
9292
certbot==${CERTBOT_VERSION} \
9393
certbot-dns-acmedns \
9494
certbot-dns-aliyun \
@@ -150,9 +150,9 @@ RUN \
150150
rm -f /etc/nginx/conf.d/stream.conf && \
151151
echo "**** correct ip6tables legacy issue ****" && \
152152
rm \
153-
/sbin/ip6tables && \
153+
/usr/sbin/ip6tables && \
154154
ln -s \
155-
/sbin/ip6tables-nft /sbin/ip6tables && \
155+
/usr/sbin/ip6tables-nft /usr/sbin/ip6tables && \
156156
echo "**** remove unnecessary fail2ban filters ****" && \
157157
rm \
158158
/etc/fail2ban/jail.d/alpine-ssh.conf && \

Jenkinsfile

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ pipeline {
575575
--label \"org.opencontainers.image.title=Swag\" \
576576
--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.\" \
577577
--no-cache --pull -t ${IMAGE}:${META_TAG} --platform=linux/amd64 \
578-
--provenance=false --sbom=false --builder=container --load \
578+
--provenance=true --sbom=true --builder=container --load \
579579
--build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ."
580580
sh '''#! /bin/bash
581581
set -e
@@ -604,7 +604,9 @@ pipeline {
604604
for i in "${CACHE[@]}"; do
605605
docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} &
606606
done
607-
wait
607+
for p in $(jobs -p); do
608+
wait "$p" || { echo "job $p failed" >&2; exit 1; }
609+
done
608610
fi
609611
'''
610612
}
@@ -639,7 +641,7 @@ pipeline {
639641
--label \"org.opencontainers.image.title=Swag\" \
640642
--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.\" \
641643
--no-cache --pull -t ${IMAGE}:amd64-${META_TAG} --platform=linux/amd64 \
642-
--provenance=false --sbom=false --builder=container --load \
644+
--provenance=true --sbom=true --builder=container --load \
643645
--build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ."
644646
sh '''#! /bin/bash
645647
set -e
@@ -668,7 +670,9 @@ pipeline {
668670
for i in "${CACHE[@]}"; do
669671
docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} &
670672
done
671-
wait
673+
for p in $(jobs -p); do
674+
wait "$p" || { echo "job $p failed" >&2; exit 1; }
675+
done
672676
fi
673677
'''
674678
}
@@ -696,7 +700,7 @@ pipeline {
696700
--label \"org.opencontainers.image.title=Swag\" \
697701
--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.\" \
698702
--no-cache --pull -f Dockerfile.aarch64 -t ${IMAGE}:arm64v8-${META_TAG} --platform=linux/arm64 \
699-
--provenance=false --sbom=false --builder=container --load \
703+
--provenance=true --sbom=true --builder=container --load \
700704
--build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ."
701705
sh '''#! /bin/bash
702706
set -e
@@ -725,7 +729,9 @@ pipeline {
725729
for i in "${CACHE[@]}"; do
726730
docker push ${i}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} &
727731
done
728-
wait
732+
for p in $(jobs -p); do
733+
wait "$p" || { echo "job $p failed" >&2; exit 1; }
734+
done
729735
fi
730736
'''
731737
}
@@ -968,7 +974,7 @@ pipeline {
968974
echo '{"tag_name":"'${META_TAG}'",\
969975
"target_commitish": "master",\
970976
"name": "'${META_TAG}'",\
971-
"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
977+
"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
972978
printf '","draft": false,"prerelease": false}' >> releasebody.json
973979
paste -d'\\0' start releasebody.json > releasebody.json.done
974980
curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/releases -d @releasebody.json.done'''

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,15 @@ This will *ask* Google et al not to index and list your site. Be careful with th
149149

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

152+
## Read-Only Operation
153+
154+
This image can be run with a read-only container filesystem. For details please [read the docs](https://docs.linuxserver.io/misc/read-only/).
155+
156+
### Caveats
157+
158+
* `/tmp` must be mounted to tmpfs
159+
* fail2ban will not be available
160+
152161
## Usage
153162

154163
To help you get started creating a container from this image you can either use docker-compose or the docker cli.
@@ -236,6 +245,7 @@ Containers are configured using parameters passed at runtime (such as those abov
236245
| `-e EXTRA_DOMAINS=` | Additional fully qualified domain names (comma separated, no spaces) ie. `example.net,subdomain.example.net,*.example.org` |
237246
| `-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. |
238247
| `-v /config` | Persistent config files |
248+
| `--read-only=true` | Run container with a read-only filesystem. Please [read the docs](https://docs.linuxserver.io/misc/read-only/). |
239249
| `--cap-add=NET_ADMIN` | Required for fail2Ban to be able to modify iptables rules. |
240250

241251
### Portainer notice
@@ -404,6 +414,7 @@ Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64
404414

405415
## Versions
406416

417+
* **17.12.24:** - Rebase to Alpine 3.21.
407418
* **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).
408419
* **30.08.24:** - Fix zerossl cert revocation.
409420
* **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.

readme-vars.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ opt_param_env_vars:
4040
opt_param_usage_include_ports: true
4141
opt_param_ports:
4242
- {external_port: "80", internal_port: "80", port_desc: "HTTP port (required for HTTP validation and HTTP -> HTTPS redirect)"}
43+
readonly_supported: true
44+
readonly_message: |
45+
* `/tmp` must be mounted to tmpfs
46+
* fail2ban will not be available
4347
# application setup block
4448
app_setup_block_enabled: true
4549
app_setup_block: |
@@ -200,6 +204,7 @@ init_diagram: |
200204
"swag:latest" <- Base Images
201205
# changelog
202206
changelogs:
207+
- {date: "17.12.24:", desc: "Rebase to Alpine 3.21."}
203208
- {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)."}
204209
- {date: "30.08.24:", desc: "Fix zerossl cert revocation."}
205210
- {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."}

root/app/le-renew.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ echo
66
echo "<------------------------------------------------->"
77
echo "cronjob running on $(date)"
88
echo "Running certbot renew"
9-
certbot renew --non-interactive
9+
certbot renew --non-interactive --config-dir /config/etc/letsencrypt --logs-dir /config/log/letsencrypt --work-dir /tmp/letsencrypt --config /config/etc/letsencrypt/cli.ini

root/defaults/etc/letsencrypt/renewal-hooks/deploy/10-default

100644100755
File mode changed.

root/defaults/etc/letsencrypt/renewal-hooks/post/10-nginx

100644100755
File mode changed.

0 commit comments

Comments
 (0)