Compare commits

...
122 Commits
Author SHA1 Message Date
LinuxServer-CI 6f68d40a7a Bot Updating Package Versions 2026-10-20 14:32:05 +00:00
LinuxServer-CI 4ec09cbad5 Bot Updating Templated Files 2026-10-20 14:27:09 +00:00
quietsy f503b59b62 Merge pull request #620 from linuxserver/replace-http_host
Update Nginx configuration to replace $http_host with $host$is_request_port$request_port for better compatibility
2026-10-20 17:25:21 +03:00
Eric Nemchik aeb7370675 Update Nginx configuration to replace $http_host with $host$is_request_port$request_port for better compatibility
Signed-off-by: GitHub <noreply@github.com>
2026-10-20 13:55:57 +00:00
LinuxServer-CI 12d8c0329c Bot Updating Package Versions 2026-10-17 07:42:15 +00:00
LinuxServer-CI 4d08a0d2a4 Bot Updating Templated Files 2026-10-17 07:37:14 +00:00
LinuxServer-CI 0cc53e2034 Bot Updating Package Versions 2026-10-10 09:43:54 +00:00
LinuxServer-CI 32921eb45c Bot Updating Templated Files 2026-10-10 09:36:34 +00:00
LinuxServer-CI 3061855da1 Bot Updating Templated Files 2026-10-10 09:34:53 +00:00
LinuxServer-CI fac1559e84 Bot Updating Package Versions 2026-10-03 09:00:56 +00:00
LinuxServer-CI 8763626dbc Bot Updating Package Versions 2026-09-26 08:27:40 +00:00
LinuxServer-CI cf3344e0bd Bot Updating Package Versions 2026-09-19 07:57:02 +00:00
LinuxServer-CI d00190cefc Bot Updating Templated Files 2026-09-14 18:21:57 +00:00
LinuxServer-CI 8d1fefb9a4 Bot Updating Templated Files 2026-09-14 18:20:17 +00:00
quietsy c29a049eea Merge pull request #621 from steveiliop56/refactor/x-tinyauth-location
refactor: use x-tinyauth-location header and remove dupe auth modules in tinyauth auth request
2026-09-14 21:18:35 +03:00
Stavros d2533208c6 fix: use correct x-forwarded-for header value 2026-09-13 21:50:56 +03:00
LinuxServer-CI 6559a9b1b6 Bot Updating Package Versions 2026-09-12 07:55:45 +00:00
LinuxServer-CI c367f03cbc Bot Updating Templated Files 2026-09-12 07:48:13 +00:00
LinuxServer-CI 32f4947db5 Bot Updating Templated Files 2026-09-12 07:46:28 +00:00
Stavros 1898dc3ede fix: include the x forwarded for header 2026-09-09 19:06:58 +03:00
Stavros 7820a40f01 fix: remove duplicate error page 2026-09-09 19:02:53 +03:00
Stavros 9e54158d38 refacotr: no need to copy all proxy headers to tinyauth 2026-09-08 20:30:46 +03:00
Stavros ad8764c2f8 fix: do not forward request body to auth server 2026-09-08 01:03:32 +03:00
Stavros 5189cbfb87 Merge branch 'master' into refactor/x-tinyauth-location 2026-09-08 00:02:25 +03:00
Stavros be4fdf0d4d fix: remove duplicate auth module headers 2026-09-07 23:59:53 +03:00
LinuxServer-CI f0c3932e7e Bot Updating Package Versions 2026-09-05 07:33:15 +00:00
LinuxServer-CI d9c0e32416 Bot Updating Package Versions 2026-09-01 21:44:26 +00:00
LinuxServer-CI 00c7817e50 Bot Updating Package Versions 2026-08-29 09:53:31 +00:00
LinuxServer-CI 671b9697be Bot Updating Package Versions 2026-08-22 03:46:57 +00:00
Adam 08592fdb75 Merge pull request #624 from EVOTk/patch-1
Update ovh.ini
2026-08-16 19:12:24 +01:00
LinuxServer-CI f86ef34abd Bot Updating Package Versions 2026-08-16 15:24:50 +00:00
LinuxServer-CI 478c1fa964 Bot Updating Templated Files 2026-08-16 15:17:05 +00:00
LinuxServer-CI 0b43278151 Bot Updating Templated Files 2026-08-16 15:11:31 +00:00
Eric Nemchik 21237325ee Merge pull request #622 from linuxserver/rebase-3.24
Rebase to 3.24
2026-08-16 10:08:03 -05:00
LinuxServer-CI 8bccad2000 Bot Updating Package Versions 2026-08-15 03:44:37 +00:00
EVO 9bd4e3771e Update ovh.ini
Update the broken link
2026-08-08 19:55:04 +02:00
LinuxServer-CI 55a8c4fa88 Bot Updating Package Versions 2026-08-08 04:15:45 +00:00
LinuxServer-CI 733910a7a7 Bot Updating Package Versions 2026-08-01 06:00:50 +00:00
LinuxServer-CI 55a01c005c Bot Updating Package Versions 2026-07-25 05:48:28 +00:00
Eric Nemchik fb016e60ee Remove unnecessary PHP extensions from Dockerfiles
Signed-off-by: Eric Nemchik <eric@nemchik.com>
2026-07-19 21:13:30 -05:00
Eric Nemchik 415fbce955 Rebase to 3.24
Signed-off-by: Eric Nemchik <eric@nemchik.com>
2026-07-19 20:02:36 -05:00
Stavros 84915dcfcf fix: update readme vars instead of main readme 2026-07-19 00:50:45 +03:00
Stavros 05da050b5f refactor: use x-tinyauth-location header in tinyauth auth request 2026-07-19 00:48:02 +03:00
LinuxServer-CI bc02502e97 Bot Updating Package Versions 2026-07-18 05:32:40 +00:00
LinuxServer-CI 2c22ce9573 Bot Updating Package Versions 2026-07-15 18:14:31 +00:00
Eric Nemchik 0a34712336 Merge pull request #594 from jonathanmajh/patch-1
Update tinyauth-location.conf.sample for Forward Auth
2026-07-11 21:48:18 -05:00
Eric Nemchik 4e7e4f7fee Merge branch 'master' into patch-1 2026-07-11 21:07:22 -05:00
Jonathan MaandEric Nemchik e39c6487f7 Update root/defaults/nginx/tinyauth-location.conf.sample
Co-authored-by: Eric Nemchik <eric@nemchik.com>
2026-07-11 12:58:10 -04:00
LinuxServer-CI 493982d27e Bot Updating Templated Files 2026-07-10 22:15:07 +00:00
LinuxServer-CI 1e2b94980c Bot Updating Templated Files 2026-07-10 22:13:20 +00:00
Eric Nemchik b3185a5eff Merge pull request #607 from Sausageroll2077/master
Add CERT_PROFILE support and improve ARI renewal scheduling
2026-07-10 17:11:32 -05:00
Sausageroll2077andClaude Opus 4.8 e857f808b0 Add CERT_PROFILE support and simplify renewal scheduling
Add CERT_PROFILE env var for Let's Encrypt cert profiles. Run certbot
twice daily via a cron entry with a random delay instead of the previous
sed-based cron randomization. Update changelog.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 00:09:29 +02:00
LinuxServer-CI 62d5e73cbb Bot Updating Package Versions 2026-07-10 21:57:02 +00:00
LinuxServer-CI 83ab984b17 Bot Updating Templated Files 2026-07-10 21:52:10 +00:00
Eric Nemchik 1a8290dec1 Merge pull request #618 from Sausageroll2077/add-dnsplugin-mijn-host
Add support for mijn.host DNS plugin
2026-07-10 16:50:25 -05:00
Sausageroll2077 057bbb5930 Merge branch 'master' into add-dnsplugin-mijn-host 2026-07-08 19:20:20 +02:00
LinuxServer-CI d6c053dd22 Bot Updating Package Versions 2026-07-04 06:25:57 +00:00
Sausageroll2077 883a216247 Merge branch 'master' into add-dnsplugin-mijn-host 2026-06-29 17:53:31 +02:00
LinuxServer-CI a57ebf0399 Bot Updating Package Versions 2026-06-27 06:34:42 +00:00
Sausageroll2077 37b074c528 Merge branch 'master' into add-dnsplugin-mijn-host 2026-06-26 15:52:01 +02:00
LinuxServer-CI d86d2dbb59 Bot Updating Package Versions 2026-06-25 20:47:23 +00:00
Sausageroll2077 25258a2f90 Merge branch 'master' into add-dnsplugin-mijn-host 2026-06-21 07:17:39 +02:00
LinuxServer-CI 88b7c77e02 Bot Updating Package Versions 2026-06-20 07:05:54 +00:00
Sausageroll2077andClaude Opus 4.8 2cea93f9b1 Add support for mijn.host DNS plugin
Adds certbot-dns-mijn-host as a DNSPLUGIN option (mijn-host), including
the plugin in both Dockerfiles, a credentials template under
dns-conf, and the DNSPLUGIN list in readme-vars.yml.

