mirror of
https://github.com/linuxserver/docker-swag.git
synced 2026-11-06 00:49:24 +09:00
Compare commits
238
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12d8c0329c | ||
|
|
4d08a0d2a4 | ||
|
|
0cc53e2034 | ||
|
|
32921eb45c | ||
|
|
3061855da1 | ||
|
|
fac1559e84 | ||
|
|
8763626dbc | ||
|
|
cf3344e0bd | ||
|
|
d00190cefc | ||
|
|
8d1fefb9a4 | ||
|
|
c29a049eea | ||
|
|
d2533208c6 | ||
|
|
6559a9b1b6 | ||
|
|
c367f03cbc | ||
|
|
32f4947db5 | ||
|
|
1898dc3ede | ||
|
|
7820a40f01 | ||
|
|
9e54158d38 | ||
|
|
ad8764c2f8 | ||
|
|
5189cbfb87 | ||
|
|
be4fdf0d4d | ||
|
|
f0c3932e7e | ||
|
|
d9c0e32416 | ||
|
|
00c7817e50 | ||
|
|
671b9697be | ||
|
|
08592fdb75 | ||
|
|
f86ef34abd | ||
|
|
478c1fa964 | ||
|
|
0b43278151 | ||
|
|
21237325ee | ||
|
|
8bccad2000 | ||
|
|
9bd4e3771e | ||
|
|
55a8c4fa88 | ||
|
|
733910a7a7 | ||
|
|
55a01c005c | ||
|
|
fb016e60ee | ||
|
|
415fbce955 | ||
|
|
84915dcfcf | ||
|
|
05da050b5f | ||
|
|
bc02502e97 | ||
|
|
2c22ce9573 | ||
|
|
0a34712336 | ||
|
|
4e7e4f7fee | ||
|
|
e39c6487f7 | ||
|
|
493982d27e | ||
|
|
1e2b94980c | ||
|
|
b3185a5eff | ||
|
|
e857f808b0 | ||
|
|
62d5e73cbb | ||
|
|
83ab984b17 | ||
|
|
1a8290dec1 | ||
|
|
057bbb5930 | ||
|
|
d6c053dd22 | ||
|
|
883a216247 | ||
|
|
a57ebf0399 | ||
|
|
37b074c528 | ||
|
|
d86d2dbb59 | ||
|
|
25258a2f90 | ||
|
|
88b7c77e02 | ||
|
|
2cea93f9b1 | ||
|
|
a9d1f7f0ee | ||
|
|
d3fe405b46 | ||
|
|
32c26223dd | ||
|
|
60161a3baf | ||
|
|
321837be0d | ||
|
|
c371973f5f | ||
|
|
bc18a403ba | ||
|
|
b104a66e06 | ||
|
|
80bc4b4243 | ||
|
|
7cf7838a87 | ||
|
|
0cb2c16f7d | ||
|
|
36129452e8 | ||
|
|
bb2b29d9c1 | ||
|
|
b7ea5c43ec | ||
|
|
8fbf8ab449 | ||
|
|
6b1745980a | ||
|
|
9c5ae4f09a | ||
|
|
321c7f3295 | ||
|
|
005a68591d | ||
|
|
01bfb62124 | ||
|
|
04ad8386bf | ||
|
|
b409073642 | ||
|
|
1c8a8d004e | ||
|
|
9235e504a1 | ||
|
|
ef520118f5 | ||
|
|
4a4e84d26b | ||
|
|
8c002e6c56 | ||
|
|
ea840fbfbc | ||
|
|
42ba97e46a | ||
|
|
b4b73022db | ||
|
|
9d5ebb6a7a | ||
|
|
7ad019e68d | ||
|
|
59ef2df680 | ||
|
|
db874b2c0f | ||
|
|
6182a75998 | ||
|
|
145c5d84f6 | ||
|
|
1039f2a04c | ||
|
|
156e3ac160 | ||
|
|
e649bd71da | ||
|
|
b54c263769 | ||
|
|
7b11fb9643 | ||
|
|
72d187c734 | ||
|
|
b6752babcd | ||
|
|
6f38cebe04 | ||
|
|
62b3a02aed | ||
|
|
2deac3dac6 | ||
|
|
48cbb269cc | ||
|
|
8489cde7c0 | ||
|
|
a120a68aae | ||
|
|
1674ff4509 | ||
|
|
52707530e2 | ||
|
|
cbf78b31bb | ||
|
|
2fc01f4e21 | ||
|
|
5491278c13 | ||
|
|
4a7daa06ad | ||
|
|
77dc5ff352 | ||
|
|
e834e13141 | ||
|
|
0ab1a76dae | ||
|
|
8b8b491df3 | ||
|
|
7f080d8564 | ||
|
|
3ffa4aaa77 | ||
|
|
bb730cbc72 | ||
|
|
6b609ad159 | ||
|
|
f7a31bb18e | ||
|
|
01a5c0123e | ||
|
|
012b4ac68f | ||
|
|
8961b7e923 | ||
|
|
1e3524f927 | ||
|
|
a2f969a62e | ||
|
|
caaaccb0b3 | ||
|
|
ae11ca79a0 | ||
|
|
9d7c0d6239 | ||
|
|
eb151ebd19 | ||
|
|
4076c6b012 | ||
|
|
8437debed5 | ||
|
|
0f177af593 | ||
|
|
23dd0531f1 | ||
|
|
56d0503cb3 | ||
|
|
9397e9c70f | ||
|
|
e87649ffcd | ||
|
|
e11a8ded00 | ||
|
|
576de0400c | ||
|
|
ad2d99029a | ||
|
|
b8d0c422ab | ||
|
|
07c7399089 | ||
|
|
2d9590691c | ||
|
|
72e5347c3b | ||
|
|
be7016bcc1 | ||
|
|
ccd2464a26 | ||
|
|
fb4ba0deb0 | ||
|
|
7d8332e624 | ||
|
|
0e19ad9d0f | ||
|
|
d9dbcd0756 | ||
|
|
8381b03a05 | ||
|
|
a1efcf3cd4 | ||
|
|
834de14952 | ||
|
|
8353859972 | ||
|
|
f491b59335 | ||
|
|
ca399a7fa2 | ||
|
|
d602e9bccf | ||
|
|
284a8c66f9 | ||
|
|
1905b3c920 | ||
|
|
c9efb531b0 | ||
|
|
26d05580ef | ||
|
|
a2a7292e39 | ||
|
|
5316c58910 | ||
|
|
fa860e1349 | ||
|
|
72f60b132b | ||
|
|
24cf84fd61 | ||
|
|
d4ceeb2f67 | ||
|
|
1282274a1a | ||
|
|
b05df6cf2a | ||
|
|
b96738cdf2 | ||
|
|
2d6a54a526 | ||
|
|
bb78c0f50e | ||
|
|
56ff1d5e19 | ||
|
|
7f9835b43f | ||
|
|
f3ac0dd394 | ||
|
|
0168126729 | ||
|
|
0e55f7b67e | ||
|
|
b52e35e494 | ||
|
|
ef2a5f2077 | ||
|
|
0c910b9a7b | ||
|
|
9ab0f727d0 | ||
|
|
adcdf5d748 | ||
|
|
7a38630c0b | ||
|
|
6b6e7b74b5 | ||
|
|
3b6d0484b9 | ||
|
|
0d952bcee1 | ||
|
|
35deb8f654 | ||
|
|
2ec9bacf0c | ||
|
|
bcbad63147 | ||
|
|
962c2322eb | ||
|
|
dd8fd8ad05 | ||
|
|
b818ae1f58 | ||
|
|
43466fe490 | ||
|
|
3781360d72 | ||
|
|
a01e4aca17 | ||
|
|
b87c9d2886 | ||
|
|
08aa9cc07b | ||
|
|
23e05f1f7a | ||
|
|
f80d14bf8c | ||
|
|
a5f1da0bcf | ||
|
|
7e7e22753c | ||
|
|
9f76c031fe | ||
|
|
2b2ccf9e9a | ||
|
|
54ed99d81a | ||
|
|
a3f72898ff | ||
|
|
8b8d33a81a | ||
|
|
82ba5dd791 | ||
|
|
e7c815c27f | ||
|
|
563ae7e9c5 | ||
|
|
8caf2a1841 | ||
|
|
15a3bc9d2c | ||
|
|
1567416bfb | ||
|
|
f909c85857 | ||
|
|
2992a09e32 | ||
|
|
5a8b8010ee | ||
|
|
586eaa3b4c | ||
|
|
2528e2f027 | ||
|
|
4632ecb91a | ||
|
|
615ccbc589 | ||
|
|
199d0a6707 | ||
|
|
f8171d73ce | ||
|
|
503578a870 | ||
|
|
b4978e40c5 | ||
|
|
ed765dbdc1 | ||
|
|
6fcd946c0a | ||
|
|
c1d1a87a0c | ||
|
|
990c95b7d9 | ||
|
|
d83dc89c84 | ||
|
|
7046e938e0 | ||
|
|
27e2e83f03 | ||
|
|
f11dbcea78 | ||
|
|
07e9ada724 | ||
|
|
ae72916deb | ||
|
|
06b385d25c | ||
|
|
8753119d54 |
No files matched your search
Executable → Regular
File mode changed.
@@ -6,7 +6,7 @@
|
||||
* Read, and fill the Pull Request template
|
||||
* If this is a fix for a typo (in code, documentation, or the README) please file an issue and let us sort it out. We do not need a PR
|
||||
* If the PR is addressing an existing issue include, closes #\<issue number>, in the body of the PR commit message
|
||||
* If you want to discuss changes, you can also bring it up in [#dev-talk](https://discordapp.com/channels/354974912613449730/757585807061155840) in our [Discord server](https://discord.gg/YWrKVTn)
|
||||
* If you want to discuss changes, you can also bring it up in [#dev-talk](https://discordapp.com/channels/354974912613449730/757585807061155840) in our [Discord server](https://linuxserver.io/discord)
|
||||
|
||||
## Common files
|
||||
|
||||
|
||||
Executable → Regular
File mode changed.
Executable → Regular
+3
-3
@@ -1,11 +1,11 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Discord chat support
|
||||
url: https://discord.gg/YWrKVTn
|
||||
url: https://linuxserver.io/discord
|
||||
about: Realtime support / chat with the community and the team.
|
||||
|
||||
- name: Discourse discussion forum
|
||||
url: https://discourse.linuxserver.io
|
||||
- name: Github Discussions
|
||||
url: https://github.com/orgs/linuxserver/discussions
|
||||
about: Post on our community forum.
|
||||
|
||||
- name: Documentation
|
||||
|
||||
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
@@ -3,7 +3,6 @@
|
||||
[linuxserverurl]: https://linuxserver.io
|
||||
[][linuxserverurl]
|
||||
|
||||
|
||||
<!--- Before submitting a pull request please check the following -->
|
||||
|
||||
<!--- If this is a fix for a typo (in code, documentation, or the README) please file an issue and let us sort it out. We do not need a PR -->
|
||||
@@ -12,7 +11,6 @@
|
||||
<!--- You have included links to any files / patches etc your PR may be using in the body of the PR commit message -->
|
||||
<!--- We maintain a changelog of major revisions to the container at the end of readme-vars.yml in the root of this repository, please add your changes there if appropriate -->
|
||||
|
||||
|
||||
<!--- Coding guidelines: -->
|
||||
<!--- 1. Installed packages in the Dockerfiles should be in alphabetical order -->
|
||||
<!--- 2. Changes to Dockerfile should be replicated in Dockerfile.armhf and Dockerfile.aarch64 if applicable -->
|
||||
@@ -21,11 +19,16 @@
|
||||
|
||||
------------------------------
|
||||
|
||||
- [ ] I have read the [contributing](https://github.com/linuxserver/docker-swag/blob/master/.github/CONTRIBUTING.md) guideline and understand that I have made the correct modifications
|
||||
- [ ] I have read the [contributing](https://github.com/linuxserver/docker-swag/blob/master/.github/CONTRIBUTING.md) guideline and understand that I have made the correct modifications
|
||||
|
||||
<!--- LLM disclosure: -->
|
||||
|
||||
- [ ] An LLM assisted me in writing the code or text for this PR
|
||||
- [ ] An LLM agent wrote the code or text for this PR
|
||||
|
||||
------------------------------
|
||||
|
||||
<!--- We welcome all PR’s though this doesn’t guarantee it will be accepted. -->
|
||||
<!--- We welcome all PRs though this doesn’t guarantee it will be accepted. -->
|
||||
|
||||
## Description:
|
||||
<!--- Describe your changes in detail -->
|
||||
@@ -38,6 +41,5 @@
|
||||
<!--- Include details of your testing environment, and the tests you ran to -->
|
||||
<!--- see how your change affects other areas of the code, etc. -->
|
||||
|
||||
|
||||
## Source / References:
|
||||
<!--- Please include any forum posts/github links relevant to the PR -->
|
||||
Executable → Regular
+3
@@ -8,6 +8,9 @@ on:
|
||||
pull_request_review:
|
||||
types: [submitted,edited,dismissed]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
manage-project:
|
||||
permissions:
|
||||
|
||||
Executable → Regular
+3
@@ -4,6 +4,9 @@ on:
|
||||
- cron: '35 15 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
permissions:
|
||||
|
||||
@@ -3,11 +3,14 @@ name: External Trigger Main
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
external-trigger-master:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.1
|
||||
- uses: linuxserver/github-workflows/.github/actions/checkout@v1
|
||||
|
||||
- name: External Trigger
|
||||
if: github.ref == 'refs/heads/master'
|
||||
@@ -15,7 +18,10 @@ jobs:
|
||||
SKIP_EXTERNAL_TRIGGER: ${{ vars.SKIP_EXTERNAL_TRIGGER }}
|
||||
run: |
|
||||
printf "# External trigger for docker-swag\n\n" >> $GITHUB_STEP_SUMMARY
|
||||
if grep -q "^swag_master" <<< "${SKIP_EXTERNAL_TRIGGER}"; then
|
||||
if grep -q "^swag_master_" <<< "${SKIP_EXTERNAL_TRIGGER}"; then
|
||||
echo "> [!NOTE]" >> $GITHUB_STEP_SUMMARY
|
||||
echo "> Github organizational variable \`SKIP_EXTERNAL_TRIGGER\` contains \`swag_master_\`; will skip trigger if version matches." >> $GITHUB_STEP_SUMMARY
|
||||
elif grep -q "^swag_master" <<< "${SKIP_EXTERNAL_TRIGGER}"; then
|
||||
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
|
||||
echo "> Github organizational variable \`SKIP_EXTERNAL_TRIGGER\` contains \`swag_master\`; skipping trigger." >> $GITHUB_STEP_SUMMARY
|
||||
exit 0
|
||||
@@ -25,6 +31,11 @@ jobs:
|
||||
printf "\n## Retrieving external version\n\n" >> $GITHUB_STEP_SUMMARY
|
||||
EXT_RELEASE=$(curl -sL "https://pypi.python.org/pypi/certbot/json" |jq -r '. | .info.version')
|
||||
echo "Type is \`pip_version\`" >> $GITHUB_STEP_SUMMARY
|
||||
if grep -q "^swag_master_${EXT_RELEASE}" <<< "${SKIP_EXTERNAL_TRIGGER}"; then
|
||||
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
|
||||
echo "> Github organizational variable \`SKIP_EXTERNAL_TRIGGER\` matches current external release; skipping trigger." >> $GITHUB_STEP_SUMMARY
|
||||
exit 0
|
||||
fi
|
||||
if [ -z "${EXT_RELEASE}" ] || [ "${EXT_RELEASE}" == "null" ]; then
|
||||
echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY
|
||||
echo "> Can't retrieve external version, exiting" >> $GITHUB_STEP_SUMMARY
|
||||
@@ -35,8 +46,8 @@ jobs:
|
||||
"username": "Github Actions"}' ${{ secrets.DISCORD_WEBHOOK }}
|
||||
exit 1
|
||||
fi
|
||||
EXT_RELEASE=$(echo ${EXT_RELEASE} | sed 's/[~,%@+;:/]//g')
|
||||
echo "External version: \`${EXT_RELEASE}\`" >> $GITHUB_STEP_SUMMARY
|
||||
EXT_RELEASE_SANITIZED=$(echo ${EXT_RELEASE} | sed 's/[~,%@+;:/]//g')
|
||||
echo "Sanitized external version: \`${EXT_RELEASE_SANITIZED}\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Retrieving last pushed version" >> $GITHUB_STEP_SUMMARY
|
||||
image="linuxserver/swag"
|
||||
tag="latest"
|
||||
@@ -92,8 +103,8 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
echo "Last pushed version: \`${IMAGE_VERSION}\`" >> $GITHUB_STEP_SUMMARY
|
||||
if [ "${EXT_RELEASE}" == "${IMAGE_VERSION}" ]; then
|
||||
echo "Version \`${EXT_RELEASE}\` already pushed, exiting" >> $GITHUB_STEP_SUMMARY
|
||||
if [ "${EXT_RELEASE_SANITIZED}" == "${IMAGE_VERSION}" ]; then
|
||||
echo "Sanitized version \`${EXT_RELEASE_SANITIZED}\` already pushed, exiting" >> $GITHUB_STEP_SUMMARY
|
||||
exit 0
|
||||
elif [ $(curl -s https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-swag/job/master/lastBuild/api/json | jq -r '.building') == "true" ]; then
|
||||
echo "New version \`${EXT_RELEASE}\` found; but there already seems to be an active build on Jenkins; exiting" >> $GITHUB_STEP_SUMMARY
|
||||
@@ -108,7 +119,7 @@ jobs:
|
||||
"username": "Github Actions"}' ${{ secrets.DISCORD_WEBHOOK }}
|
||||
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
|
||||
echo "New sanitized version \`${EXT_RELEASE_SANITIZED}\` found; old version was \`${IMAGE_VERSION}\`. Triggering new build" >> $GITHUB_STEP_SUMMARY
|
||||
if [[ "${artifacts_found}" == "true" ]]; then
|
||||
echo "All artifacts seem to be uploaded." >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
@@ -128,7 +139,7 @@ jobs:
|
||||
--data-urlencode "description=GHA external trigger https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
|
||||
--data-urlencode "Submit=Submit"
|
||||
echo "**** Notifying Discord ****"
|
||||
TRIGGER_REASON="A version change was detected for swag tag latest. Old version:${IMAGE_VERSION} New version:${EXT_RELEASE}"
|
||||
TRIGGER_REASON="A version change was detected for swag tag latest. Old version:${IMAGE_VERSION} New version:${EXT_RELEASE_SANITIZED}"
|
||||
curl -X POST -H "Content-Type: application/json" --data '{"avatar_url": "https://cdn.discordapp.com/avatars/354986384542662657/df91181b3f1cf0ef1592fbe18e0962d7.png","embeds": [{"color": 9802903,
|
||||
"description": "**Build Triggered** \n**Reason:** '"${TRIGGER_REASON}"' \n**Build URL:** '"${buildurl}display/redirect"' \n"}],
|
||||
"username": "Github Actions"}' ${{ secrets.DISCORD_WEBHOOK }}
|
||||
|
||||
@@ -5,11 +5,14 @@ on:
|
||||
- cron: '2 * * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
external-trigger-scheduler:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.1
|
||||
- uses: linuxserver/github-workflows/.github/actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: '0'
|
||||
|
||||
|
||||
@@ -2,12 +2,18 @@ name: Greetings
|
||||
|
||||
on: [pull_request_target, issues]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
greeting:
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/first-interaction@v1
|
||||
- uses: linuxserver/github-workflows/.github/actions/first-interaction@v1
|
||||
with:
|
||||
issue-message: 'Thanks for opening your first issue here! Be sure to follow the relevant issue templates, or risk having this issue marked as invalid.'
|
||||
pr-message: 'Thanks for opening this pull request! Be sure to follow the [pull request template](https://github.com/linuxserver/docker-swag/blob/master/.github/PULL_REQUEST_TEMPLATE.md)!'
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue_message: 'Thanks for opening your first issue here! Be sure to follow the relevant issue templates, or risk having this issue marked as invalid.'
|
||||
pr_message: 'Thanks for opening this pull request! Be sure to follow the [pull request template](https://github.com/linuxserver/docker-swag/blob/master/.github/PULL_REQUEST_TEMPLATE.md)!'
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -5,11 +5,14 @@ on:
|
||||
- cron: '1 3 * * 6'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
package-trigger-scheduler:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.1
|
||||
- uses: linuxserver/github-workflows/.github/actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: '0'
|
||||
|
||||
|
||||
Executable → Regular
File mode changed.
@@ -1 +1,2 @@
|
||||
.idea
|
||||
.jenkins-external
|
||||
@@ -0,0 +1,127 @@
|
||||
<!-- DO NOT EDIT THIS FILE MANUALLY -->
|
||||
<!-- This file is globally distributed to all container image projects from https://github.com/linuxserver/docker-jenkins-builder -->
|
||||
# AGENTS.md - LinuxServer.io container image repository
|
||||
|
||||
This file is for AI coding agents (and the humans driving them) working in a LinuxServer.io `docker-*` image repository. Read it fully before proposing or making any change.
|
||||
|
||||
We welcome contributions, including AI-assisted ones, but this is a volunteer-run project that ships 150+ images to millions of users from one shared template. A change that looks like an improvement in isolation is often wrong for us. When this file and your instincts disagree, this file wins. When this file is silent, copy what the surrounding code already does.
|
||||
|
||||
## 1. Decide where the change belongs before writing any code
|
||||
|
||||
Our images are built for **broad consumption**. Every package, env var and init step we add is something we have to maintain, rebuild weekly and support forever, for every user, whether they use it or not. We do not ship Swiss Army Knife images. Work down this list and stop at the first match:
|
||||
|
||||
1. **It is a bug or feature in the application itself** (not in our packaging): it belongs upstream with the app's developers. Do not patch, fork or work around upstream application behaviour in the image.
|
||||
2. **It is an unsupported or reasonable-endeavours environment** (Podman, k8s, Portainer, Watchtower, NFS/SMB `/config`, LXC, custom entrypoints, etc. See the [Support Policy](https://docs.linuxserver.io/misc/support-policy/)): we will not add logic to the image to accommodate it.
|
||||
3. **It only matters to one user or one setup**: use a private [custom script](https://docs.linuxserver.io/general/container-customization/#custom-scripts) in `/custom-cont-init.d` or [custom service](https://docs.linuxserver.io/general/container-customization/#custom-services) in `/custom-services.d`. No PR needed.
|
||||
4. **It is useful to a subset of users** (an extra package, plugin dependency, alternative UI, hardware driver, third party integration, extra daemon, niche toggle): it is a **[Docker Mod](https://github.com/linuxserver/docker-mods)**, not a change to this repo. Check whether one already exists first (`universal-*` mods work on every image; `<image>-*` mods are image specific). If not, create one from the template in the docker-mods repo; each mod lives on its own branch there.
|
||||
5. **The large majority of this image's users benefit, or the image is actually broken**: a PR to this repo is appropriate. Examples: the app fails to start, a new upstream release needs a new runtime dependency, a base image rebase, a permissions bug, a wrong default, incorrect docs in `readme-vars.yml`.
|
||||
|
||||
If you are an agent and the requested change lands on 1-4, **stop and tell your operator** where it belongs instead of writing the PR. "It is only a few lines" is not a reason to put it in the image. If in doubt, a human should open an issue or ask in `#contibutor-discussion` on [Discord](https://linuxserver.io/discord) before doing the work.
|
||||
|
||||
### If it is a mod
|
||||
|
||||
Mods are the pressure valve that keeps the images small. Roughly what lives there today, and therefore does **not** belong in an image: extra OS/pip packages and language toolchains, GPU/hardware driver stacks, alternative web UIs and themes, third party plugins and scanners, integrations with external services (Cloudflare, CrowdSec, Apprise, GeoIP, VPN providers), Docker socket automation, sidecar daemons (redis, tunnels), post-processing scripts, and env-var-to-config-file shims.
|
||||
|
||||
- Follow the README and `template` branch in [docker-mods](https://github.com/linuxserver/docker-mods). A mod is a `FROM scratch` single layer of files extracted over `/` at container start, wired into s6 as `init-mod-<image>-<mod>-*` / `svc-mod-<image>-<mod>` units.
|
||||
- Mods never call `apk`/`apt`/`pip` directly; they append to `/mod-repo-packages-to-install.list` or `/mod-pip-packages-to-install.list` and let the base image do one batched install. Handle Alpine and Ubuntu package names where the mod is universal.
|
||||
- Most good mods are a 10-40 line script. If yours is not, reconsider the approach.
|
||||
- A mod is also the proving ground. If a mod becomes something nearly everyone uses, the team may absorb it into the image later and turn the mod into a no-op with a deprecation notice. That is the team's call, not a reason to skip the mod step.
|
||||
|
||||
## 2. Repository layout and what you must not edit
|
||||
|
||||
| Path | Notes |
|
||||
| --- | --- |
|
||||
| `Dockerfile`, `Dockerfile.aarch64` (sometimes `Dockerfile.riscv64`) | One per architecture. **Any change must be replicated to all of them.** They normally differ only in base image tag and arch strings. |
|
||||
| `root/` | Copied to `/` in the image. s6-overlay v3 services live in `root/etc/s6-overlay/s6-rc.d/`, defaults in `root/defaults/`, one-time upgrade steps in `root/migrations/`. |
|
||||
| `readme-vars.yml` | **Source of truth for the README, docs site, Unraid template and changelog.** Edit this. |
|
||||
| `jenkins-vars.yml` | Build pipeline variables (version detection, CI test settings). Rarely needs touching. |
|
||||
| `README.md` | **Generated. Never edit.** |
|
||||
| `Jenkinsfile` | **Generated. Never edit.** |
|
||||
| `package_versions.txt` | **Generated by CI. Never edit.** |
|
||||
| `.github/**`, `.editorconfig`, `LICENSE`, `AGENTS.md` | **Generated / globally distributed. Never edit here.** Changes go to [docker-jenkins-builder](https://github.com/linuxserver/docker-jenkins-builder). |
|
||||
|
||||
Do not add new top level files or tooling: no `docker-compose.yml`, `Makefile`, test suites, linter configs, pre-commit hooks, extra workflows, `CHANGELOG.md`, `SECURITY.md`, devcontainers, or helper scripts. The repo is intentionally small.
|
||||
|
||||
Some repos have multiple live branches that publish different tags (`nightly`, `develop`, `libtorrentv1`, etc.). Each is maintained independently. Target the branch the change applies to, never merge one into another, and do not assume `master` or `main` is the only one that matters.
|
||||
|
||||
## 3. Code style: keep it simple, match what is there
|
||||
|
||||
The goal of every image is the thinnest possible layer between our base image and the upstream app: install it, drop a sane default config into `/config` on first run, fix permissions, start it. Prefer deleting logic to adding it. The base image already handles PUID/PGID, `UMASK`, `TZ`, `FILE__` secrets, mods, custom scripts, cron and device permissions; never reimplement those.
|
||||
|
||||
### Dockerfiles
|
||||
|
||||
- Base is always `ghcr.io/linuxserver/baseimage-*`. Do not change distro, switch to upstream/distroless images, or add multi-stage complexity unless a maintainer asked for it. Base image rebases are done by the team.
|
||||
- Follow the existing shape exactly: a single `RUN` chain joined with `&& \`, each step announced with `echo "**** doing thing ****"`, two space indentation, a `**** cleanup ****` step at the end removing `/tmp/*` and package caches.
|
||||
- Packages are listed **one per line in alphabetical order**. Build-only dependencies go in a `build-dependencies` virtual package (Alpine) or are purged (Ubuntu) in the same layer.
|
||||
- Do not hardcode or pin the application version. Keep the `if [ -z ${APP_VERSION+x} ]; then ...` pattern; CI supplies the version as a build arg and `jenkins-vars.yml` defines how it is detected.
|
||||
- Do not add `HEALTHCHECK`, `USER`, `ENTRYPOINT` or `CMD`. The base image owns init (`/init`), and the container must start as root unless the image already documents non-root support.
|
||||
- Do not touch the `LABEL maintainer` or `build_version` lines.
|
||||
|
||||
### Init scripts and services (`root/etc/s6-overlay/s6-rc.d/`)
|
||||
|
||||
- Naming: `init-<app>-config` (oneshot) and `svc-<app>` (longrun). Wire them in using empty files in `dependencies.d/` and `user/contents.d/`, exactly as the existing ones do. Oneshots have `type`, `up` (the path to `run`) and `run`. No legacy `cont-init.d` / `services.d`.
|
||||
- Every script starts with:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
```
|
||||
|
||||
- Bash, four space indentation, `[[ ]]` tests, `"${VAR}"` quoting, short lowercase `#` comments. Scripts must be shellcheck clean.
|
||||
- Use `lsiown` instead of `chown`, run the app as `abc` via `s6-setuidgid abc`, and `exec` the final process so s6 supervises it. Keep `s6-notifyoncheck` readiness checks where they exist.
|
||||
- If `readme-vars.yml` has `nonroot_supported: true` or `readonly_supported: true`, every new privileged operation (chown, writing outside `/config` and `/run`, `s6-setuidgid`) must be guarded the same way the existing code does it (`if [[ -z ${LSIO_NON_ROOT_USER} ]]; then` etc.). Do not break those modes.
|
||||
- User data and config live in `/config`. Copy defaults only if the file does not already exist; never overwrite user config on startup. If an existing user's config must change, add a numbered script in `root/migrations/`.
|
||||
- Avoid recursive `lsiown` on large data paths (media, downloads); it makes startup take minutes for real users.
|
||||
- New environment variables are a last resort. If the app can be configured through its own config file or UI, that is the answer. We do not wrap app settings in env vars.
|
||||
|
||||
## 4. Documentation and changelog
|
||||
|
||||
- All user-facing docs changes go in `readme-vars.yml` (`app_setup_block`, `param_env_vars`, `opt_param_*`, etc.). Reference: [`_container-vars-blank`](https://github.com/linuxserver/docker-jenkins-builder/blob/master/ansible/vars/_container-vars-blank).
|
||||
- Any change to a Dockerfile or to anything under `root/` needs a new entry at the **top** of `changelogs:` in `readme-vars.yml`, one short factual line:
|
||||
|
||||
```yaml
|
||||
- {date: "DD.MM.YY:", desc: "Add libfoo to fix thumbnail generation."}
|
||||
```
|
||||
|
||||
- Optionally regenerate the templated files to check your vars render (see the [jenkins-builder README](https://github.com/linuxserver/docker-jenkins-builder#running-against-local-project)), but do not hand edit the output.
|
||||
|
||||
## 5. Test it for real
|
||||
|
||||
A change that has not been built and run is not ready. At minimum:
|
||||
|
||||
```bash
|
||||
docker build --no-cache --pull -t lscr.io/linuxserver/<app>:test .
|
||||
docker run --rm -e PUID=1000 -e PGID=1000 -e TZ=Etc/UTC -v "$(pwd)/testconfig:/config" -p <port>:<port> lscr.io/linuxserver/<app>:test
|
||||
```
|
||||
|
||||
Confirm the init completes (`[ls.io-init] done.`), the app comes up, and it survives a restart against an **existing** `/config`, not just a fresh one. If you touched the aarch64 Dockerfile with anything arch specific, build that too (`lscr.io/linuxserver/qemu-static`). If you, the agent, cannot run Docker, say so plainly in your output; do not claim testing that did not happen.
|
||||
|
||||
## 6. Pull requests
|
||||
|
||||
- **Disclose AI use.** If any part of the PR (code, description, or the investigation behind it) was produced with an AI tool, say so in the PR description: which tool, and what it was used for. Agents: add this line yourself, do not leave it to the operator. Undisclosed AI-generated PRs will be closed. Disclosure does not count against a PR; a human who cannot explain their own PR does.
|
||||
- **A human is accountable.** The person opening the PR must have read and understood every line, built and run the image, and be able to answer review questions in their own words. Do not paste maintainer questions into a chatbot and paste the answers back. Fully autonomous agents must not open PRs or issues on our repos.
|
||||
- **One focused change per PR.** The smallest diff that fixes the problem. No drive-by refactors, reformatting, comment rewording, "modernisation", dependency shuffling, or fixes for things nobody reported.
|
||||
- **No typo / wording-only PRs.** Open an issue instead and we will sort it out.
|
||||
- **Finish before you open.** Do not open drafts and iterate in public with a stream of fixup commits.
|
||||
- **Fill in the PR template honestly**, keep its structure, and tick the contributing checkbox only if it is true. Description, benefit to the wider userbase, how it was tested (real commands, real output), and links. Write it short and plain: no generated summaries, emoji headers, or bullet lists restating the diff.
|
||||
- Reference the issue with `closes #<number>` when there is one. For anything non trivial, there should be an human-submitted issue or Discord discussion first.
|
||||
- Commit messages are short, plain, imperative sentences (`Add libfoo for thumbnail support`). No conventional-commit prefixes, no emoji.
|
||||
- A PR is a proposal; it may be declined even if it works. The most common reason is section 1 of this file.
|
||||
|
||||
## 7. Issues
|
||||
|
||||
- GitHub issues are for reproducible bugs in **our image** and for feature requests.
|
||||
- Agents must not file issues on a user's behalf from a guess. An issue needs a real reproduction on the latest image, with mods and custom scripts disabled, the compose/run command and full container logs from startup, using the issue template.
|
||||
- Do not submit AI-generated root cause analyses or "security audits" of the image as issues. Scanner output about CVEs in upstream or distro packages is not actionable; images are rebuilt regularly to pull in distro fixes.
|
||||
- Support questions must always be submitted by a human and go to [Discord](https://linuxserver.io/discord) or the [forum](https://github.com/orgs/linuxserver/discussions); see [how to get support](https://docs.linuxserver.io/general/how-to-get-support/).
|
||||
|
||||
## 8. Quick self check before you finish
|
||||
|
||||
- [ ] This change benefits most users of this image, and is not a mod, custom script, or upstream issue.
|
||||
- [ ] Only hand-maintained files were edited (`Dockerfile*`, `root/**`, `readme-vars.yml`, rarely `jenkins-vars.yml`).
|
||||
- [ ] Every Dockerfile variant got the same change; packages are alphabetical.
|
||||
- [ ] Style matches the neighbouring code; shebang and shellcheck directive present; non-root / read-only guards preserved.
|
||||
- [ ] Changelog entry added at the top of `changelogs:` with today's date as `DD.MM.YY:`.
|
||||
- [ ] Image was built and run, including against an existing `/config`.
|
||||
- [ ] The diff contains nothing the task did not require.
|
||||
- [ ] PR description discloses AI use and a human has reviewed everything.
|
||||
+32
-33
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM ghcr.io/linuxserver/baseimage-alpine-nginx:3.21
|
||||
FROM ghcr.io/linuxserver/baseimage-alpine-nginx:3.24
|
||||
|
||||
# set version label
|
||||
ARG BUILD_DATE
|
||||
@@ -49,37 +49,34 @@ RUN \
|
||||
nginx-mod-stream \
|
||||
nginx-mod-stream-geoip2 \
|
||||
nginx-vim \
|
||||
php83-bcmath \
|
||||
php83-bz2 \
|
||||
php83-dom \
|
||||
php83-exif \
|
||||
php83-ftp \
|
||||
php83-gd \
|
||||
php83-gmp \
|
||||
php83-imap \
|
||||
php83-intl \
|
||||
php83-ldap \
|
||||
php83-mysqli \
|
||||
php83-mysqlnd \
|
||||
php83-opcache \
|
||||
php83-pdo_mysql \
|
||||
php83-pdo_odbc \
|
||||
php83-pdo_pgsql \
|
||||
php83-pdo_sqlite \
|
||||
php83-pear \
|
||||
php83-pecl-apcu \
|
||||
php83-pecl-mcrypt \
|
||||
php83-pecl-memcached \
|
||||
php83-pecl-redis \
|
||||
php83-pgsql \
|
||||
php83-posix \
|
||||
php83-soap \
|
||||
php83-sockets \
|
||||
php83-sodium \
|
||||
php83-sqlite3 \
|
||||
php83-tokenizer \
|
||||
php83-xmlreader \
|
||||
php83-xsl \
|
||||
php85-bcmath \
|
||||
php85-bz2 \
|
||||
php85-dom \
|
||||
php85-exif \
|
||||
php85-ftp \
|
||||
php85-gd \
|
||||
php85-gmp \
|
||||
php85-intl \
|
||||
php85-ldap \
|
||||
php85-mysqli \
|
||||
php85-mysqlnd \
|
||||
php85-pdo_mysql \
|
||||
php85-pdo_odbc \
|
||||
php85-pdo_pgsql \
|
||||
php85-pdo_sqlite \
|
||||
php85-pear \
|
||||
php85-pecl-apcu \
|
||||
php85-pecl-memcached \
|
||||
php85-pecl-redis \
|
||||
php85-pgsql \
|
||||
php85-posix \
|
||||
php85-soap \
|
||||
php85-sockets \
|
||||
php85-sodium \
|
||||
php85-sqlite3 \
|
||||
php85-tokenizer \
|
||||
php85-xmlreader \
|
||||
php85-xsl \
|
||||
whois && \
|
||||
echo "**** install certbot plugins ****" && \
|
||||
if [ -z ${CERTBOT_VERSION+x} ]; then \
|
||||
@@ -89,7 +86,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.21/ \
|
||||
pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.24/ \
|
||||
certbot==${CERTBOT_VERSION} \
|
||||
certbot-dns-acmedns \
|
||||
certbot-dns-aliyun \
|
||||
@@ -115,12 +112,14 @@ RUN \
|
||||
certbot-dns-google \
|
||||
certbot-dns-he \
|
||||
certbot-dns-hetzner \
|
||||
certbot-dns-hetzner-cloud \
|
||||
certbot-dns-infomaniak \
|
||||
certbot-dns-inwx \
|
||||
certbot-dns-ionos \
|
||||
certbot-dns-linode \
|
||||
certbot-dns-loopia \
|
||||
certbot-dns-luadns \
|
||||
certbot-dns-mijn-host \
|
||||
certbot-dns-namecheap \
|
||||
certbot-dns-netcup \
|
||||
certbot-dns-njalla \
|
||||
|
||||
+32
-33
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM ghcr.io/linuxserver/baseimage-alpine-nginx:arm64v8-3.21
|
||||
FROM ghcr.io/linuxserver/baseimage-alpine-nginx:arm64v8-3.24
|
||||
|
||||
# set version label
|
||||
ARG BUILD_DATE
|
||||
@@ -49,37 +49,34 @@ RUN \
|
||||
nginx-mod-stream \
|
||||
nginx-mod-stream-geoip2 \
|
||||
nginx-vim \
|
||||
php83-bcmath \
|
||||
php83-bz2 \
|
||||
php83-dom \
|
||||
php83-exif \
|
||||
php83-ftp \
|
||||
php83-gd \
|
||||
php83-gmp \
|
||||
php83-imap \
|
||||
php83-intl \
|
||||
php83-ldap \
|
||||
php83-mysqli \
|
||||
php83-mysqlnd \
|
||||
php83-opcache \
|
||||
php83-pdo_mysql \
|
||||
php83-pdo_odbc \
|
||||
php83-pdo_pgsql \
|
||||
php83-pdo_sqlite \
|
||||
php83-pear \
|
||||
php83-pecl-apcu \
|
||||
php83-pecl-mcrypt \
|
||||
php83-pecl-memcached \
|
||||
php83-pecl-redis \
|
||||
php83-pgsql \
|
||||
php83-posix \
|
||||
php83-soap \
|
||||
php83-sockets \
|
||||
php83-sodium \
|
||||
php83-sqlite3 \
|
||||
php83-tokenizer \
|
||||
php83-xmlreader \
|
||||
php83-xsl \
|
||||
php85-bcmath \
|
||||
php85-bz2 \
|
||||
php85-dom \
|
||||
php85-exif \
|
||||
php85-ftp \
|
||||
php85-gd \
|
||||
php85-gmp \
|
||||
php85-intl \
|
||||
php85-ldap \
|
||||
php85-mysqli \
|
||||
php85-mysqlnd \
|
||||
php85-pdo_mysql \
|
||||
php85-pdo_odbc \
|
||||
php85-pdo_pgsql \
|
||||
php85-pdo_sqlite \
|
||||
php85-pear \
|
||||
php85-pecl-apcu \
|
||||
php85-pecl-memcached \
|
||||
php85-pecl-redis \
|
||||
php85-pgsql \
|
||||
php85-posix \
|
||||
php85-soap \
|
||||
php85-sockets \
|
||||
php85-sodium \
|
||||
php85-sqlite3 \
|
||||
php85-tokenizer \
|
||||
php85-xmlreader \
|
||||
php85-xsl \
|
||||
whois && \
|
||||
echo "**** install certbot plugins ****" && \
|
||||
if [ -z ${CERTBOT_VERSION+x} ]; then \
|
||||
@@ -89,7 +86,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.21/ \
|
||||
pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.24/ \
|
||||
certbot==${CERTBOT_VERSION} \
|
||||
certbot-dns-acmedns \
|
||||
certbot-dns-aliyun \
|
||||
@@ -115,12 +112,14 @@ RUN \
|
||||
certbot-dns-google \
|
||||
certbot-dns-he \
|
||||
certbot-dns-hetzner \
|
||||
certbot-dns-hetzner-cloud \
|
||||
certbot-dns-infomaniak \
|
||||
certbot-dns-inwx \
|
||||
certbot-dns-ionos \
|
||||
certbot-dns-linode \
|
||||
certbot-dns-loopia \
|
||||
certbot-dns-luadns \
|
||||
certbot-dns-mijn-host \
|
||||
certbot-dns-namecheap \
|
||||
certbot-dns-netcup \
|
||||
certbot-dns-njalla \
|
||||
|
||||
Vendored
+468
-187
@@ -52,20 +52,87 @@ pipeline {
|
||||
'''
|
||||
}
|
||||
}
|
||||
/* ############################
|
||||
Bash Function For GHCR Retry
|
||||
############################ */
|
||||
// Create a reusable script for a ghcr retry bash function
|
||||
stage("Create Bash Function"){
|
||||
steps{
|
||||
sh '''#! /bin/bash
|
||||
# create our retry function
|
||||
retry_ghcr() {
|
||||
local max_attempts=7
|
||||
local base_delay=10
|
||||
local max_delay=90
|
||||
local attempt=1
|
||||
local errfile exit_code delay pause
|
||||
errfile=$(mktemp)
|
||||
while true; do
|
||||
# run inside an if so a caller's set -e cannot abort before we get to retry
|
||||
if "$@" 2> >(tee "${errfile}" >&2); then
|
||||
exit_code=0
|
||||
else
|
||||
exit_code=$?
|
||||
fi
|
||||
# make sure tee has finished writing before we read the file
|
||||
wait $! 2>/dev/null || true
|
||||
if [[ "${exit_code}" == "0" ]]; then
|
||||
rm -f "${errfile}"
|
||||
return 0
|
||||
elif ! grep -q -i -E "retry-after:|toomanyrequests|too many requests" "${errfile}"; then
|
||||
rm -f "${errfile}"
|
||||
return "${exit_code}"
|
||||
elif (( attempt >= max_attempts )); then
|
||||
rm -f "${errfile}"
|
||||
echo "retry: $* failed after ${attempt} attempts (exit ${exit_code})" >&2
|
||||
return "${exit_code}"
|
||||
else
|
||||
# exponential delay: base * 2^(attempt-1), capped at max_delay
|
||||
delay=$(( base_delay * 2 ** (attempt - 1) ))
|
||||
(( delay > max_delay )) && delay="${max_delay}"
|
||||
# jitter between half and full delay so parallel builds spread out
|
||||
pause=$(( delay / 2 + RANDOM % (delay / 2 + 1) ))
|
||||
echo "retry: attempt ${attempt}/${max_attempts} failed (exit ${exit_code}); waiting ${pause}s..." >&2
|
||||
sleep "${pause}"
|
||||
((attempt++))
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
declare -f retry_ghcr > ${WORKSPACE}/retry_ghcr.sh
|
||||
'''
|
||||
}
|
||||
}
|
||||
// Setup all the basic environment variables needed for the build
|
||||
stage("Set ENV Variables base"){
|
||||
steps{
|
||||
echo "Running on node: ${NODE_NAME}"
|
||||
sh '''#! /bin/bash
|
||||
containers=$(docker ps -aq)
|
||||
echo "Pruning builder"
|
||||
docker builder prune -f --builder container || :
|
||||
containers=$(docker ps -q)
|
||||
if [[ -n "${containers}" ]]; then
|
||||
docker stop ${containers}
|
||||
BUILDX_CONTAINER_ID=$(docker ps -qf 'name=buildx_buildkit')
|
||||
for container in ${containers}; do
|
||||
if [[ "${container}" == "${BUILDX_CONTAINER_ID}" ]]; then
|
||||
echo "skipping buildx container in docker stop"
|
||||
else
|
||||
echo "Stopping container ${container}"
|
||||
docker stop ${container}
|
||||
fi
|
||||
done
|
||||
fi
|
||||
docker system prune -af --volumes || : '''
|
||||
docker system prune -f --volumes || :
|
||||
docker image prune -af || :
|
||||
'''
|
||||
script{
|
||||
env.EXIT_STATUS = ''
|
||||
env.CI_TEST_ATTEMPTED = ''
|
||||
env.PUSH_ATTEMPTED = ''
|
||||
env.LS_RELEASE = sh(
|
||||
script: '''docker run --rm quay.io/skopeo/stable:v1 inspect docker://ghcr.io/${LS_USER}/${CONTAINER_NAME}:latest 2>/dev/null | jq -r '.Labels.build_version' | awk '{print $3}' | grep '\\-ls' || : ''',
|
||||
script: '''#! /bin/bash
|
||||
source ${WORKSPACE}/retry_ghcr.sh
|
||||
retry_ghcr docker run --rm quay.io/skopeo/stable:v1 inspect docker://ghcr.io/${LS_USER}/${CONTAINER_NAME}:latest | jq -r '.Labels.build_version' | awk '{print $3}' | grep '\\-ls' || : ''',
|
||||
returnStdout: true).trim()
|
||||
env.LS_RELEASE_NOTES = sh(
|
||||
script: '''cat readme-vars.yml | awk -F \\" '/date: "[0-9][0-9].[0-9][0-9].[0-9][0-9]:/ {print $4;exit;}' | sed -E ':a;N;$!ba;s/\\r{0,1}\\n/\\\\n/g' ''',
|
||||
@@ -82,8 +149,16 @@ pipeline {
|
||||
env.CODE_URL = 'https://github.com/' + env.LS_USER + '/' + env.LS_REPO + '/commit/' + env.GIT_COMMIT
|
||||
env.DOCKERHUB_LINK = 'https://hub.docker.com/r/' + env.DOCKERHUB_IMAGE + '/tags/'
|
||||
env.PULL_REQUEST = env.CHANGE_ID
|
||||
env.TEMPLATED_FILES = 'Jenkinsfile README.md LICENSE .editorconfig ./.github/CONTRIBUTING.md ./.github/FUNDING.yml ./.github/ISSUE_TEMPLATE/config.yml ./.github/ISSUE_TEMPLATE/issue.bug.yml ./.github/ISSUE_TEMPLATE/issue.feature.yml ./.github/PULL_REQUEST_TEMPLATE.md ./.github/workflows/external_trigger_scheduler.yml ./.github/workflows/greetings.yml ./.github/workflows/package_trigger_scheduler.yml ./.github/workflows/call_issue_pr_tracker.yml ./.github/workflows/call_issues_cron.yml ./.github/workflows/permissions.yml ./.github/workflows/external_trigger.yml ./root/donate.txt'
|
||||
env.TEMPLATED_FILES = 'Jenkinsfile README.md LICENSE .editorconfig AGENTS.md ./.github/CONTRIBUTING.md ./.github/FUNDING.yml ./.github/ISSUE_TEMPLATE/config.yml ./.github/ISSUE_TEMPLATE/issue.bug.yml ./.github/ISSUE_TEMPLATE/issue.feature.yml ./.github/PULL_REQUEST_TEMPLATE.md ./.github/workflows/external_trigger_scheduler.yml ./.github/workflows/greetings.yml ./.github/workflows/package_trigger_scheduler.yml ./.github/workflows/call_issue_pr_tracker.yml ./.github/workflows/call_issues_cron.yml ./.github/workflows/permissions.yml ./.github/workflows/external_trigger.yml ./root/donate.txt'
|
||||
if ( env.SYFT_IMAGE_TAG == null ) {
|
||||
env.SYFT_IMAGE_TAG = 'latest'
|
||||
}
|
||||
if ( env.GITLAB_TIMEOUT == null ) {
|
||||
env.GITLAB_TIMEOUT = '600'
|
||||
}
|
||||
}
|
||||
echo "Using syft image tag ${SYFT_IMAGE_TAG}"
|
||||
echo "Using gitlab registry timeout ${GITLAB_TIMEOUT}"
|
||||
sh '''#! /bin/bash
|
||||
echo "The default github branch detected as ${GH_DEFAULT_BRANCH}" '''
|
||||
script{
|
||||
@@ -192,6 +267,7 @@ pipeline {
|
||||
env.META_TAG = env.EXT_RELEASE_CLEAN + '-ls' + env.LS_TAG_NUMBER
|
||||
env.EXT_RELEASE_TAG = 'version-' + env.EXT_RELEASE_CLEAN
|
||||
env.BUILDCACHE = 'docker.io/lsiodev/buildcache,registry.gitlab.com/linuxserver.io/docker-jenkins-builder/lsiodev-buildcache,ghcr.io/linuxserver/lsiodev-buildcache,quay.io/linuxserver.io/lsiodev-buildcache'
|
||||
env.CITEST_IMAGETAG = 'latest'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -217,6 +293,7 @@ pipeline {
|
||||
env.EXT_RELEASE_TAG = 'version-' + env.EXT_RELEASE_CLEAN
|
||||
env.DOCKERHUB_LINK = 'https://hub.docker.com/r/' + env.DEV_DOCKERHUB_IMAGE + '/tags/'
|
||||
env.BUILDCACHE = 'docker.io/lsiodev/buildcache,registry.gitlab.com/linuxserver.io/docker-jenkins-builder/lsiodev-buildcache,ghcr.io/linuxserver/lsiodev-buildcache,quay.io/linuxserver.io/lsiodev-buildcache'
|
||||
env.CITEST_IMAGETAG = 'develop'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -242,6 +319,7 @@ pipeline {
|
||||
env.CODE_URL = 'https://github.com/' + env.LS_USER + '/' + env.LS_REPO + '/pull/' + env.PULL_REQUEST
|
||||
env.DOCKERHUB_LINK = 'https://hub.docker.com/r/' + env.PR_DOCKERHUB_IMAGE + '/tags/'
|
||||
env.BUILDCACHE = 'docker.io/lsiodev/buildcache,registry.gitlab.com/linuxserver.io/docker-jenkins-builder/lsiodev-buildcache,ghcr.io/linuxserver/lsiodev-buildcache,quay.io/linuxserver.io/lsiodev-buildcache'
|
||||
env.CITEST_IMAGETAG = 'develop'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -260,11 +338,13 @@ pipeline {
|
||||
}
|
||||
sh '''curl -sL https://raw.githubusercontent.com/linuxserver/docker-jenkins-builder/master/checkrun.sh | /bin/bash'''
|
||||
sh '''#! /bin/bash
|
||||
source ${WORKSPACE}/retry_ghcr.sh
|
||||
retry_ghcr docker pull ghcr.io/linuxserver/baseimage-alpine:3.23
|
||||
docker run --rm \
|
||||
-v ${WORKSPACE}:/mnt \
|
||||
-e AWS_ACCESS_KEY_ID=\"${S3_KEY}\" \
|
||||
-e AWS_SECRET_ACCESS_KEY=\"${S3_SECRET}\" \
|
||||
ghcr.io/linuxserver/baseimage-alpine:3.20 s6-envdir -fn -- /var/run/s6/container_environment /bin/bash -c "\
|
||||
ghcr.io/linuxserver/baseimage-alpine:3.23 s6-envdir -fn -- /var/run/s6/container_environment /bin/bash -c "\
|
||||
apk add --no-cache python3 && \
|
||||
python3 -m venv /lsiopy && \
|
||||
pip install --no-cache-dir -U pip && \
|
||||
@@ -286,7 +366,8 @@ pipeline {
|
||||
sh '''#! /bin/bash
|
||||
set -e
|
||||
TEMPDIR=$(mktemp -d)
|
||||
docker pull ghcr.io/linuxserver/jenkins-builder:latest
|
||||
source ${WORKSPACE}/retry_ghcr.sh
|
||||
retry_ghcr docker pull ghcr.io/linuxserver/jenkins-builder:latest
|
||||
# Cloned repo paths for templating:
|
||||
# ${TEMPDIR}/docker-${CONTAINER_NAME}: Cloned branch master of ${LS_USER}/${LS_REPO} for running the jenkins builder on
|
||||
# ${TEMPDIR}/repo/${LS_REPO}: Cloned branch master of ${LS_USER}/${LS_REPO} for commiting various templated file changes and pushing back to Github
|
||||
@@ -345,6 +426,7 @@ pipeline {
|
||||
sed -i 's|^changelogs:|# init diagram\\ninit_diagram:\\n\\n# changelog\\nchangelogs:|' readme-vars.yml
|
||||
fi
|
||||
mkdir -p ${TEMPDIR}/d2
|
||||
retry_ghcr docker pull ghcr.io/linuxserver/d2-builder:latest
|
||||
docker run --rm -v ${TEMPDIR}/d2:/output -e PUID=$(id -u) -e PGID=$(id -g) -e RAW="true" ghcr.io/linuxserver/d2-builder:latest ${CONTAINER_NAME}:latest
|
||||
ls -al ${TEMPDIR}/d2
|
||||
yq -ei ".init_diagram |= load_str(\\"${TEMPDIR}/d2/${CONTAINER_NAME}-latest.d2\\")" readme-vars.yml
|
||||
@@ -561,22 +643,25 @@ pipeline {
|
||||
steps {
|
||||
echo "Running on node: ${NODE_NAME}"
|
||||
sh "sed -r -i 's|(^FROM .*)|\\1\\n\\nENV LSIO_FIRST_PARTY=true|g' Dockerfile"
|
||||
sh "docker buildx build \
|
||||
--label \"org.opencontainers.image.created=${GITHUB_DATE}\" \
|
||||
--label \"org.opencontainers.image.authors=linuxserver.io\" \
|
||||
--label \"org.opencontainers.image.url=https://github.com/linuxserver/docker-swag/packages\" \
|
||||
--label \"org.opencontainers.image.documentation=https://docs.linuxserver.io/images/docker-swag\" \
|
||||
--label \"org.opencontainers.image.source=https://github.com/linuxserver/docker-swag\" \
|
||||
--label \"org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}\" \
|
||||
--label \"org.opencontainers.image.revision=${COMMIT_SHA}\" \
|
||||
--label \"org.opencontainers.image.vendor=linuxserver.io\" \
|
||||
--label \"org.opencontainers.image.licenses=GPL-3.0-only\" \
|
||||
--label \"org.opencontainers.image.ref.name=${COMMIT_SHA}\" \
|
||||
--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=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
|
||||
source ${WORKSPACE}/retry_ghcr.sh
|
||||
retry_ghcr docker buildx build \
|
||||
--label "org.opencontainers.image.created=${GITHUB_DATE}" \
|
||||
--label "org.opencontainers.image.authors=linuxserver.io" \
|
||||
--label "org.opencontainers.image.url=https://github.com/linuxserver/docker-swag/packages" \
|
||||
--label "org.opencontainers.image.documentation=https://docs.linuxserver.io/images/docker-swag" \
|
||||
--label "org.opencontainers.image.source=https://github.com/linuxserver/docker-swag" \
|
||||
--label "org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}" \
|
||||
--label "org.opencontainers.image.revision=${COMMIT_SHA}" \
|
||||
--label "org.opencontainers.image.vendor=linuxserver.io" \
|
||||
--label "org.opencontainers.image.licenses=GPL-3.0-only" \
|
||||
--label "org.opencontainers.image.ref.name=${COMMIT_SHA}" \
|
||||
--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=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
|
||||
IFS=',' read -ra CACHE <<< "$BUILDCACHE"
|
||||
@@ -595,17 +680,36 @@ pipeline {
|
||||
retry_backoff(5,5) {
|
||||
sh '''#! /bin/bash
|
||||
set -e
|
||||
# run a registry.gitlab.com command under what is left of the gitlab time budget
|
||||
gitlab_timeout() {
|
||||
local remaining=$(( GITLAB_DEADLINE - SECONDS ))
|
||||
if (( remaining <= 0 )); then
|
||||
echo "gitlab timeout budget of ${GITLAB_TIMEOUT}s used up, skipping: $*" >&2
|
||||
return 124
|
||||
fi
|
||||
timeout "${remaining}" "$@"
|
||||
}
|
||||
GITLAB_DEADLINE=$(( SECONDS + GITLAB_TIMEOUT ))
|
||||
|
||||
echo $DOCKERHUB_TOKEN | docker login -u linuxserverci --password-stdin
|
||||
echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin
|
||||
echo $GITLAB_TOKEN | docker login registry.gitlab.com -u LinuxServer.io --password-stdin
|
||||
echo $QUAYPASS | docker login quay.io -u $QUAYUSER --password-stdin
|
||||
|
||||
if [[ "${PACKAGE_CHECK}" != "true" ]]; then
|
||||
declare -A pids
|
||||
IFS=',' read -ra CACHE <<< "$BUILDCACHE"
|
||||
for i in "${CACHE[@]}"; do
|
||||
docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} &
|
||||
if [[ "${i}" == *"registry.gitlab.com"* ]]; then
|
||||
TIMEOUT_CMD="gitlab_timeout"
|
||||
else
|
||||
TIMEOUT_CMD=""
|
||||
fi
|
||||
${TIMEOUT_CMD} docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} &
|
||||
pids[$!]="$i"
|
||||
done
|
||||
for p in $(jobs -p); do
|
||||
wait "$p" || { echo "job $p failed" >&2; exit 1; }
|
||||
for p in "${!pids[@]}"; do
|
||||
wait "$p" || { if [[ "${pids[$p]}" != *"quay.io"* && "${pids[$p]}" != *"registry.gitlab.com"* ]]; then exit 1; fi; }
|
||||
done
|
||||
fi
|
||||
'''
|
||||
@@ -627,22 +731,25 @@ pipeline {
|
||||
steps {
|
||||
echo "Running on node: ${NODE_NAME}"
|
||||
sh "sed -r -i 's|(^FROM .*)|\\1\\n\\nENV LSIO_FIRST_PARTY=true|g' Dockerfile"
|
||||
sh "docker buildx build \
|
||||
--label \"org.opencontainers.image.created=${GITHUB_DATE}\" \
|
||||
--label \"org.opencontainers.image.authors=linuxserver.io\" \
|
||||
--label \"org.opencontainers.image.url=https://github.com/linuxserver/docker-swag/packages\" \
|
||||
--label \"org.opencontainers.image.documentation=https://docs.linuxserver.io/images/docker-swag\" \
|
||||
--label \"org.opencontainers.image.source=https://github.com/linuxserver/docker-swag\" \
|
||||
--label \"org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}\" \
|
||||
--label \"org.opencontainers.image.revision=${COMMIT_SHA}\" \
|
||||
--label \"org.opencontainers.image.vendor=linuxserver.io\" \
|
||||
--label \"org.opencontainers.image.licenses=GPL-3.0-only\" \
|
||||
--label \"org.opencontainers.image.ref.name=${COMMIT_SHA}\" \
|
||||
--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=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
|
||||
source ${WORKSPACE}/retry_ghcr.sh
|
||||
retry_ghcr docker buildx build \
|
||||
--label "org.opencontainers.image.created=${GITHUB_DATE}" \
|
||||
--label "org.opencontainers.image.authors=linuxserver.io" \
|
||||
--label "org.opencontainers.image.url=https://github.com/linuxserver/docker-swag/packages" \
|
||||
--label "org.opencontainers.image.documentation=https://docs.linuxserver.io/images/docker-swag" \
|
||||
--label "org.opencontainers.image.source=https://github.com/linuxserver/docker-swag" \
|
||||
--label "org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}" \
|
||||
--label "org.opencontainers.image.revision=${COMMIT_SHA}" \
|
||||
--label "org.opencontainers.image.vendor=linuxserver.io" \
|
||||
--label "org.opencontainers.image.licenses=GPL-3.0-only" \
|
||||
--label "org.opencontainers.image.ref.name=${COMMIT_SHA}" \
|
||||
--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=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
|
||||
IFS=',' read -ra CACHE <<< "$BUILDCACHE"
|
||||
@@ -661,17 +768,36 @@ pipeline {
|
||||
retry_backoff(5,5) {
|
||||
sh '''#! /bin/bash
|
||||
set -e
|
||||
# run a registry.gitlab.com command under what is left of the gitlab time budget
|
||||
gitlab_timeout() {
|
||||
local remaining=$(( GITLAB_DEADLINE - SECONDS ))
|
||||
if (( remaining <= 0 )); then
|
||||
echo "gitlab timeout budget of ${GITLAB_TIMEOUT}s used up, skipping: $*" >&2
|
||||
return 124
|
||||
fi
|
||||
timeout "${remaining}" "$@"
|
||||
}
|
||||
GITLAB_DEADLINE=$(( SECONDS + GITLAB_TIMEOUT ))
|
||||
|
||||
echo $DOCKERHUB_TOKEN | docker login -u linuxserverci --password-stdin
|
||||
echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin
|
||||
echo $GITLAB_TOKEN | docker login registry.gitlab.com -u LinuxServer.io --password-stdin
|
||||
echo $QUAYPASS | docker login quay.io -u $QUAYUSER --password-stdin
|
||||
|
||||
if [[ "${PACKAGE_CHECK}" != "true" ]]; then
|
||||
declare -A pids
|
||||
IFS=',' read -ra CACHE <<< "$BUILDCACHE"
|
||||
for i in "${CACHE[@]}"; do
|
||||
docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} &
|
||||
if [[ "${i}" == *"registry.gitlab.com"* ]]; then
|
||||
TIMEOUT_CMD="gitlab_timeout"
|
||||
else
|
||||
TIMEOUT_CMD=""
|
||||
fi
|
||||
${TIMEOUT_CMD} docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} &
|
||||
pids[$!]="$i"
|
||||
done
|
||||
for p in $(jobs -p); do
|
||||
wait "$p" || { echo "job $p failed" >&2; exit 1; }
|
||||
for p in "${!pids[@]}"; do
|
||||
wait "$p" || { if [[ "${pids[$p]}" != *"quay.io"* && "${pids[$p]}" != *"registry.gitlab.com"* ]]; then exit 1; fi; }
|
||||
done
|
||||
fi
|
||||
'''
|
||||
@@ -686,22 +812,64 @@ pipeline {
|
||||
steps {
|
||||
echo "Running on node: ${NODE_NAME}"
|
||||
sh "sed -r -i 's|(^FROM .*)|\\1\\n\\nENV LSIO_FIRST_PARTY=true|g' Dockerfile.aarch64"
|
||||
sh "docker buildx build \
|
||||
--label \"org.opencontainers.image.created=${GITHUB_DATE}\" \
|
||||
--label \"org.opencontainers.image.authors=linuxserver.io\" \
|
||||
--label \"org.opencontainers.image.url=https://github.com/linuxserver/docker-swag/packages\" \
|
||||
--label \"org.opencontainers.image.documentation=https://docs.linuxserver.io/images/docker-swag\" \
|
||||
--label \"org.opencontainers.image.source=https://github.com/linuxserver/docker-swag\" \
|
||||
--label \"org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}\" \
|
||||
--label \"org.opencontainers.image.revision=${COMMIT_SHA}\" \
|
||||
--label \"org.opencontainers.image.vendor=linuxserver.io\" \
|
||||
--label \"org.opencontainers.image.licenses=GPL-3.0-only\" \
|
||||
--label \"org.opencontainers.image.ref.name=${COMMIT_SHA}\" \
|
||||
--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=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
|
||||
# create our retry function
|
||||
retry_ghcr() {
|
||||
local max_attempts=7
|
||||
local base_delay=10
|
||||
local max_delay=90
|
||||
local attempt=1
|
||||
local errfile exit_code delay pause
|
||||
errfile=$(mktemp)
|
||||
while true; do
|
||||
# run inside an if so a caller's set -e cannot abort before we get to retry
|
||||
if "$@" 2> >(tee "${errfile}" >&2); then
|
||||
exit_code=0
|
||||
else
|
||||
exit_code=$?
|
||||
fi
|
||||
# make sure tee has finished writing before we read the file
|
||||
wait $! 2>/dev/null || true
|
||||
if [[ "${exit_code}" == "0" ]]; then
|
||||
rm -f "${errfile}"
|
||||
return 0
|
||||
elif ! grep -q -i -E "retry-after:|toomanyrequests|too many requests" "${errfile}"; then
|
||||
rm -f "${errfile}"
|
||||
return "${exit_code}"
|
||||
elif (( attempt >= max_attempts )); then
|
||||
rm -f "${errfile}"
|
||||
echo "retry: $* failed after ${attempt} attempts (exit ${exit_code})" >&2
|
||||
return "${exit_code}"
|
||||
else
|
||||
# exponential delay: base * 2^(attempt-1), capped at max_delay
|
||||
delay=$(( base_delay * 2 ** (attempt - 1) ))
|
||||
(( delay > max_delay )) && delay="${max_delay}"
|
||||
# jitter between half and full delay so parallel builds spread out
|
||||
pause=$(( delay / 2 + RANDOM % (delay / 2 + 1) ))
|
||||
echo "retry: attempt ${attempt}/${max_attempts} failed (exit ${exit_code}); waiting ${pause}s..." >&2
|
||||
sleep "${pause}"
|
||||
((attempt++))
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
retry_ghcr docker buildx build \
|
||||
--label "org.opencontainers.image.created=${GITHUB_DATE}" \
|
||||
--label "org.opencontainers.image.authors=linuxserver.io" \
|
||||
--label "org.opencontainers.image.url=https://github.com/linuxserver/docker-swag/packages" \
|
||||
--label "org.opencontainers.image.documentation=https://docs.linuxserver.io/images/docker-swag" \
|
||||
--label "org.opencontainers.image.source=https://github.com/linuxserver/docker-swag" \
|
||||
--label "org.opencontainers.image.version=${EXT_RELEASE_CLEAN}-ls${LS_TAG_NUMBER}" \
|
||||
--label "org.opencontainers.image.revision=${COMMIT_SHA}" \
|
||||
--label "org.opencontainers.image.vendor=linuxserver.io" \
|
||||
--label "org.opencontainers.image.licenses=GPL-3.0-only" \
|
||||
--label "org.opencontainers.image.ref.name=${COMMIT_SHA}" \
|
||||
--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=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
|
||||
IFS=',' read -ra CACHE <<< "$BUILDCACHE"
|
||||
@@ -720,17 +888,35 @@ pipeline {
|
||||
retry_backoff(5,5) {
|
||||
sh '''#! /bin/bash
|
||||
set -e
|
||||
# run a registry.gitlab.com command under what is left of the gitlab time budget
|
||||
gitlab_timeout() {
|
||||
local remaining=$(( GITLAB_DEADLINE - SECONDS ))
|
||||
if (( remaining <= 0 )); then
|
||||
echo "gitlab timeout budget of ${GITLAB_TIMEOUT}s used up, skipping: $*" >&2
|
||||
return 124
|
||||
fi
|
||||
timeout "${remaining}" "$@"
|
||||
}
|
||||
GITLAB_DEADLINE=$(( SECONDS + GITLAB_TIMEOUT ))
|
||||
|
||||
echo $DOCKERHUB_TOKEN | docker login -u linuxserverci --password-stdin
|
||||
echo $GITHUB_TOKEN | docker login ghcr.io -u LinuxServer-CI --password-stdin
|
||||
echo $GITLAB_TOKEN | docker login registry.gitlab.com -u LinuxServer.io --password-stdin
|
||||
echo $QUAYPASS | docker login quay.io -u $QUAYUSER --password-stdin
|
||||
if [[ "${PACKAGE_CHECK}" != "true" ]]; then
|
||||
declare -A pids
|
||||
IFS=',' read -ra CACHE <<< "$BUILDCACHE"
|
||||
for i in "${CACHE[@]}"; do
|
||||
docker push ${i}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} &
|
||||
if [[ "${i}" == *"registry.gitlab.com"* ]]; then
|
||||
TIMEOUT_CMD="gitlab_timeout"
|
||||
else
|
||||
TIMEOUT_CMD=""
|
||||
fi
|
||||
${TIMEOUT_CMD} docker push ${i}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} &
|
||||
pids[$!]="$i"
|
||||
done
|
||||
for p in $(jobs -p); do
|
||||
wait "$p" || { echo "job $p failed" >&2; exit 1; }
|
||||
for p in "${!pids[@]}"; do
|
||||
wait "$p" || { if [[ "${pids[$p]}" != *"quay.io"* && "${pids[$p]}" != *"registry.gitlab.com"* ]]; then exit 1; fi; }
|
||||
done
|
||||
fi
|
||||
'''
|
||||
@@ -741,7 +927,8 @@ pipeline {
|
||||
if [[ -n "${containers}" ]]; then
|
||||
docker stop ${containers}
|
||||
fi
|
||||
docker system prune -af --volumes || :
|
||||
docker system prune -f --volumes || :
|
||||
docker image prune -af || :
|
||||
'''
|
||||
}
|
||||
}
|
||||
@@ -764,10 +951,12 @@ pipeline {
|
||||
LOCAL_CONTAINER=${IMAGE}:${META_TAG}
|
||||
fi
|
||||
touch ${TEMPDIR}/package_versions.txt
|
||||
source ${WORKSPACE}/retry_ghcr.sh
|
||||
retry_ghcr docker pull ghcr.io/anchore/syft:${SYFT_IMAGE_TAG}
|
||||
docker run --rm \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock:ro \
|
||||
-v ${TEMPDIR}:/tmp \
|
||||
ghcr.io/anchore/syft:latest \
|
||||
ghcr.io/anchore/syft:${SYFT_IMAGE_TAG} \
|
||||
${LOCAL_CONTAINER} -o table=/tmp/package_versions.txt
|
||||
NEW_PACKAGE_TAG=$(md5sum ${TEMPDIR}/package_versions.txt | cut -c1-8 )
|
||||
echo "Package tag sha from current packages in buit container is ${NEW_PACKAGE_TAG} comparing to old ${PACKAGE_TAG} from github"
|
||||
@@ -843,6 +1032,7 @@ pipeline {
|
||||
script{
|
||||
env.CI_URL = 'https://ci-tests.linuxserver.io/' + env.IMAGE + '/' + env.META_TAG + '/index.html'
|
||||
env.CI_JSON_URL = 'https://ci-tests.linuxserver.io/' + env.IMAGE + '/' + env.META_TAG + '/report.json'
|
||||
env.CI_TEST_ATTEMPTED = 'true'
|
||||
}
|
||||
sh '''#! /bin/bash
|
||||
set -e
|
||||
@@ -854,9 +1044,10 @@ pipeline {
|
||||
CI_DOCKERENV="LSIO_FIRST_PARTY=true"
|
||||
fi
|
||||
fi
|
||||
docker pull ghcr.io/linuxserver/ci:latest
|
||||
source ${WORKSPACE}/retry_ghcr.sh
|
||||
retry_ghcr docker pull ghcr.io/linuxserver/ci:${CITEST_IMAGETAG}
|
||||
if [ "${MULTIARCH}" == "true" ]; then
|
||||
docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} --platform=arm64
|
||||
retry_ghcr docker pull ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} --platform=arm64
|
||||
docker tag ghcr.io/linuxserver/lsiodev-buildcache:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} ${IMAGE}:arm64v8-${META_TAG}
|
||||
fi
|
||||
docker run --rm \
|
||||
@@ -877,7 +1068,10 @@ pipeline {
|
||||
-e WEB_AUTH=\"${CI_AUTH}\" \
|
||||
-e WEB_PATH=\"${CI_WEBPATH}\" \
|
||||
-e NODE_NAME=\"${NODE_NAME}\" \
|
||||
-t ghcr.io/linuxserver/ci:latest \
|
||||
-e SYFT_IMAGE_TAG=\"${CI_SYFT_IMAGE_TAG:-${SYFT_IMAGE_TAG}}\" \
|
||||
-e COMMIT_SHA=\"${COMMIT_SHA}\" \
|
||||
-e BUILD_NUMBER=\"${BUILD_NUMBER}\" \
|
||||
-t ghcr.io/linuxserver/ci:${CITEST_IMAGETAG} \
|
||||
python3 test_build.py'''
|
||||
}
|
||||
}
|
||||
@@ -892,10 +1086,29 @@ pipeline {
|
||||
environment name: 'EXIT_STATUS', value: ''
|
||||
}
|
||||
steps {
|
||||
script{
|
||||
env.PUSH_ATTEMPTED = 'true'
|
||||
}
|
||||
retry_backoff(5,5) {
|
||||
sh '''#! /bin/bash
|
||||
set -e
|
||||
# run a registry.gitlab.com command under what is left of the gitlab time budget
|
||||
gitlab_timeout() {
|
||||
local remaining=$(( GITLAB_DEADLINE - SECONDS ))
|
||||
if (( remaining <= 0 )); then
|
||||
echo "gitlab timeout budget of ${GITLAB_TIMEOUT}s used up, skipping: $*" >&2
|
||||
return 124
|
||||
fi
|
||||
timeout "${remaining}" "$@"
|
||||
}
|
||||
GITLAB_DEADLINE=$(( SECONDS + GITLAB_TIMEOUT ))
|
||||
|
||||
for PUSHIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}" "${QUAYIMAGE}"; do
|
||||
if [[ "${PUSHIMAGE}" == "${GITLABIMAGE}" ]]; then
|
||||
TIMEOUT_CMD="gitlab_timeout"
|
||||
else
|
||||
TIMEOUT_CMD=""
|
||||
fi
|
||||
[[ ${PUSHIMAGE%%/*} =~ \\. ]] && PUSHIMAGEPLUS="${PUSHIMAGE}" || PUSHIMAGEPLUS="docker.io/${PUSHIMAGE}"
|
||||
IFS=',' read -ra CACHE <<< "$BUILDCACHE"
|
||||
for i in "${CACHE[@]}"; do
|
||||
@@ -903,9 +1116,11 @@ pipeline {
|
||||
CACHEIMAGE=${i}
|
||||
fi
|
||||
done
|
||||
docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${META_TAG} -t ${PUSHIMAGE}:latest -t ${PUSHIMAGE}:${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER}
|
||||
${TIMEOUT_CMD} docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${META_TAG} -t ${PUSHIMAGE}:latest -t ${PUSHIMAGE}:${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \
|
||||
{ if [[ "${PUSHIMAGE}" != "${QUAYIMAGE}" && "${PUSHIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; }
|
||||
if [ -n "${SEMVER}" ]; then
|
||||
docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER}
|
||||
${TIMEOUT_CMD} docker buildx imagetools create --prefer-index=false -t ${PUSHIMAGE}:${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \
|
||||
{ if [[ "${PUSHIMAGE}" != "${QUAYIMAGE}" && "${PUSHIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; }
|
||||
fi
|
||||
done
|
||||
'''
|
||||
@@ -919,31 +1134,66 @@ pipeline {
|
||||
environment name: 'EXIT_STATUS', value: ''
|
||||
}
|
||||
steps {
|
||||
script{
|
||||
env.PUSH_ATTEMPTED = 'true'
|
||||
}
|
||||
retry_backoff(5,5) {
|
||||
sh '''#! /bin/bash
|
||||
set -e
|
||||
# run a registry.gitlab.com command under what is left of the gitlab time budget
|
||||
gitlab_timeout() {
|
||||
local remaining=$(( GITLAB_DEADLINE - SECONDS ))
|
||||
if (( remaining <= 0 )); then
|
||||
echo "gitlab timeout budget of ${GITLAB_TIMEOUT}s used up, skipping: $*" >&2
|
||||
return 124
|
||||
fi
|
||||
timeout "${remaining}" "$@"
|
||||
}
|
||||
GITLAB_DEADLINE=$(( SECONDS + GITLAB_TIMEOUT ))
|
||||
|
||||
for MANIFESTIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}" "${QUAYIMAGE}"; do
|
||||
[[ ${MANIFESTIMAGE%%/*} =~ \\. ]] && MANIFESTIMAGEPLUS="${MANIFESTIMAGE}" || MANIFESTIMAGEPLUS="docker.io/${MANIFESTIMAGE}"
|
||||
if [[ "${MANIFESTIMAGE}" == "${GITLABIMAGE}" ]]; then
|
||||
TIMEOUT_CMD="gitlab_timeout"
|
||||
else
|
||||
TIMEOUT_CMD=""
|
||||
fi
|
||||
if [[ "${MANIFESTIMAGE%%/*}" =~ \\. ]]; then
|
||||
MANIFESTIMAGEPLUS="${MANIFESTIMAGE}"
|
||||
else
|
||||
MANIFESTIMAGEPLUS="docker.io/${MANIFESTIMAGE}"
|
||||
fi
|
||||
IFS=',' read -ra CACHE <<< "$BUILDCACHE"
|
||||
for i in "${CACHE[@]}"; do
|
||||
if [[ "${MANIFESTIMAGEPLUS}" == "$(cut -d "/" -f1 <<< ${i})"* ]]; then
|
||||
CACHEIMAGE=${i}
|
||||
fi
|
||||
done
|
||||
docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${META_TAG} -t ${MANIFESTIMAGE}:amd64-latest -t ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER}
|
||||
docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${META_TAG} -t ${MANIFESTIMAGE}:arm64v8-latest -t ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER}
|
||||
${TIMEOUT_CMD} docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${META_TAG} -t ${MANIFESTIMAGE}:amd64-latest -t ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \
|
||||
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; }
|
||||
${TIMEOUT_CMD} docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${META_TAG} -t ${MANIFESTIMAGE}:arm64v8-latest -t ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || \
|
||||
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; }
|
||||
if [ -n "${SEMVER}" ]; then
|
||||
docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER}
|
||||
docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${SEMVER} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER}
|
||||
${TIMEOUT_CMD} docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:amd64-${SEMVER} ${CACHEIMAGE}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} || \
|
||||
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; }
|
||||
${TIMEOUT_CMD} docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${SEMVER} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || \
|
||||
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; }
|
||||
fi
|
||||
done
|
||||
for MANIFESTIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}" "${QUAYIMAGE}"; do
|
||||
docker buildx imagetools create -t ${MANIFESTIMAGE}:latest ${MANIFESTIMAGE}:amd64-latest ${MANIFESTIMAGE}:arm64v8-latest
|
||||
docker buildx imagetools create -t ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${META_TAG}
|
||||
|
||||
docker buildx imagetools create -t ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG}
|
||||
if [[ "${MANIFESTIMAGE}" == "${GITLABIMAGE}" ]]; then
|
||||
TIMEOUT_CMD="gitlab_timeout"
|
||||
else
|
||||
TIMEOUT_CMD=""
|
||||
fi
|
||||
${TIMEOUT_CMD} docker buildx imagetools create -t ${MANIFESTIMAGE}:latest ${MANIFESTIMAGE}:amd64-latest ${MANIFESTIMAGE}:arm64v8-latest || \
|
||||
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; }
|
||||
${TIMEOUT_CMD} docker buildx imagetools create -t ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${META_TAG} || \
|
||||
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; }
|
||||
${TIMEOUT_CMD} docker buildx imagetools create -t ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} || \
|
||||
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; }
|
||||
if [ -n "${SEMVER}" ]; then
|
||||
docker buildx imagetools create -t ${MANIFESTIMAGE}:${SEMVER} ${MANIFESTIMAGE}:amd64-${SEMVER} ${MANIFESTIMAGE}:arm64v8-${SEMVER}
|
||||
${TIMEOUT_CMD} docker buildx imagetools create -t ${MANIFESTIMAGE}:${SEMVER} ${MANIFESTIMAGE}:amd64-${SEMVER} ${MANIFESTIMAGE}:arm64v8-${SEMVER} || \
|
||||
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" && "${MANIFESTIMAGE}" != "${GITLABIMAGE}" ]]; then exit 1; fi; }
|
||||
fi
|
||||
done
|
||||
'''
|
||||
@@ -961,23 +1211,41 @@ pipeline {
|
||||
environment name: 'EXIT_STATUS', value: ''
|
||||
}
|
||||
steps {
|
||||
echo "Pushing New tag for current commit ${META_TAG}"
|
||||
sh '''curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/git/tags \
|
||||
-d '{"tag":"'${META_TAG}'",\
|
||||
"object": "'${COMMIT_SHA}'",\
|
||||
"message": "Tagging Release '${EXT_RELEASE_CLEAN}'-ls'${LS_TAG_NUMBER}' to master",\
|
||||
"type": "commit",\
|
||||
"tagger": {"name": "LinuxServer-CI","email": "ci@linuxserver.io","date": "'${GITHUB_DATE}'"}}' '''
|
||||
echo "Pushing New release for Tag"
|
||||
sh '''#! /bin/bash
|
||||
echo "Auto-generating release notes"
|
||||
if [ "$(git tag --points-at HEAD)" != "" ]; then
|
||||
echo "Existing tag points to current commit, suggesting no new LS changes"
|
||||
AUTO_RELEASE_NOTES="No changes"
|
||||
else
|
||||
AUTO_RELEASE_NOTES=$(curl -fsL -H "Authorization: token ${GITHUB_TOKEN}" -H "Accept: application/vnd.github+json" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/releases/generate-notes \
|
||||
-d '{"tag_name":"'${META_TAG}'",\
|
||||
"target_commitish": "master"}' \
|
||||
| jq -r '.body' | sed 's|## What.s Changed||')
|
||||
fi
|
||||
echo "Pushing New tag for current commit ${META_TAG}"
|
||||
curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/git/tags \
|
||||
-d '{"tag":"'${META_TAG}'",\
|
||||
"object": "'${COMMIT_SHA}'",\
|
||||
"message": "Tagging Release '${EXT_RELEASE_CLEAN}'-ls'${LS_TAG_NUMBER}' to master",\
|
||||
"type": "commit",\
|
||||
"tagger": {"name": "LinuxServer-CI","email": "ci@linuxserver.io","date": "'${GITHUB_DATE}'"}}'
|
||||
echo "Pushing New release for Tag"
|
||||
echo "Updating PIP version of ${EXT_PIP} to ${EXT_RELEASE_CLEAN}" > releasebody.json
|
||||
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**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'''
|
||||
jq -n \
|
||||
--arg tag_name "$META_TAG" \
|
||||
--arg target_commitish "master" \
|
||||
--arg ci_url "${CI_URL:-N/A}" \
|
||||
--arg ls_notes "$AUTO_RELEASE_NOTES" \
|
||||
--arg remote_notes "$(cat releasebody.json)" \
|
||||
'{
|
||||
"tag_name": $tag_name,
|
||||
"target_commitish": $target_commitish,
|
||||
"name": $tag_name,
|
||||
"body": ("**CI Report:**\\n\\n" + $ci_url + "\\n\\n**LinuxServer Changes:**\\n\\n" + $ls_notes + "\\n\\n**Remote Changes:**\\n\\n" + $remote_notes),
|
||||
"draft": false,
|
||||
"prerelease": false }' > 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
|
||||
'''
|
||||
}
|
||||
}
|
||||
// Add protection to the release branch
|
||||
@@ -1015,98 +1283,13 @@ EOF
|
||||
) '''
|
||||
}
|
||||
}
|
||||
// If this is a Pull request send the CI link as a comment on it
|
||||
stage('Pull Request Comment') {
|
||||
when {
|
||||
not {environment name: 'CHANGE_ID', value: ''}
|
||||
environment name: 'EXIT_STATUS', value: ''
|
||||
}
|
||||
steps {
|
||||
sh '''#! /bin/bash
|
||||
# Function to retrieve JSON data from URL
|
||||
get_json() {
|
||||
local url="$1"
|
||||
local response=$(curl -s "$url")
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to retrieve JSON data from $url"
|
||||
return 1
|
||||
fi
|
||||
local json=$(echo "$response" | jq .)
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to parse JSON data from $url"
|
||||
return 1
|
||||
fi
|
||||
echo "$json"
|
||||
}
|
||||
|
||||
build_table() {
|
||||
local data="$1"
|
||||
|
||||
# Get the keys in the JSON data
|
||||
local keys=$(echo "$data" | jq -r 'to_entries | map(.key) | .[]')
|
||||
|
||||
# Check if keys are empty
|
||||
if [ -z "$keys" ]; then
|
||||
echo "JSON report data does not contain any keys or the report does not exist."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Build table header
|
||||
local header="| Tag | Passed |\\n| --- | --- |\\n"
|
||||
|
||||
# Loop through the JSON data to build the table rows
|
||||
local rows=""
|
||||
for build in $keys; do
|
||||
local status=$(echo "$data" | jq -r ".[\\"$build\\"].test_success")
|
||||
if [ "$status" = "true" ]; then
|
||||
status="✅"
|
||||
else
|
||||
status="❌"
|
||||
fi
|
||||
local row="| "$build" | "$status" |\\n"
|
||||
rows="${rows}${row}"
|
||||
done
|
||||
|
||||
local table="${header}${rows}"
|
||||
local escaped_table=$(echo "$table" | sed 's/\"/\\\\"/g')
|
||||
echo "$escaped_table"
|
||||
}
|
||||
|
||||
if [[ "${CI}" = "true" ]]; then
|
||||
# Retrieve JSON data from URL
|
||||
data=$(get_json "$CI_JSON_URL")
|
||||
# Create table from JSON data
|
||||
table=$(build_table "$data")
|
||||
echo -e "$table"
|
||||
|
||||
curl -X POST -H "Authorization: token $GITHUB_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
"https://api.github.com/repos/$LS_USER/$LS_REPO/issues/$PULL_REQUEST/comments" \
|
||||
-d "{\\"body\\": \\"I am a bot, here are the test results for this PR: \\n${CI_URL}\\n${SHELLCHECK_URL}\\n${table}\\"}"
|
||||
else
|
||||
curl -X POST -H "Authorization: token $GITHUB_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
"https://api.github.com/repos/$LS_USER/$LS_REPO/issues/$PULL_REQUEST/comments" \
|
||||
-d "{\\"body\\": \\"I am a bot, here is the pushed image/manifest for this PR: \\n\\n\\`${GITHUBIMAGE}:${META_TAG}\\`\\"}"
|
||||
fi
|
||||
'''
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ######################
|
||||
Send status to Discord
|
||||
Comment on PR and Send status to Discord
|
||||
###################### */
|
||||
post {
|
||||
always {
|
||||
sh '''#!/bin/bash
|
||||
rm -rf /config/.ssh/id_sign
|
||||
rm -rf /config/.ssh/id_sign.pub
|
||||
git config --global --unset gpg.format
|
||||
git config --global --unset user.signingkey
|
||||
git config --global --unset commit.gpgsign
|
||||
'''
|
||||
script{
|
||||
script {
|
||||
env.JOB_DATE = sh(
|
||||
script: '''date '+%Y-%m-%dT%H:%M:%S%:z' ''',
|
||||
returnStdout: true).trim()
|
||||
@@ -1149,15 +1332,113 @@ EOF
|
||||
"username": "Jenkins"}' ${BUILDS_DISCORD} '''
|
||||
}
|
||||
}
|
||||
script {
|
||||
if (env.GITHUBIMAGE =~ /lspipepr/){
|
||||
if (env.CI_TEST_ATTEMPTED == "true" || env.PUSH_ATTEMPTED == "true"){
|
||||
sh '''#! /bin/bash
|
||||
# Function to retrieve JSON data from URL
|
||||
get_json() {
|
||||
local url="$1"
|
||||
local response=$(curl -s "$url")
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to retrieve JSON data from $url"
|
||||
return 1
|
||||
fi
|
||||
local json=$(echo "$response" | jq .)
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to parse JSON data from $url"
|
||||
return 1
|
||||
fi
|
||||
echo "$json"
|
||||
}
|
||||
|
||||
build_table() {
|
||||
local data="$1"
|
||||
|
||||
# Get the keys in the JSON data
|
||||
local keys=$(echo "$data" | jq -r 'to_entries | map(.key) | .[]')
|
||||
|
||||
# Check if keys are empty
|
||||
if [ -z "$keys" ]; then
|
||||
echo "JSON report data does not contain any keys or the report does not exist."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Build table header
|
||||
local header="| Tag | Passed |\\n| --- | --- |\\n"
|
||||
|
||||
# Loop through the JSON data to build the table rows
|
||||
local rows=""
|
||||
for build in $keys; do
|
||||
local status=$(echo "$data" | jq -r ".[\\"$build\\"].test_success")
|
||||
if [ "$status" = "true" ]; then
|
||||
status="✅"
|
||||
else
|
||||
status="❌"
|
||||
fi
|
||||
local row="| "$build" | "$status" |\\n"
|
||||
rows="${rows}${row}"
|
||||
done
|
||||
|
||||
local table="${header}${rows}"
|
||||
local escaped_table=$(echo "$table" | sed 's/\"/\\\\"/g')
|
||||
echo "$escaped_table"
|
||||
}
|
||||
|
||||
if [[ "${CI}" = "true" ]]; then
|
||||
# Retrieve JSON data from URL
|
||||
data=$(get_json "$CI_JSON_URL")
|
||||
# Create table from JSON data
|
||||
table=$(build_table "$data")
|
||||
echo -e "$table"
|
||||
|
||||
curl -X POST -H "Authorization: token $GITHUB_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
"https://api.github.com/repos/$LS_USER/$LS_REPO/issues/$PULL_REQUEST/comments" \
|
||||
-d "{\\"body\\": \\"I am a bot, here are the test results for this PR for commit ${COMMIT_SHA:0:7} : \\n${CI_URL}\\n${SHELLCHECK_URL}\\n${table}\\"}"
|
||||
else
|
||||
curl -X POST -H "Authorization: token $GITHUB_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
"https://api.github.com/repos/$LS_USER/$LS_REPO/issues/$PULL_REQUEST/comments" \
|
||||
-d "{\\"body\\": \\"I am a bot, here is the pushed image/manifest for this PR for commit ${COMMIT_SHA:0:7} : \\n\\n\\`${GITHUBIMAGE}:${META_TAG}\\`\\"}"
|
||||
fi
|
||||
'''
|
||||
} else {
|
||||
sh '''#! /bin/bash
|
||||
curl -X POST -H "Authorization: token $GITHUB_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
"https://api.github.com/repos/$LS_USER/$LS_REPO/issues/$PULL_REQUEST/comments" \
|
||||
-d "{\\"body\\": \\"I am a bot, the build for PR commit ${COMMIT_SHA:0:7} failed and as a result no CI test was attempted and no images were pushed.\\"}"
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
sh '''#!/bin/bash
|
||||
rm -rf /config/.ssh/id_sign
|
||||
rm -rf /config/.ssh/id_sign.pub
|
||||
git config --global --unset gpg.format
|
||||
git config --global --unset user.signingkey
|
||||
git config --global --unset commit.gpgsign
|
||||
'''
|
||||
}
|
||||
cleanup {
|
||||
sh '''#! /bin/bash
|
||||
echo "Performing docker system prune!!"
|
||||
containers=$(docker ps -aq)
|
||||
echo "Pruning builder!!"
|
||||
docker builder prune -f --builder container || :
|
||||
containers=$(docker ps -q)
|
||||
if [[ -n "${containers}" ]]; then
|
||||
docker stop ${containers}
|
||||
BUILDX_CONTAINER_ID=$(docker ps -qf 'name=buildx_buildkit')
|
||||
for container in ${containers}; do
|
||||
if [[ "${container}" == "${BUILDX_CONTAINER_ID}" ]]; then
|
||||
echo "skipping buildx container in docker stop"
|
||||
else
|
||||
echo "Stopping container ${container}"
|
||||
docker stop ${container}
|
||||
fi
|
||||
done
|
||||
fi
|
||||
docker system prune -af --volumes || :
|
||||
docker system prune -f --volumes || :
|
||||
docker image prune -af || :
|
||||
'''
|
||||
cleanWs()
|
||||
}
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
[](https://linuxserver.io)
|
||||
|
||||
[](https://blog.linuxserver.io "all the things you can do with our containers including How-To guides, opinions and much more!")
|
||||
[](https://discord.gg/YWrKVTn "realtime support / chat with the community and the team.")
|
||||
[](https://discourse.linuxserver.io "post on our community forum.")
|
||||
[](https://fleet.linuxserver.io "an online web interface which displays all of our maintained images.")
|
||||
[](https://linuxserver.io/discord "realtime support / chat with the community and the team.")
|
||||
[](https://github.com/orgs/linuxserver/discussions "post on our community forum.")
|
||||
[](https://github.com/linuxserver "view the source for all of our repositories.")
|
||||
[](https://opencollective.com/linuxserver "please consider helping us by either donating or contributing to our budget")
|
||||
|
||||
@@ -20,9 +19,8 @@ The [LinuxServer.io](https://linuxserver.io) team brings you another container r
|
||||
Find us at:
|
||||
|
||||
* [Blog](https://blog.linuxserver.io) - all the things you can do with our containers including How-To guides, opinions and much more!
|
||||
* [Discord](https://discord.gg/YWrKVTn) - realtime support / chat with the community and the team.
|
||||
* [Discourse](https://discourse.linuxserver.io) - post on our community forum.
|
||||
* [Fleet](https://fleet.linuxserver.io) - an online web interface which displays all of our maintained images.
|
||||
* [Discord](https://linuxserver.io/discord) - realtime support / chat with the community and the team.
|
||||
* [Discussions](https://github.com/orgs/linuxserver/discussions) - post on our community forum.
|
||||
* [GitHub](https://github.com/linuxserver) - view the source for all of our repositories.
|
||||
* [Open Collective](https://opencollective.com/linuxserver) - please consider helping us by either donating or contributing to our budget
|
||||
|
||||
@@ -54,7 +52,6 @@ The architectures supported by this image are:
|
||||
| :----: | :----: | ---- |
|
||||
| x86-64 | ✅ | amd64-\<version tag\> |
|
||||
| arm64 | ✅ | arm64v8-\<version tag\> |
|
||||
| armhf | ❌ | |
|
||||
|
||||
## Application Setup
|
||||
|
||||
@@ -71,7 +68,7 @@ The architectures supported by this image are:
|
||||
2. Certs that cover sub-subdomains of your main subdomain (ie. `*.yoursubdomain.duckdns.org`, set the `SUBDOMAINS` variable to `wildcard`)
|
||||
* `--cap-add=NET_ADMIN` is required for fail2ban to modify iptables
|
||||
* After setup, navigate to `https://example.com` to access the default homepage (http access through port 80 is disabled by default, you can enable it by editing the default site config at `/config/nginx/site-confs/default.conf`).
|
||||
* Certs are checked nightly and if expiration is within 30 days, renewal is attempted. If your cert is about to expire in less than 30 days, check the logs under `/config/log/letsencrypt` to see why the renewals have been failing. It is recommended to input your e-mail in docker parameters so you receive expiration notices from Let's Encrypt in those circumstances.
|
||||
* Certs are checked twice daily using ACME Renewal Information (ARI) to determine the optimal renewal window. If your cert is about to expire, check the logs under `/config/log/letsencrypt` to see why the renewals have been failing.
|
||||
|
||||
### Certbot Plugins
|
||||
|
||||
@@ -145,6 +142,16 @@ This will *ask* Google et al not to index and list your site. Be careful with th
|
||||
* Proxy sample files WILL be updated, however your renamed (enabled) proxy files will not.
|
||||
* You can check the new sample and adjust your active config as needed.
|
||||
|
||||
### QUIC support
|
||||
|
||||
This image supports QUIC (also known as HTTP/3) but it must be explicitly enabled in each proxy conf, and the default conf, because if the listener is enabled and you don't expose 443/UDP, it can break connections with some browsers.
|
||||
|
||||
To enable QUIC, expose 443/UDP to your clients, then uncomment both QUIC listeners in all of your active proxy confs, as well as the default conf, and restart the container.
|
||||
|
||||
You should also uncomment the `Alt-Svc` header in your `ssl.conf` so that browsers are aware that you offer QUIC connectivity.
|
||||
|
||||
It is [recommended](https://quic-go.net/docs/quic/optimizations/#udp-buffer-sizes) to increase the UDP send/recieve buffer **on the host** by setting the `net.core.rmem_max` and `net.core.wmem_max` sysctls. Suggested values are 4-16Mb (4194304-16777216 bytes). For persistence between reboots use `/etc/sysctl.d/`.
|
||||
|
||||
### Migration from the old `linuxserver/letsencrypt` image
|
||||
|
||||
Please follow the instructions [on this blog post](https://www.linuxserver.io/blog/2020-08-21-introducing-swag#migrate).
|
||||
@@ -163,7 +170,7 @@ This image can be run with a read-only container filesystem. For details please
|
||||
To help you get started creating a container from this image you can either use docker-compose or the docker cli.
|
||||
|
||||
>[!NOTE]
|
||||
>Unless a parameter is flaged as 'optional', it is *mandatory* and a value must be provided.
|
||||
>Unless a parameter is flagged as 'optional', it is *mandatory* and a value must be provided.
|
||||
|
||||
### docker-compose (recommended, [click here for more info](https://docs.linuxserver.io/general/docker-compose))
|
||||
|
||||
@@ -183,6 +190,7 @@ services:
|
||||
- VALIDATION=http
|
||||
- SUBDOMAINS=www, #optional
|
||||
- CERTPROVIDER= #optional
|
||||
- CERT_PROFILE= #optional
|
||||
- DNSPLUGIN=cloudflare #optional
|
||||
- PROPAGATION= #optional
|
||||
- EMAIL= #optional
|
||||
@@ -197,6 +205,7 @@ services:
|
||||
ports:
|
||||
- 443:443
|
||||
- 80:80 #optional
|
||||
- 443:443/udp #optional
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
@@ -213,6 +222,7 @@ docker run -d \
|
||||
-e VALIDATION=http \
|
||||
-e SUBDOMAINS=www, `#optional` \
|
||||
-e CERTPROVIDER= `#optional` \
|
||||
-e CERT_PROFILE= `#optional` \
|
||||
-e DNSPLUGIN=cloudflare `#optional` \
|
||||
-e PROPAGATION= `#optional` \
|
||||
-e EMAIL= `#optional` \
|
||||
@@ -224,6 +234,7 @@ docker run -d \
|
||||
-e SWAG_AUTORELOAD_WATCHLIST= `#optional` \
|
||||
-p 443:443 \
|
||||
-p 80:80 `#optional` \
|
||||
-p 443:443/udp `#optional` \
|
||||
-v /path/to/swag/config:/config \
|
||||
--restart unless-stopped \
|
||||
lscr.io/linuxserver/swag:latest
|
||||
@@ -237,6 +248,7 @@ Containers are configured using parameters passed at runtime (such as those abov
|
||||
| :----: | --- |
|
||||
| `-p 443:443` | HTTPS port |
|
||||
| `-p 80` | HTTP port (required for HTTP validation and HTTP -> HTTPS redirect) |
|
||||
| `-p 443/udp` | QUIC (HTTP/3) port. Must be enabled in the default and proxy confs. |
|
||||
| `-e PUID=1000` | for UserID - see below for explanation |
|
||||
| `-e PGID=1000` | for GroupID - see below for explanation |
|
||||
| `-e TZ=Etc/UTC` | specify a timezone to use, see this [list](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List). |
|
||||
@@ -244,15 +256,16 @@ Containers are configured using parameters passed at runtime (such as those abov
|
||||
| `-e VALIDATION=http` | Certbot validation method to use, options are `http` or `dns` (`dns` method also requires `DNSPLUGIN` variable set). |
|
||||
| `-e SUBDOMAINS=www,` | Subdomains you'd like the cert to cover (comma separated, no spaces) ie. `www,ftp,cloud`. For a wildcard cert, set this *exactly* to `wildcard` (wildcard cert is available via `dns` validation only) |
|
||||
| `-e CERTPROVIDER=` | Optionally define the cert provider. Set to `zerossl` for ZeroSSL certs (requires existing [ZeroSSL account](https://app.zerossl.com/signup) and the e-mail address entered in `EMAIL` env var). Otherwise defaults to Let's Encrypt. |
|
||||
| `-e DNSPLUGIN=cloudflare` | Required if `VALIDATION` is set to `dns`. Options are `acmedns`, `aliyun`, `azure`, `bunny`, `cloudflare`, `cpanel`, `desec`, `digitalocean`, `directadmin`, `dnsimple`, `dnsmadeeasy`, `dnspod`, `do`, `domeneshop`, `dreamhost`, `duckdns`, `dynu`, `freedns`, `gandi`, `gehirn`, `glesys`, `godaddy`, `google`, `he`, `hetzner`, `infomaniak`, `inwx`, `ionos`, `linode`, `loopia`, `luadns`, `namecheap`, `netcup`, `njalla`, `nsone`, `ovh`, `porkbun`, `rfc2136`, `route53`, `sakuracloud`, `standalone`, `transip`, and `vultr`. Also need to enter the credentials into the corresponding ini (or json for some plugins) file under `/config/dns-conf`. |
|
||||
| `-e CERT_PROFILE=` | Optionally define a cert profile to use for cert generation. This is useful if you want to use a custom cert profile instead of the default one. Currently only supported for Let's Encrypt. See https://letsencrypt.org/docs/profiles/ |
|
||||
| `-e DNSPLUGIN=cloudflare` | Required if `VALIDATION` is set to `dns`. Options are `acmedns`, `aliyun`, `azure`, `bunny`, `cloudflare`, `cpanel`, `desec`, `digitalocean`, `directadmin`, `dnsimple`, `dnsmadeeasy`, `dnspod`, `do`, `domeneshop`, `dreamhost`, `duckdns`, `dynu`, `freedns`, `gandi`, `gehirn`, `glesys`, `godaddy`, `google`, `he`, `hetzner`, `hetzner-cloud`, `infomaniak`, `inwx`, `ionos`, `linode`, `loopia`, `luadns`, `mijn-host`, `namecheap`, `netcup`, `njalla`, `nsone`, `ovh`, `porkbun`, `rfc2136`, `route53`, `sakuracloud`, `standalone`, `transip`, and `vultr`. Also need to enter the credentials into the corresponding ini (or json for some plugins) file under `/config/dns-conf`. |
|
||||
| `-e PROPAGATION=` | Optionally override (in seconds) the default propagation time for the dns plugins. |
|
||||
| `-e EMAIL=` | Optional e-mail address used for cert expiration notifications (Required for ZeroSSL). |
|
||||
| `-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. |
|
||||
| `-e SWAG_AUTORELOAD=` | Set to `true` to enable automatic reloading of nginx confs on change. Your filesystem must support inotify. This functionality was previously offered [via mod](https://github.com/linuxserver/docker-mods/tree/swag-auto-reload). |
|
||||
| `-e SWAG_AUTORELOAD_WATCHLIST=` | A `|`-separated list of additional folders for auto reload to watch in addition to `/config/nginx` |
|
||||
| `-e SWAG_AUTORELOAD=` | Set to `true` to enable automatic reloading of confs on change without stopping/restarting nginx. Your filesystem must support inotify. This functionality was previously offered [via mod](https://github.com/linuxserver/docker-mods/tree/swag-auto-reload). |
|
||||
| `-e SWAG_AUTORELOAD_WATCHLIST=` | A [pipe](https://en.wikipedia.org/wiki/Vertical_bar)-separated list of additional folders for auto reload to watch in addition to `/config/nginx` |
|
||||
| `-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. |
|
||||
@@ -423,6 +436,16 @@ Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64
|
||||
|
||||
## Versions
|
||||
|
||||
* **09.09.26:** - Use new X-Tinyauth-Location header in Tinyauth locations and remove duplicate auth module headers.
|
||||
* **19.07.26:** - Rebase to Alpine 3.24 with PHP 8.5.
|
||||
* **10.07.26:** - Add support for Let's Encrypt cert profiles. Run certbot twice daily with a random delay.
|
||||
* **19.06.26:** - Add support for mijn.host dns validation.
|
||||
* **01.06.26:** - Remove obsolete old cert check logic.
|
||||
* **23.01.26:** - Reorder init to fix proxy conf version checks.
|
||||
* **21.12.25:** - Add support for hetzner-cloud dns validation.
|
||||
* **04.11.25:** - Switch default Gandi credentials from API Key to Token, allow DNS propagation time for Azure DNS plugin.
|
||||
* **18.07.25:** - Rebase to Alpine 3.22 with PHP 8.4. Add QUIC support. Drop PHP bindings for mcrypt as it is no longer maintained.
|
||||
* **05.05.25:** - Disable Certbot's built in log rotation.
|
||||
* **19.01.25:** - Add [Auto Reload](https://github.com/linuxserver/docker-mods/tree/swag-auto-reload) functionality to SWAG.
|
||||
* **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).
|
||||
|
||||
+322
-311
@@ -1,365 +1,376 @@
|
||||
NAME VERSION TYPE
|
||||
Simple Launcher 1.1.0.14 dotnet (+5 duplicates)
|
||||
Simple Launcher 1.1.0.14 binary (+5 duplicates)
|
||||
acl-libs 2.3.2-r1 apk
|
||||
acme 3.1.0 python
|
||||
alpine-baselayout 3.6.8-r1 apk
|
||||
alpine-baselayout-data 3.6.8-r1 apk
|
||||
alpine-keys 2.5-r0 apk
|
||||
alpine-release 3.21.2-r0 apk
|
||||
aom-libs 3.11.0-r0 apk
|
||||
apache2-utils 2.4.62-r0 apk
|
||||
apk-tools 2.14.6-r2 apk
|
||||
apr 1.7.5-r0 apk
|
||||
apr-util 1.6.3-r1 apk
|
||||
acme 5.8.0 python
|
||||
alpine-baselayout 3.7.2-r1 apk
|
||||
alpine-baselayout-data 3.7.2-r1 apk
|
||||
alpine-keys 2.6-r0 apk
|
||||
alpine-release 3.24.2-r0 apk
|
||||
annotated-types 0.8.0 python
|
||||
anyio 4.15.1 python
|
||||
aom-libs 3.14.1-r0 apk
|
||||
apache2-utils 2.4.69-r0 apk
|
||||
apk-tools 3.0.8-r0 apk
|
||||
apr 1.7.6-r0 apk
|
||||
apr-util 1.6.4-r0 apk
|
||||
argon2-libs 20190702-r5 apk
|
||||
attrs 24.3.0 python
|
||||
autocommand 2.2.2 python
|
||||
azure-common 1.1.28 python
|
||||
azure-core 1.32.0 python
|
||||
azure-identity 1.19.0 python
|
||||
azure-mgmt-core 1.5.0 python
|
||||
azure-mgmt-dns 8.2.0 python
|
||||
azure-core 1.41.0 python
|
||||
azure-identity 1.26.0 python
|
||||
azure-mgmt-core 1.6.0 python
|
||||
azure-mgmt-dns 9.0.0 python
|
||||
backports-tarfile 1.2.0 python
|
||||
bash 5.2.37-r0 apk
|
||||
beautifulsoup4 4.12.3 python
|
||||
boto3 1.36.2 python
|
||||
botocore 1.36.2 python
|
||||
brotli-libs 1.1.0-r2 apk
|
||||
bash 5.3.9-r1 apk
|
||||
beautifulsoup4 4.15.0 python
|
||||
boto3 1.43.114 python
|
||||
botocore 1.43.114 python
|
||||
brotli-libs 1.2.0-r1 apk
|
||||
bs4 0.0.2 python
|
||||
busybox 1.37.0-r12 apk
|
||||
busybox-binsh 1.37.0-r12 apk
|
||||
c-ares 1.34.3-r0 apk
|
||||
c-client 2007f-r15 apk
|
||||
ca-certificates 20241121-r1 apk
|
||||
ca-certificates-bundle 20241121-r1 apk
|
||||
cachetools 5.5.0 python
|
||||
catatonit 0.2.0-r0 apk
|
||||
certbot 3.1.0 python
|
||||
busybox 1.37.0-r31 apk
|
||||
busybox-binsh 1.37.0-r31 apk
|
||||
c-ares 1.34.8-r0 apk
|
||||
ca-certificates 20260909-r0 apk
|
||||
ca-certificates-bundle 20260909-r0 apk
|
||||
catatonit 0.2.1-r0 apk
|
||||
certbot 5.8.0 python
|
||||
certbot-dns-acmedns 0.1.0 python
|
||||
certbot-dns-aliyun 2.0.0 python
|
||||
certbot-dns-azure 2.6.1 python
|
||||
certbot-dns-azure 1.5.0 python
|
||||
certbot-dns-bunny 3.0.0 python
|
||||
certbot-dns-cloudflare 3.1.0 python
|
||||
certbot-dns-cloudflare 5.8.0 python
|
||||
certbot-dns-cpanel 0.4.0 python
|
||||
certbot-dns-desec 1.2.1 python
|
||||
certbot-dns-digitalocean 3.1.0 python
|
||||
certbot-dns-directadmin 1.0.13 python
|
||||
certbot-dns-dnsimple 3.1.0 python
|
||||
certbot-dns-dnsmadeeasy 3.1.0 python
|
||||
certbot-dns-desec 1.3.2 python
|
||||
certbot-dns-digitalocean 5.8.0 python
|
||||
certbot-dns-directadmin 1.0.15 python
|
||||
certbot-dns-dnsimple 5.8.0 python
|
||||
certbot-dns-dnsmadeeasy 5.8.0 python
|
||||
certbot-dns-dnspod 0.1.0 python
|
||||
certbot-dns-do 0.31.0 python
|
||||
certbot-dns-domeneshop 0.2.9 python
|
||||
certbot-dns-dreamhost 1.0 python
|
||||
certbot-dns-duckdns 1.5 python
|
||||
certbot-dns-duckdns 1.9.0 python
|
||||
certbot-dns-dynudns 0.0.6 python
|
||||
certbot-dns-freedns 0.2.0 python
|
||||
certbot-dns-gehirn 3.1.0 python
|
||||
certbot-dns-gehirn 5.8.0 python
|
||||
certbot-dns-glesys 2.1.0 python
|
||||
certbot-dns-godaddy 2.8.0 python
|
||||
certbot-dns-google 3.1.0 python
|
||||
certbot-dns-google 5.8.0 python
|
||||
certbot-dns-he 1.0.0 python
|
||||
certbot-dns-hetzner 2.0.1 python
|
||||
certbot-dns-infomaniak 0.2.3 python
|
||||
certbot-dns-inwx 3.0.1 python
|
||||
certbot-dns-hetzner 4.0.0 python
|
||||
certbot-dns-hetzner-cloud 1.0.5 python
|
||||
certbot-dns-infomaniak 0.3.3 python
|
||||
certbot-dns-inwx 3.0.3 python
|
||||
certbot-dns-ionos 2024.11.9 python
|
||||
certbot-dns-linode 3.1.0 python
|
||||
certbot-dns-linode 5.8.0 python
|
||||
certbot-dns-loopia 1.0.1 python
|
||||
certbot-dns-luadns 3.1.0 python
|
||||
certbot-dns-luadns 5.8.0 python
|
||||
certbot-dns-mijn-host 0.0.10 python
|
||||
certbot-dns-namecheap 1.0.0 python
|
||||
certbot-dns-netcup 1.4.4 python
|
||||
certbot-dns-netcup 2.1.0 python
|
||||
certbot-dns-njalla 2.0.2 python
|
||||
certbot-dns-nsone 3.1.0 python
|
||||
certbot-dns-ovh 3.1.0 python
|
||||
certbot-dns-porkbun 0.9.1 python
|
||||
certbot-dns-rfc2136 3.1.0 python
|
||||
certbot-dns-route53 3.1.0 python
|
||||
certbot-dns-sakuracloud 3.1.0 python
|
||||
certbot-dns-standalone 1.1 python
|
||||
certbot-dns-nsone 5.8.0 python
|
||||
certbot-dns-ovh 5.8.0 python
|
||||
certbot-dns-porkbun 0.11.0 python
|
||||
certbot-dns-rfc2136 5.8.0 python
|
||||
certbot-dns-route53 5.8.0 python
|
||||
certbot-dns-sakuracloud 5.8.0 python
|
||||
certbot-dns-standalone 1.2.1 python
|
||||
certbot-dns-transip 0.5.2 python
|
||||
certbot-dns-vultr 1.1.0 python
|
||||
certbot-plugin-gandi 1.5.0 python
|
||||
certifi 2024.12.14 python
|
||||
cffi 1.17.1 python
|
||||
charset-normalizer 3.4.1 python
|
||||
cloudflare 2.19.4 python
|
||||
composer 2.8.4 binary
|
||||
configargparse 1.7 python
|
||||
certifi 2026.7.22 python
|
||||
cffi 2.1.1 python
|
||||
charset-normalizer 3.5.2 python
|
||||
cli UNKNOWN binary
|
||||
cli-32 UNKNOWN binary
|
||||
cli-64 UNKNOWN binary
|
||||
cli-arm64 UNKNOWN binary
|
||||
cloudflare 5.9.0 python
|
||||
composer 2.10.3 binary
|
||||
configargparse 1.8.0 python
|
||||
configobj 5.0.9 python
|
||||
coreutils 9.5-r2 apk
|
||||
coreutils-env 9.5-r2 apk
|
||||
coreutils-fmt 9.5-r2 apk
|
||||
coreutils-sha512sum 9.5-r2 apk
|
||||
cryptography 44.0.0 python
|
||||
curl 8.11.1-r0 apk
|
||||
coreutils 9.11-r0 apk
|
||||
coreutils-env 9.11-r0 apk
|
||||
coreutils-fmt 9.11-r0 apk
|
||||
coreutils-sha512sum 9.11-r0 apk
|
||||
cryptography 50.0.2 python
|
||||
curl 8.22.0-r0 apk
|
||||
distro 1.9.0 python
|
||||
dns-lexicon 3.20.1 python
|
||||
dnslib 0.9.25 python
|
||||
dnspython 2.7.0 python
|
||||
dns-lexicon 3.25.2 python
|
||||
dnslib 0.9.26 python
|
||||
dnspython 2.9.0 python
|
||||
domeneshop 0.4.4 python
|
||||
fail2ban 1.1.0 python
|
||||
fail2ban 1.1.0-r2 apk
|
||||
fail2ban-pyc 1.1.0-r2 apk
|
||||
filelock 3.16.1 python
|
||||
findutils 4.10.0-r0 apk
|
||||
fontconfig 2.15.0-r1 apk
|
||||
freetype 2.13.3-r0 apk
|
||||
fail2ban 1.1.0-r3 apk
|
||||
fail2ban-pyc 1.1.0-r3 apk
|
||||
filelock 4.2.0 python
|
||||
findutils 4.10.0-r1 apk
|
||||
fontconfig 2.17.1-r1 apk
|
||||
freetype 2.14.3-r0 apk
|
||||
future 1.0.0 python
|
||||
gdbm 1.24-r0 apk
|
||||
git 2.47.2-r0 apk
|
||||
git-init-template 2.47.2-r0 apk
|
||||
git-perl 2.47.2-r0 apk
|
||||
gmp 6.3.0-r2 apk
|
||||
gnupg 2.4.7-r0 apk
|
||||
gnupg-dirmngr 2.4.7-r0 apk
|
||||
gnupg-gpgconf 2.4.7-r0 apk
|
||||
gnupg-keyboxd 2.4.7-r0 apk
|
||||
gnupg-utils 2.4.7-r0 apk
|
||||
gnupg-wks-client 2.4.7-r0 apk
|
||||
gnutls 3.8.8-r0 apk
|
||||
google-api-core 2.24.0 python
|
||||
google-api-python-client 2.159.0 python
|
||||
google-auth 2.37.0 python
|
||||
google-auth-httplib2 0.2.0 python
|
||||
googleapis-common-protos 1.66.0 python
|
||||
gpg 2.4.7-r0 apk
|
||||
gpg-agent 2.4.7-r0 apk
|
||||
gpg-wks-server 2.4.7-r0 apk
|
||||
gpgsm 2.4.7-r0 apk
|
||||
gpgv 2.4.7-r0 apk
|
||||
httplib2 0.22.0 python
|
||||
icu-data-en 74.2-r0 apk
|
||||
icu-libs 74.2-r0 apk
|
||||
idna 3.10 python
|
||||
importlib-metadata 8.0.0 python
|
||||
inflect 7.3.1 python
|
||||
gdbm 1.26-r0 apk
|
||||
git 2.54.0-r0 apk
|
||||
git-init-template 2.54.0-r0 apk
|
||||
git-perl 2.54.0-r0 apk
|
||||
gmp 6.3.0-r4 apk
|
||||
gnupg 2.4.9-r1 apk
|
||||
gnupg-dirmngr 2.4.9-r1 apk
|
||||
gnupg-gpgconf 2.4.9-r1 apk
|
||||
gnupg-keyboxd 2.4.9-r1 apk
|
||||
gnupg-utils 2.4.9-r1 apk
|
||||
gnupg-wks-client 2.4.9-r1 apk
|
||||
gnutls 3.8.13-r0 apk
|
||||
google-api-core 2.42.0 python
|
||||
google-api-python-client 2.201.0 python
|
||||
google-auth 2.62.0 python
|
||||
google-auth-httplib2 0.4.4 python
|
||||
googleapis-common-protos 1.75.5 python
|
||||
gpg 2.4.9-r1 apk
|
||||
gpg-agent 2.4.9-r1 apk
|
||||
gpg-wks-server 2.4.9-r1 apk
|
||||
gpgsm 2.4.9-r1 apk
|
||||
gpgv 2.4.9-r1 apk
|
||||
gui UNKNOWN binary
|
||||
gui-32 UNKNOWN binary
|
||||
gui-64 UNKNOWN binary
|
||||
gui-arm64 UNKNOWN binary
|
||||
h11 0.16.0 python
|
||||
hcloud 2.27.0 python
|
||||
httpcore 1.0.9 python
|
||||
httplib2 0.32.0 python
|
||||
httpx 0.28.1 python
|
||||
icu-data-en 78.1-r0 apk
|
||||
icu-libs 78.1-r0 apk
|
||||
idna 3.20 python
|
||||
importlib-metadata 8.7.1 python
|
||||
inotify-tools 4.23.9.0-r0 apk
|
||||
inotify-tools-libs 4.23.9.0-r0 apk
|
||||
inwx-domrobot 3.2.0 python
|
||||
iptables 1.8.10-r5 apk
|
||||
iptables-legacy 1.8.10-r5 apk
|
||||
iptables 1.8.13-r0 apk
|
||||
iptables-legacy 1.8.13-r0 apk
|
||||
isodate 0.7.2 python
|
||||
jaraco-collections 5.1.0 python
|
||||
jaraco-context 5.3.0 python
|
||||
jaraco-functools 4.0.1 python
|
||||
jaraco-text 3.12.1 python
|
||||
jmespath 1.0.1 python
|
||||
josepy 1.14.0 python
|
||||
jq 1.7.1-r0 apk
|
||||
jsonlines 4.0.0 python
|
||||
jsonpickle 4.0.1 python
|
||||
libassuan 2.5.7-r0 apk
|
||||
jaraco-context 6.1.0 python
|
||||
jaraco-functools 4.4.0 python
|
||||
jaraco-text 4.0.0 python
|
||||
jinja2 3.1.6 python
|
||||
jmespath 1.1.0 python
|
||||
josepy 2.2.0 python
|
||||
jq 1.8.2-r0 apk
|
||||
jsonpickle 4.1.4 python
|
||||
libapk 3.0.8-r0 apk
|
||||
libassuan 3.0.2-r0 apk
|
||||
libattr 2.5.2-r2 apk
|
||||
libavif 1.0.4-r0 apk
|
||||
libavif 1.4.1-r0 apk
|
||||
libbsd 0.12.2-r0 apk
|
||||
libbz2 1.0.8-r6 apk
|
||||
libcrypto3 3.3.2-r4 apk
|
||||
libcurl 8.11.1-r0 apk
|
||||
libdav1d 1.5.0-r0 apk
|
||||
libedit 20240808.3.1-r0 apk
|
||||
libevent 2.1.12-r7 apk
|
||||
libexpat 2.6.4-r0 apk
|
||||
libffi 3.4.6-r0 apk
|
||||
libgcc 14.2.0-r4 apk
|
||||
libgcrypt 1.10.3-r1 apk
|
||||
libgd 2.3.3-r9 apk
|
||||
libgpg-error 1.51-r0 apk
|
||||
libice 1.1.1-r6 apk
|
||||
libidn2 2.3.7-r0 apk
|
||||
libintl 0.22.5-r0 apk
|
||||
libip4tc 1.8.10-r5 apk
|
||||
libip6tc 1.8.10-r5 apk
|
||||
libjpeg-turbo 3.0.4-r0 apk
|
||||
libksba 1.6.7-r0 apk
|
||||
libldap 2.6.8-r0 apk
|
||||
libmaxminddb-libs 1.9.1-r0 apk
|
||||
libmcrypt 2.5.8-r10 apk
|
||||
libmd 1.1.0-r0 apk
|
||||
libcrypto3 3.5.9-r0 apk
|
||||
libcurl 8.22.0-r0 apk
|
||||
libdav1d 1.5.3-r0 apk
|
||||
libedit 20260508.3.1-r1 apk
|
||||
libevent 2.1.13-r0 apk
|
||||
libexpat 2.8.5-r0 apk
|
||||
libffi 3.5.2-r1 apk
|
||||
libgcc 15.2.0-r5 apk
|
||||
libgcrypt 1.12.2-r0 apk
|
||||
libgd 2.3.3-r10 apk
|
||||
libgpg-error 1.61-r0 apk
|
||||
libice 1.1.2-r0 apk
|
||||
libidn2 2.3.8-r0 apk
|
||||
libintl 1.0-r0 apk
|
||||
libip4tc 1.8.13-r0 apk
|
||||
libip6tc 1.8.13-r0 apk
|
||||
libjpeg-turbo 3.1.3-r0 apk
|
||||
libksba 1.7.0-r0 apk
|
||||
libldap 2.6.15-r0 apk
|
||||
libmaxminddb-libs 1.13.3-r0 apk
|
||||
libmd 1.2.0-r0 apk
|
||||
libmemcached-libs 1.1.4-r1 apk
|
||||
libmnl 1.0.5-r2 apk
|
||||
libncursesw 6.5_p20241006-r3 apk
|
||||
libnftnl 1.2.8-r0 apk
|
||||
libpanelw 6.5_p20241006-r3 apk
|
||||
libpng 1.6.44-r0 apk
|
||||
libpq 17.2-r0 apk
|
||||
libproc2 4.0.4-r2 apk
|
||||
libncursesw 6.6_p20260516-r0 apk
|
||||
libnftnl 1.3.1-r0 apk
|
||||
libpanelw 6.6_p20260516-r0 apk
|
||||
libpng 1.6.59-r0 apk
|
||||
libpq 18.6-r0 apk
|
||||
libproc2 4.0.6-r0 apk
|
||||
libpsl 0.21.5-r3 apk
|
||||
libsasl 2.1.28-r8 apk
|
||||
libseccomp 2.5.5-r1 apk
|
||||
libsharpyuv 1.4.0-r0 apk
|
||||
libsm 1.2.4-r4 apk
|
||||
libsodium 1.0.20-r0 apk
|
||||
libssl3 3.3.2-r4 apk
|
||||
libstdc++ 14.2.0-r4 apk
|
||||
libtasn1 4.19.0-r2 apk
|
||||
libunistring 1.2-r0 apk
|
||||
libuuid 2.40.4-r0 apk
|
||||
libwebp 1.4.0-r0 apk
|
||||
libx11 1.8.10-r0 apk
|
||||
libxau 1.0.11-r4 apk
|
||||
libxcb 1.16.1-r0 apk
|
||||
libsasl 2.1.28-r9 apk
|
||||
libseccomp 2.6.1-r0 apk
|
||||
libsharpyuv 1.6.0-r0 apk
|
||||
libsm 1.2.6-r0 apk
|
||||
libsodium 1.0.22-r0 apk
|
||||
libssl3 3.5.9-r0 apk
|
||||
libstdc++ 15.2.0-r5 apk
|
||||
libtasn1 4.21.0-r0 apk
|
||||
libunistring 1.4.2-r0 apk
|
||||
libuuid 2.42.3-r1 apk
|
||||
libwebp 1.6.0-r0 apk
|
||||
libx11 1.8.13-r0 apk
|
||||
libxau 1.0.12-r0 apk
|
||||
libxcb 1.17.0-r2 apk
|
||||
libxdmcp 1.1.5-r1 apk
|
||||
libxext 1.3.6-r2 apk
|
||||
libxml2 2.13.4-r3 apk
|
||||
libxpm 3.5.17-r0 apk
|
||||
libxslt 1.1.42-r1 apk
|
||||
libxext 1.3.7-r0 apk
|
||||
libxml2 2.13.9-r2 apk
|
||||
libxpm 3.5.19-r0 apk
|
||||
libxslt 1.1.43-r3 apk
|
||||
libxt 1.3.1-r0 apk
|
||||
libxtables 1.8.10-r5 apk
|
||||
libzip 1.11.2-r0 apk
|
||||
linux-pam 1.6.1-r1 apk
|
||||
logrotate 3.21.0-r1 apk
|
||||
libxtables 1.8.13-r0 apk
|
||||
libyuv 0.0.1928-r0 apk
|
||||
libzip 1.11.4-r2 apk
|
||||
linux-pam 1.7.1-r2 apk
|
||||
logrotate 3.22.0-r0 apk
|
||||
loopialib 0.2.0 python
|
||||
lxml 5.3.0 python
|
||||
lz4-libs 1.10.0-r0 apk
|
||||
memcached 1.6.32-r0 apk
|
||||
mock 5.1.0 python
|
||||
more-itertools 10.3.0 python
|
||||
mpdecimal 4.0.0-r0 apk
|
||||
msal 1.31.1 python
|
||||
msal-extensions 1.2.0 python
|
||||
musl 1.2.5-r8 apk
|
||||
musl-utils 1.2.5-r8 apk
|
||||
my-test-package 1.0 python
|
||||
nano 8.2-r0 apk
|
||||
ncurses-terminfo-base 6.5_p20241006-r3 apk
|
||||
netcat-openbsd 1.226.1.1-r0 apk
|
||||
nettle 3.10-r1 apk
|
||||
nghttp2-libs 1.64.0-r0 apk
|
||||
nginx 1.26.2-r4 apk
|
||||
nginx-mod-devel-kit 1.26.2-r4 apk
|
||||
nginx-mod-http-brotli 1.26.2-r4 apk
|
||||
nginx-mod-http-dav-ext 1.26.2-r4 apk
|
||||
nginx-mod-http-echo 1.26.2-r4 apk
|
||||
nginx-mod-http-fancyindex 1.26.2-r4 apk
|
||||
nginx-mod-http-geoip2 1.26.2-r4 apk
|
||||
nginx-mod-http-headers-more 1.26.2-r4 apk
|
||||
nginx-mod-http-image-filter 1.26.2-r4 apk
|
||||
nginx-mod-http-perl 1.26.2-r4 apk
|
||||
nginx-mod-http-redis2 1.26.2-r4 apk
|
||||
nginx-mod-http-set-misc 1.26.2-r4 apk
|
||||
nginx-mod-http-upload-progress 1.26.2-r4 apk
|
||||
nginx-mod-http-xslt-filter 1.26.2-r4 apk
|
||||
nginx-mod-mail 1.26.2-r4 apk
|
||||
nginx-mod-rtmp 1.26.2-r4 apk
|
||||
nginx-mod-stream 1.26.2-r4 apk
|
||||
nginx-mod-stream-geoip2 1.26.2-r4 apk
|
||||
nginx-vim 1.26.2-r4 apk
|
||||
npth 1.6-r4 apk
|
||||
oniguruma 6.9.9-r0 apk
|
||||
openssl 3.3.2-r4 apk
|
||||
p11-kit 0.25.5-r2 apk
|
||||
packaging 24.2 python
|
||||
lxml 6.1.3 python
|
||||
lz4-libs 1.10.0-r1 apk
|
||||
markupsafe 3.0.4 python
|
||||
memcached 1.6.42-r0 apk
|
||||
mock 5.2.0 python
|
||||
more-itertools 10.8.0 python
|
||||
mpdecimal 4.0.1-r0 apk
|
||||
msal 1.39.0 python
|
||||
msal-extensions 1.3.1 python
|
||||
musl 1.2.6-r2 apk
|
||||
musl-utils 1.2.6-r2 apk
|
||||
nano 9.2-r0 apk
|
||||
ncurses-terminfo-base 6.6_p20260516-r0 apk
|
||||
netcat-openbsd 1.234.1-r0 apk
|
||||
nettle 3.10.2-r0 apk
|
||||
nghttp2-libs 1.70.0-r0 apk
|
||||
nginx 1.30.4-r1 apk
|
||||
nginx-mod-devel-kit 1.30.4-r1 apk
|
||||
nginx-mod-http-brotli 1.30.4-r1 apk
|
||||
nginx-mod-http-dav-ext 1.30.4-r1 apk
|
||||
nginx-mod-http-echo 1.30.4-r1 apk
|
||||
nginx-mod-http-fancyindex 1.30.4-r1 apk
|
||||
nginx-mod-http-geoip2 1.30.4-r1 apk
|
||||
nginx-mod-http-headers-more 1.30.4-r1 apk
|
||||
nginx-mod-http-image-filter 1.30.4-r1 apk
|
||||
nginx-mod-http-perl 1.30.4-r1 apk
|
||||
nginx-mod-http-redis2 1.30.4-r1 apk
|
||||
nginx-mod-http-set-misc 1.30.4-r1 apk
|
||||
nginx-mod-http-upload-progress 1.30.4-r1 apk
|
||||
nginx-mod-http-xslt-filter 1.30.4-r1 apk
|
||||
nginx-mod-mail 1.30.4-r1 apk
|
||||
nginx-mod-rtmp 1.30.4-r1 apk
|
||||
nginx-mod-stream 1.30.4-r1 apk
|
||||
nginx-mod-stream-geoip2 1.30.4-r1 apk
|
||||
nginx-vim 1.30.4-r1 apk
|
||||
npth 1.8-r0 apk
|
||||
oniguruma 6.9.10-r0 apk
|
||||
openssl 3.5.9-r0 apk
|
||||
opentelemetry-api 1.45.1 python
|
||||
p11-kit 0.26.2-r0 apk
|
||||
packaging 26.0 python
|
||||
packaging 26.3 python
|
||||
parsedatetime 2.6 python
|
||||
pcre 8.45-r3 apk
|
||||
pcre2 10.43-r0 apk
|
||||
perl 5.40.1-r0 apk
|
||||
perl-error 0.17029-r2 apk
|
||||
perl-git 2.47.2-r0 apk
|
||||
php83 8.3.16-r0 apk
|
||||
php83-bcmath 8.3.16-r0 apk
|
||||
php83-bz2 8.3.16-r0 apk
|
||||
php83-common 8.3.16-r0 apk
|
||||
php83-ctype 8.3.16-r0 apk
|
||||
php83-curl 8.3.16-r0 apk
|
||||
php83-dom 8.3.16-r0 apk
|
||||
php83-exif 8.3.16-r0 apk
|
||||
php83-fileinfo 8.3.16-r0 apk
|
||||
php83-fpm 8.3.16-r0 apk
|
||||
php83-ftp 8.3.16-r0 apk
|
||||
php83-gd 8.3.16-r0 apk
|
||||
php83-gmp 8.3.16-r0 apk
|
||||
php83-iconv 8.3.16-r0 apk
|
||||
php83-imap 8.3.16-r0 apk
|
||||
php83-intl 8.3.16-r0 apk
|
||||
php83-ldap 8.3.16-r0 apk
|
||||
php83-mbstring 8.3.16-r0 apk
|
||||
php83-mysqli 8.3.16-r0 apk
|
||||
php83-mysqlnd 8.3.16-r0 apk
|
||||
php83-opcache 8.3.16-r0 apk
|
||||
php83-openssl 8.3.16-r0 apk
|
||||
php83-pdo 8.3.16-r0 apk
|
||||
php83-pdo_mysql 8.3.16-r0 apk
|
||||
php83-pdo_odbc 8.3.16-r0 apk
|
||||
php83-pdo_pgsql 8.3.16-r0 apk
|
||||
php83-pdo_sqlite 8.3.16-r0 apk
|
||||
php83-pear 8.3.16-r0 apk
|
||||
php83-pecl-apcu 5.1.24-r0 apk
|
||||
php83-pecl-igbinary 3.2.16-r0 apk
|
||||
php83-pecl-mcrypt 1.0.7-r0 apk
|
||||
php83-pecl-memcached 3.3.0-r0 apk
|
||||
php83-pecl-msgpack 3.0.0-r0 apk
|
||||
php83-pecl-redis 6.1.0-r0 apk
|
||||
php83-pgsql 8.3.16-r0 apk
|
||||
php83-phar 8.3.16-r0 apk
|
||||
php83-posix 8.3.16-r0 apk
|
||||
php83-session 8.3.16-r0 apk
|
||||
php83-simplexml 8.3.16-r0 apk
|
||||
php83-soap 8.3.16-r0 apk
|
||||
php83-sockets 8.3.16-r0 apk
|
||||
php83-sodium 8.3.16-r0 apk
|
||||
php83-sqlite3 8.3.16-r0 apk
|
||||
php83-tokenizer 8.3.16-r0 apk
|
||||
php83-xml 8.3.16-r0 apk
|
||||
php83-xmlreader 8.3.16-r0 apk
|
||||
php83-xmlwriter 8.3.16-r0 apk
|
||||
php83-xsl 8.3.16-r0 apk
|
||||
php83-zip 8.3.16-r0 apk
|
||||
pinentry 1.3.1-r0 apk
|
||||
pip 24.3.1 python
|
||||
pkb-client 2.0.0 python
|
||||
platformdirs 4.2.2 python
|
||||
pcre2 10.49-r0 apk
|
||||
perl 5.42.2-r1 apk
|
||||
perl-error 0.17030-r0 apk
|
||||
perl-git 2.54.0-r0 apk
|
||||
php85 8.5.11-r0 apk
|
||||
php85-bcmath 8.5.11-r0 apk
|
||||
php85-bz2 8.5.11-r0 apk
|
||||
php85-common 8.5.11-r0 apk
|
||||
php85-ctype 8.5.11-r0 apk
|
||||
php85-curl 8.5.11-r0 apk
|
||||
php85-dom 8.5.11-r0 apk
|
||||
php85-exif 8.5.11-r0 apk
|
||||
php85-fileinfo 8.5.11-r0 apk
|
||||
php85-fpm 8.5.11-r0 apk
|
||||
php85-ftp 8.5.11-r0 apk
|
||||
php85-gd 8.5.11-r0 apk
|
||||
php85-gmp 8.5.11-r0 apk
|
||||
php85-iconv 8.5.11-r0 apk
|
||||
php85-intl 8.5.11-r0 apk
|
||||
php85-ldap 8.5.11-r0 apk
|
||||
php85-mbstring 8.5.11-r0 apk
|
||||
php85-mysqli 8.5.11-r0 apk
|
||||
php85-mysqlnd 8.5.11-r0 apk
|
||||
php85-openssl 8.5.11-r0 apk
|
||||
php85-pdo 8.5.11-r0 apk
|
||||
php85-pdo_mysql 8.5.11-r0 apk
|
||||
php85-pdo_odbc 8.5.11-r0 apk
|
||||
php85-pdo_pgsql 8.5.11-r0 apk
|
||||
php85-pdo_sqlite 8.5.11-r0 apk
|
||||
php85-pear 8.5.11-r0 apk
|
||||
php85-pecl-apcu 5.1.28-r0 apk
|
||||
php85-pecl-igbinary 3.2.17_rc1-r0 apk
|
||||
php85-pecl-memcached 3.4.0-r0 apk
|
||||
php85-pecl-msgpack 3.0.1-r0 apk
|
||||
php85-pecl-redis 6.3.0-r0 apk
|
||||
php85-pgsql 8.5.11-r0 apk
|
||||
php85-phar 8.5.11-r0 apk
|
||||
php85-posix 8.5.11-r0 apk
|
||||
php85-session 8.5.11-r0 apk
|
||||
php85-simplexml 8.5.11-r0 apk
|
||||
php85-soap 8.5.11-r0 apk
|
||||
php85-sockets 8.5.11-r0 apk
|
||||
php85-sodium 8.5.11-r0 apk
|
||||
php85-sqlite3 8.5.11-r0 apk
|
||||
php85-tokenizer 8.5.11-r0 apk
|
||||
php85-xml 8.5.11-r0 apk
|
||||
php85-xmlreader 8.5.11-r0 apk
|
||||
php85-xmlwriter 8.5.11-r0 apk
|
||||
php85-xsl 8.5.11-r0 apk
|
||||
php85-zip 8.5.11-r0 apk
|
||||
pinentry 1.3.2-r0 apk
|
||||
pip 26.2.1 python
|
||||
pkb-client 2.3.1 python
|
||||
platformdirs 4.4.0 python
|
||||
popt 1.19-r4 apk
|
||||
portalocker 2.10.1 python
|
||||
procps-ng 4.0.4-r2 apk
|
||||
proto-plus 1.25.0 python
|
||||
protobuf 5.29.3 python
|
||||
procps-ng 4.0.6-r0 apk
|
||||
proto-plus 1.29.0 python
|
||||
protobuf 7.36.2 python
|
||||
pyacmedns 0.4 python
|
||||
pyasn1 0.6.1 python
|
||||
pyasn1-modules 0.4.1 python
|
||||
pyc 3.12.8-r1 apk
|
||||
pycparser 2.22 python
|
||||
pyjwt 2.10.1 python
|
||||
pyasn1 0.6.4 python
|
||||
pyasn1-modules 0.4.2 python
|
||||
pyc 3.14.8-r0 apk
|
||||
pycparser 3.11 python
|
||||
pydantic 2.14.1 python
|
||||
pydantic-core 2.50.1 python
|
||||
pyjwt 2.15.1 python
|
||||
pynamecheap 0.0.3 python
|
||||
pyopenssl 25.0.0 python
|
||||
pyotp 2.9.0 python
|
||||
pyparsing 3.2.1 python
|
||||
pyrfc3339 2.0.1 python
|
||||
pyopenssl 26.4.0 python
|
||||
pyotp 2.10.0 python
|
||||
pyparsing 3.3.3 python
|
||||
pyrfc3339 2.1.1 python
|
||||
python-dateutil 2.9.0.post0 python
|
||||
python-digitalocean 1.17.0 python
|
||||
python-transip 0.6.0 python
|
||||
python3 3.12.8-r1 apk
|
||||
python3-pyc 3.12.8-r1 apk
|
||||
python3-pycache-pyc0 3.12.8-r1 apk
|
||||
pytz 2024.2 python
|
||||
pyyaml 6.0.2 python
|
||||
readline 8.2.13-r0 apk
|
||||
requests 2.32.3 python
|
||||
requests-file 2.1.0 python
|
||||
python3 3.14.8-r0 apk
|
||||
python3-pyc 3.14.8-r0 apk
|
||||
python3-pycache-pyc0 3.14.8-r0 apk
|
||||
pyyaml 6.0.3 python
|
||||
readline 8.3.3-r1 apk
|
||||
requests 2.34.2 python
|
||||
requests-file 3.0.1 python
|
||||
requests-mock 1.12.1 python
|
||||
rsa 4.9 python
|
||||
s3transfer 0.11.1 python
|
||||
scanelf 1.3.8-r1 apk
|
||||
setuptools 75.8.0 python
|
||||
shadow 4.16.0-r1 apk
|
||||
requests-unixsocket 0.4.1 python
|
||||
s3transfer 0.19.2 python
|
||||
scanelf 1.3.9-r1 apk
|
||||
setuptools 84.0.0 python
|
||||
shadow 4.18.0-r1 apk
|
||||
six 1.17.0 python
|
||||
skalibs-libs 2.14.3.0-r0 apk
|
||||
soupsieve 2.6 python
|
||||
sqlite-libs 3.47.1-r0 apk
|
||||
ssl_client 1.37.0-r12 apk
|
||||
tiff 4.7.0-r0 apk
|
||||
tldextract 5.1.3 python
|
||||
tomli 2.0.1 python
|
||||
typeguard 4.3.0 python
|
||||
typing-extensions 4.12.2 python (+1 duplicate)
|
||||
tzdata 2024b-r1 apk
|
||||
unixodbc 2.3.12-r0 apk
|
||||
uritemplate 4.1.1 python
|
||||
urllib3 2.3.0 python
|
||||
utmps-libs 0.1.2.3-r2 apk
|
||||
wheel 0.43.0 python
|
||||
wheel 0.45.1 python
|
||||
whois 5.5.23-r0 apk
|
||||
xz-libs 5.6.3-r0 apk
|
||||
zipp 3.19.2 python
|
||||
zlib 1.3.1-r2 apk
|
||||
zope-interface 7.2 python
|
||||
zstd-libs 1.5.6-r2 apk
|
||||
skalibs-libs 2.15.0.0-r0 apk
|
||||
sniffio 1.3.1 python
|
||||
soupsieve 3.0.3 python
|
||||
sqlite-libs 3.53.4-r0 apk
|
||||
ssl_client 1.37.0-r31 apk
|
||||
tiff 4.7.2-r0 apk
|
||||
tldextract 5.4.0 python
|
||||
tomli 2.4.0 python
|
||||
typing-extensions 4.16.0 python
|
||||
typing-inspection 0.4.4 python
|
||||
tzdata 2026e-r0 apk
|
||||
unixodbc 2.3.14-r1 apk
|
||||
uritemplate 4.2.0 python
|
||||
urllib3 2.8.0 python
|
||||
utmps-libs 0.1.3.3-r0 apk
|
||||
wheel 0.46.3 python
|
||||
wheel 0.48.0 python
|
||||
whois 5.6.6-r0 apk
|
||||
xz-libs 5.8.4-r0 apk
|
||||
zipp 3.23.0 python
|
||||
zlib 1.3.2-r1 apk
|
||||
zope-interface 8.7 python
|
||||
zstd-libs 1.5.7-r2 apk
|
||||
+33
-7
@@ -6,6 +6,7 @@ project_url: "https://linuxserver.io"
|
||||
project_logo: "https://github.com/linuxserver/docker-templates/raw/master/linuxserver.io/img/swag.gif"
|
||||
project_blurb: "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."
|
||||
project_lsio_github_repo_url: "https://github.com/linuxserver/docker-{{ project_name }}"
|
||||
project_categories: "Reverse Proxy"
|
||||
# supported architectures
|
||||
available_architectures:
|
||||
- {arch: "{{ arch_x86_64 }}", tag: "amd64-latest"}
|
||||
@@ -31,18 +32,20 @@ opt_param_usage_include_env: true
|
||||
opt_param_env_vars:
|
||||
- {env_var: "SUBDOMAINS", env_value: "www,", desc: "Subdomains you'd like the cert to cover (comma separated, no spaces) ie. `www,ftp,cloud`. For a wildcard cert, set this *exactly* to `wildcard` (wildcard cert is available via `dns` validation only)"}
|
||||
- {env_var: "CERTPROVIDER", env_value: "", desc: "Optionally define the cert provider. Set to `zerossl` for ZeroSSL certs (requires existing [ZeroSSL account](https://app.zerossl.com/signup) and the e-mail address entered in `EMAIL` env var). Otherwise defaults to Let's Encrypt."}
|
||||
- {env_var: "DNSPLUGIN", env_value: "cloudflare", desc: "Required if `VALIDATION` is set to `dns`. Options are `acmedns`, `aliyun`, `azure`, `bunny`, `cloudflare`, `cpanel`, `desec`, `digitalocean`, `directadmin`, `dnsimple`, `dnsmadeeasy`, `dnspod`, `do`, `domeneshop`, `dreamhost`, `duckdns`, `dynu`, `freedns`, `gandi`, `gehirn`, `glesys`, `godaddy`, `google`, `he`, `hetzner`, `infomaniak`, `inwx`, `ionos`, `linode`, `loopia`, `luadns`, `namecheap`, `netcup`, `njalla`, `nsone`, `ovh`, `porkbun`, `rfc2136`, `route53`, `sakuracloud`, `standalone`, `transip`, and `vultr`. Also need to enter the credentials into the corresponding ini (or json for some plugins) file under `/config/dns-conf`."}
|
||||
- {env_var: "CERT_PROFILE", env_value: "", desc: "Optionally define a cert profile to use for cert generation. This is useful if you want to use a custom cert profile instead of the default one. Currently only supported for Let's Encrypt. See https://letsencrypt.org/docs/profiles/ "}
|
||||
- {env_var: "DNSPLUGIN", env_value: "cloudflare", desc: "Required if `VALIDATION` is set to `dns`. Options are `acmedns`, `aliyun`, `azure`, `bunny`, `cloudflare`, `cpanel`, `desec`, `digitalocean`, `directadmin`, `dnsimple`, `dnsmadeeasy`, `dnspod`, `do`, `domeneshop`, `dreamhost`, `duckdns`, `dynu`, `freedns`, `gandi`, `gehirn`, `glesys`, `godaddy`, `google`, `he`, `hetzner`, `hetzner-cloud`, `infomaniak`, `inwx`, `ionos`, `linode`, `loopia`, `luadns`, `mijn-host`, `namecheap`, `netcup`, `njalla`, `nsone`, `ovh`, `porkbun`, `rfc2136`, `route53`, `sakuracloud`, `standalone`, `transip`, and `vultr`. Also need to enter the credentials into the corresponding ini (or json for some plugins) file under `/config/dns-conf`."}
|
||||
- {env_var: "PROPAGATION", env_value: "", desc: "Optionally override (in seconds) the default propagation time for the dns plugins."}
|
||||
- {env_var: "EMAIL", env_value: "", desc: "Optional e-mail address used for cert expiration notifications (Required for ZeroSSL)."}
|
||||
- {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."}
|
||||
- {env_var: "SWAG_AUTORELOAD", env_value: "", desc: "Set to `true` to enable automatic reloading of nginx confs on change. Your filesystem must support inotify. This functionality was previously offered [via mod](https://github.com/linuxserver/docker-mods/tree/swag-auto-reload)."}
|
||||
- {env_var: "SWAG_AUTORELOAD_WATCHLIST", env_value: "", desc: "A `|`-separated list of additional folders for auto reload to watch in addition to `/config/nginx`"}
|
||||
- {env_var: "SWAG_AUTORELOAD", env_value: "", desc: "Set to `true` to enable automatic reloading of confs on change without stopping/restarting nginx. Your filesystem must support inotify. This functionality was previously offered [via mod](https://github.com/linuxserver/docker-mods/tree/swag-auto-reload)."}
|
||||
- {env_var: "SWAG_AUTORELOAD_WATCHLIST", env_value: "", desc: "A [pipe](https://en.wikipedia.org/wiki/Vertical_bar)-separated list of additional folders for auto reload to watch in addition to `/config/nginx`"}
|
||||
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)"}
|
||||
- {external_port: "443", internal_port: "443/udp", port_desc: "QUIC (HTTP/3) port. Must be enabled in the default and proxy confs."}
|
||||
readonly_supported: true
|
||||
readonly_message: |
|
||||
* `/tmp` must be mounted to tmpfs
|
||||
@@ -63,7 +66,7 @@ app_setup_block: |
|
||||
2. Certs that cover sub-subdomains of your main subdomain (ie. `*.yoursubdomain.duckdns.org`, set the `SUBDOMAINS` variable to `wildcard`)
|
||||
* `--cap-add=NET_ADMIN` is required for fail2ban to modify iptables
|
||||
* After setup, navigate to `https://example.com` to access the default homepage (http access through port 80 is disabled by default, you can enable it by editing the default site config at `/config/nginx/site-confs/default.conf`).
|
||||
* Certs are checked nightly and if expiration is within 30 days, renewal is attempted. If your cert is about to expire in less than 30 days, check the logs under `/config/log/letsencrypt` to see why the renewals have been failing. It is recommended to input your e-mail in docker parameters so you receive expiration notices from Let's Encrypt in those circumstances.
|
||||
* Certs are checked twice daily using ACME Renewal Information (ARI) to determine the optimal renewal window. If your cert is about to expire, check the logs under `/config/log/letsencrypt` to see why the renewals have been failing.
|
||||
|
||||
### Certbot Plugins
|
||||
|
||||
@@ -137,6 +140,16 @@ app_setup_block: |
|
||||
* Proxy sample files WILL be updated, however your renamed (enabled) proxy files will not.
|
||||
* You can check the new sample and adjust your active config as needed.
|
||||
|
||||
### QUIC support
|
||||
|
||||
This image supports QUIC (also known as HTTP/3) but it must be explicitly enabled in each proxy conf, and the default conf, because if the listener is enabled and you don't expose 443/UDP, it can break connections with some browsers.
|
||||
|
||||
To enable QUIC, expose 443/UDP to your clients, then uncomment both QUIC listeners in all of your active proxy confs, as well as the default conf, and restart the container.
|
||||
|
||||
You should also uncomment the `Alt-Svc` header in your `ssl.conf` so that browsers are aware that you offer QUIC connectivity.
|
||||
|
||||
It is [recommended](https://quic-go.net/docs/quic/optimizations/#udp-buffer-sizes) to increase the UDP send/recieve buffer **on the host** by setting the `net.core.rmem_max` and `net.core.wmem_max` sysctls. Suggested values are 4-16Mb (4194304-16777216 bytes). For persistence between reboots use `/etc/sysctl.d/`.
|
||||
|
||||
### Migration from the old `linuxserver/letsencrypt` image
|
||||
|
||||
Please follow the instructions [on this blog post](https://www.linuxserver.io/blog/2020-08-21-introducing-swag#migrate).
|
||||
@@ -163,8 +176,9 @@ init_diagram: |
|
||||
init-outdated-config -> init-config-end
|
||||
init-config -> init-crontab-config
|
||||
init-mods-end -> init-custom-files
|
||||
init-adduser -> init-device-perms
|
||||
base -> init-envfile
|
||||
init-swag-samples -> init-fail2ban-config
|
||||
init-require-url -> init-fail2ban-config
|
||||
init-os-end -> init-folders
|
||||
init-php -> init-keygen
|
||||
base -> init-migrations
|
||||
@@ -174,6 +188,7 @@ init_diagram: |
|
||||
init-samples -> init-nginx
|
||||
init-version-checks -> init-nginx-end
|
||||
init-adduser -> init-os-end
|
||||
init-device-perms -> init-os-end
|
||||
init-envfile -> init-os-end
|
||||
init-renew -> init-outdated-config
|
||||
init-keygen -> init-permissions
|
||||
@@ -184,9 +199,10 @@ init_diagram: |
|
||||
init-folders -> init-samples
|
||||
init-custom-files -> init-services
|
||||
init-fail2ban-config -> init-swag-config
|
||||
init-require-url -> init-swag-folders
|
||||
init-permissions -> init-swag-folders
|
||||
init-swag-folders -> init-swag-samples
|
||||
init-permissions -> init-version-checks
|
||||
init-swag-samples -> init-version-checks
|
||||
init-services -> svc-cron
|
||||
svc-cron -> legacy-services
|
||||
init-services -> svc-fail2ban
|
||||
@@ -199,11 +215,21 @@ init_diagram: |
|
||||
svc-swag-auto-reload -> legacy-services
|
||||
}
|
||||
Base Images: {
|
||||
"baseimage-alpine-nginx:3.21" <- "baseimage-alpine:3.21"
|
||||
"baseimage-alpine-nginx:3.24" <- "baseimage-alpine:3.24"
|
||||
}
|
||||
"swag:latest" <- Base Images
|
||||
# changelog
|
||||
changelogs:
|
||||
- {date: "09.09.26:", desc: "Use new X-Tinyauth-Location header in Tinyauth locations and remove duplicate auth module headers."}
|
||||
- {date: "19.07.26:", desc: "Rebase to Alpine 3.24 with PHP 8.5."}
|
||||
- {date: "10.07.26:", desc: "Add support for Let's Encrypt cert profiles. Run certbot twice daily with a random delay."}
|
||||
- {date: "19.06.26:", desc: "Add support for mijn.host dns validation."}
|
||||
- {date: "01.06.26:", desc: "Remove obsolete old cert check logic."}
|
||||
- {date: "23.01.26:", desc: "Reorder init to fix proxy conf version checks."}
|
||||
- {date: "21.12.25:", desc: "Add support for hetzner-cloud dns validation."}
|
||||
- {date: "04.11.25:", desc: "Switch default Gandi credentials from API Key to Token, allow DNS propagation time for Azure DNS plugin."}
|
||||
- {date: "18.07.25:", desc: "Rebase to Alpine 3.22 with PHP 8.4. Add QUIC support. Drop PHP bindings for mcrypt as it is no longer maintained."}
|
||||
- {date: "05.05.25:", desc: "Disable Certbot's built in log rotation."}
|
||||
- {date: "19.01.25:", desc: "Add [Auto Reload](https://github.com/linuxserver/docker-mods/tree/swag-auto-reload) functionality to SWAG."}
|
||||
- {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)."}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Instructions: https://github.com/obynio/certbot-plugin-gandi#usage
|
||||
# Replace with your value
|
||||
# live dns v5 api key
|
||||
dns_gandi_api_key=APIKEY
|
||||
# Replace with your Gandi Live DNS v5 Personal Access Token
|
||||
dns_gandi_token=TOKEN
|
||||
|
||||
# optional organization id, remove it if not used
|
||||
#dns_gandi_sharing_id=SHARINGID
|
||||
@@ -0,0 +1,2 @@
|
||||
# Hetzner Cloud API Token
|
||||
dns_hetzner_cloud_api_token = your_api_token_here
|
||||
@@ -0,0 +1,3 @@
|
||||
# Instructions: https://github.com/mijnhost/certbot-dns-mijn-host
|
||||
# Replace with your API key from your mijn.host account.
|
||||
dns_mijn_host_api_key = yourapikeygoeshere
|
||||
@@ -1,4 +1,4 @@
|
||||
# Instructions: https://github.com/certbot/certbot/blob/master/certbot-dns-ovh/certbot_dns_ovh/__init__.py#L20
|
||||
# Instructions: https://github.com/certbot/certbot/blob/main/certbot-dns-ovh/src/certbot_dns_ovh/__init__.py#L24
|
||||
# Replace with your values
|
||||
dns_ovh_endpoint = ovh-eu
|
||||
dns_ovh_application_key = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
## Version 2024/03/14 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/authelia-location.conf.sample
|
||||
## Version 2025/03/25 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/authelia-location.conf.sample
|
||||
# Make sure that your authelia container is in the same user defined bridge network and is named authelia
|
||||
# Rename /config/nginx/proxy-confs/authelia.subdomain.conf.sample to /config/nginx/proxy-confs/authelia.subdomain.conf
|
||||
# For authelia 4.37 and below, make sure that the authelia configuration.yml has 'path: "authelia"' defined
|
||||
# For authelia 4.38 and above, make sure that the authelia configuration.yml has 'address: "tcp://:9091/authelia"' defined
|
||||
|
||||
## Send a subrequest to Authelia to verify if the user is authenticated and has permission to access the resource
|
||||
## For authelia 4.37 and below, use the following line
|
||||
# auth_request /authelia/api/verify;
|
||||
## For authelia 4.38 and above, use the following line
|
||||
auth_request /authelia/api/authz/auth-request;
|
||||
|
||||
## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal
|
||||
|
||||
@@ -1,44 +1,15 @@
|
||||
## Version 2024/03/16 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/authelia-server.conf.sample
|
||||
## Version 2025/03/25 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/authelia-server.conf.sample
|
||||
# Make sure that your authelia container is in the same user defined bridge network and is named authelia
|
||||
# Rename /config/nginx/proxy-confs/authelia.subdomain.conf.sample to /config/nginx/proxy-confs/authelia.subdomain.conf
|
||||
# For authelia 4.37 and below, make sure that the authelia configuration.yml has 'path: "authelia"' defined
|
||||
# For authelia 4.38 and above, make sure that the authelia configuration.yml has 'address: "tcp://:9091/authelia"' defined
|
||||
|
||||
# location for authelia subfolder requests
|
||||
location ^~ /authelia {
|
||||
auth_request off; # requests to this subfolder must be accessible without authentication
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_authelia authelia;
|
||||
proxy_pass http://$upstream_authelia:9091;
|
||||
}
|
||||
|
||||
# location for authelia 4.37 and below auth requests
|
||||
location = /authelia/api/verify {
|
||||
internal;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_authelia authelia;
|
||||
proxy_pass http://$upstream_authelia:9091;
|
||||
|
||||
## Include the Set-Cookie header if present
|
||||
auth_request_set $set_cookie $upstream_http_set_cookie;
|
||||
add_header Set-Cookie $set_cookie;
|
||||
|
||||
proxy_pass_request_body off;
|
||||
proxy_set_header Content-Length "";
|
||||
}
|
||||
|
||||
# location for authelia 4.38 and above auth requests
|
||||
# location for authelia auth requests
|
||||
location = /authelia/api/authz/auth-request {
|
||||
internal;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_authelia authelia;
|
||||
proxy_pass http://$upstream_authelia:9091;
|
||||
proxy_pass http://$upstream_authelia:9091/api/authz/auth-request;
|
||||
|
||||
## Include the Set-Cookie header if present
|
||||
auth_request_set $set_cookie $upstream_http_set_cookie;
|
||||
@@ -62,11 +33,6 @@ location @authelia_proxy_signin {
|
||||
## Translate the Location response header from the auth subrequest into a variable
|
||||
auth_request_set $signin_url $upstream_http_location;
|
||||
|
||||
if ($signin_url = '') {
|
||||
## Set the $signin_url variable
|
||||
set $signin_url https://$http_host/authelia/?rd=$target_url;
|
||||
}
|
||||
|
||||
## Redirect to login
|
||||
return 302 $signin_url;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
## Version 2023/04/27 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/authentik-server.conf.sample
|
||||
## Version 2025/03/25 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/authentik-server.conf.sample
|
||||
# Make sure that your authentik container is in the same user defined bridge network and is named authentik-server
|
||||
# Rename /config/nginx/proxy-confs/authentik.subdomain.conf.sample to /config/nginx/proxy-confs/authentik.subdomain.conf
|
||||
|
||||
@@ -19,7 +19,7 @@ location = /outpost.goauthentik.io/auth/nginx {
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_authentik authentik-server;
|
||||
proxy_pass http://$upstream_authentik:9000;
|
||||
proxy_pass http://$upstream_authentik:9000/outpost.goauthentik.io/auth/nginx;
|
||||
|
||||
## Include the Set-Cookie header if present
|
||||
auth_request_set $set_cookie $upstream_http_set_cookie;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
## Version 2024/12/17 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/site-confs/default.conf.sample
|
||||
## Version 2026/03/07 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/site-confs/default.conf.sample
|
||||
|
||||
# redirect all traffic to https
|
||||
server {
|
||||
@@ -13,7 +13,9 @@ server {
|
||||
# main server block
|
||||
server {
|
||||
listen 443 ssl default_server;
|
||||
# listen 443 quic reuseport default_server;
|
||||
listen [::]:443 ssl default_server;
|
||||
# listen [::]:443 quic reuseport default_server;
|
||||
|
||||
server_name _;
|
||||
|
||||
@@ -34,6 +36,9 @@ server {
|
||||
# enable for Authentik (requires authentik-location.conf in the location block)
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
# enable for Tinyauth (requires tinyauth-location.conf in the location block)
|
||||
#include /config/nginx/tinyauth-server.conf;
|
||||
|
||||
location / {
|
||||
# enable for basic auth
|
||||
#auth_basic "Restricted";
|
||||
@@ -48,6 +53,9 @@ server {
|
||||
# enable for Authentik (requires authentik-server.conf in the server block)
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
# enable for Tinyauth (requires tinyauth-server.conf in the server block)
|
||||
#include /config/nginx/tinyauth-location.conf;
|
||||
|
||||
try_files $uri $uri/ /index.html /index.htm /index.php$is_args$args;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
## Version 2026/07/19 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/tinyauth-location.conf.sample
|
||||
# Make sure that your tinyauth container is in the same user defined bridge network and is named tinyauth
|
||||
# Rename /config/nginx/proxy-confs/tinyauth.subdomain.conf.sample to /config/nginx/proxy-confs/tinyauth.subdomain.conf
|
||||
|
||||
## Send a subrequest to tinyauth to verify if the user is authenticated and has permission to access the resource
|
||||
auth_request /tinyauth;
|
||||
auth_request_set $redirection_url $upstream_http_x_tinyauth_location;
|
||||
error_page 401 403 =302 $redirection_url;
|
||||
|
||||
## Translate the user information response headers from the auth subrequest into variables
|
||||
auth_request_set $email $upstream_http_remote_email;
|
||||
auth_request_set $groups $upstream_http_remote_groups;
|
||||
auth_request_set $name $upstream_http_remote_name;
|
||||
auth_request_set $user $upstream_http_remote_user;
|
||||
|
||||
## Inject the user information into the request made to the actual upstream
|
||||
proxy_set_header Remote-Email $email;
|
||||
proxy_set_header Remote-Groups $groups;
|
||||
proxy_set_header Remote-Name $name;
|
||||
proxy_set_header Remote-User $user;
|
||||
|
||||
## Can be extended with more custom headers https://tinyauth.app/docs/reference/headers#nginxnginx-proxy-manager
|
||||
@@ -0,0 +1,22 @@
|
||||
## Version 2026/09/08 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/tinyauth-server.conf.sample
|
||||
# Make sure that your tinyauth container is in the same user defined bridge network and is named tinyauth
|
||||
# Rename /config/nginx/proxy-confs/tinyauth.subdomain.conf.sample to /config/nginx/proxy-confs/tinyauth.subdomain.conf
|
||||
|
||||
# location for tinyauth auth requests
|
||||
location /tinyauth {
|
||||
internal;
|
||||
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_tinyauth tinyauth;
|
||||
proxy_pass http://$upstream_tinyauth:3000/api/auth/nginx;
|
||||
|
||||
# Don't send the body to the auth server
|
||||
proxy_pass_request_body off;
|
||||
proxy_set_header Content-Length "";
|
||||
|
||||
# Headers needed for authentication
|
||||
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
|
||||
proxy_set_header X-Original-Method $request_method;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
}
|
||||
@@ -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/renewal.log 2>&1
|
||||
0 */12 * * * sleep $((60 + $RANDOM % 230)); /app/le-renew.sh >> /config/log/letsencrypt/renewal.log 2>&1
|
||||
@@ -12,12 +12,13 @@ EXTRA_DOMAINS=${EXTRA_DOMAINS}\\n\
|
||||
ONLY_SUBDOMAINS=${ONLY_SUBDOMAINS}\\n\
|
||||
VALIDATION=${VALIDATION}\\n\
|
||||
CERTPROVIDER=${CERTPROVIDER}\\n\
|
||||
CERT_PROFILE=${CERT_PROFILE}\\n\
|
||||
DNSPLUGIN=${DNSPLUGIN}\\n\
|
||||
EMAIL=${EMAIL}\\n\
|
||||
STAGING=${STAGING}\\n"
|
||||
|
||||
# Sanitize variables
|
||||
SANED_VARS=(DNSPLUGIN EMAIL EXTRA_DOMAINS ONLY_SUBDOMAINS STAGING SUBDOMAINS URL VALIDATION CERTPROVIDER)
|
||||
SANED_VARS=(DNSPLUGIN EMAIL EXTRA_DOMAINS ONLY_SUBDOMAINS STAGING SUBDOMAINS URL VALIDATION CERTPROVIDER CERT_PROFILE)
|
||||
for i in "${SANED_VARS[@]}"; do
|
||||
export echo "${i}"="${!i//\"/}"
|
||||
export echo "${i}"="$(echo "${!i}" | tr '[:upper:]' '[:lower:]')"
|
||||
@@ -56,6 +57,12 @@ touch /config/etc/letsencrypt/cli.ini
|
||||
lsiown abc:abc /config/etc/letsencrypt/cli.ini
|
||||
grep -qF 'agree-tos' /config/etc/letsencrypt/cli.ini || echo 'agree-tos=true' >>/config/etc/letsencrypt/cli.ini
|
||||
|
||||
# Check for broken dns credentials value in cli.ini and remove
|
||||
sed -i '/dns--credentials/d' /config/etc/letsencrypt/cli.ini
|
||||
|
||||
# Disable Certbot's built in log rotation
|
||||
set_ini_value "max-log-backups" "0" /config/etc/letsencrypt/cli.ini
|
||||
|
||||
# copy dns default configs
|
||||
cp -n /defaults/dns-conf/* /config/dns-conf/ 2> >(grep -v 'cp: not replacing')
|
||||
lsiown -R abc:abc /config/dns-conf
|
||||
@@ -74,7 +81,7 @@ if [[ -f "/config/donoteditthisfile.conf" ]]; then
|
||||
mv /config/donoteditthisfile.conf /config/.donoteditthisfile.conf
|
||||
fi
|
||||
if [[ ! -f "/config/.donoteditthisfile.conf" ]]; then
|
||||
echo -e "ORIGURL=\"${URL}\" ORIGSUBDOMAINS=\"${SUBDOMAINS}\" ORIGONLY_SUBDOMAINS=\"${ONLY_SUBDOMAINS}\" ORIGEXTRA_DOMAINS=\"${EXTRA_DOMAINS}\" ORIGVALIDATION=\"${VALIDATION}\" ORIGDNSPLUGIN=\"${DNSPLUGIN}\" ORIGPROPAGATION=\"${PROPAGATION}\" ORIGSTAGING=\"${STAGING}\" ORIGCERTPROVIDER=\"${CERTPROVIDER}\" ORIGEMAIL=\"${EMAIL}\"" >/config/.donoteditthisfile.conf
|
||||
echo -e "ORIGURL=\"${URL}\" ORIGSUBDOMAINS=\"${SUBDOMAINS}\" ORIGONLY_SUBDOMAINS=\"${ONLY_SUBDOMAINS}\" ORIGEXTRA_DOMAINS=\"${EXTRA_DOMAINS}\" ORIGVALIDATION=\"${VALIDATION}\" ORIGDNSPLUGIN=\"${DNSPLUGIN}\" ORIGPROPAGATION=\"${PROPAGATION}\" ORIGSTAGING=\"${STAGING}\" ORIGCERTPROVIDER=\"${CERTPROVIDER}\" ORIGEMAIL=\"${EMAIL}\" ORIGCERT_PROFILE=\"${CERT_PROFILE}\"" >/config/.donoteditthisfile.conf
|
||||
echo "Created .donoteditthisfile.conf"
|
||||
fi
|
||||
|
||||
@@ -162,9 +169,9 @@ fi
|
||||
rm -rf /config/keys/letsencrypt
|
||||
if [[ "${ONLY_SUBDOMAINS}" = "true" ]] && [[ ! "${SUBDOMAINS}" = "wildcard" ]]; then
|
||||
DOMAIN="$(echo "${SUBDOMAINS}" | tr ',' ' ' | awk '{print $1}').${URL}"
|
||||
ln -s /config/etc/letsencrypt/live/"${DOMAIN}" /config/keys/letsencrypt
|
||||
ln -s ../etc/letsencrypt/live/"${DOMAIN}" /config/keys/letsencrypt
|
||||
else
|
||||
ln -s /config/etc/letsencrypt/live/"${URL}" /config/keys/letsencrypt
|
||||
ln -s ../etc/letsencrypt/live/"${URL}" /config/keys/letsencrypt
|
||||
fi
|
||||
|
||||
# cleanup unused csr and keys folders
|
||||
@@ -180,7 +187,8 @@ if [[ ! "${URL}" = "${ORIGURL}" ]] ||
|
||||
[[ ! "${DNSPLUGIN}" = "${ORIGDNSPLUGIN}" ]] ||
|
||||
[[ ! "${PROPAGATION}" = "${ORIGPROPAGATION}" ]] ||
|
||||
[[ ! "${STAGING}" = "${ORIGSTAGING}" ]] ||
|
||||
[[ ! "${CERTPROVIDER}" = "${ORIGCERTPROVIDER}" ]]; then
|
||||
[[ ! "${CERTPROVIDER}" = "${ORIGCERTPROVIDER}" ]] ||
|
||||
[[ ! "${CERT_PROFILE}" = "${ORIGCERT_PROFILE}" ]]; then
|
||||
echo "Different validation parameters entered than what was used before. Revoking and deleting existing certificate, and an updated one will be created"
|
||||
if [[ "${ORIGCERTPROVIDER}" = "zerossl" ]]; then
|
||||
REV_ACMESERVER=("https://acme.zerossl.com/v2/DV90")
|
||||
@@ -198,19 +206,7 @@ if [[ ! "${URL}" = "${ORIGURL}" ]] ||
|
||||
fi
|
||||
|
||||
# saving new variables
|
||||
echo -e "ORIGURL=\"${URL}\" ORIGSUBDOMAINS=\"${SUBDOMAINS}\" ORIGONLY_SUBDOMAINS=\"${ONLY_SUBDOMAINS}\" ORIGEXTRA_DOMAINS=\"${EXTRA_DOMAINS}\" ORIGVALIDATION=\"${VALIDATION}\" ORIGDNSPLUGIN=\"${DNSPLUGIN}\" ORIGPROPAGATION=\"${PROPAGATION}\" ORIGSTAGING=\"${STAGING}\" ORIGCERTPROVIDER=\"${CERTPROVIDER}\" ORIGEMAIL=\"${EMAIL}\"" >/config/.donoteditthisfile.conf
|
||||
|
||||
# Check if the cert is using the old LE root cert, revoke and regen if necessary
|
||||
if [[ -f "/config/keys/letsencrypt/chain.pem" ]] && { [[ "${CERTPROVIDER}" == "letsencrypt" ]] || [[ "${CERTPROVIDER}" == "" ]]; } && [[ "${STAGING}" != "true" ]] && ! openssl x509 -in /config/keys/letsencrypt/chain.pem -noout -issuer | grep -q "ISRG Root X"; then
|
||||
echo "The cert seems to be using the old LE root cert, which is no longer valid. Deleting and revoking."
|
||||
REV_ACMESERVER=("https://acme-v02.api.letsencrypt.org/directory")
|
||||
if [[ -f /config/etc/letsencrypt/live/"${ORIGDOMAIN}"/fullchain.pem ]]; then
|
||||
certbot revoke --config-dir /config/etc/letsencrypt --logs-dir /config/log/letsencrypt --work-dir /tmp/letsencrypt --config /config/etc/letsencrypt/cli.ini --non-interactive --cert-path /config/etc/letsencrypt/live/"${ORIGDOMAIN}"/fullchain.pem --server "${REV_ACMESERVER[@]}" || true
|
||||
else
|
||||
certbot revoke --config-dir /config/etc/letsencrypt --logs-dir /config/log/letsencrypt --work-dir /tmp/letsencrypt --config /config/etc/letsencrypt/cli.ini --non-interactive --cert-name "${ORIGDOMAIN}" --server "${REV_ACMESERVER[@]}" || true
|
||||
fi
|
||||
rm -rf /config/etc/letsencrypt/{accounts,archive,live,renewal}
|
||||
fi
|
||||
echo -e "ORIGURL=\"${URL}\" ORIGSUBDOMAINS=\"${SUBDOMAINS}\" ORIGONLY_SUBDOMAINS=\"${ONLY_SUBDOMAINS}\" ORIGEXTRA_DOMAINS=\"${EXTRA_DOMAINS}\" ORIGVALIDATION=\"${VALIDATION}\" ORIGDNSPLUGIN=\"${DNSPLUGIN}\" ORIGPROPAGATION=\"${PROPAGATION}\" ORIGSTAGING=\"${STAGING}\" ORIGCERTPROVIDER=\"${CERTPROVIDER}\" ORIGEMAIL=\"${EMAIL}\" ORIGCERT_PROFILE=\"${CERT_PROFILE}\"" >/config/.donoteditthisfile.conf
|
||||
|
||||
# if zerossl is selected or staging is set to true, use the relevant server
|
||||
if [[ "${CERTPROVIDER}" = "zerossl" ]] && [[ "${STAGING}" = "true" ]]; then
|
||||
@@ -233,6 +229,21 @@ fi
|
||||
|
||||
set_ini_value "server" "${ACMESERVER}" /config/etc/letsencrypt/cli.ini
|
||||
|
||||
# set certificate profile (e.g. "shortlived" for 6-day certs, "classic" for 90-day)
|
||||
# Profiles are a Let's Encrypt ACME feature; ZeroSSL ignores it.
|
||||
if [[ -n "${CERT_PROFILE}" ]]; then
|
||||
if [[ "${CERTPROVIDER}" = "zerossl" ]]; then
|
||||
echo "ZeroSSL does not support ACME profiles, ignoring CERT_PROFILE variable"
|
||||
sed -i "/^preferred-profile\b/d" /config/etc/letsencrypt/cli.ini
|
||||
else
|
||||
echo "Requesting certificate with profile: ${CERT_PROFILE}"
|
||||
set_ini_value "preferred-profile" "${CERT_PROFILE}" /config/etc/letsencrypt/cli.ini
|
||||
fi
|
||||
else
|
||||
# remove if previously set so going back to default works
|
||||
sed -i "/^preferred-profile\b/d" /config/etc/letsencrypt/cli.ini
|
||||
fi
|
||||
|
||||
# figuring out domain only vs domain & subdomains vs subdomains only
|
||||
DOMAINS_ARRAY=()
|
||||
if [[ -z "${SUBDOMAINS}" ]] || [[ "${ONLY_SUBDOMAINS}" != true ]]; then
|
||||
@@ -297,7 +308,7 @@ if [[ "${VALIDATION}" = "dns" ]]; then
|
||||
sed -i "/^dns-${DNSPLUGIN}-credentials\b/d" /config/etc/letsencrypt/cli.ini
|
||||
fi
|
||||
# plugins that don't support setting propagation
|
||||
if [[ "${DNSPLUGIN}" =~ ^(azure|gandi|route53|standalone)$ ]]; then
|
||||
if [[ "${DNSPLUGIN}" =~ ^(gandi|route53|standalone)$ ]]; then
|
||||
if [[ -n "${PROPAGATION}" ]]; then echo "${DNSPLUGIN} dns plugin does not support setting propagation time"; fi
|
||||
sed -i "/^dns-${DNSPLUGIN}-propagation-seconds\b/d" /config/etc/letsencrypt/cli.ini
|
||||
fi
|
||||
|
||||
File renamed without changes.
@@ -3,7 +3,7 @@
|
||||
|
||||
# Check if the cert is expired or expires within a day, if so, renew
|
||||
if openssl x509 -in /config/keys/letsencrypt/fullchain.pem -noout -checkend 86400 >/dev/null; then
|
||||
echo "The cert does not expire within the next day. Letting the cron script handle the renewal attempts overnight (2:08am)."
|
||||
echo "The cert does not expire within the next day. Letting the cron script handle the renewal attempts."
|
||||
else
|
||||
echo "The cert is either expired or it expires within the next day. Attempting to renew. This could take up to 10 minutes."
|
||||
/app/le-renew.sh
|
||||
|
||||
@@ -22,6 +22,14 @@ if [[ ! -f /config/nginx/authentik-server.conf ]]; then
|
||||
cp /defaults/nginx/authentik-server.conf.sample /config/nginx/authentik-server.conf
|
||||
fi
|
||||
|
||||
# copy tinyauth config files if they don't exist
|
||||
if [[ ! -f /config/nginx/tinyauth-location.conf ]]; then
|
||||
cp /defaults/nginx/tinyauth-location.conf.sample /config/nginx/tinyauth-location.conf
|
||||
fi
|
||||
if [[ ! -f /config/nginx/tinyauth-server.conf ]]; then
|
||||
cp /defaults/nginx/tinyauth-server.conf.sample /config/nginx/tinyauth-server.conf
|
||||
fi
|
||||
|
||||
# copy old ldap config file to new location
|
||||
if [[ -f /config/nginx/ldap.conf ]] && [[ ! -f /config/nginx/ldap-server.conf ]]; then
|
||||
cp /config/nginx/ldap.conf /config/nginx/ldap-server.conf
|
||||
|
||||
File renamed without changes.
Whitespace-only changes.
Reference in new issue
Block a user