diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..dd686e0 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,51 @@ +name-template: 'v$RESOLVED_VERSION 🌈' +tag-template: 'v$RESOLVED_VERSION' +categories: + - title: '🚀 Features' + labels: + - 'feature' + - 'enhancement' + - title: '🐛 Bug Fixes' + labels: + - 'fix' + - 'bugfix' + - 'bug' + - title: '🖊️ Refactors' + labels: + - 'refactor' + - title: '👗 Style' + labels: + - 'style' + - title: '📝 Documentation' + labels: + - 'docs' + - 'documentation' + - title: '🧰 Maintenance' + label: 'chore' +change-template: '- $TITLE @$AUTHOR (#$NUMBER)' +version-resolver: + major: + labels: + # - 'major' + - 'breaking' + minor: + labels: + # - 'minor' + - 'feature' + - 'enhancement' + - 'refactor' + patch: + labels: + # - 'patch' + - 'fix' + - 'bugfix' + - 'bug' + - 'style' + - 'docs' + - 'documentation' + default: patch +sort-by: title +template: | + ## Changes + + $CHANGES \ No newline at end of file diff --git a/.github/workflows/ci-master-pr.yml b/.github/workflows/ci-master-pr.yml index 7758b65..88e2a33 100644 --- a/.github/workflows/ci-master-pr.yml +++ b/.github/workflows/ci-master-pr.yml @@ -9,6 +9,108 @@ on: - master jobs: + build-v2-5-0-alpine-3-13: + runs-on: ubuntu-18.04 + env: + VARIANT_TAG: v2.5.0-alpine-3.13 + # VARIANT_TAG_WITH_REF: v2.5.0-alpine-3.13-${GITHUB_REF} + VARIANT_BUILD_DIR: variants/v2.5.0-alpine-3.13 + steps: + - uses: actions/checkout@v1 + - name: Display system info (linux) + run: | + set -e + hostname + whoami + cat /etc/*release + lscpu + free + df -h + pwd + docker info + docker version + - name: Login to docker registry + run: echo "${DOCKERHUB_REGISTRY_PASSWORD}" | docker login -u "${DOCKERHUB_REGISTRY_USER}" --password-stdin + env: + DOCKERHUB_REGISTRY_USER: ${{ secrets.DOCKERHUB_REGISTRY_USER }} + DOCKERHUB_REGISTRY_PASSWORD: ${{ secrets.DOCKERHUB_REGISTRY_PASSWORD }} + - name: Build and push image + env: + DOCKERHUB_REGISTRY_USER: ${{ secrets.DOCKERHUB_REGISTRY_USER }} + run: | + set -e + + # Get 'project-name' from 'namespace/project-name' + CI_PROJECT_NAME=$( echo "${GITHUB_REPOSITORY}" | rev | cut -d '/' -f 1 | rev ) + + # Get 'ref-name' from 'refs/heads/ref-name' + REF=$( echo "${GITHUB_REF}" | rev | cut -d '/' -f 1 | rev ) + SHA_SHORT=$( echo "${GITHUB_SHA}" | cut -c1-7 ) + + # Generate the final tags. E.g. 'master-v1.0.0-alpine' and 'master-b29758a-v1.0.0-alpine' + VARIANT_TAG_WITH_REF="${REF}-${VARIANT_TAG}" + VARIANT_TAG_WITH_REF_AND_SHA_SHORT="${REF}-${SHA_SHORT}-${VARIANT_TAG}" + + docker build \ + -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF}" \ + -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF_AND_SHA_SHORT}" \ + "${VARIANT_BUILD_DIR}" + docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF}" + docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF_AND_SHA_SHORT}" + - name: Clean-up + run: docker logout + if: always() + build-v2-4-10-alpine-3-12: + runs-on: ubuntu-18.04 + env: + VARIANT_TAG: v2.4.10-alpine-3.12 + # VARIANT_TAG_WITH_REF: v2.4.10-alpine-3.12-${GITHUB_REF} + VARIANT_BUILD_DIR: variants/v2.4.10-alpine-3.12 + steps: + - uses: actions/checkout@v1 + - name: Display system info (linux) + run: | + set -e + hostname + whoami + cat /etc/*release + lscpu + free + df -h + pwd + docker info + docker version + - name: Login to docker registry + run: echo "${DOCKERHUB_REGISTRY_PASSWORD}" | docker login -u "${DOCKERHUB_REGISTRY_USER}" --password-stdin + env: + DOCKERHUB_REGISTRY_USER: ${{ secrets.DOCKERHUB_REGISTRY_USER }} + DOCKERHUB_REGISTRY_PASSWORD: ${{ secrets.DOCKERHUB_REGISTRY_PASSWORD }} + - name: Build and push image + env: + DOCKERHUB_REGISTRY_USER: ${{ secrets.DOCKERHUB_REGISTRY_USER }} + run: | + set -e + + # Get 'project-name' from 'namespace/project-name' + CI_PROJECT_NAME=$( echo "${GITHUB_REPOSITORY}" | rev | cut -d '/' -f 1 | rev ) + + # Get 'ref-name' from 'refs/heads/ref-name' + REF=$( echo "${GITHUB_REF}" | rev | cut -d '/' -f 1 | rev ) + SHA_SHORT=$( echo "${GITHUB_SHA}" | cut -c1-7 ) + + # Generate the final tags. E.g. 'master-v1.0.0-alpine' and 'master-b29758a-v1.0.0-alpine' + VARIANT_TAG_WITH_REF="${REF}-${VARIANT_TAG}" + VARIANT_TAG_WITH_REF_AND_SHA_SHORT="${REF}-${SHA_SHORT}-${VARIANT_TAG}" + + docker build \ + -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF}" \ + -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF_AND_SHA_SHORT}" \ + "${VARIANT_BUILD_DIR}" + docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF}" + docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF_AND_SHA_SHORT}" + - name: Clean-up + run: docker logout + if: always() build-v2-4-8-alpine-3-11: runs-on: ubuntu-18.04 env: @@ -467,4 +569,57 @@ jobs: docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF_AND_SHA_SHORT}" - name: Clean-up run: docker logout - if: always() \ No newline at end of file + if: always() + resolve-release-tag: + runs-on: ubuntu-latest + outputs: + TAG: ${{ steps.resolve-release-tag.outputs.TAG }} + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Resolve release tag + id: resolve-release-tag + run: | + set +e + # E.g. 20210402 + TODAYS_DATE=$( date -u '+%Y%m%d' ) + # Is this the first tag for this date? + TODAYS_DATE_TAGS=$( git tag --list | grep "^$TODAYS_DATE" ) + TAG= + if [ -z "$TODAYS_DATE_TAGS" ]; then + # E.g. 20210402.0.0 + TAG="$TODAYS_DATE.0.0" # Send this to stdout + else + # E.g. if there are 20210402.0.0, 20210402.0.1, 20210402.0.2, this returns 2 + VERSION_MINOR_LATEST=$( echo "$TODAYS_DATE_TAGS" | cut -d '.' -f 3 | sort -nr | head -n1 ) + # Minor version + VERSION_MINOR=$( expr "$VERSION_MINOR_LATEST" + 1 ) + # E.g. 20210402.0.3 + TAG="$TODAYS_DATE.0.$VERSION_MINOR" # Send this to stdout + fi + echo "TODAYS_DATE: $TODAYS_DATE" + echo "TODAYS_DATE_TAGS: $TODAYS_DATE_TAGS" + echo "TAG: $TAG" + echo "::set-output name=TAG::$TAG" + - name: Print outputs + run: echo ${{ steps.resolve-release-tag.outputs.TAG }} + update-draft-release: + needs: [build-v2-5-0-alpine-3-13, build-v2-4-10-alpine-3-12, build-v2-4-8-alpine-3-11, build-v2-4-7-alpine-3-10, build-v2-4-6-alpine-3-9, build-v2-4-6-alpine-3-8, build-v2-4-4-alpine-3-7, build-v2-4-4-alpine-3-6, build-v2-3-18-alpine-3-5, build-v2-3-18-alpine-3-4, build-v2-3-18-alpine-3-3, resolve-release-tag] + if: github.ref == 'refs/heads/master' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Print inputs + run: echo ${{ needs.resolve-release-tag.outputs.TAG }} + # Drafts your next Release notes as Pull Requests are merged into "master" + - uses: release-drafter/release-drafter@v5 + with: + config-name: release-drafter.yml + publish: false + name: ${{ needs.resolve-release-tag.outputs.TAG }} + tag: ${{ needs.resolve-release-tag.outputs.TAG }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ci-release.yml b/.github/workflows/ci-release.yml index c1af4bb..e82b7ca 100644 --- a/.github/workflows/ci-release.yml +++ b/.github/workflows/ci-release.yml @@ -6,6 +6,114 @@ on: - release jobs: + build-v2-5-0-alpine-3-13: + runs-on: ubuntu-18.04 + env: + VARIANT_TAG: v2.5.0-alpine-3.13 + # VARIANT_TAG_WITH_REF: v2.5.0-alpine-3.13-${GITHUB_REF} + VARIANT_BUILD_DIR: variants/v2.5.0-alpine-3.13 + steps: + - uses: actions/checkout@v1 + - name: Display system info (linux) + run: | + set -e + hostname + whoami + cat /etc/*release + lscpu + free + df -h + pwd + docker info + docker version + - name: Login to docker registry + run: echo "${DOCKERHUB_REGISTRY_PASSWORD}" | docker login -u "${DOCKERHUB_REGISTRY_USER}" --password-stdin + env: + DOCKERHUB_REGISTRY_USER: ${{ secrets.DOCKERHUB_REGISTRY_USER }} + DOCKERHUB_REGISTRY_PASSWORD: ${{ secrets.DOCKERHUB_REGISTRY_PASSWORD }} + - name: Build and push image + env: + DOCKERHUB_REGISTRY_USER: ${{ secrets.DOCKERHUB_REGISTRY_USER }} + run: | + set -e + + # Get 'project-name' from 'namespace/project-name' + CI_PROJECT_NAME=$( echo "${GITHUB_REPOSITORY}" | rev | cut -d '/' -f 1 | rev ) + + # Get 'ref-name' from 'refs/heads/ref-name' + REF=$( echo "${GITHUB_REF}" | rev | cut -d '/' -f 1 | rev ) + SHA_SHORT=$( echo "${GITHUB_SHA}" | cut -c1-7 ) + + # Generate the final tags. E.g. 'release-v1.0.0-alpine' and 'release-b29758a-v1.0.0-alpine' + VARIANT_TAG_WITH_REF="${REF}-${VARIANT_TAG}" + VARIANT_TAG_WITH_REF_AND_SHA_SHORT="${REF}-${SHA_SHORT}-${VARIANT_TAG}" + + docker build \ + -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG}" \ + -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF}" \ + -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF_AND_SHA_SHORT}" \ + -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:latest" \ + "${VARIANT_BUILD_DIR}" + docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG}" + docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF}" + docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF_AND_SHA_SHORT}" + docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:latest" + - name: Clean-up + run: docker logout + if: always() + build-v2-4-10-alpine-3-12: + runs-on: ubuntu-18.04 + env: + VARIANT_TAG: v2.4.10-alpine-3.12 + # VARIANT_TAG_WITH_REF: v2.4.10-alpine-3.12-${GITHUB_REF} + VARIANT_BUILD_DIR: variants/v2.4.10-alpine-3.12 + steps: + - uses: actions/checkout@v1 + - name: Display system info (linux) + run: | + set -e + hostname + whoami + cat /etc/*release + lscpu + free + df -h + pwd + docker info + docker version + - name: Login to docker registry + run: echo "${DOCKERHUB_REGISTRY_PASSWORD}" | docker login -u "${DOCKERHUB_REGISTRY_USER}" --password-stdin + env: + DOCKERHUB_REGISTRY_USER: ${{ secrets.DOCKERHUB_REGISTRY_USER }} + DOCKERHUB_REGISTRY_PASSWORD: ${{ secrets.DOCKERHUB_REGISTRY_PASSWORD }} + - name: Build and push image + env: + DOCKERHUB_REGISTRY_USER: ${{ secrets.DOCKERHUB_REGISTRY_USER }} + run: | + set -e + + # Get 'project-name' from 'namespace/project-name' + CI_PROJECT_NAME=$( echo "${GITHUB_REPOSITORY}" | rev | cut -d '/' -f 1 | rev ) + + # Get 'ref-name' from 'refs/heads/ref-name' + REF=$( echo "${GITHUB_REF}" | rev | cut -d '/' -f 1 | rev ) + SHA_SHORT=$( echo "${GITHUB_SHA}" | cut -c1-7 ) + + # Generate the final tags. E.g. 'release-v1.0.0-alpine' and 'release-b29758a-v1.0.0-alpine' + VARIANT_TAG_WITH_REF="${REF}-${VARIANT_TAG}" + VARIANT_TAG_WITH_REF_AND_SHA_SHORT="${REF}-${SHA_SHORT}-${VARIANT_TAG}" + + docker build \ + -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG}" \ + -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF}" \ + -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF_AND_SHA_SHORT}" \ + "${VARIANT_BUILD_DIR}" + docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG}" + docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF}" + docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF_AND_SHA_SHORT}" + - name: Clean-up + run: docker logout + if: always() build-v2-4-8-alpine-3-11: runs-on: ubuntu-18.04 env: @@ -52,12 +160,10 @@ jobs: -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG}" \ -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF}" \ -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF_AND_SHA_SHORT}" \ - -t "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:latest" \ "${VARIANT_BUILD_DIR}" docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG}" docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF}" docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF_AND_SHA_SHORT}" - docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:latest" - name: Clean-up run: docker logout if: always() @@ -484,4 +590,66 @@ jobs: docker push "${DOCKERHUB_REGISTRY_USER}/${CI_PROJECT_NAME}:${VARIANT_TAG_WITH_REF_AND_SHA_SHORT}" - name: Clean-up run: docker logout - if: always() \ No newline at end of file + if: always() + converge-master-and-release-branches: + needs: [build-v2-5-0-alpine-3-13, build-v2-4-10-alpine-3-12, build-v2-4-8-alpine-3-11, build-v2-4-7-alpine-3-10, build-v2-4-6-alpine-3-9, build-v2-4-6-alpine-3-8, build-v2-4-4-alpine-3-7, build-v2-4-4-alpine-3-6, build-v2-3-18-alpine-3-5, build-v2-3-18-alpine-3-4, build-v2-3-18-alpine-3-3] + if: github.ref == 'refs/heads/release' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Merge release into master (fast-forward) + run: | + git checkout master + git merge release + git push origin master + resolve-release-tag: + runs-on: ubuntu-latest + outputs: + TAG: ${{ steps.resolve-release-tag.outputs.TAG }} + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Resolve release tag + id: resolve-release-tag + run: | + set +e + # E.g. 20210402 + TODAYS_DATE=$( date -u '+%Y%m%d' ) + # Is this the first tag for this date? + TODAYS_DATE_TAGS=$( git tag --list | grep "^$TODAYS_DATE" ) + TAG= + if [ -z "$TODAYS_DATE_TAGS" ]; then + # E.g. 20210402.0.0 + TAG="$TODAYS_DATE.0.0" # Send this to stdout + else + # E.g. if there are 20210402.0.0, 20210402.0.1, 20210402.0.2, this returns 2 + VERSION_MINOR_LATEST=$( echo "$TODAYS_DATE_TAGS" | cut -d '.' -f 3 | sort -nr | head -n1 ) + # Minor version + VERSION_MINOR=$( expr "$VERSION_MINOR_LATEST" + 1 ) + # E.g. 20210402.0.3 + TAG="$TODAYS_DATE.0.$VERSION_MINOR" # Send this to stdout + fi + echo "TODAYS_DATE: $TODAYS_DATE" + echo "TODAYS_DATE_TAGS: $TODAYS_DATE_TAGS" + echo "TAG: $TAG" + echo "::set-output name=TAG::$TAG" + - name: Print outputs + run: echo ${{ steps.resolve-release-tag.outputs.TAG }} + publish-draft-release: + needs: [build-v2-5-0-alpine-3-13, build-v2-4-10-alpine-3-12, build-v2-4-8-alpine-3-11, build-v2-4-7-alpine-3-10, build-v2-4-6-alpine-3-9, build-v2-4-6-alpine-3-8, build-v2-4-4-alpine-3-7, build-v2-4-4-alpine-3-6, build-v2-3-18-alpine-3-5, build-v2-3-18-alpine-3-4, build-v2-3-18-alpine-3-3] + if: github.ref == 'refs/heads/release' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + # Drafts your next Release notes as Pull Requests are merged into "master" + - uses: release-drafter/release-drafter@v5 + with: + config-name: release-drafter.yml + publish: true + name: ${{ needs.resolve-release-tag.outputs.TAG }} + tag: ${{ needs.resolve-release-tag.outputs.TAG }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/README.md b/README.md index a7262d0..1744b22 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,9 @@ Dockerized `openvpn`. | Tag | Dockerfile Build Context | |:-------:|:---------:| -| `:v2.4.8-alpine-3.11`, `:latest` | [View](variants/v2.4.8-alpine-3.11 ) | +| `:v2.5.0-alpine-3.13`, `:latest` | [View](variants/v2.5.0-alpine-3.13 ) | +| `:v2.4.10-alpine-3.12` | [View](variants/v2.4.10-alpine-3.12 ) | +| `:v2.4.8-alpine-3.11` | [View](variants/v2.4.8-alpine-3.11 ) | | `:v2.4.7-alpine-3.10` | [View](variants/v2.4.7-alpine-3.10 ) | | `:v2.4.6-alpine-3.9` | [View](variants/v2.4.6-alpine-3.9 ) | | `:v2.4.6-alpine-3.8` | [View](variants/v2.4.6-alpine-3.8 ) | @@ -29,7 +31,7 @@ It is assumed that you have knowledge of configuring `openvpn`. To run the image, at the least you should mount a `/etc/openvpn/server.conf`, which may be a unified openvpn profile (see INLINE FILE SUPPORT section in the [openvpn manual](https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage)). ```sh -docker run --rm -it --cap-add NET_ADMIN -v /path/to/server.conf:/etc/openvpn/server.conf theohbrothers/docker-openvpn:v2.4.8-alpine-3.11 +docker run --rm -it --cap-add NET_ADMIN -v /path/to/server.conf:/etc/openvpn/server.conf theohbrothers/docker-openvpn:v2.5.0-alpine-3.13 ``` ## Environment variables @@ -42,7 +44,7 @@ The defaults should work, so that there should be no need to specify any environ | `OPENVPN_ROUTES` | Space-delimited CIDRs to add iptables `POSTROUTING` NAT rules, performed only when `NAT` is `1` | `192.168.50.0/24 192.168.51.0/24` | | `NAT` | Whether to use NAT. `0` to disable. `1` to enable. If NAT is enabled, iptables `POSTROUTING` rules will be provisioned | `1` | | `NAT_INTERFACE` | Interface on which to use NAT. E.g. `eth0` | `eth0` | -| `CUSTOM_FIREWALL_SCRIPT` | Custom script for firewall. If present, this script is executed before any other `iptables` rules are provisioned | `/etc/openvpn/firewall.sh` | +| `CUSTOM_FIREWALL_SCRIPT` | Full path to a custom script for firewall. If present, this script is executed before any other `iptables` rules are provisioned | `/etc/openvpn/firewall.sh` | ## `docker-entrypoint.sh` diff --git a/generate/definitions/FILES.ps1 b/generate/definitions/FILES.ps1 index a8ad32c..cd946c2 100644 --- a/generate/definitions/FILES.ps1 +++ b/generate/definitions/FILES.ps1 @@ -2,6 +2,7 @@ $FILES = @( '.github/workflows/ci-master-pr.yml' '.github/workflows/ci-release.yml' + '.github/release-drafter.yml' # '.gitlab-ci.yml' 'README.md' ) diff --git a/generate/definitions/VARIANTS.ps1 b/generate/definitions/VARIANTS.ps1 index 0fadaa7..7a567ee 100644 --- a/generate/definitions/VARIANTS.ps1 +++ b/generate/definitions/VARIANTS.ps1 @@ -1,12 +1,30 @@ # Docker image variants' definitions $local:VARIANTS_MATRIX = @( + @{ + package = 'openvpn' + package_version = '2.5.0-r1' + distro = 'alpine' + distro_version = '3.13' + subvariants = @( + @{ components = @(); tag_as_latest = $true } + ) + } + @{ + package = 'openvpn' + package_version = '2.4.10-r0' + distro = 'alpine' + distro_version = '3.12' + subvariants = @( + @{ components = @() } + ) + } @{ package = 'openvpn' package_version = '2.4.8-r1' distro = 'alpine' distro_version = '3.11' subvariants = @( - @{ components = @(); tag_as_latest = $true } + @{ components = @() } ) } @{ diff --git a/generate/templates/.github/release-drafter.yml.ps1 b/generate/templates/.github/release-drafter.yml.ps1 new file mode 100644 index 0000000..820248a --- /dev/null +++ b/generate/templates/.github/release-drafter.yml.ps1 @@ -0,0 +1,53 @@ +@' +name-template: 'v$RESOLVED_VERSION 🌈' +tag-template: 'v$RESOLVED_VERSION' +categories: + - title: '🚀 Features' + labels: + - 'feature' + - 'enhancement' + - title: '🐛 Bug Fixes' + labels: + - 'fix' + - 'bugfix' + - 'bug' + - title: '🖊️ Refactors' + labels: + - 'refactor' + - title: '👗 Style' + labels: + - 'style' + - title: '📝 Documentation' + labels: + - 'docs' + - 'documentation' + - title: '🧰 Maintenance' + label: 'chore' +change-template: '- $TITLE @$AUTHOR (#$NUMBER)' +version-resolver: + major: + labels: + # - 'major' + - 'breaking' + minor: + labels: + # - 'minor' + - 'feature' + - 'enhancement' + - 'refactor' + patch: + labels: + # - 'patch' + - 'fix' + - 'bugfix' + - 'bug' + - 'style' + - 'docs' + - 'documentation' + default: patch +sort-by: title +template: | + ## Changes + + $CHANGES +'@ diff --git a/generate/templates/.github/workflows/ci-master-pr.yml.ps1 b/generate/templates/.github/workflows/ci-master-pr.yml.ps1 index 5b7ee06..36c9c60 100644 --- a/generate/templates/.github/workflows/ci-master-pr.yml.ps1 +++ b/generate/templates/.github/workflows/ci-master-pr.yml.ps1 @@ -12,6 +12,7 @@ on: jobs: '@ +$local:WORKFLOW_JOB_NAMES = $VARIANTS | % { "build-$( $_['tag'].Replace('.', '-') )" } $( $VARIANTS | % { @" @@ -71,3 +72,68 @@ $( $VARIANTS | % { if: always() '@ }) + +@' + + resolve-release-tag: + runs-on: ubuntu-latest + outputs: + TAG: ${{ steps.resolve-release-tag.outputs.TAG }} + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Resolve release tag + id: resolve-release-tag + run: | + set +e + # E.g. 20210402 + TODAYS_DATE=$( date -u '+%Y%m%d' ) + # Is this the first tag for this date? + TODAYS_DATE_TAGS=$( git tag --list | grep "^$TODAYS_DATE" ) + TAG= + if [ -z "$TODAYS_DATE_TAGS" ]; then + # E.g. 20210402.0.0 + TAG="$TODAYS_DATE.0.0" # Send this to stdout + else + # E.g. if there are 20210402.0.0, 20210402.0.1, 20210402.0.2, this returns 2 + VERSION_MINOR_LATEST=$( echo "$TODAYS_DATE_TAGS" | cut -d '.' -f 3 | sort -nr | head -n1 ) + # Minor version + VERSION_MINOR=$( expr "$VERSION_MINOR_LATEST" + 1 ) + # E.g. 20210402.0.3 + TAG="$TODAYS_DATE.0.$VERSION_MINOR" # Send this to stdout + fi + echo "TODAYS_DATE: $TODAYS_DATE" + echo "TODAYS_DATE_TAGS: $TODAYS_DATE_TAGS" + echo "TAG: $TAG" + echo "::set-output name=TAG::$TAG" + - name: Print outputs + run: echo ${{ steps.resolve-release-tag.outputs.TAG }} +'@ + +@" + + update-draft-release: + needs: [$( $local:WORKFLOW_JOB_NAMES -join ', ' ), resolve-release-tag] +"@ +@' + + if: github.ref == 'refs/heads/master' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Print inputs + run: echo ${{ needs.resolve-release-tag.outputs.TAG }} + # Drafts your next Release notes as Pull Requests are merged into "master" + - uses: release-drafter/release-drafter@v5 + with: + config-name: release-drafter.yml + publish: false + name: ${{ needs.resolve-release-tag.outputs.TAG }} + tag: ${{ needs.resolve-release-tag.outputs.TAG }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +'@ diff --git a/generate/templates/.github/workflows/ci-release.yml.ps1 b/generate/templates/.github/workflows/ci-release.yml.ps1 index 87f701c..0c226e2 100644 --- a/generate/templates/.github/workflows/ci-release.yml.ps1 +++ b/generate/templates/.github/workflows/ci-release.yml.ps1 @@ -9,6 +9,7 @@ on: jobs: '@ +$local:WORKFLOW_JOB_NAMES = $VARIANTS | % { "build-$( $_['tag'].Replace('.', '-') )" } $( $VARIANTS | % { @" @@ -88,3 +89,80 @@ if ( $_['tag_as_latest'] ) { if: always() '@ }) + +@" + + converge-master-and-release-branches: + needs: [$( $local:WORKFLOW_JOB_NAMES -join ', ' )] + if: github.ref == 'refs/heads/release' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Merge release into master (fast-forward) + run: | + git checkout master + git merge release + git push origin master +"@ + +@' + + resolve-release-tag: + runs-on: ubuntu-latest + outputs: + TAG: ${{ steps.resolve-release-tag.outputs.TAG }} + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Resolve release tag + id: resolve-release-tag + run: | + set +e + # E.g. 20210402 + TODAYS_DATE=$( date -u '+%Y%m%d' ) + # Is this the first tag for this date? + TODAYS_DATE_TAGS=$( git tag --list | grep "^$TODAYS_DATE" ) + TAG= + if [ -z "$TODAYS_DATE_TAGS" ]; then + # E.g. 20210402.0.0 + TAG="$TODAYS_DATE.0.0" # Send this to stdout + else + # E.g. if there are 20210402.0.0, 20210402.0.1, 20210402.0.2, this returns 2 + VERSION_MINOR_LATEST=$( echo "$TODAYS_DATE_TAGS" | cut -d '.' -f 3 | sort -nr | head -n1 ) + # Minor version + VERSION_MINOR=$( expr "$VERSION_MINOR_LATEST" + 1 ) + # E.g. 20210402.0.3 + TAG="$TODAYS_DATE.0.$VERSION_MINOR" # Send this to stdout + fi + echo "TODAYS_DATE: $TODAYS_DATE" + echo "TODAYS_DATE_TAGS: $TODAYS_DATE_TAGS" + echo "TAG: $TAG" + echo "::set-output name=TAG::$TAG" + - name: Print outputs + run: echo ${{ steps.resolve-release-tag.outputs.TAG }} +'@ + +@" + + publish-draft-release: + needs: [$( $local:WORKFLOW_JOB_NAMES -join ', ' )] +"@ +@' + + if: github.ref == 'refs/heads/release' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + # Drafts your next Release notes as Pull Requests are merged into "master" + - uses: release-drafter/release-drafter@v5 + with: + config-name: release-drafter.yml + publish: true + name: ${{ needs.resolve-release-tag.outputs.TAG }} + tag: ${{ needs.resolve-release-tag.outputs.TAG }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +'@ diff --git a/generate/templates/Dockerfile.ps1 b/generate/templates/Dockerfile.ps1 index 6f4fb3f..f05b3ea 100644 --- a/generate/templates/Dockerfile.ps1 +++ b/generate/templates/Dockerfile.ps1 @@ -7,7 +7,7 @@ COPY docker-entrypoint.sh /docker-entrypoint.sh RUN chmod +x /docker-entrypoint.sh COPY openvpn /etc/openvpn -RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn +RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn && chmod 750 /etc/openvpn/*.sh ENTRYPOINT ["/docker-entrypoint.sh"] "@ diff --git a/generate/templates/README.md.ps1 b/generate/templates/README.md.ps1 index 16d5a66..336e454 100644 --- a/generate/templates/README.md.ps1 +++ b/generate/templates/README.md.ps1 @@ -50,7 +50,7 @@ The defaults should work, so that there should be no need to specify any environ | ``OPENVPN_ROUTES`` | Space-delimited CIDRs to add iptables ``POSTROUTING`` NAT rules, performed only when ``NAT`` is ``1`` | ``192.168.50.0/24 192.168.51.0/24`` | | ``NAT`` | Whether to use NAT. ``0`` to disable. ``1`` to enable. If NAT is enabled, iptables ``POSTROUTING`` rules will be provisioned | ``1`` | | ``NAT_INTERFACE`` | Interface on which to use NAT. E.g. ``eth0`` | ``eth0`` | -| ``CUSTOM_FIREWALL_SCRIPT`` | Custom script for firewall. If present, this script is executed before any other ``iptables`` rules are provisioned | ``/etc/openvpn/firewall.sh`` | +| ``CUSTOM_FIREWALL_SCRIPT`` | Full path to a custom script for firewall. If present, this script is executed before any other ``iptables`` rules are provisioned | ``/etc/openvpn/firewall.sh`` | ## ``docker-entrypoint.sh`` diff --git a/generate/templates/docker-entrypoint.sh.ps1 b/generate/templates/docker-entrypoint.sh.ps1 index 3582a78..ac3605e 100644 --- a/generate/templates/docker-entrypoint.sh.ps1 +++ b/generate/templates/docker-entrypoint.sh.ps1 @@ -30,16 +30,17 @@ if [ ! -c /dev/net/tun ]; then fi if [ -f "$CUSTOM_FIREWALL_SCRIPT" ]; then output "Executing custom firewall script: $CUSTOM_FIREWALL_SCRIPT" - sh "$CUSTOM_FIREWALL_SCRIPT" + . "$CUSTOM_FIREWALL_SCRIPT" else output "Not executing custom firewall script $CUSTOM_FIREWALL_SCRIPT because it does not exist" fi if [ "$NAT" = 1 ]; then output "NAT is enabled" - output "Provisioning nat iptables rules" + output "Provisioning NAT iptables rules" + output "NAT_INTERFACE: $NAT_INTERFACE" iptables -t nat -C POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE if [ -n "$OPENVPN_ROUTES" ]; then - output "Provisioning nat iptables rules for OPENVPN_ROUTES" + output "Provisioning NAT iptables rules for OPENVPN_ROUTES" for r in $OPENVPN_ROUTES; do iptables -t nat -C POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE done @@ -48,11 +49,12 @@ if [ "$NAT" = 1 ]; then fi else output "NAT is disabled." - output "Not adding nat iptables rules" + output "Not adding NAT iptables rules" fi output "Listing iptables rules:" iptables -L -nv +output "Listing iptables NAT rules:" iptables -L -nv -t nat # Generate the command line. openvpn man: https://openvpn.net/community-resources/reference-manual-for-openvpn-2-4/ diff --git a/generate/templates/openvpn/firewall.sh.ps1 b/generate/templates/openvpn/firewall.sh.ps1 index c7469c5..52a525e 100644 --- a/generate/templates/openvpn/firewall.sh.ps1 +++ b/generate/templates/openvpn/firewall.sh.ps1 @@ -1,11 +1,15 @@ @' #!/bin/sh +# This iptables script is useful for openpvn in server mode. Not so much for client mode. + set -eo pipefail -# Only allow DNS, HTTP, HTTPS from tunnel to world -echo "$NAT_INTERFACE" +# Drop everything by default from tunnel to world iptables -P FORWARD DROP +# Allow DNS from tunnel to world iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT +# Allow HTTP and HTTPS from tunnel to world iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT + '@ diff --git a/variants/v2.3.18-alpine-3.3/Dockerfile b/variants/v2.3.18-alpine-3.3/Dockerfile index 5055cc2..5464ae5 100644 --- a/variants/v2.3.18-alpine-3.3/Dockerfile +++ b/variants/v2.3.18-alpine-3.3/Dockerfile @@ -8,7 +8,7 @@ COPY docker-entrypoint.sh /docker-entrypoint.sh RUN chmod +x /docker-entrypoint.sh COPY openvpn /etc/openvpn -RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn +RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn && chmod 750 /etc/openvpn/*.sh ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/variants/v2.3.18-alpine-3.3/docker-entrypoint.sh b/variants/v2.3.18-alpine-3.3/docker-entrypoint.sh index 32ab579..f6f6d19 100644 --- a/variants/v2.3.18-alpine-3.3/docker-entrypoint.sh +++ b/variants/v2.3.18-alpine-3.3/docker-entrypoint.sh @@ -29,16 +29,17 @@ if [ ! -c /dev/net/tun ]; then fi if [ -f "$CUSTOM_FIREWALL_SCRIPT" ]; then output "Executing custom firewall script: $CUSTOM_FIREWALL_SCRIPT" - sh "$CUSTOM_FIREWALL_SCRIPT" + . "$CUSTOM_FIREWALL_SCRIPT" else output "Not executing custom firewall script $CUSTOM_FIREWALL_SCRIPT because it does not exist" fi if [ "$NAT" = 1 ]; then output "NAT is enabled" - output "Provisioning nat iptables rules" + output "Provisioning NAT iptables rules" + output "NAT_INTERFACE: $NAT_INTERFACE" iptables -t nat -C POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE if [ -n "$OPENVPN_ROUTES" ]; then - output "Provisioning nat iptables rules for OPENVPN_ROUTES" + output "Provisioning NAT iptables rules for OPENVPN_ROUTES" for r in $OPENVPN_ROUTES; do iptables -t nat -C POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE done @@ -47,11 +48,12 @@ if [ "$NAT" = 1 ]; then fi else output "NAT is disabled." - output "Not adding nat iptables rules" + output "Not adding NAT iptables rules" fi output "Listing iptables rules:" iptables -L -nv +output "Listing iptables NAT rules:" iptables -L -nv -t nat # Generate the command line. openvpn man: https://openvpn.net/community-resources/reference-manual-for-openvpn-2-4/ diff --git a/variants/v2.3.18-alpine-3.3/openvpn/firewall.sh b/variants/v2.3.18-alpine-3.3/openvpn/firewall.sh index aa19e0f..511ab5a 100644 --- a/variants/v2.3.18-alpine-3.3/openvpn/firewall.sh +++ b/variants/v2.3.18-alpine-3.3/openvpn/firewall.sh @@ -1,9 +1,12 @@ #!/bin/sh +# This iptables script is useful for openpvn in server mode. Not so much for client mode. + set -eo pipefail -# Only allow DNS, HTTP, HTTPS from tunnel to world -echo "$NAT_INTERFACE" +# Drop everything by default from tunnel to world iptables -P FORWARD DROP +# Allow DNS from tunnel to world iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT -iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT \ No newline at end of file +# Allow HTTP and HTTPS from tunnel to world +iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT diff --git a/variants/v2.3.18-alpine-3.4/Dockerfile b/variants/v2.3.18-alpine-3.4/Dockerfile index 59eae14..eaf4aa5 100644 --- a/variants/v2.3.18-alpine-3.4/Dockerfile +++ b/variants/v2.3.18-alpine-3.4/Dockerfile @@ -8,7 +8,7 @@ COPY docker-entrypoint.sh /docker-entrypoint.sh RUN chmod +x /docker-entrypoint.sh COPY openvpn /etc/openvpn -RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn +RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn && chmod 750 /etc/openvpn/*.sh ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/variants/v2.3.18-alpine-3.4/docker-entrypoint.sh b/variants/v2.3.18-alpine-3.4/docker-entrypoint.sh index 32ab579..f6f6d19 100644 --- a/variants/v2.3.18-alpine-3.4/docker-entrypoint.sh +++ b/variants/v2.3.18-alpine-3.4/docker-entrypoint.sh @@ -29,16 +29,17 @@ if [ ! -c /dev/net/tun ]; then fi if [ -f "$CUSTOM_FIREWALL_SCRIPT" ]; then output "Executing custom firewall script: $CUSTOM_FIREWALL_SCRIPT" - sh "$CUSTOM_FIREWALL_SCRIPT" + . "$CUSTOM_FIREWALL_SCRIPT" else output "Not executing custom firewall script $CUSTOM_FIREWALL_SCRIPT because it does not exist" fi if [ "$NAT" = 1 ]; then output "NAT is enabled" - output "Provisioning nat iptables rules" + output "Provisioning NAT iptables rules" + output "NAT_INTERFACE: $NAT_INTERFACE" iptables -t nat -C POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE if [ -n "$OPENVPN_ROUTES" ]; then - output "Provisioning nat iptables rules for OPENVPN_ROUTES" + output "Provisioning NAT iptables rules for OPENVPN_ROUTES" for r in $OPENVPN_ROUTES; do iptables -t nat -C POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE done @@ -47,11 +48,12 @@ if [ "$NAT" = 1 ]; then fi else output "NAT is disabled." - output "Not adding nat iptables rules" + output "Not adding NAT iptables rules" fi output "Listing iptables rules:" iptables -L -nv +output "Listing iptables NAT rules:" iptables -L -nv -t nat # Generate the command line. openvpn man: https://openvpn.net/community-resources/reference-manual-for-openvpn-2-4/ diff --git a/variants/v2.3.18-alpine-3.4/openvpn/firewall.sh b/variants/v2.3.18-alpine-3.4/openvpn/firewall.sh index aa19e0f..511ab5a 100644 --- a/variants/v2.3.18-alpine-3.4/openvpn/firewall.sh +++ b/variants/v2.3.18-alpine-3.4/openvpn/firewall.sh @@ -1,9 +1,12 @@ #!/bin/sh +# This iptables script is useful for openpvn in server mode. Not so much for client mode. + set -eo pipefail -# Only allow DNS, HTTP, HTTPS from tunnel to world -echo "$NAT_INTERFACE" +# Drop everything by default from tunnel to world iptables -P FORWARD DROP +# Allow DNS from tunnel to world iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT -iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT \ No newline at end of file +# Allow HTTP and HTTPS from tunnel to world +iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT diff --git a/variants/v2.3.18-alpine-3.5/Dockerfile b/variants/v2.3.18-alpine-3.5/Dockerfile index 714468d..c17cfc9 100644 --- a/variants/v2.3.18-alpine-3.5/Dockerfile +++ b/variants/v2.3.18-alpine-3.5/Dockerfile @@ -8,7 +8,7 @@ COPY docker-entrypoint.sh /docker-entrypoint.sh RUN chmod +x /docker-entrypoint.sh COPY openvpn /etc/openvpn -RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn +RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn && chmod 750 /etc/openvpn/*.sh ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/variants/v2.3.18-alpine-3.5/docker-entrypoint.sh b/variants/v2.3.18-alpine-3.5/docker-entrypoint.sh index 32ab579..f6f6d19 100644 --- a/variants/v2.3.18-alpine-3.5/docker-entrypoint.sh +++ b/variants/v2.3.18-alpine-3.5/docker-entrypoint.sh @@ -29,16 +29,17 @@ if [ ! -c /dev/net/tun ]; then fi if [ -f "$CUSTOM_FIREWALL_SCRIPT" ]; then output "Executing custom firewall script: $CUSTOM_FIREWALL_SCRIPT" - sh "$CUSTOM_FIREWALL_SCRIPT" + . "$CUSTOM_FIREWALL_SCRIPT" else output "Not executing custom firewall script $CUSTOM_FIREWALL_SCRIPT because it does not exist" fi if [ "$NAT" = 1 ]; then output "NAT is enabled" - output "Provisioning nat iptables rules" + output "Provisioning NAT iptables rules" + output "NAT_INTERFACE: $NAT_INTERFACE" iptables -t nat -C POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE if [ -n "$OPENVPN_ROUTES" ]; then - output "Provisioning nat iptables rules for OPENVPN_ROUTES" + output "Provisioning NAT iptables rules for OPENVPN_ROUTES" for r in $OPENVPN_ROUTES; do iptables -t nat -C POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE done @@ -47,11 +48,12 @@ if [ "$NAT" = 1 ]; then fi else output "NAT is disabled." - output "Not adding nat iptables rules" + output "Not adding NAT iptables rules" fi output "Listing iptables rules:" iptables -L -nv +output "Listing iptables NAT rules:" iptables -L -nv -t nat # Generate the command line. openvpn man: https://openvpn.net/community-resources/reference-manual-for-openvpn-2-4/ diff --git a/variants/v2.3.18-alpine-3.5/openvpn/firewall.sh b/variants/v2.3.18-alpine-3.5/openvpn/firewall.sh index aa19e0f..511ab5a 100644 --- a/variants/v2.3.18-alpine-3.5/openvpn/firewall.sh +++ b/variants/v2.3.18-alpine-3.5/openvpn/firewall.sh @@ -1,9 +1,12 @@ #!/bin/sh +# This iptables script is useful for openpvn in server mode. Not so much for client mode. + set -eo pipefail -# Only allow DNS, HTTP, HTTPS from tunnel to world -echo "$NAT_INTERFACE" +# Drop everything by default from tunnel to world iptables -P FORWARD DROP +# Allow DNS from tunnel to world iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT -iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT \ No newline at end of file +# Allow HTTP and HTTPS from tunnel to world +iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT diff --git a/variants/v2.4.10-alpine-3.12/Dockerfile b/variants/v2.4.10-alpine-3.12/Dockerfile new file mode 100644 index 0000000..af2dba1 --- /dev/null +++ b/variants/v2.4.10-alpine-3.12/Dockerfile @@ -0,0 +1,14 @@ + + +FROM alpine:3.12 + +RUN apk add --no-cache openvpn=2.4.10-r0 iptables + +COPY docker-entrypoint.sh /docker-entrypoint.sh +RUN chmod +x /docker-entrypoint.sh + +COPY openvpn /etc/openvpn +RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn && chmod 750 /etc/openvpn/*.sh + +ENTRYPOINT ["/docker-entrypoint.sh"] + diff --git a/variants/v2.4.10-alpine-3.12/docker-compose.yml b/variants/v2.4.10-alpine-3.12/docker-compose.yml new file mode 100644 index 0000000..73da372 --- /dev/null +++ b/variants/v2.4.10-alpine-3.12/docker-compose.yml @@ -0,0 +1,18 @@ +version: '2.1' +services: + openvpn: + container_name: openvpn + image: theohbrothers/docker-openvpn:v2.4.10-alpine-3.12 + ports: + - "1194:1194/udp" + cap_add: + - NET_ADMIN + # sysctls for the container if it is not set on the host. See: https://docs.docker.com/compose/compose-file/compose-file-v2/#sysctls + sysctls: + - net.ipv4.conf.all.forwarding=1 + # - net.ipv6.conf.all.disable_ipv6=0 + # - net.ipv6.conf.default.forwarding=1 + # - net.ipv6.conf.all.forwarding=1 + restart: unless-stopped + volumes: + - ./openvpn/server.conf:/etc/openvpn/server.conf \ No newline at end of file diff --git a/variants/v2.4.10-alpine-3.12/docker-entrypoint.sh b/variants/v2.4.10-alpine-3.12/docker-entrypoint.sh new file mode 100644 index 0000000..f6f6d19 --- /dev/null +++ b/variants/v2.4.10-alpine-3.12/docker-entrypoint.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +set -aeo pipefail + +output() { + echo -e "[$( date -u '+%Y-%m-%dT%H:%M:%S%z' )] $1" +} + +error() { + echo -e "[$( date -u '+%Y-%m-%dT%H:%M:%S%z' )] $1" >&2 +} + +# Env vars +OPENVPN=openvpn +OPENVPN_SERVER_CONFIG_FILE=${OPENVPN_SERVER_CONFIG_FILE:-/etc/openvpn/server.conf} +# OPENVPN_CLIENT_CONFIG_DIR=${OPENVPN_CLIENT_CONFIG_DIR:-/etc/openvpn/ccd} +# OPENVPN_STATUS_FILE=${OPENVPN_STATUS_FILE:-} +# OPENVPN_STATUS_FILE_WRITE_FREQUENCY_SECONDS={$OPENVPN_STATUS_FILE_WRITE_FREQUENCY_SECONDS:-10} +OPENVPN_ROUTES=${OPENVPN_ROUTES:-} +NAT=${NAT:-1} +NAT_INTERFACE=${NAT_INTERFACE:-eth0} +CUSTOM_FIREWALL_SCRIPT=${CUSTOM_FIREWALL_SCRIPT:-/etc/openvpn/firewall.sh} + +# Provision +output "Provisioning tun device" +mkdir -p /dev/net +if [ ! -c /dev/net/tun ]; then + mknod /dev/net/tun c 10 200 +fi +if [ -f "$CUSTOM_FIREWALL_SCRIPT" ]; then + output "Executing custom firewall script: $CUSTOM_FIREWALL_SCRIPT" + . "$CUSTOM_FIREWALL_SCRIPT" +else + output "Not executing custom firewall script $CUSTOM_FIREWALL_SCRIPT because it does not exist" +fi +if [ "$NAT" = 1 ]; then + output "NAT is enabled" + output "Provisioning NAT iptables rules" + output "NAT_INTERFACE: $NAT_INTERFACE" + iptables -t nat -C POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE + if [ -n "$OPENVPN_ROUTES" ]; then + output "Provisioning NAT iptables rules for OPENVPN_ROUTES" + for r in $OPENVPN_ROUTES; do + iptables -t nat -C POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE + done + else + output "Not provisioning route iptables rules because OPENVPN_ROUTES is empty" + fi +else + output "NAT is disabled." + output "Not adding NAT iptables rules" +fi + +output "Listing iptables rules:" +iptables -L -nv +output "Listing iptables NAT rules:" +iptables -L -nv -t nat + +# Generate the command line. openvpn man: https://openvpn.net/community-resources/reference-manual-for-openvpn-2-4/ +output "Generating command line" +set "$OPENVPN" --cd /etc/openvpn +set "$@" --config "$OPENVPN_SERVER_CONFIG_FILE" +# set "$@" --client-config-dir "$OPENVPN_CLIENT_CONFIG_DIR" +if [ -n "$OPENVPN_STATUS_FILE" ]; then + set "$@" --status "$OPENVPN_STATUS_FILE" "$OPENVPN_STATUS_FILE_WRITE_FREQUENCY_SECONDS" +fi + +# Exec +output "openvpn command line: $@" +exec "$@" \ No newline at end of file diff --git a/variants/v2.4.10-alpine-3.12/openvpn/client.conf b/variants/v2.4.10-alpine-3.12/openvpn/client.conf new file mode 100644 index 0000000..953eefa --- /dev/null +++ b/variants/v2.4.10-alpine-3.12/openvpn/client.conf @@ -0,0 +1,23 @@ +# See sample config file: https://github.com/OpenVPN/openvpn/blob/v2.4.8/sample/sample-config-files/client.conf +# redirect-gateway def1 bypass-dhcp +client +dev tun +proto udp +remote 10.8.0.1 1194 +resolv-retry infinite +nobind +# user nobody +# group nobody +persist-key +persist-tun +ca pki/ca.crt +cert pki/issued/client.crt +key pki/private/client.key +remote-cert-tls server +tls-auth pki/ta.key 1 +# key-direction 1 +cipher AES-256-CBC +# auth SHA256 +comp-lzo no +verb 3 +# mute 20 diff --git a/variants/v2.4.10-alpine-3.12/openvpn/firewall.sh b/variants/v2.4.10-alpine-3.12/openvpn/firewall.sh new file mode 100644 index 0000000..511ab5a --- /dev/null +++ b/variants/v2.4.10-alpine-3.12/openvpn/firewall.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# This iptables script is useful for openpvn in server mode. Not so much for client mode. + +set -eo pipefail + +# Drop everything by default from tunnel to world +iptables -P FORWARD DROP +# Allow DNS from tunnel to world +iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT +# Allow HTTP and HTTPS from tunnel to world +iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT diff --git a/variants/v2.4.10-alpine-3.12/openvpn/server.conf b/variants/v2.4.10-alpine-3.12/openvpn/server.conf new file mode 100644 index 0000000..72fef1d --- /dev/null +++ b/variants/v2.4.10-alpine-3.12/openvpn/server.conf @@ -0,0 +1,25 @@ +# See sample config file: https://github.com/OpenVPN/openvpn/blob/v2.4.8/sample/sample-config-files/server.conf +port 1194 +proto udp +dev tun +ca pki/ca.crt +cert pki/issued/server.crt +key pki/private/server.key +dh pki/dh.pem +crl-verify pki/crl.pem +server 10.8.0.0 255.255.255.0 +ifconfig-pool-persist ipp.txt +;client-config-dir ccd +keepalive 10 120 +tls-auth pki/ta.key 0 +cipher AES-256-CBC +max-clients 5 +user nobody +group nogroup +persist-key +persist-tun +status server.status.log +# log-append server.log +verb 3 +mute 20 +explicit-exit-notify 1 \ No newline at end of file diff --git a/variants/v2.4.4-alpine-3.6/Dockerfile b/variants/v2.4.4-alpine-3.6/Dockerfile index 2987042..58e692a 100644 --- a/variants/v2.4.4-alpine-3.6/Dockerfile +++ b/variants/v2.4.4-alpine-3.6/Dockerfile @@ -8,7 +8,7 @@ COPY docker-entrypoint.sh /docker-entrypoint.sh RUN chmod +x /docker-entrypoint.sh COPY openvpn /etc/openvpn -RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn +RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn && chmod 750 /etc/openvpn/*.sh ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/variants/v2.4.4-alpine-3.6/docker-entrypoint.sh b/variants/v2.4.4-alpine-3.6/docker-entrypoint.sh index 32ab579..f6f6d19 100644 --- a/variants/v2.4.4-alpine-3.6/docker-entrypoint.sh +++ b/variants/v2.4.4-alpine-3.6/docker-entrypoint.sh @@ -29,16 +29,17 @@ if [ ! -c /dev/net/tun ]; then fi if [ -f "$CUSTOM_FIREWALL_SCRIPT" ]; then output "Executing custom firewall script: $CUSTOM_FIREWALL_SCRIPT" - sh "$CUSTOM_FIREWALL_SCRIPT" + . "$CUSTOM_FIREWALL_SCRIPT" else output "Not executing custom firewall script $CUSTOM_FIREWALL_SCRIPT because it does not exist" fi if [ "$NAT" = 1 ]; then output "NAT is enabled" - output "Provisioning nat iptables rules" + output "Provisioning NAT iptables rules" + output "NAT_INTERFACE: $NAT_INTERFACE" iptables -t nat -C POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE if [ -n "$OPENVPN_ROUTES" ]; then - output "Provisioning nat iptables rules for OPENVPN_ROUTES" + output "Provisioning NAT iptables rules for OPENVPN_ROUTES" for r in $OPENVPN_ROUTES; do iptables -t nat -C POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE done @@ -47,11 +48,12 @@ if [ "$NAT" = 1 ]; then fi else output "NAT is disabled." - output "Not adding nat iptables rules" + output "Not adding NAT iptables rules" fi output "Listing iptables rules:" iptables -L -nv +output "Listing iptables NAT rules:" iptables -L -nv -t nat # Generate the command line. openvpn man: https://openvpn.net/community-resources/reference-manual-for-openvpn-2-4/ diff --git a/variants/v2.4.4-alpine-3.6/openvpn/firewall.sh b/variants/v2.4.4-alpine-3.6/openvpn/firewall.sh index aa19e0f..511ab5a 100644 --- a/variants/v2.4.4-alpine-3.6/openvpn/firewall.sh +++ b/variants/v2.4.4-alpine-3.6/openvpn/firewall.sh @@ -1,9 +1,12 @@ #!/bin/sh +# This iptables script is useful for openpvn in server mode. Not so much for client mode. + set -eo pipefail -# Only allow DNS, HTTP, HTTPS from tunnel to world -echo "$NAT_INTERFACE" +# Drop everything by default from tunnel to world iptables -P FORWARD DROP +# Allow DNS from tunnel to world iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT -iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT \ No newline at end of file +# Allow HTTP and HTTPS from tunnel to world +iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT diff --git a/variants/v2.4.4-alpine-3.7/Dockerfile b/variants/v2.4.4-alpine-3.7/Dockerfile index 0b3b20c..2ad7da3 100644 --- a/variants/v2.4.4-alpine-3.7/Dockerfile +++ b/variants/v2.4.4-alpine-3.7/Dockerfile @@ -8,7 +8,7 @@ COPY docker-entrypoint.sh /docker-entrypoint.sh RUN chmod +x /docker-entrypoint.sh COPY openvpn /etc/openvpn -RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn +RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn && chmod 750 /etc/openvpn/*.sh ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/variants/v2.4.4-alpine-3.7/docker-entrypoint.sh b/variants/v2.4.4-alpine-3.7/docker-entrypoint.sh index 32ab579..f6f6d19 100644 --- a/variants/v2.4.4-alpine-3.7/docker-entrypoint.sh +++ b/variants/v2.4.4-alpine-3.7/docker-entrypoint.sh @@ -29,16 +29,17 @@ if [ ! -c /dev/net/tun ]; then fi if [ -f "$CUSTOM_FIREWALL_SCRIPT" ]; then output "Executing custom firewall script: $CUSTOM_FIREWALL_SCRIPT" - sh "$CUSTOM_FIREWALL_SCRIPT" + . "$CUSTOM_FIREWALL_SCRIPT" else output "Not executing custom firewall script $CUSTOM_FIREWALL_SCRIPT because it does not exist" fi if [ "$NAT" = 1 ]; then output "NAT is enabled" - output "Provisioning nat iptables rules" + output "Provisioning NAT iptables rules" + output "NAT_INTERFACE: $NAT_INTERFACE" iptables -t nat -C POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE if [ -n "$OPENVPN_ROUTES" ]; then - output "Provisioning nat iptables rules for OPENVPN_ROUTES" + output "Provisioning NAT iptables rules for OPENVPN_ROUTES" for r in $OPENVPN_ROUTES; do iptables -t nat -C POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE done @@ -47,11 +48,12 @@ if [ "$NAT" = 1 ]; then fi else output "NAT is disabled." - output "Not adding nat iptables rules" + output "Not adding NAT iptables rules" fi output "Listing iptables rules:" iptables -L -nv +output "Listing iptables NAT rules:" iptables -L -nv -t nat # Generate the command line. openvpn man: https://openvpn.net/community-resources/reference-manual-for-openvpn-2-4/ diff --git a/variants/v2.4.4-alpine-3.7/openvpn/firewall.sh b/variants/v2.4.4-alpine-3.7/openvpn/firewall.sh index aa19e0f..511ab5a 100644 --- a/variants/v2.4.4-alpine-3.7/openvpn/firewall.sh +++ b/variants/v2.4.4-alpine-3.7/openvpn/firewall.sh @@ -1,9 +1,12 @@ #!/bin/sh +# This iptables script is useful for openpvn in server mode. Not so much for client mode. + set -eo pipefail -# Only allow DNS, HTTP, HTTPS from tunnel to world -echo "$NAT_INTERFACE" +# Drop everything by default from tunnel to world iptables -P FORWARD DROP +# Allow DNS from tunnel to world iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT -iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT \ No newline at end of file +# Allow HTTP and HTTPS from tunnel to world +iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT diff --git a/variants/v2.4.6-alpine-3.8/Dockerfile b/variants/v2.4.6-alpine-3.8/Dockerfile index a9e545c..b9056ae 100644 --- a/variants/v2.4.6-alpine-3.8/Dockerfile +++ b/variants/v2.4.6-alpine-3.8/Dockerfile @@ -8,7 +8,7 @@ COPY docker-entrypoint.sh /docker-entrypoint.sh RUN chmod +x /docker-entrypoint.sh COPY openvpn /etc/openvpn -RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn +RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn && chmod 750 /etc/openvpn/*.sh ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/variants/v2.4.6-alpine-3.8/docker-entrypoint.sh b/variants/v2.4.6-alpine-3.8/docker-entrypoint.sh index 32ab579..f6f6d19 100644 --- a/variants/v2.4.6-alpine-3.8/docker-entrypoint.sh +++ b/variants/v2.4.6-alpine-3.8/docker-entrypoint.sh @@ -29,16 +29,17 @@ if [ ! -c /dev/net/tun ]; then fi if [ -f "$CUSTOM_FIREWALL_SCRIPT" ]; then output "Executing custom firewall script: $CUSTOM_FIREWALL_SCRIPT" - sh "$CUSTOM_FIREWALL_SCRIPT" + . "$CUSTOM_FIREWALL_SCRIPT" else output "Not executing custom firewall script $CUSTOM_FIREWALL_SCRIPT because it does not exist" fi if [ "$NAT" = 1 ]; then output "NAT is enabled" - output "Provisioning nat iptables rules" + output "Provisioning NAT iptables rules" + output "NAT_INTERFACE: $NAT_INTERFACE" iptables -t nat -C POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE if [ -n "$OPENVPN_ROUTES" ]; then - output "Provisioning nat iptables rules for OPENVPN_ROUTES" + output "Provisioning NAT iptables rules for OPENVPN_ROUTES" for r in $OPENVPN_ROUTES; do iptables -t nat -C POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE done @@ -47,11 +48,12 @@ if [ "$NAT" = 1 ]; then fi else output "NAT is disabled." - output "Not adding nat iptables rules" + output "Not adding NAT iptables rules" fi output "Listing iptables rules:" iptables -L -nv +output "Listing iptables NAT rules:" iptables -L -nv -t nat # Generate the command line. openvpn man: https://openvpn.net/community-resources/reference-manual-for-openvpn-2-4/ diff --git a/variants/v2.4.6-alpine-3.8/openvpn/firewall.sh b/variants/v2.4.6-alpine-3.8/openvpn/firewall.sh index aa19e0f..511ab5a 100644 --- a/variants/v2.4.6-alpine-3.8/openvpn/firewall.sh +++ b/variants/v2.4.6-alpine-3.8/openvpn/firewall.sh @@ -1,9 +1,12 @@ #!/bin/sh +# This iptables script is useful for openpvn in server mode. Not so much for client mode. + set -eo pipefail -# Only allow DNS, HTTP, HTTPS from tunnel to world -echo "$NAT_INTERFACE" +# Drop everything by default from tunnel to world iptables -P FORWARD DROP +# Allow DNS from tunnel to world iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT -iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT \ No newline at end of file +# Allow HTTP and HTTPS from tunnel to world +iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT diff --git a/variants/v2.4.6-alpine-3.9/Dockerfile b/variants/v2.4.6-alpine-3.9/Dockerfile index a3bfbc6..7a70462 100644 --- a/variants/v2.4.6-alpine-3.9/Dockerfile +++ b/variants/v2.4.6-alpine-3.9/Dockerfile @@ -8,7 +8,7 @@ COPY docker-entrypoint.sh /docker-entrypoint.sh RUN chmod +x /docker-entrypoint.sh COPY openvpn /etc/openvpn -RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn +RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn && chmod 750 /etc/openvpn/*.sh ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/variants/v2.4.6-alpine-3.9/docker-entrypoint.sh b/variants/v2.4.6-alpine-3.9/docker-entrypoint.sh index 32ab579..f6f6d19 100644 --- a/variants/v2.4.6-alpine-3.9/docker-entrypoint.sh +++ b/variants/v2.4.6-alpine-3.9/docker-entrypoint.sh @@ -29,16 +29,17 @@ if [ ! -c /dev/net/tun ]; then fi if [ -f "$CUSTOM_FIREWALL_SCRIPT" ]; then output "Executing custom firewall script: $CUSTOM_FIREWALL_SCRIPT" - sh "$CUSTOM_FIREWALL_SCRIPT" + . "$CUSTOM_FIREWALL_SCRIPT" else output "Not executing custom firewall script $CUSTOM_FIREWALL_SCRIPT because it does not exist" fi if [ "$NAT" = 1 ]; then output "NAT is enabled" - output "Provisioning nat iptables rules" + output "Provisioning NAT iptables rules" + output "NAT_INTERFACE: $NAT_INTERFACE" iptables -t nat -C POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE if [ -n "$OPENVPN_ROUTES" ]; then - output "Provisioning nat iptables rules for OPENVPN_ROUTES" + output "Provisioning NAT iptables rules for OPENVPN_ROUTES" for r in $OPENVPN_ROUTES; do iptables -t nat -C POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE done @@ -47,11 +48,12 @@ if [ "$NAT" = 1 ]; then fi else output "NAT is disabled." - output "Not adding nat iptables rules" + output "Not adding NAT iptables rules" fi output "Listing iptables rules:" iptables -L -nv +output "Listing iptables NAT rules:" iptables -L -nv -t nat # Generate the command line. openvpn man: https://openvpn.net/community-resources/reference-manual-for-openvpn-2-4/ diff --git a/variants/v2.4.6-alpine-3.9/openvpn/firewall.sh b/variants/v2.4.6-alpine-3.9/openvpn/firewall.sh index aa19e0f..511ab5a 100644 --- a/variants/v2.4.6-alpine-3.9/openvpn/firewall.sh +++ b/variants/v2.4.6-alpine-3.9/openvpn/firewall.sh @@ -1,9 +1,12 @@ #!/bin/sh +# This iptables script is useful for openpvn in server mode. Not so much for client mode. + set -eo pipefail -# Only allow DNS, HTTP, HTTPS from tunnel to world -echo "$NAT_INTERFACE" +# Drop everything by default from tunnel to world iptables -P FORWARD DROP +# Allow DNS from tunnel to world iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT -iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT \ No newline at end of file +# Allow HTTP and HTTPS from tunnel to world +iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT diff --git a/variants/v2.4.7-alpine-3.10/Dockerfile b/variants/v2.4.7-alpine-3.10/Dockerfile index a9ec1e2..4cd3657 100644 --- a/variants/v2.4.7-alpine-3.10/Dockerfile +++ b/variants/v2.4.7-alpine-3.10/Dockerfile @@ -8,7 +8,7 @@ COPY docker-entrypoint.sh /docker-entrypoint.sh RUN chmod +x /docker-entrypoint.sh COPY openvpn /etc/openvpn -RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn +RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn && chmod 750 /etc/openvpn/*.sh ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/variants/v2.4.7-alpine-3.10/docker-entrypoint.sh b/variants/v2.4.7-alpine-3.10/docker-entrypoint.sh index 32ab579..f6f6d19 100644 --- a/variants/v2.4.7-alpine-3.10/docker-entrypoint.sh +++ b/variants/v2.4.7-alpine-3.10/docker-entrypoint.sh @@ -29,16 +29,17 @@ if [ ! -c /dev/net/tun ]; then fi if [ -f "$CUSTOM_FIREWALL_SCRIPT" ]; then output "Executing custom firewall script: $CUSTOM_FIREWALL_SCRIPT" - sh "$CUSTOM_FIREWALL_SCRIPT" + . "$CUSTOM_FIREWALL_SCRIPT" else output "Not executing custom firewall script $CUSTOM_FIREWALL_SCRIPT because it does not exist" fi if [ "$NAT" = 1 ]; then output "NAT is enabled" - output "Provisioning nat iptables rules" + output "Provisioning NAT iptables rules" + output "NAT_INTERFACE: $NAT_INTERFACE" iptables -t nat -C POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE if [ -n "$OPENVPN_ROUTES" ]; then - output "Provisioning nat iptables rules for OPENVPN_ROUTES" + output "Provisioning NAT iptables rules for OPENVPN_ROUTES" for r in $OPENVPN_ROUTES; do iptables -t nat -C POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE done @@ -47,11 +48,12 @@ if [ "$NAT" = 1 ]; then fi else output "NAT is disabled." - output "Not adding nat iptables rules" + output "Not adding NAT iptables rules" fi output "Listing iptables rules:" iptables -L -nv +output "Listing iptables NAT rules:" iptables -L -nv -t nat # Generate the command line. openvpn man: https://openvpn.net/community-resources/reference-manual-for-openvpn-2-4/ diff --git a/variants/v2.4.7-alpine-3.10/openvpn/firewall.sh b/variants/v2.4.7-alpine-3.10/openvpn/firewall.sh index aa19e0f..511ab5a 100644 --- a/variants/v2.4.7-alpine-3.10/openvpn/firewall.sh +++ b/variants/v2.4.7-alpine-3.10/openvpn/firewall.sh @@ -1,9 +1,12 @@ #!/bin/sh +# This iptables script is useful for openpvn in server mode. Not so much for client mode. + set -eo pipefail -# Only allow DNS, HTTP, HTTPS from tunnel to world -echo "$NAT_INTERFACE" +# Drop everything by default from tunnel to world iptables -P FORWARD DROP +# Allow DNS from tunnel to world iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT -iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT \ No newline at end of file +# Allow HTTP and HTTPS from tunnel to world +iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT diff --git a/variants/v2.4.8-alpine-3.11/Dockerfile b/variants/v2.4.8-alpine-3.11/Dockerfile index 39bb7cc..2fb2666 100644 --- a/variants/v2.4.8-alpine-3.11/Dockerfile +++ b/variants/v2.4.8-alpine-3.11/Dockerfile @@ -8,7 +8,7 @@ COPY docker-entrypoint.sh /docker-entrypoint.sh RUN chmod +x /docker-entrypoint.sh COPY openvpn /etc/openvpn -RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn +RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn && chmod 750 /etc/openvpn/*.sh ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/variants/v2.4.8-alpine-3.11/docker-entrypoint.sh b/variants/v2.4.8-alpine-3.11/docker-entrypoint.sh index 32ab579..f6f6d19 100755 --- a/variants/v2.4.8-alpine-3.11/docker-entrypoint.sh +++ b/variants/v2.4.8-alpine-3.11/docker-entrypoint.sh @@ -29,16 +29,17 @@ if [ ! -c /dev/net/tun ]; then fi if [ -f "$CUSTOM_FIREWALL_SCRIPT" ]; then output "Executing custom firewall script: $CUSTOM_FIREWALL_SCRIPT" - sh "$CUSTOM_FIREWALL_SCRIPT" + . "$CUSTOM_FIREWALL_SCRIPT" else output "Not executing custom firewall script $CUSTOM_FIREWALL_SCRIPT because it does not exist" fi if [ "$NAT" = 1 ]; then output "NAT is enabled" - output "Provisioning nat iptables rules" + output "Provisioning NAT iptables rules" + output "NAT_INTERFACE: $NAT_INTERFACE" iptables -t nat -C POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE if [ -n "$OPENVPN_ROUTES" ]; then - output "Provisioning nat iptables rules for OPENVPN_ROUTES" + output "Provisioning NAT iptables rules for OPENVPN_ROUTES" for r in $OPENVPN_ROUTES; do iptables -t nat -C POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE done @@ -47,11 +48,12 @@ if [ "$NAT" = 1 ]; then fi else output "NAT is disabled." - output "Not adding nat iptables rules" + output "Not adding NAT iptables rules" fi output "Listing iptables rules:" iptables -L -nv +output "Listing iptables NAT rules:" iptables -L -nv -t nat # Generate the command line. openvpn man: https://openvpn.net/community-resources/reference-manual-for-openvpn-2-4/ diff --git a/variants/v2.4.8-alpine-3.11/openvpn/firewall.sh b/variants/v2.4.8-alpine-3.11/openvpn/firewall.sh index aa19e0f..511ab5a 100644 --- a/variants/v2.4.8-alpine-3.11/openvpn/firewall.sh +++ b/variants/v2.4.8-alpine-3.11/openvpn/firewall.sh @@ -1,9 +1,12 @@ #!/bin/sh +# This iptables script is useful for openpvn in server mode. Not so much for client mode. + set -eo pipefail -# Only allow DNS, HTTP, HTTPS from tunnel to world -echo "$NAT_INTERFACE" +# Drop everything by default from tunnel to world iptables -P FORWARD DROP +# Allow DNS from tunnel to world iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT -iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT \ No newline at end of file +# Allow HTTP and HTTPS from tunnel to world +iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT diff --git a/variants/v2.5.0-alpine-3.13/Dockerfile b/variants/v2.5.0-alpine-3.13/Dockerfile new file mode 100644 index 0000000..f7ad736 --- /dev/null +++ b/variants/v2.5.0-alpine-3.13/Dockerfile @@ -0,0 +1,14 @@ + + +FROM alpine:3.13 + +RUN apk add --no-cache openvpn=2.5.0-r1 iptables + +COPY docker-entrypoint.sh /docker-entrypoint.sh +RUN chmod +x /docker-entrypoint.sh + +COPY openvpn /etc/openvpn +RUN chown -R root:root /etc/openvpn && chmod 750 /etc/openvpn && chmod 750 /etc/openvpn/*.sh + +ENTRYPOINT ["/docker-entrypoint.sh"] + diff --git a/variants/v2.5.0-alpine-3.13/docker-compose.yml b/variants/v2.5.0-alpine-3.13/docker-compose.yml new file mode 100644 index 0000000..34c71b5 --- /dev/null +++ b/variants/v2.5.0-alpine-3.13/docker-compose.yml @@ -0,0 +1,18 @@ +version: '2.1' +services: + openvpn: + container_name: openvpn + image: theohbrothers/docker-openvpn:v2.5.0-alpine-3.13 + ports: + - "1194:1194/udp" + cap_add: + - NET_ADMIN + # sysctls for the container if it is not set on the host. See: https://docs.docker.com/compose/compose-file/compose-file-v2/#sysctls + sysctls: + - net.ipv4.conf.all.forwarding=1 + # - net.ipv6.conf.all.disable_ipv6=0 + # - net.ipv6.conf.default.forwarding=1 + # - net.ipv6.conf.all.forwarding=1 + restart: unless-stopped + volumes: + - ./openvpn/server.conf:/etc/openvpn/server.conf \ No newline at end of file diff --git a/variants/v2.5.0-alpine-3.13/docker-entrypoint.sh b/variants/v2.5.0-alpine-3.13/docker-entrypoint.sh new file mode 100644 index 0000000..f6f6d19 --- /dev/null +++ b/variants/v2.5.0-alpine-3.13/docker-entrypoint.sh @@ -0,0 +1,70 @@ +#!/bin/sh + +set -aeo pipefail + +output() { + echo -e "[$( date -u '+%Y-%m-%dT%H:%M:%S%z' )] $1" +} + +error() { + echo -e "[$( date -u '+%Y-%m-%dT%H:%M:%S%z' )] $1" >&2 +} + +# Env vars +OPENVPN=openvpn +OPENVPN_SERVER_CONFIG_FILE=${OPENVPN_SERVER_CONFIG_FILE:-/etc/openvpn/server.conf} +# OPENVPN_CLIENT_CONFIG_DIR=${OPENVPN_CLIENT_CONFIG_DIR:-/etc/openvpn/ccd} +# OPENVPN_STATUS_FILE=${OPENVPN_STATUS_FILE:-} +# OPENVPN_STATUS_FILE_WRITE_FREQUENCY_SECONDS={$OPENVPN_STATUS_FILE_WRITE_FREQUENCY_SECONDS:-10} +OPENVPN_ROUTES=${OPENVPN_ROUTES:-} +NAT=${NAT:-1} +NAT_INTERFACE=${NAT_INTERFACE:-eth0} +CUSTOM_FIREWALL_SCRIPT=${CUSTOM_FIREWALL_SCRIPT:-/etc/openvpn/firewall.sh} + +# Provision +output "Provisioning tun device" +mkdir -p /dev/net +if [ ! -c /dev/net/tun ]; then + mknod /dev/net/tun c 10 200 +fi +if [ -f "$CUSTOM_FIREWALL_SCRIPT" ]; then + output "Executing custom firewall script: $CUSTOM_FIREWALL_SCRIPT" + . "$CUSTOM_FIREWALL_SCRIPT" +else + output "Not executing custom firewall script $CUSTOM_FIREWALL_SCRIPT because it does not exist" +fi +if [ "$NAT" = 1 ]; then + output "NAT is enabled" + output "Provisioning NAT iptables rules" + output "NAT_INTERFACE: $NAT_INTERFACE" + iptables -t nat -C POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -o "$NAT_INTERFACE" -j MASQUERADE + if [ -n "$OPENVPN_ROUTES" ]; then + output "Provisioning NAT iptables rules for OPENVPN_ROUTES" + for r in $OPENVPN_ROUTES; do + iptables -t nat -C POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE || iptables -t nat -A POSTROUTING -s "$r" -o "$NAT_INTERFACE" -j MASQUERADE + done + else + output "Not provisioning route iptables rules because OPENVPN_ROUTES is empty" + fi +else + output "NAT is disabled." + output "Not adding NAT iptables rules" +fi + +output "Listing iptables rules:" +iptables -L -nv +output "Listing iptables NAT rules:" +iptables -L -nv -t nat + +# Generate the command line. openvpn man: https://openvpn.net/community-resources/reference-manual-for-openvpn-2-4/ +output "Generating command line" +set "$OPENVPN" --cd /etc/openvpn +set "$@" --config "$OPENVPN_SERVER_CONFIG_FILE" +# set "$@" --client-config-dir "$OPENVPN_CLIENT_CONFIG_DIR" +if [ -n "$OPENVPN_STATUS_FILE" ]; then + set "$@" --status "$OPENVPN_STATUS_FILE" "$OPENVPN_STATUS_FILE_WRITE_FREQUENCY_SECONDS" +fi + +# Exec +output "openvpn command line: $@" +exec "$@" \ No newline at end of file diff --git a/variants/v2.5.0-alpine-3.13/openvpn/client.conf b/variants/v2.5.0-alpine-3.13/openvpn/client.conf new file mode 100644 index 0000000..953eefa --- /dev/null +++ b/variants/v2.5.0-alpine-3.13/openvpn/client.conf @@ -0,0 +1,23 @@ +# See sample config file: https://github.com/OpenVPN/openvpn/blob/v2.4.8/sample/sample-config-files/client.conf +# redirect-gateway def1 bypass-dhcp +client +dev tun +proto udp +remote 10.8.0.1 1194 +resolv-retry infinite +nobind +# user nobody +# group nobody +persist-key +persist-tun +ca pki/ca.crt +cert pki/issued/client.crt +key pki/private/client.key +remote-cert-tls server +tls-auth pki/ta.key 1 +# key-direction 1 +cipher AES-256-CBC +# auth SHA256 +comp-lzo no +verb 3 +# mute 20 diff --git a/variants/v2.5.0-alpine-3.13/openvpn/firewall.sh b/variants/v2.5.0-alpine-3.13/openvpn/firewall.sh new file mode 100644 index 0000000..511ab5a --- /dev/null +++ b/variants/v2.5.0-alpine-3.13/openvpn/firewall.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +# This iptables script is useful for openpvn in server mode. Not so much for client mode. + +set -eo pipefail + +# Drop everything by default from tunnel to world +iptables -P FORWARD DROP +# Allow DNS from tunnel to world +iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p udp -m udp --dport 53 -m conntrack --ctstate NEW -j ACCEPT +# Allow HTTP and HTTPS from tunnel to world +iptables -A FORWARD -i tun+ -o "$NAT_INTERFACE" -p tcp -m tcp -m conntrack --ctstate NEW -m multiport --dports 80,443 -j ACCEPT diff --git a/variants/v2.5.0-alpine-3.13/openvpn/server.conf b/variants/v2.5.0-alpine-3.13/openvpn/server.conf new file mode 100644 index 0000000..72fef1d --- /dev/null +++ b/variants/v2.5.0-alpine-3.13/openvpn/server.conf @@ -0,0 +1,25 @@ +# See sample config file: https://github.com/OpenVPN/openvpn/blob/v2.4.8/sample/sample-config-files/server.conf +port 1194 +proto udp +dev tun +ca pki/ca.crt +cert pki/issued/server.crt +key pki/private/server.key +dh pki/dh.pem +crl-verify pki/crl.pem +server 10.8.0.0 255.255.255.0 +ifconfig-pool-persist ipp.txt +;client-config-dir ccd +keepalive 10 120 +tls-auth pki/ta.key 0 +cipher AES-256-CBC +max-clients 5 +user nobody +group nogroup +persist-key +persist-tun +status server.status.log +# log-append server.log +verb 3 +mute 20 +explicit-exit-notify 1 \ No newline at end of file