diff --git a/.github/workflows/external_trigger.yml b/.github/workflows/external_trigger.yml index 6134d63f..979e0a31 100644 --- a/.github/workflows/external_trigger.yml +++ b/.github/workflows/external_trigger.yml @@ -48,13 +48,30 @@ jobs: --header "Accept: application/vnd.oci.image.index.v1+json" \ --header "Authorization: Bearer ${token}" \ "https://ghcr.io/v2/${image}/manifests/${tag}") - multidigest=$(jq -r ".manifests[] | select(.platform.architecture == \"amd64\").digest?" <<< "${multidigest}") - digest=$(curl -s \ - --header "Accept: application/vnd.docker.distribution.manifest.v2+json" \ - --header "Accept: application/vnd.oci.image.manifest.v1+json" \ - --header "Authorization: Bearer ${token}" \ - "https://ghcr.io/v2/${image}/manifests/${multidigest}" \ - | jq -r '.config.digest') + if jq -e '.layers // empty' <<< "${multidigest}" >/dev/null 2>&1; then + # If there's a layer element it's a single-arch manifest so just get that digest + digest=$(jq -r '.config.digest' <<< "${multidigest}") + else + # Otherwise it's multi-arch or has manifest annotations + if jq -e '.manifests[]?.annotations // empty' <<< "${multidigest}" >/dev/null 2>&1; then + # Check for manifest annotations and delete if found + multidigest=$(jq 'del(.manifests[] | select(.annotations))' <<< "${multidigest}") + fi + if [[ $(jq '.manifests | length' <<< "${multidigest}") -gt 1 ]]; then + # If there's still more than one digest, it's multi-arch + multidigest=$(jq -r ".manifests[] | select(.platform.architecture == \"amd64\").digest?" <<< "${multidigest}") + else + # Otherwise it's single arch + multidigest=$(jq -r ".manifests[].digest?" <<< "${multidigest}") + fi + if digest=$(curl -s \ + --header "Accept: application/vnd.docker.distribution.manifest.v2+json" \ + --header "Accept: application/vnd.oci.image.manifest.v1+json" \ + --header "Authorization: Bearer ${token}" \ + "https://ghcr.io/v2/${image}/manifests/${multidigest}"); then + digest=$(jq -r '.config.digest' <<< "${digest}"); + fi + fi image_info=$(curl -sL \ --header "Authorization: Bearer ${token}" \ "https://ghcr.io/v2/${image}/blobs/${digest}") @@ -92,7 +109,7 @@ jobs: else printf "\n## Trigger new build\n\n" >> $GITHUB_STEP_SUMMARY echo "New version \`${EXT_RELEASE}\` found; old version was \`${IMAGE_VERSION}\`. Triggering new build" >> $GITHUB_STEP_SUMMARY - if "${artifacts_found}" == "true" ]]; then + if [[ "${artifacts_found}" == "true" ]]; then echo "All artifacts seem to be uploaded." >> $GITHUB_STEP_SUMMARY fi response=$(curl -iX POST \ diff --git a/.github/workflows/package_trigger_scheduler.yml b/.github/workflows/package_trigger_scheduler.yml index bbd82fc7..1906f884 100644 --- a/.github/workflows/package_trigger_scheduler.yml +++ b/.github/workflows/package_trigger_scheduler.yml @@ -27,9 +27,18 @@ jobs: fi printf "\n## Evaluating \`%s\`\n\n" ${br} >> $GITHUB_STEP_SUMMARY JENKINS_VARS=$(curl -sX GET https://raw.githubusercontent.com/linuxserver/docker-swag/${br}/jenkins-vars.yml) - if [[ "${br}" == $(yq -r '.ls_branch' <<< "${JENKINS_VARS}") ]]; then + if ! curl -sfX GET https://raw.githubusercontent.com/linuxserver/docker-swag/${br}/Jenkinsfile >/dev/null 2>&1; then + echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + echo "> No Jenkinsfile found. Branch is either deprecated or is an early dev branch." >> $GITHUB_STEP_SUMMARY + skipped_branches="${skipped_branches}${br} " + elif [[ "${br}" == $(yq -r '.ls_branch' <<< "${JENKINS_VARS}") ]]; then echo "Branch appears to be live; checking workflow." >> $GITHUB_STEP_SUMMARY - if [[ $(yq -r '.skip_package_check' <<< "${JENKINS_VARS}") == "true" ]]; then + README_VARS=$(curl -sX GET https://raw.githubusercontent.com/linuxserver/docker-swag/${br}/readme-vars.yml) + if [[ $(yq -r '.project_deprecation_status' <<< "${README_VARS}") == "true" ]]; then + echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + echo "> Branch appears to be deprecated; skipping trigger." >> $GITHUB_STEP_SUMMARY + skipped_branches="${skipped_branches}${br} " + elif [[ $(yq -r '.skip_package_check' <<< "${JENKINS_VARS}") == "true" ]]; then echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY echo "> Skipping branch ${br} due to \`skip_package_check\` being set in \`jenkins-vars.yml\`." >> $GITHUB_STEP_SUMMARY skipped_branches="${skipped_branches}${br} " @@ -37,7 +46,7 @@ jobs: echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY echo "> Github organizational variable \`SKIP_PACKAGE_TRIGGER\` contains \`swag_${br}\`; skipping trigger." >> $GITHUB_STEP_SUMMARY skipped_branches="${skipped_branches}${br} " - elif [ $(curl -s https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-swag/job/${br}/lastBuild/api/json | jq -r '.building') == "true" ]; then + elif [ $(curl -s https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-swag/job/${br}/lastBuild/api/json | jq -r '.building' 2>/dev/null) == "true" ]; then echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY echo "> There already seems to be an active build on Jenkins; skipping package trigger for ${br}" >> $GITHUB_STEP_SUMMARY skipped_branches="${skipped_branches}${br} " @@ -49,6 +58,11 @@ jobs: response=$(curl -iX POST \ https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-swag/job/${br}/buildWithParameters?PACKAGE_CHECK=true \ --user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} | grep -i location | sed "s|^[L|l]ocation: \(.*\)|\1|") + if [[ -z "${response}" ]]; then + echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + echo "> Jenkins build could not be triggered. Skipping branch." + continue + fi echo "Jenkins [job queue url](${response%$'\r'})" >> $GITHUB_STEP_SUMMARY echo "Sleeping 10 seconds until job starts" >> $GITHUB_STEP_SUMMARY sleep 10 @@ -56,11 +70,14 @@ jobs: buildurl="${buildurl%$'\r'}" echo "Jenkins job [build url](${buildurl})" >> $GITHUB_STEP_SUMMARY echo "Attempting to change the Jenkins job description" >> $GITHUB_STEP_SUMMARY - curl -iX POST \ + if ! curl -ifX POST \ "${buildurl}submitDescription" \ --user ${{ secrets.JENKINS_USER }}:${{ secrets.JENKINS_TOKEN }} \ --data-urlencode "description=GHA package trigger https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" \ - --data-urlencode "Submit=Submit" + --data-urlencode "Submit=Submit"; then + echo "> [!WARNING]" >> $GITHUB_STEP_SUMMARY + echo "> Unable to change the Jenkins job description." + fi sleep 20 fi else diff --git a/Dockerfile b/Dockerfile index 16811e71..f7918535 100755 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1 -FROM ghcr.io/linuxserver/baseimage-alpine-nginx:3.20 +FROM cr.spad.uk/linuxserver/baseimage-alpine-nginx:3.21 # set version label ARG BUILD_DATE @@ -88,7 +88,7 @@ RUN \ pip install -U --no-cache-dir \ pip \ wheel && \ - pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.20/ \ + pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.21/ \ certbot==${CERTBOT_VERSION} \ certbot-dns-acmedns \ certbot-dns-aliyun \ @@ -150,9 +150,9 @@ RUN \ rm -f /etc/nginx/conf.d/stream.conf && \ echo "**** correct ip6tables legacy issue ****" && \ rm \ - /sbin/ip6tables && \ + /usr/sbin/ip6tables && \ ln -s \ - /sbin/ip6tables-nft /sbin/ip6tables && \ + /usr/sbin/ip6tables-nft /usr/sbin/ip6tables && \ echo "**** remove unnecessary fail2ban filters ****" && \ rm \ /etc/fail2ban/jail.d/alpine-ssh.conf && \ diff --git a/Dockerfile.aarch64 b/Dockerfile.aarch64 index 2aa2823e..9bc2aed0 100755 --- a/Dockerfile.aarch64 +++ b/Dockerfile.aarch64 @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1 -FROM ghcr.io/linuxserver/baseimage-alpine-nginx:arm64v8-3.20 +FROM ghcr.io/linuxserver/baseimage-alpine-nginx:arm64v8-3.21 # set version label ARG BUILD_DATE @@ -88,7 +88,7 @@ RUN \ pip install -U --no-cache-dir \ pip \ wheel && \ - pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.20/ \ + pip install -U --no-cache-dir --find-links https://wheel-index.linuxserver.io/alpine-3.21/ \ certbot==${CERTBOT_VERSION} \ certbot-dns-acmedns \ certbot-dns-aliyun \ @@ -150,9 +150,9 @@ RUN \ rm -f /etc/nginx/conf.d/stream.conf && \ echo "**** correct ip6tables legacy issue ****" && \ rm \ - /sbin/ip6tables && \ + /usr/sbin/ip6tables && \ ln -s \ - /sbin/ip6tables-nft /sbin/ip6tables && \ + /usr/sbin/ip6tables-nft /usr/sbin/ip6tables && \ echo "**** remove unnecessary fail2ban filters ****" && \ rm \ /etc/fail2ban/jail.d/alpine-ssh.conf && \ diff --git a/Jenkinsfile b/Jenkinsfile index 9f4102ef..8f490af6 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -575,7 +575,7 @@ pipeline { --label \"org.opencontainers.image.title=Swag\" \ --label \"org.opencontainers.image.description=SWAG - Secure Web Application Gateway (formerly known as letsencrypt, no relation to Let's Encrypt™) sets up an Nginx webserver and reverse proxy with php support and a built-in certbot client that automates free SSL server certificate generation and renewal processes (Let's Encrypt and ZeroSSL). It also contains fail2ban for intrusion prevention.\" \ --no-cache --pull -t ${IMAGE}:${META_TAG} --platform=linux/amd64 \ - --provenance=false --sbom=false --builder=container --load \ + --provenance=true --sbom=true --builder=container --load \ --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." sh '''#! /bin/bash set -e @@ -604,7 +604,9 @@ pipeline { for i in "${CACHE[@]}"; do docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} & done - wait + for p in $(jobs -p); do + wait "$p" || { echo "job $p failed" >&2; exit 1; } + done fi ''' } @@ -639,7 +641,7 @@ pipeline { --label \"org.opencontainers.image.title=Swag\" \ --label \"org.opencontainers.image.description=SWAG - Secure Web Application Gateway (formerly known as letsencrypt, no relation to Let's Encrypt™) sets up an Nginx webserver and reverse proxy with php support and a built-in certbot client that automates free SSL server certificate generation and renewal processes (Let's Encrypt and ZeroSSL). It also contains fail2ban for intrusion prevention.\" \ --no-cache --pull -t ${IMAGE}:amd64-${META_TAG} --platform=linux/amd64 \ - --provenance=false --sbom=false --builder=container --load \ + --provenance=true --sbom=true --builder=container --load \ --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." sh '''#! /bin/bash set -e @@ -668,7 +670,9 @@ pipeline { for i in "${CACHE[@]}"; do docker push ${i}:amd64-${COMMIT_SHA}-${BUILD_NUMBER} & done - wait + for p in $(jobs -p); do + wait "$p" || { echo "job $p failed" >&2; exit 1; } + done fi ''' } @@ -696,7 +700,7 @@ pipeline { --label \"org.opencontainers.image.title=Swag\" \ --label \"org.opencontainers.image.description=SWAG - Secure Web Application Gateway (formerly known as letsencrypt, no relation to Let's Encrypt™) sets up an Nginx webserver and reverse proxy with php support and a built-in certbot client that automates free SSL server certificate generation and renewal processes (Let's Encrypt and ZeroSSL). It also contains fail2ban for intrusion prevention.\" \ --no-cache --pull -f Dockerfile.aarch64 -t ${IMAGE}:arm64v8-${META_TAG} --platform=linux/arm64 \ - --provenance=false --sbom=false --builder=container --load \ + --provenance=true --sbom=true --builder=container --load \ --build-arg ${BUILD_VERSION_ARG}=${EXT_RELEASE} --build-arg VERSION=\"${VERSION_TAG}\" --build-arg BUILD_DATE=${GITHUB_DATE} ." sh '''#! /bin/bash set -e @@ -725,7 +729,9 @@ pipeline { for i in "${CACHE[@]}"; do docker push ${i}:arm64v8-${COMMIT_SHA}-${BUILD_NUMBER} & done - wait + for p in $(jobs -p); do + wait "$p" || { echo "job $p failed" >&2; exit 1; } + done fi ''' } @@ -968,7 +974,7 @@ pipeline { echo '{"tag_name":"'${META_TAG}'",\ "target_commitish": "master",\ "name": "'${META_TAG}'",\ - "body": "**CI Report:**\\n\\n'${CI_URL:-N/A}'\\n\\n**LinuxServer Changes:**\\n\\n'${LS_RELEASE_NOTES}'\\n\\n**PIP Changes:**\\n\\n' > start + "body": "**CI Report:**\\n\\n'${CI_URL:-N/A}'\\n\\n**LinuxServer Changes:**\\n\\n'${LS_RELEASE_NOTES}'\\n\\n**Remote Changes:**\\n\\n' > start printf '","draft": false,"prerelease": false}' >> releasebody.json paste -d'\\0' start releasebody.json > releasebody.json.done curl -H "Authorization: token ${GITHUB_TOKEN}" -X POST https://api.github.com/repos/${LS_USER}/${LS_REPO}/releases -d @releasebody.json.done''' diff --git a/README.md b/README.md index ebcf8f32..14a75caa 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,15 @@ This will *ask* Google et al not to index and list your site. Be careful with th Please follow the instructions [on this blog post](https://www.linuxserver.io/blog/2020-08-21-introducing-swag#migrate). +## Read-Only Operation + +This image can be run with a read-only container filesystem. For details please [read the docs](https://docs.linuxserver.io/misc/read-only/). + +### Caveats + +* `/tmp` must be mounted to tmpfs +* fail2ban will not be available + ## Usage To help you get started creating a container from this image you can either use docker-compose or the docker cli. @@ -236,6 +245,7 @@ Containers are configured using parameters passed at runtime (such as those abov | `-e EXTRA_DOMAINS=` | Additional fully qualified domain names (comma separated, no spaces) ie. `example.net,subdomain.example.net,*.example.org` | | `-e STAGING=false` | Set to `true` to retrieve certs in staging mode. Rate limits will be much higher, but the resulting cert will not pass the browser's security test. Only to be used for testing purposes. | | `-v /config` | Persistent config files | +| `--read-only=true` | Run container with a read-only filesystem. Please [read the docs](https://docs.linuxserver.io/misc/read-only/). | | `--cap-add=NET_ADMIN` | Required for fail2Ban to be able to modify iptables rules. | ### Portainer notice @@ -404,6 +414,7 @@ Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64 ## Versions +* **17.12.24:** - Rebase to Alpine 3.21. * **21.10.24:** - Fix naming issue with Dynu plugin. If you are using Dynu, please make sure your credentials are set in /config/dns-conf/dynu.ini and your DNSPLUGIN variable is set to dynu (not dynudns). * **30.08.24:** - Fix zerossl cert revocation. * **24.07.14:** - Rebase to Alpine 3.20. Remove deprecated Google Domains certbot plugin. Existing users should update their nginx confs to avoid http2 deprecation warnings. diff --git a/readme-vars.yml b/readme-vars.yml index 2a9e9d6d..4cf02008 100644 --- a/readme-vars.yml +++ b/readme-vars.yml @@ -40,6 +40,10 @@ opt_param_env_vars: opt_param_usage_include_ports: true opt_param_ports: - {external_port: "80", internal_port: "80", port_desc: "HTTP port (required for HTTP validation and HTTP -> HTTPS redirect)"} +readonly_supported: true +readonly_message: | + * `/tmp` must be mounted to tmpfs + * fail2ban will not be available # application setup block app_setup_block_enabled: true app_setup_block: | @@ -200,6 +204,7 @@ init_diagram: | "swag:latest" <- Base Images # changelog changelogs: + - {date: "17.12.24:", desc: "Rebase to Alpine 3.21."} - {date: "21.10.24:", desc: "Fix naming issue with Dynu plugin. If you are using Dynu, please make sure your credentials are set in /config/dns-conf/dynu.ini and your DNSPLUGIN variable is set to dynu (not dynudns)."} - {date: "30.08.24:", desc: "Fix zerossl cert revocation."} - {date: "24.07.14:", desc: "Rebase to Alpine 3.20. Remove deprecated Google Domains certbot plugin. Existing users should update their nginx confs to avoid http2 deprecation warnings."} diff --git a/root/app/le-renew.sh b/root/app/le-renew.sh index 7f2137a2..c597f359 100755 --- a/root/app/le-renew.sh +++ b/root/app/le-renew.sh @@ -6,4 +6,4 @@ echo echo "<------------------------------------------------->" echo "cronjob running on $(date)" echo "Running certbot renew" -certbot renew --non-interactive +certbot renew --non-interactive --config-dir /config/etc/letsencrypt --logs-dir /config/log/letsencrypt --work-dir /tmp/letsencrypt --config /config/etc/letsencrypt/cli.ini diff --git a/root/defaults/etc/letsencrypt/renewal-hooks/deploy/10-default b/root/defaults/etc/letsencrypt/renewal-hooks/deploy/10-default old mode 100644 new mode 100755 diff --git a/root/defaults/etc/letsencrypt/renewal-hooks/post/10-nginx b/root/defaults/etc/letsencrypt/renewal-hooks/post/10-nginx old mode 100644 new mode 100755 diff --git a/root/defaults/etc/letsencrypt/renewal-hooks/pre/10-nginx b/root/defaults/etc/letsencrypt/renewal-hooks/pre/10-nginx old mode 100644 new mode 100755 diff --git a/root/etc/crontabs/root b/root/etc/crontabs/root index 15de5f74..c848b3f5 100644 --- a/root/etc/crontabs/root +++ b/root/etc/crontabs/root @@ -5,4 +5,4 @@ 0 3 * * 6 run-parts /etc/periodic/weekly 0 5 1 * * run-parts /etc/periodic/monthly -8 2 * * * /app/le-renew.sh >> /config/log/letsencrypt/letsencrypt.log 2>&1 +8 2 * * * /app/le-renew.sh >> /config/log/letsencrypt/renewal.log 2>&1 diff --git a/root/etc/s6-overlay/s6-rc.d/init-certbot-config/run b/root/etc/s6-overlay/s6-rc.d/init-certbot-config/run index 32835102..51e8e5e4 100755 --- a/root/etc/s6-overlay/s6-rc.d/init-certbot-config/run +++ b/root/etc/s6-overlay/s6-rc.d/init-certbot-config/run @@ -38,12 +38,6 @@ if [[ "${VALIDATION}" = "dns" ]] && ! echo "${CERTBOT_DNS_AUTHENTICATORS}" | gre sleep infinity fi -# set owner of certbot's CONFIG_DIR, WORK_DIR, and LOGS_DIR to abc -lsiown -R abc:abc \ - /etc/letsencrypt \ - /var/lib/letsencrypt \ - /var/log/letsencrypt - # set_ini_value logic: # - if the name is not found in the file, append the name=value to the end of the file # - if the name is found in the file, replace the value @@ -67,7 +61,6 @@ cp -n /defaults/dns-conf/* /config/dns-conf/ 2> >(grep -v 'cp: not replacing') lsiown -R abc:abc /config/dns-conf # copy default renewal hooks -chmod -R +x /defaults/etc/letsencrypt/renewal-hooks cp -nR /defaults/etc/letsencrypt/renewal-hooks/* /config/etc/letsencrypt/renewal-hooks/ 2> >(grep -v 'cp: not replacing') lsiown -R abc:abc /config/etc/letsencrypt/renewal-hooks @@ -169,14 +162,14 @@ fi rm -rf /config/keys/letsencrypt if [[ "${ONLY_SUBDOMAINS}" = "true" ]] && [[ ! "${SUBDOMAINS}" = "wildcard" ]]; then DOMAIN="$(echo "${SUBDOMAINS}" | tr ',' ' ' | awk '{print $1}').${URL}" - ln -s ../etc/letsencrypt/live/"${DOMAIN}" /config/keys/letsencrypt + ln -s /config/etc/letsencrypt/live/"${DOMAIN}" /config/keys/letsencrypt else - ln -s ../etc/letsencrypt/live/"${URL}" /config/keys/letsencrypt + ln -s /config/etc/letsencrypt/live/"${URL}" /config/keys/letsencrypt fi # cleanup unused csr and keys folders -rm -rf /etc/letsencrypt/csr -rm -rf /etc/letsencrypt/keys +rm -rf /config/etc/letsencrypt/csr +rm -rf /config/etc/letsencrypt/keys # checking for changes in cert variables, revoking certs if necessary if [[ ! "${URL}" = "${ORIGURL}" ]] || @@ -197,9 +190,9 @@ if [[ ! "${URL}" = "${ORIGURL}" ]] || REV_ACMESERVER=("https://acme-v02.api.letsencrypt.org/directory") fi if [[ -f /config/etc/letsencrypt/live/"${ORIGDOMAIN}"/fullchain.pem ]]; then - certbot revoke --non-interactive --cert-path /config/etc/letsencrypt/live/"${ORIGDOMAIN}"/fullchain.pem --key-path /config/etc/letsencrypt/live/"${ORIGDOMAIN}"/privkey.pem --server "${REV_ACMESERVER[@]}" || true + 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 --key-path /config/etc/letsencrypt/live/"${ORIGDOMAIN}"/privkey.pem --server "${REV_ACMESERVER[@]}" || true else - certbot revoke --non-interactive --cert-name "${ORIGDOMAIN}" --server "${REV_ACMESERVER[@]}" || true + 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 @@ -212,9 +205,9 @@ if [[ -f "/config/keys/letsencrypt/chain.pem" ]] && { [[ "${CERTPROVIDER}" == "l 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 --non-interactive --cert-path /config/etc/letsencrypt/live/"${ORIGDOMAIN}"/fullchain.pem --server "${REV_ACMESERVER[@]}" || true + 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 --non-interactive --cert-name "${ORIGDOMAIN}" --server "${REV_ACMESERVER[@]}" || true + 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 @@ -347,7 +340,7 @@ if [[ ! -f "/config/keys/letsencrypt/fullchain.pem" ]]; then set_ini_value "eab-hmac-key" "${ZEROSSL_EAB_HMAC_KEY}" /config/etc/letsencrypt/cli.ini fi echo "Generating new certificate" - certbot certonly --non-interactive --renew-by-default + certbot certonly --config-dir /config/etc/letsencrypt --logs-dir /config/log/letsencrypt --work-dir /tmp/letsencrypt --config /config/etc/letsencrypt/cli.ini --non-interactive --renew-by-default if [[ ! -d /config/keys/letsencrypt ]]; then if [[ "${VALIDATION}" = "dns" ]]; then echo "ERROR: Cert does not exist! Please see the validation error above. Make sure you entered correct credentials into the ${DNSCREDENTIALFILE} file." diff --git a/root/etc/s6-overlay/s6-rc.d/init-fail2ban-config/run b/root/etc/s6-overlay/s6-rc.d/init-fail2ban-config/run index 968043ab..2c575214 100755 --- a/root/etc/s6-overlay/s6-rc.d/init-fail2ban-config/run +++ b/root/etc/s6-overlay/s6-rc.d/init-fail2ban-config/run @@ -1,38 +1,42 @@ #!/usr/bin/with-contenv bash # shellcheck shell=bash -if ! iptables -L &> /dev/null; then - ln -sf /sbin/xtables-legacy-multi /sbin/iptables - ln -sf /sbin/xtables-legacy-multi /sbin/iptables-save - ln -sf /sbin/xtables-legacy-multi /sbin/iptables-restore - ln -sf /sbin/xtables-legacy-multi /sbin/ip6tables - ln -sf /sbin/xtables-legacy-multi /sbin/ip6tables-save - ln -sf /sbin/xtables-legacy-multi /sbin/ip6tables-restore -fi +if [[ -z ${LSIO_READ_ONLY_FS} ]] && [[ -z ${LSIO_NON_ROOT_USER} ]]; then + if ! iptables -L &> /dev/null; then + ln -sf /usr/sbin/xtables-legacy-multi /usr/sbin/iptables + ln -sf /usr/sbin/xtables-legacy-multi /usr/sbin/iptables-save + ln -sf /usr/sbin/xtables-legacy-multi /usr/sbin/iptables-restore + ln -sf /usr/sbin/xtables-legacy-multi /usr/sbin/ip6tables + ln -sf /usr/sbin/xtables-legacy-multi /usr/sbin/ip6tables-save + ln -sf /usr/sbin/xtables-legacy-multi /usr/sbin/ip6tables-restore + fi -# copy/update the fail2ban config defaults to/in /config -cp -R /defaults/fail2ban/filter.d /config/fail2ban/ -cp -R /defaults/fail2ban/action.d /config/fail2ban/ -# if jail.local is missing in /config, copy default -if [[ ! -f /config/fail2ban/jail.local ]]; then - cp /defaults/fail2ban/jail.local /config/fail2ban/jail.local -fi -# Replace fail2ban config with user config -if [[ -d /etc/fail2ban/filter.d ]]; then - rm -rf /etc/fail2ban/filter.d -fi -if [[ -d /etc/fail2ban/action.d ]]; then - rm -rf /etc/fail2ban/action.d -fi -cp -R /config/fail2ban/filter.d /etc/fail2ban/ -cp -R /config/fail2ban/action.d /etc/fail2ban/ -cp /defaults/fail2ban/fail2ban.local /etc/fail2ban/ -cp /config/fail2ban/jail.local /etc/fail2ban/jail.local + # copy/update the fail2ban config defaults to/in /config + cp -R /defaults/fail2ban/filter.d /config/fail2ban/ + cp -R /defaults/fail2ban/action.d /config/fail2ban/ + # if jail.local is missing in /config, copy default + if [[ ! -f /config/fail2ban/jail.local ]]; then + cp /defaults/fail2ban/jail.local /config/fail2ban/jail.local + fi + # Replace fail2ban config with user config + if [[ -d /etc/fail2ban/filter.d ]]; then + rm -rf /etc/fail2ban/filter.d + fi + if [[ -d /etc/fail2ban/action.d ]]; then + rm -rf /etc/fail2ban/action.d + fi + cp -R /config/fail2ban/filter.d /etc/fail2ban/ + cp -R /config/fail2ban/action.d /etc/fail2ban/ + cp /defaults/fail2ban/fail2ban.local /etc/fail2ban/ + cp /config/fail2ban/jail.local /etc/fail2ban/jail.local -# logfiles needed by fail2ban -if [[ ! -f /config/log/nginx/error.log ]]; then - touch /config/log/nginx/error.log -fi -if [[ ! -f /config/log/nginx/access.log ]]; then - touch /config/log/nginx/access.log + # logfiles needed by fail2ban + if [[ ! -f /config/log/nginx/error.log ]]; then + touch /config/log/nginx/error.log + fi + if [[ ! -f /config/log/nginx/access.log ]]; then + touch /config/log/nginx/access.log + fi +else + rm -rf /etc/logrotate.d/fail2ban fi diff --git a/root/etc/s6-overlay/s6-rc.d/init-permissions-config/run b/root/etc/s6-overlay/s6-rc.d/init-permissions-config/run index 6c91e71d..3422f4eb 100755 --- a/root/etc/s6-overlay/s6-rc.d/init-permissions-config/run +++ b/root/etc/s6-overlay/s6-rc.d/init-permissions-config/run @@ -4,8 +4,10 @@ # permissions lsiown -R abc:abc \ /config -chmod -R 0644 /etc/logrotate.d chmod -R +r /config/log +if [[ -z ${LSIO_READ_ONLY_FS} ]]; then + chmod -R 0644 /etc/logrotate.d +fi # Workaround for systems with chmod errors true diff --git a/root/etc/s6-overlay/s6-rc.d/init-swag-folders/run b/root/etc/s6-overlay/s6-rc.d/init-swag-folders/run index c18da5b8..f42b79e9 100755 --- a/root/etc/s6-overlay/s6-rc.d/init-swag-folders/run +++ b/root/etc/s6-overlay/s6-rc.d/init-swag-folders/run @@ -7,6 +7,7 @@ mkdir -p \ /config/etc/letsencrypt/renewal-hooks \ /config/log/{fail2ban,letsencrypt,nginx} \ /config/nginx/proxy-confs \ - /run/fail2ban -rm -rf /etc/letsencrypt -ln -s /config/etc/letsencrypt /etc/letsencrypt + /run/fail2ban \ + /tmp/letsencrypt \ + /tmp/nginx/cache + diff --git a/root/etc/s6-overlay/s6-rc.d/svc-fail2ban/run b/root/etc/s6-overlay/s6-rc.d/svc-fail2ban/run index a06f3d0e..5dbe7a28 100755 --- a/root/etc/s6-overlay/s6-rc.d/svc-fail2ban/run +++ b/root/etc/s6-overlay/s6-rc.d/svc-fail2ban/run @@ -1,5 +1,9 @@ #!/usr/bin/with-contenv bash # shellcheck shell=bash -exec \ - fail2ban-client -x -f start +if [[ -z ${LSIO_READ_ONLY_FS} ]] && [[ -z ${LSIO_NON_ROOT_USER} ]]; then + exec \ + fail2ban-client -x -f start +else + sleep infinity +fi