Closes #606

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 20:21:49 +02:00
LinuxServer-CI a9d1f7f0ee Bot Updating Package Versions 2026-06-13 07:04:48 +00:00
LinuxServer-CI d3fe405b46 Bot Updating Package Versions 2026-06-06 06:35:32 +00:00
LinuxServer-CI 32c26223dd Bot Updating Package Versions 2026-06-01 16:09:07 +00:00
aptalca 60161a3baf Merge pull request #613 from linuxserver/cert-check
remove obsolete old cert check logic
2026-06-01 12:02:02 -04:00
aptalca 321837be0d remove obsolete old cert check logic 2026-06-01 11:04:38 -04:00
LinuxServer-CI c371973f5f Bot Updating Package Versions 2026-05-30 06:29:09 +00:00
LinuxServer-CI bc18a403ba Bot Updating Package Versions 2026-05-23 06:17:54 +00:00
LinuxServer-CI b104a66e06 Bot Updating Package Versions 2026-05-16 06:00:50 +00:00
LinuxServer-CI 80bc4b4243 Bot Updating Package Versions 2026-05-14 20:15:20 +00:00
LinuxServer-CI 7cf7838a87 Bot Updating Package Versions 2026-05-14 19:54:29 +00:00
LinuxServer-CI 0cb2c16f7d Bot Updating Package Versions 2026-05-11 17:29:24 +00:00
LinuxServer-CI 36129452e8 Bot Updating Package Versions 2026-05-09 05:55:56 +00:00
LinuxServer-CI bb2b29d9c1 Bot Updating Templated Files 2026-05-09 05:51:19 +00:00
LinuxServer-CI b7ea5c43ec Bot Updating Package Versions 2026-05-02 05:43:26 +00:00
LinuxServer-CI 8fbf8ab449 Bot Updating Package Versions 2026-04-25 05:17:58 +00:00
Jonathan Ma 6b1745980a Merge branch 'master' into patch-1 2026-04-23 08:56:57 -04:00
LinuxServer-CI 9c5ae4f09a Bot Updating Package Versions 2026-04-18 05:12:40 +00:00
LinuxServer-CI 321c7f3295 Bot Updating Package Versions 2026-04-11 05:00:44 +00:00
LinuxServer-CI 005a68591d Bot Updating Package Versions 2026-04-07 19:22:47 +00:00
LinuxServer-CI 01bfb62124 Bot Updating Templated Files 2026-04-07 19:18:28 +00:00
LinuxServer-CI 04ad8386bf Bot Updating Package Versions 2026-04-04 04:55:57 +00:00
LinuxServer-CI b409073642 Bot Updating Package Versions 2026-03-28 04:58:53 +00:00
LinuxServer-CI 1c8a8d004e Bot Updating Package Versions 2026-03-21 04:42:40 +00:00
LinuxServer-CI 9235e504a1 Bot Updating Package Versions 2026-03-14 04:48:10 +00:00
LinuxServer-CI ef520118f5 Bot Updating Package Versions 2026-03-10 19:42:05 +00:00
Adam 4a4e84d26b Merge pull request #602 from linuxserver/tinyauth-fix
Add missing tinyauth blocks to default conf
2026-03-07 14:05:10 +00:00
thespad 8c002e6c56 Add missing tinyauth blocks to default conf 2026-03-07 13:57:15 +00:00
LinuxServer-CI ea840fbfbc Bot Updating Package Versions 2026-03-07 04:26:21 +00:00
LinuxServer-CI 42ba97e46a Bot Updating Package Versions
Mark stale issues and pull requests / stale (push) Failing after 0s
External Trigger Scheduler / external-trigger-scheduler (push) Failing after 10s
2026-02-28 04:20:29 +00:00
LinuxServer-CI b4b73022db Bot Updating Package Versions
External Trigger Scheduler / external-trigger-scheduler (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Package Trigger Scheduler / package-trigger-scheduler (push) Has been cancelled
2026-02-21 04:42:02 +00:00
LinuxServer-CI 9d5ebb6a7a Bot Updating Package Versions
External Trigger Scheduler / external-trigger-scheduler (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Package Trigger Scheduler / package-trigger-scheduler (push) Has been cancelled
2026-02-14 04:50:10 +00:00
LinuxServer-CI 7ad019e68d Bot Updating Templated Files 2026-02-14 04:45:56 +00:00
LinuxServer-CI 59ef2df680 Bot Updating Templated Files 2026-02-14 04:44:20 +00:00
LinuxServer-CI db874b2c0f Bot Updating Package Versions
External Trigger Scheduler / external-trigger-scheduler (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Package Trigger Scheduler / package-trigger-scheduler (push) Has been cancelled
2026-02-10 05:08:06 +00:00
LinuxServer-CI 6182a75998 Bot Updating Package Versions
External Trigger Scheduler / external-trigger-scheduler (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
2026-02-07 04:43:17 +00:00
LinuxServer-CI 145c5d84f6 Bot Updating Package Versions
External Trigger Scheduler / external-trigger-scheduler (push) Has been cancelled
Package Trigger Scheduler / package-trigger-scheduler (push) Has been cancelled
2026-02-06 14:17:14 +00:00
LinuxServer-CI 1039f2a04c Bot Updating Package Versions
External Trigger Scheduler / external-trigger-scheduler (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
2026-02-03 19:48:04 +00:00
LinuxServer-CI 156e3ac160 Bot Updating Package Versions
External Trigger Scheduler / external-trigger-scheduler (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
2026-01-31 04:29:28 +00:00
LinuxServer-CI e649bd71da Bot Updating Package Versions
External Trigger Scheduler / external-trigger-scheduler (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Package Trigger Scheduler / package-trigger-scheduler (push) Has been cancelled
2026-01-26 00:38:36 +00:00
LinuxServer-CI b54c263769 Bot Updating Templated Files 2026-01-26 00:34:15 +00:00
aptalca 7b11fb9643 Merge pull request #600 from linuxserver/sample-race
reorder init to make sure samples are copied before version checks
2026-01-25 19:32:30 -05:00
LinuxServer-CI 72d187c734 Bot Updating Package Versions
External Trigger Scheduler / external-trigger-scheduler (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
2026-01-24 04:03:28 +00:00
aptalca b6752babcd sandwich swag folder creation and sample copying between nginx base's permissions and version checks to make sure samples are there when the check happens 2026-01-23 21:37:09 -05:00
Adam 6f38cebe04 Merge pull request #597 from hadjilucasL/patch-1
External Trigger Scheduler / external-trigger-scheduler (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Package Trigger Scheduler / package-trigger-scheduler (push) Has been cancelled
2026-01-18 10:04:48 +00:00
LinuxServer-CI 62b3a02aed Bot Updating Package Versions
External Trigger Scheduler / external-trigger-scheduler (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
2026-01-17 03:59:34 +00:00
LinuxServer-CI 2deac3dac6 Bot Updating Package Versions
External Trigger Scheduler / external-trigger-scheduler (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Package Trigger Scheduler / package-trigger-scheduler (push) Has been cancelled
2026-01-13 11:05:27 +00:00
LinuxServer-CI 48cbb269cc Bot Updating Templated Files 2026-01-13 11:00:44 +00:00
Adam 8489cde7c0 Merge pull request #596 from CaptivatingCat/hetzner-cloud 2026-01-13 10:59:01 +00:00
CaptivatingCat a120a68aae Merge branch 'master' into hetzner-cloud 2026-01-11 14:55:29 +01:00
LinuxServer-CI 1674ff4509 Bot Updating Package Versions
External Trigger Scheduler / external-trigger-scheduler (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
2026-01-10 04:00:48 +00:00
CaptivatingCat 52707530e2 Merge branch 'master' into hetzner-cloud 2026-01-07 23:30:22 +01:00
CaptivatingCat cbf78b31bb Fix missing quote in readme-vars.yml 2026-01-07 23:29:05 +01:00
Lucas Hadjilucas 2fc01f4e21 Merge branch 'master' into patch-1 2026-01-04 21:36:59 +02:00
CaptivatingCat 4a7daa06ad Merge branch 'master' into hetzner-cloud 2025-12-31 22:39:27 +01:00
Lucas Hadjilucas 77dc5ff352 Merge branch 'master' into patch-1 2025-12-27 23:14:14 +02:00
Lucas Hadjilucas 0ab1a76dae Restore symlink paths for letsencrypt keys
To solve #549
2025-12-23 22:46:59 +02:00
CaptivatingCat 8b8b491df3 add support for hetzner-cloud dns validation 2025-12-21 00:55:30 +01:00
Jonathan Ma 3ffa4aaa77 Update tinyauth-location.conf.sample for Forward Auth
Updated version information and added headers for Forward Auth in the tinyauth NGINX configuration.
2025-12-17 15:28:03 -05:00
28 changed files with 1065 additions and 683 deletions

No files matched your search

+2 -2
View File
@@ -4,8 +4,8 @@ contact_links:
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
+7 -5
View File
@@ -3,7 +3,6 @@
[linuxserverurl]: https://linuxserver.io
[![linuxserver.io](https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/linuxserver_medium.png)][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 -->
+1 -1
View File
@@ -10,7 +10,7 @@ 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'
@@ -12,7 +12,7 @@ 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'
+4 -4
View File
@@ -12,8 +12,8 @@ jobs:
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 }}
@@ -12,7 +12,7 @@ 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'
+127
View File
@@ -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 -32
View File
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1
FROM ghcr.io/linuxserver/baseimage-alpine-nginx:3.22
FROM ghcr.io/linuxserver/baseimage-alpine-nginx:3.24
# set version label
ARG BUILD_DATE
@@ -49,36 +49,34 @@ RUN \
nginx-mod-stream \
nginx-mod-stream-geoip2 \
nginx-vim \
php84-bcmath \
php84-bz2 \
php84-dom \
php84-exif \
php84-ftp \
php84-gd \
php84-gmp \
php84-imap \
php84-intl \
php84-ldap \
php84-mysqli \
php84-mysqlnd \
php84-opcache \
php84-pdo_mysql \
php84-pdo_odbc \
php84-pdo_pgsql \
php84-pdo_sqlite \
php84-pear \
php84-pecl-apcu \
php84-pecl-memcached \
php84-pecl-redis \
php84-pgsql \
php84-posix \
php84-soap \
php84-sockets \
php84-sodium \
php84-sqlite3 \
php84-tokenizer \
php84-xmlreader \
php84-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 \
@@ -88,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.22/ \
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 \
@@ -114,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 -32
View File
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1
FROM ghcr.io/linuxserver/baseimage-alpine-nginx:arm64v8-3.22
FROM ghcr.io/linuxserver/baseimage-alpine-nginx:arm64v8-3.24
# set version label
ARG BUILD_DATE
@@ -49,36 +49,34 @@ RUN \
nginx-mod-stream \
nginx-mod-stream-geoip2 \
nginx-vim \
php84-bcmath \
php84-bz2 \
php84-dom \
php84-exif \
php84-ftp \
php84-gd \
php84-gmp \
php84-imap \
php84-intl \
php84-ldap \
php84-mysqli \
php84-mysqlnd \
php84-opcache \
php84-pdo_mysql \
php84-pdo_odbc \
php84-pdo_pgsql \
php84-pdo_sqlite \
php84-pear \
php84-pecl-apcu \
php84-pecl-memcached \
php84-pecl-redis \
php84-pgsql \
php84-posix \
php84-soap \
php84-sockets \
php84-sodium \
php84-sqlite3 \
php84-tokenizer \
php84-xmlreader \
php84-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 \
@@ -88,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.22/ \
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 \
@@ -114,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
+381 -168
View File
@@ -52,6 +52,57 @@ 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{
@@ -76,8 +127,12 @@ pipeline {
'''
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' ''',
@@ -94,12 +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{
@@ -279,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 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 && \
@@ -305,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
@@ -364,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
@@ -580,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"
@@ -614,6 +680,17 @@ 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
@@ -623,11 +700,16 @@ pipeline {
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 "${!pids[@]}"; do
wait "$p" || { [[ "${pids[$p]}" != *"quay.io"* ]] && exit 1; }
wait "$p" || { if [[ "${pids[$p]}" != *"quay.io"* && "${pids[$p]}" != *"registry.gitlab.com"* ]]; then exit 1; fi; }
done
fi
'''
@@ -649,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"
@@ -683,6 +768,17 @@ 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
@@ -692,11 +788,16 @@ pipeline {
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 "${!pids[@]}"; do
wait "$p" || { [[ "${pids[$p]}" != *"quay.io"* ]] && exit 1; }
wait "$p" || { if [[ "${pids[$p]}" != *"quay.io"* && "${pids[$p]}" != *"registry.gitlab.com"* ]]; then exit 1; fi; }
done
fi
'''
@@ -711,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"
@@ -745,6 +888,17 @@ 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
@@ -753,11 +907,16 @@ pipeline {
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 "${!pids[@]}"; do
wait "$p" || { [[ "${pids[$p]}" != *"quay.io"* ]] && exit 1; }
wait "$p" || { if [[ "${pids[$p]}" != *"quay.io"* && "${pids[$p]}" != *"registry.gitlab.com"* ]]; then exit 1; fi; }
done
fi
'''
@@ -792,6 +951,8 @@ 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 \
@@ -871,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
@@ -882,9 +1044,10 @@ pipeline {
CI_DOCKERENV="LSIO_FIRST_PARTY=true"
fi
fi
docker pull ghcr.io/linuxserver/ci:${CITEST_IMAGETAG}
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 \
@@ -923,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
@@ -934,11 +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} || \
{ if [[ "${PUSHIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
${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} || \
{ if [[ "${PUSHIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
${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
'''
@@ -952,38 +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} || \
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
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}" ]]; then exit 1; fi; }
${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} || \
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
docker buildx imagetools create --prefer-index=false -t ${MANIFESTIMAGE}:arm64v8-${SEMVER} ${CACHEIMAGE}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} || \
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
${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 || \
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
docker buildx imagetools create -t ${MANIFESTIMAGE}:${META_TAG} ${MANIFESTIMAGE}:amd64-${META_TAG} ${MANIFESTIMAGE}:arm64v8-${META_TAG} || \
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
docker buildx imagetools create -t ${MANIFESTIMAGE}:${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:amd64-${EXT_RELEASE_TAG} ${MANIFESTIMAGE}:arm64v8-${EXT_RELEASE_TAG} || \
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
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} || \
{ if [[ "${MANIFESTIMAGE}" != "${QUAYIMAGE}" ]]; then exit 1; fi; }
${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
'''
@@ -1073,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()
@@ -1207,6 +1332,94 @@ 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
+16 -5
View File
@@ -4,7 +4,7 @@
[![Blog](https://img.shields.io/static/v1.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=linuxserver.io&message=Blog)](https://blog.linuxserver.io "all the things you can do with our containers including How-To guides, opinions and much more!")
[![Discord](https://img.shields.io/discord/354974912613449730.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=Discord&logo=discord)](https://linuxserver.io/discord "realtime support / chat with the community and the team.")
[![Discourse](https://img.shields.io/discourse/https/discourse.linuxserver.io/topics.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&logo=discourse)](https://discourse.linuxserver.io "post on our community forum.")
[![Discussions](https://img.shields.io/badge/Github-Discussions-94398d?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&logo=github)](https://github.com/orgs/linuxserver/discussions "post on our community forum.")
[![GitHub](https://img.shields.io/static/v1.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=linuxserver.io&message=GitHub&logo=github)](https://github.com/linuxserver "view the source for all of our repositories.")
[![Open Collective](https://img.shields.io/opencollective/all/linuxserver.svg?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=Supporters&logo=open%20collective)](https://opencollective.com/linuxserver "please consider helping us by either donating or contributing to our budget")
@@ -20,7 +20,7 @@ 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://linuxserver.io/discord) - realtime support / chat with the community and the team.
* [Discourse](https://discourse.linuxserver.io) - post on our community forum.
* [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
@@ -68,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
@@ -170,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))
@@ -190,6 +190,7 @@ services:
- VALIDATION=http
- SUBDOMAINS=www, #optional
- CERTPROVIDER= #optional
- CERT_PROFILE= #optional
- DNSPLUGIN=cloudflare #optional
- PROPAGATION= #optional
- EMAIL= #optional
@@ -221,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` \
@@ -254,7 +256,8 @@ 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` |
@@ -433,6 +436,14 @@ Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64
## Versions
* **20.10.26:** - [Existing users should update:](https://github.com/linuxserver/docker-swag/blob/master/README.md#updating-configs) proxy.conf, authelia-server.conf, authentik-server.conf, tinyauth-server.conf - Update Nginx configuration to replace $http_host with $host$is_request_port$request_port for better compatibility.
* **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.
+375 -372
View File
@@ -1,372 +1,375 @@
NAME VERSION TYPE
Simple Launcher 1.1.0.14 binary (+5 duplicates)
acl-libs 2.3.2-r1 apk
acme 5.2.2 python
alpine-baselayout 3.7.0-r0 apk
alpine-baselayout-data 3.7.0-r0 apk
alpine-keys 2.5-r0 apk
alpine-release 3.22.2-r0 apk
aom-libs 3.12.1-r0 apk
apache2-utils 2.4.66-r0 apk
apk-tools 2.14.9-r3 apk
apr 1.7.5-r0 apk
apr-util 1.6.3-r1 apk
argon2-libs 20190702-r5 apk
attrs 25.4.0 python
autocommand 2.2.2 python
azure-common 1.1.28 python
azure-core 1.37.0 python
azure-identity 1.25.1 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.14.3 python
boto3 1.42.21 python
botocore 1.42.21 python
brotli-libs 1.1.0-r2 apk
bs4 0.0.2 python
busybox 1.37.0-r20 apk
busybox-binsh 1.37.0-r20 apk
c-ares 1.34.6-r0 apk
c-client 2007f-r15 apk
ca-certificates 20250911-r0 apk
ca-certificates-bundle 20250911-r0 apk
cachetools 6.2.4 python
catatonit 0.2.1-r0 apk
certbot 5.2.2 python
certbot-dns-acmedns 0.1.0 python
certbot-dns-aliyun 2.0.0 python
certbot-dns-azure 1.5.0 python
certbot-dns-bunny 3.0.0 python
certbot-dns-cloudflare 5.2.2 python
certbot-dns-cpanel 0.4.0 python
certbot-dns-desec 1.3.2 python
certbot-dns-digitalocean 5.2.2 python
certbot-dns-directadmin 1.0.15 python
certbot-dns-dnsimple 5.2.2 python
certbot-dns-dnsmadeeasy 5.2.2 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.7.1 python
certbot-dns-dynudns 0.0.6 python
certbot-dns-freedns 0.2.0 python
certbot-dns-gehirn 5.2.2 python
certbot-dns-glesys 2.1.0 python
certbot-dns-godaddy 2.8.0 python
certbot-dns-google 5.2.2 python
certbot-dns-he 1.0.0 python
certbot-dns-hetzner 2.0.1 python
certbot-dns-infomaniak 0.2.4 python
certbot-dns-inwx 3.0.3 python
certbot-dns-ionos 2024.11.9 python
certbot-dns-linode 5.2.2 python
certbot-dns-loopia 1.0.1 python
certbot-dns-luadns 5.2.2 python
certbot-dns-namecheap 1.0.0 python
certbot-dns-netcup 2.0.0 python
certbot-dns-njalla 2.0.2 python
certbot-dns-nsone 5.2.2 python
certbot-dns-ovh 5.2.2 python
certbot-dns-porkbun 0.11.0 python
certbot-dns-rfc2136 5.2.2 python
certbot-dns-route53 5.2.2 python
certbot-dns-sakuracloud 5.2.2 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 2025.11.12 python
cffi 2.0.0 python
charset-normalizer 3.4.4 python
cli UNKNOWN binary
cli-32 UNKNOWN binary
cli-64 UNKNOWN binary
cli-arm64 UNKNOWN binary
cloudflare 2.19.4 python
composer 2.9.3 binary
configargparse 1.7.1 python
configobj 5.0.9 python
coreutils 9.7-r1 apk
coreutils-env 9.7-r1 apk
coreutils-fmt 9.7-r1 apk
coreutils-sha512sum 9.7-r1 apk
cryptography 46.0.3 python
curl 8.14.1-r2 apk
distro 1.9.0 python
dns-lexicon 3.23.2 python
dnslib 0.9.26 python
dnspython 2.8.0 python
domeneshop 0.4.4 python
fail2ban 1.1.0 python
fail2ban 1.1.0-r3 apk
fail2ban-pyc 1.1.0-r3 apk
filelock 3.20.2 python
findutils 4.10.0-r0 apk
fontconfig 2.15.0-r3 apk
freetype 2.13.3-r0 apk
future 1.0.0 python
gdbm 1.24-r0 apk
git 2.49.1-r0 apk
git-init-template 2.49.1-r0 apk
git-perl 2.49.1-r0 apk
gmp 6.3.0-r3 apk
gnupg 2.4.9-r0 apk
gnupg-dirmngr 2.4.9-r0 apk
gnupg-gpgconf 2.4.9-r0 apk
gnupg-keyboxd 2.4.9-r0 apk
gnupg-utils 2.4.9-r0 apk
gnupg-wks-client 2.4.9-r0 apk
gnutls 3.8.8-r0 apk
google-api-core 2.28.1 python
google-api-python-client 2.187.0 python
google-auth 2.45.0 python
google-auth-httplib2 0.3.0 python
googleapis-common-protos 1.72.0 python
gpg 2.4.9-r0 apk
gpg-agent 2.4.9-r0 apk
gpg-wks-server 2.4.9-r0 apk
gpgsm 2.4.9-r0 apk
gpgv 2.4.9-r0 apk
gui UNKNOWN binary
gui-32 UNKNOWN binary
gui-64 UNKNOWN binary
gui-arm64 UNKNOWN binary
httplib2 0.31.0 python
icu-data-en 76.1-r1 apk
icu-libs 76.1-r1 apk
idna 3.11 python
importlib-metadata 8.0.0 python
inflect 7.3.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.11-r1 apk
iptables-legacy 1.8.11-r1 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
jinja2 3.1.6 python
jmespath 1.0.1 python
josepy 2.2.0 python
jq 1.8.1-r0 apk
jsonlines 4.0.0 python
jsonpickle 4.1.1 python
libapk2 2.14.9-r3 apk
libassuan 2.5.7-r0 apk
libattr 2.5.2-r2 apk
libavif 1.3.0-r0 apk
libbsd 0.12.2-r0 apk
libbz2 1.0.8-r6 apk
libcrypto3 3.5.4-r0 apk
libcurl 8.14.1-r2 apk
libdav1d 1.5.1-r0 apk
libedit 20250104.3.1-r1 apk
libevent 2.1.12-r8 apk
libexpat 2.7.3-r0 apk
libffi 3.4.8-r0 apk
libgcc 14.2.0-r6 apk
libgcrypt 1.10.3-r1 apk
libgd 2.3.3-r10 apk
libgpg-error 1.55-r0 apk
libice 1.1.2-r0 apk
libidn2 2.3.7-r0 apk
libintl 0.24.1-r0 apk
libip4tc 1.8.11-r1 apk
libip6tc 1.8.11-r1 apk
libjpeg-turbo 3.1.0-r0 apk
libksba 1.6.7-r0 apk
libldap 2.6.8-r0 apk
libmaxminddb-libs 1.9.1-r0 apk
libmd 1.1.0-r0 apk
libmemcached-libs 1.1.4-r1 apk
libmnl 1.0.5-r2 apk
libncursesw 6.5_p20250503-r0 apk
libnftnl 1.2.9-r0 apk
libpanelw 6.5_p20250503-r0 apk
libpng 1.6.53-r0 apk
libpq 17.7-r0 apk
libproc2 4.0.4-r3 apk
libpsl 0.21.5-r3 apk
libsasl 2.1.28-r8 apk
libseccomp 2.6.0-r0 apk
libsharpyuv 1.5.0-r0 apk
libsm 1.2.5-r0 apk
libsodium 1.0.20-r1 apk
libssl3 3.5.4-r0 apk
libstdc++ 14.2.0-r6 apk
libtasn1 4.20.0-r0 apk
libunistring 1.3-r0 apk
libuuid 2.41-r9 apk
libwebp 1.5.0-r0 apk
libx11 1.8.11-r0 apk
libxau 1.0.12-r0 apk
libxcb 1.17.0-r0 apk
libxdmcp 1.1.5-r1 apk
libxext 1.3.6-r2 apk
libxml2 2.13.9-r0 apk
libxpm 3.5.17-r0 apk
libxslt 1.1.43-r3 apk
libxt 1.3.1-r0 apk
libxtables 1.8.11-r1 apk
libyuv 0.0.1887.20251502-r1 apk
libzip 1.11.4-r0 apk
linux-pam 1.7.0-r4 apk
logrotate 3.21.0-r1 apk
loopialib 0.2.0 python
lxml 6.0.2 python
lz4-libs 1.10.0-r0 apk
markupsafe 3.0.3 python
memcached 1.6.32-r0 apk
mock 5.2.0 python
more-itertools 10.3.0 python
mpdecimal 4.0.1-r0 apk
msal 1.34.0 python
msal-extensions 1.3.1 python
musl 1.2.5-r10 apk
musl-utils 1.2.5-r10 apk
my-test-package 1.0 python
nano 8.4-r0 apk
ncurses-terminfo-base 6.5_p20250503-r0 apk
netcat-openbsd 1.229.1-r0 apk
nettle 3.10.1-r0 apk
nghttp2-libs 1.65.0-r0 apk
nginx 1.28.0-r3 apk
nginx-mod-devel-kit 1.28.0-r3 apk
nginx-mod-http-brotli 1.28.0-r3 apk
nginx-mod-http-dav-ext 1.28.0-r3 apk
nginx-mod-http-echo 1.28.0-r3 apk
nginx-mod-http-fancyindex 1.28.0-r3 apk
nginx-mod-http-geoip2 1.28.0-r3 apk
nginx-mod-http-headers-more 1.28.0-r3 apk
nginx-mod-http-image-filter 1.28.0-r3 apk
nginx-mod-http-perl 1.28.0-r3 apk
nginx-mod-http-redis2 1.28.0-r3 apk
nginx-mod-http-set-misc 1.28.0-r3 apk
nginx-mod-http-upload-progress 1.28.0-r3 apk
nginx-mod-http-xslt-filter 1.28.0-r3 apk
nginx-mod-mail 1.28.0-r3 apk
nginx-mod-rtmp 1.28.0-r3 apk
nginx-mod-stream 1.28.0-r3 apk
nginx-mod-stream-geoip2 1.28.0-r3 apk
nginx-vim 1.28.0-r3 apk
npth 1.8-r0 apk
oniguruma 6.9.10-r0 apk
openssl 3.5.4-r0 apk
p11-kit 0.25.5-r2 apk
packaging 24.2 python
parsedatetime 2.6 python
pcre2 10.46-r0 apk
perl 5.40.3-r0 apk
perl-error 0.17030-r0 apk
perl-git 2.49.1-r0 apk
php84 8.4.16-r0 apk
php84-bcmath 8.4.16-r0 apk
php84-bz2 8.4.16-r0 apk
php84-common 8.4.16-r0 apk
php84-ctype 8.4.16-r0 apk
php84-curl 8.4.16-r0 apk
php84-dom 8.4.16-r0 apk
php84-exif 8.4.16-r0 apk
php84-fileinfo 8.4.16-r0 apk
php84-fpm 8.4.16-r0 apk
php84-ftp 8.4.16-r0 apk
php84-gd 8.4.16-r0 apk
php84-gmp 8.4.16-r0 apk
php84-iconv 8.4.16-r0 apk
php84-intl 8.4.16-r0 apk
php84-ldap 8.4.16-r0 apk
php84-mbstring 8.4.16-r0 apk
php84-mysqli 8.4.16-r0 apk
php84-mysqlnd 8.4.16-r0 apk
php84-opcache 8.4.16-r0 apk
php84-openssl 8.4.16-r0 apk
php84-pdo 8.4.16-r0 apk
php84-pdo_mysql 8.4.16-r0 apk
php84-pdo_odbc 8.4.16-r0 apk
php84-pdo_pgsql 8.4.16-r0 apk
php84-pdo_sqlite 8.4.16-r0 apk
php84-pear 8.4.16-r0 apk
php84-pecl-apcu 5.1.27-r0 apk
php84-pecl-igbinary 3.2.16-r1 apk
php84-pecl-imap 1.0.3-r0 apk
php84-pecl-memcached 3.3.0-r0 apk
php84-pecl-msgpack 3.0.0-r0 apk
php84-pecl-redis 6.3.0-r0 apk
php84-pgsql 8.4.16-r0 apk
php84-phar 8.4.16-r0 apk
php84-posix 8.4.16-r0 apk
php84-session 8.4.16-r0 apk
php84-simplexml 8.4.16-r0 apk
php84-soap 8.4.16-r0 apk
php84-sockets 8.4.16-r0 apk
php84-sodium 8.4.16-r0 apk
php84-sqlite3 8.4.16-r0 apk
php84-tokenizer 8.4.16-r0 apk
php84-xml 8.4.16-r0 apk
php84-xmlreader 8.4.16-r0 apk
php84-xmlwriter 8.4.16-r0 apk
php84-xsl 8.4.16-r0 apk
php84-zip 8.4.16-r0 apk
pinentry 1.3.1-r0 apk
pip 25.3 python
pkb-client 2.2.0 python
platformdirs 4.2.2 python
popt 1.19-r4 apk
procps-ng 4.0.4-r3 apk
proto-plus 1.27.0 python
protobuf 6.33.2 python
pyacmedns 0.4 python
pyasn1 0.6.1 python
pyasn1-modules 0.4.2 python
pyc 3.12.12-r0 apk
pycparser 2.23 python
pyjwt 2.10.1 python
pynamecheap 0.0.3 python
pyopenssl 25.3.0 python
pyotp 2.9.0 python
pyparsing 3.3.1 python
pyrfc3339 2.1.0 python
python-dateutil 2.9.0.post0 python
python-digitalocean 1.17.0 python
python-transip 0.6.0 python
python3 3.12.12-r0 apk
python3-pyc 3.12.12-r0 apk
python3-pycache-pyc0 3.12.12-r0 apk
pyyaml 6.0.3 python
readline 8.2.13-r1 apk
requests 2.32.5 python
requests-file 3.0.1 python
requests-mock 1.12.1 python
rsa 4.9.1 python
s3transfer 0.16.0 python
scanelf 1.3.8-r1 apk
setuptools 80.9.0 python
shadow 4.17.3-r0 apk
six 1.17.0 python
skalibs-libs 2.14.4.0-r0 apk
soupsieve 2.8.1 python
sqlite-libs 3.49.2-r1 apk
ssl_client 1.37.0-r20 apk
tiff 4.7.1-r0 apk
tldextract 5.3.1 python
tomli 2.0.1 python
typeguard 4.3.0 python
typing-extensions 4.12.2 python
typing-extensions 4.15.0 python
tzdata 2025c-r0 apk
unixodbc 2.3.12-r0 apk
uritemplate 4.2.0 python
urllib3 2.6.2 python
utmps-libs 0.1.3.1-r0 apk
wheel 0.45.1 python (+1 duplicate)
whois 5.6.3-r0 apk
xz-libs 5.8.1-r0 apk
zipp 3.19.2 python
zlib 1.3.1-r2 apk
zope-interface 8.1.1 python
zstd-libs 1.5.7-r0 apk
NAME VERSION TYPE
Simple Launcher 1.1.0.14 binary (+5 duplicates)
acl-libs 2.3.2-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
autocommand 2.2.2 python
azure-common 1.1.28 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.3.9-r1 apk
beautifulsoup4 4.15.0 python
boto3 1.43.115 python
botocore 1.43.115 python
brotli-libs 1.2.0-r1 apk
bs4 0.0.2 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 1.5.0 python
certbot-dns-bunny 3.0.0 python
certbot-dns-cloudflare 5.8.0 python
certbot-dns-cpanel 0.4.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.9.0 python
certbot-dns-dynudns 0.0.6 python
certbot-dns-freedns 0.2.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 5.8.0 python
certbot-dns-he 1.0.0 python
certbot-dns-hetzner 4.0.0 python
certbot-dns-hetzner-cloud 1.1.0 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 5.8.0 python
certbot-dns-loopia 1.0.1 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 2.1.0 python
certbot-dns-njalla 2.0.2 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 2026.10.19 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.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.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-r3 apk
fail2ban-pyc 1.1.0-r3 apk
filelock 4.2.4 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.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.13-r0 apk
iptables-legacy 1.8.13-r0 apk
isodate 0.7.2 python
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.4.1-r0 apk
libbsd 0.12.2-r0 apk
libbz2 1.0.8-r6 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.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-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.14-r0 apk
libxau 1.0.12-r0 apk
libxcb 1.17.0-r2 apk
libxdmcp 1.1.5-r1 apk
libxext 1.3.7-r0 apk
libxml2 2.13.9-r2 apk
libxpm 3.5.20-r0 apk
libxslt 1.1.43-r3 apk
libxt 1.3.1-r0 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 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.3 python (+1 duplicate)
parsedatetime 2.6 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
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.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 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.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
requests-unixsocket 0.4.1 python
s3transfer 0.19.3 python
scanelf 1.3.9-r1 apk
setuptools 84.2.0 python
shadow 4.18.0-r1 apk
six 1.17.0 python
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
+15 -5
View File
@@ -32,7 +32,8 @@ 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`"}
@@ -65,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
@@ -177,7 +178,7 @@ init_diagram: |
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
@@ -198,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
@@ -213,11 +215,19 @@ init_diagram: |
svc-swag-auto-reload -> legacy-services
}
Base Images: {
"baseimage-alpine-nginx:3.22" <- "baseimage-alpine:3.22"
"baseimage-alpine-nginx:3.24" <- "baseimage-alpine:3.24"
}
"swag:latest" <- Base Images
# changelog
changelogs:
- {date: "20.10.26:", desc: "[Existing users should update:](https://github.com/linuxserver/docker-swag/blob/master/README.md#updating-configs) proxy.conf, authelia-server.conf, authentik-server.conf, tinyauth-server.conf - Update Nginx configuration to replace $http_host with $host$is_request_port$request_port for better compatibility."}
- {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."}
+2
View File
@@ -0,0 +1,2 @@
# Hetzner Cloud API Token
dns_hetzner_cloud_api_token = your_api_token_here
+3
View File
@@ -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 -1
View File
@@ -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,4 +1,4 @@
## Version 2025/03/25 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/authelia-server.conf.sample
## Version 2026/10/20 - 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
@@ -28,7 +28,7 @@ location @authelia_proxy_signin {
add_header Set-Cookie $set_cookie;
## Set the $target_url variable based on the original request
set_escape_uri $target_url $scheme://$http_host$request_uri;
set_escape_uri $target_url $scheme://$host$is_request_port$request_port$request_uri;
## Translate the Location response header from the auth subrequest into a variable
auth_request_set $signin_url $upstream_http_location;
@@ -1,4 +1,4 @@
## Version 2025/03/25 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/authentik-server.conf.sample
## Version 2026/10/20 - 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
@@ -38,10 +38,10 @@ location @goauthentik_proxy_signin {
add_header Set-Cookie $set_cookie;
## Set the $target_url variable based on the original request
set_escape_uri $target_url $scheme://$http_host$request_uri;
set_escape_uri $target_url $scheme://$host$is_request_port$request_port$request_uri;
## Set the $signin_url variable
set $signin_url https://$http_host/outpost.goauthentik.io/start?rd=$target_url;
set $signin_url https://$host$is_request_port$request_port/outpost.goauthentik.io/start?rd=$target_url;
## Redirect to login
return 302 $signin_url;
+2 -2
View File
@@ -1,4 +1,4 @@
## Version 2023/02/09 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/proxy.conf.sample
## Version 2026/10/20 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/proxy.conf.sample
# Timeout if the real server is dead
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
@@ -33,5 +33,5 @@ proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header X-Original-Method $request_method;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Original-URL $scheme://$host$is_request_port$request_port$request_uri;
proxy_set_header X-Real-IP $remote_addr;
@@ -1,4 +1,4 @@
## Version 2025/07/18 - 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 {
@@ -36,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";
@@ -50,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;
}
@@ -1,9 +1,22 @@
## Version 2025/06/08 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/tinyauth-location.conf.sample
## 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;
## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal
error_page 401 = @tinyauth_login;
## 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
+10 -23
View File
@@ -1,4 +1,4 @@
## Version 2025/06/08 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/nginx/tinyauth-server.conf.sample
## Version 2026/10/20 - 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
@@ -6,30 +6,17 @@
location /tinyauth {
internal;
include /config/nginx/proxy.conf;
include /config/nginx/resolver.conf;
set $upstream_tinyauth tinyauth;
proxy_pass http://$upstream_tinyauth:3000/api/auth/nginx;
proxy_set_header x-forwarded-proto $scheme;
proxy_set_header x-forwarded-host $http_host;
proxy_set_header x-forwarded-uri $request_uri;
}
# virtual location for tinyauth 401 redirects
location @tinyauth_login {
internal;
## Set the $target_url variable based on the original request
set_escape_uri $target_url $scheme://$http_host$request_uri;
## Set the $signin_url variable
set $domain $host;
if ($host ~* "^[^.]+\.([^.]+\..+)$") {
set $domain $1;
}
set $signin_url https://tinyauth.$domain/login?redirect_uri=$target_url;
## Redirect to login
return 302 $signin_url;
# 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://$host$is_request_port$request_port$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;
}
+1 -1
View File
@@ -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:]')"
@@ -80,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
@@ -168,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
@@ -186,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")
@@ -204,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
@@ -239,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
+1 -1
View File
@@ -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