diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1639028..7d98dd7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,17 +10,17 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: run smoke tests - run: bash run_tests.sh + - uses: actions/checkout@v3 + - name: run smoke tests + run: bash run_tests.sh test-stack: strategy: matrix: stack: [heroku-18, heroku-20, heroku-22] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: run stack test - run: bash test/stack-test.sh ${{ matrix.stack }} - env: - TAILSCALE_TEST_AUTH_KEY: ${{ secrets.TAILSCALE_TEST_AUTH_KEY }} + - uses: actions/checkout@v3 + - name: run stack test + run: bash test/stack-test.sh ${{ matrix.stack }} + env: + TAILSCALE_TEST_AUTH_KEY: ${{ secrets.TAILSCALE_TEST_AUTH_KEY }} diff --git a/CHANGELOG.md b/CHANGELOG.md index dfa3439..4fffe81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,34 +1,37 @@ ## Unreleased -* Update README to include mention of serving application to only users in your - Tailnet. +- Update README. + +## 1.1.2 + +- Remove proxychains. ## 1.1.1 (2023-06-15) -* Swap the ``_`` character for ``-`` in the hostname for +- Swap the `_` character for `-` in the hostname for the DYNO environment variable. ## 1.1.0 (2023-06-15) -* Updated the default TAILSCALE_HOSTNAME to be ``[commit]-[dyno]-[appname]``. +- Updated the default TAILSCALE_HOSTNAME to be `[commit]-[dyno]-[appname]`. This requires [Heroku Labs runtime-dyno-metadata](https://devcenter.heroku.com/articles/dyno-metadata) to be enabled. ## 1.0.1 (2023-06-15) -* Added ``TAILSCALE_BUILD_EXCLUDE_START_SCRIPT_FROM_PROFILE_D`` build environment variable +- Added `TAILSCALE_BUILD_EXCLUDE_START_SCRIPT_FROM_PROFILE_D` build environment variable to control when the tailscale script starts. ## 1.0.1 (2023-06-13) -* Updated default tailscale version from 1.40.0 to 1.42.0 +- Updated default tailscale version from 1.40.0 to 1.42.0 ## 1.0.0 (2023-05-11) -* Implement buildpack sourcing ideas from +- Implement buildpack sourcing ideas from https://github.com/moneymeets/python-poetry-buildpack, https://github.com/heroku/heroku-buildpack-pgbouncer and tailscale-docker and tailscale-heroku. -* Move the process to start tailscale into the .profile.d/ script. -* Only start Tailscale when the auth key is present in the environment +- Move the process to start tailscale into the .profile.d/ script. +- Only start Tailscale when the auth key is present in the environment variables. -* Create a ``heroku-tailscale-test.sh`` script for easier testing/verification. +- Create a `heroku-tailscale-test.sh` script for easier testing/verification. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 860f5af..06e2d77 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,9 +1,9 @@ # Contributing Guidelines -There are two different sets of tests to run. ``run_tests.sh`` does some basic -verification of the bin scripts. ``stack-test.sh`` spins up a Docker image with +There are two different sets of tests to run. `run_tests.sh` does some basic +verification of the bin scripts. `stack-test.sh` spins up a Docker image with Heroku's base image to verify the installation works locally. To run this second one, -you will need to create a Tailscale token that can connect to ``hello.ts.net``. See +you will need to create a Tailscale token that can connect to `hello.ts.net`. See [Tailscale's documentation on testing](https://tailscale.com/kb/1073/hello/?q=testing). ```shell @@ -14,17 +14,17 @@ test/stack-test.sh heroku-22 ## CI TailScale auth token -Eventually the GitHub ``TAILSCALE_TEST_AUTH_KEY`` will expire (every 90 days). +Eventually the GitHub `TAILSCALE_TEST_AUTH_KEY` will expire (every 90 days). When that happens a new token will need to be generated. It should be reusable, -ephemeral and have the ``tag:test`` tag applied to it. It will need to be copied -to the ``TAILSCALE_TEST_AUTH_KEY`` repository secret for this repo. +ephemeral and have the `tag:test` tag applied to it. It will need to be copied +to the `TAILSCALE_TEST_AUTH_KEY` repository secret for this repo. ## Releasing updates ```shell heroku plugins:install buildpack-registry -cd heroku-tailscale-buildpack +cd heroku-buildpack-tailscale git checkout main -heroku buildpacks:publish aspiredu/heroku-tailscale-buildpack -``` \ No newline at end of file +heroku buildpacks:publish sundaycarwash/heroku-buildpack-tailscale +``` diff --git a/Dockerfile b/Dockerfile index 960a4ee..3b215ff 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,6 +10,6 @@ RUN env -i PATH=$PATH HOME=$HOME STACK=$STACK /buildpack/bin/detect /app RUN env -i PATH=$PATH HOME=$HOME STACK=$STACK /buildpack/bin/compile /app /cache /env # Install test utililties -RUN apt-get update && apt-get install -y curl +RUN apt-get update || true && apt-get install -y curl WORKDIR /app diff --git a/LICENSE b/LICENSE index 68b8700..9a84ef2 100644 --- a/LICENSE +++ b/LICENSE @@ -2,180 +2,180 @@ Version 2.0, January 2004 http://www.apache.org/licenses/ - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" @@ -186,16 +186,16 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2023 - AspirEDU +Copyright 2023 - Sun Day Carwash - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/README.md b/README.md index d2c7486..0de4374 100644 --- a/README.md +++ b/README.md @@ -1,56 +1,44 @@ # Heroku buildpack to use Tailscale on Heroku -Run [Tailscale](https://tailscale.com/) on a Heroku dyno, shoving connections through proxychains. - -## Why is proxychains necessary? - -It really shouldn't be. However, I discovered that in my project to use Django and PostgreSQL, -pyscopg did not respect the ``ALL_PROXY`` environment variable. In order to get the network -communication to go through the Tailscale SOCKS5 proxy, I needed to manually force it. Enter -proxychains-ng. - -This is based on https://tailscale.com/kb/1107/heroku/. - -Thank you to @rdotts, @kongmadai, @mvisonneau for their work on tailscale-docker and tailscale-heroku. +Run [Tailscale](https://tailscale.com/) on a Heroku dyno. ## Usage -To set up your Heroku application, add the buildpack and ``TAILSCALE_AUTH_KEY`` +To set up your Heroku application, add the buildpack and `TAILSCALE_AUTH_KEY` environment variable: - $ heroku buildpacks:add https://github.com/aspiredu/heroku-tailscale-buildpack - Buildpack added. Next release on test-app will use aspiredu/heroku-tailscale-buildpack. - Run `git push heroku main` to create a new release using this buildpack. - + $ heroku buildpacks:add https://github.com/sundaycarwash/heroku-buildpack-tailscale $ heroku config:set TAILSCALE_AUTH_KEY="..." - $ git push heroku main - ... -To have your processes connect through the Tailscale proxy, you need to update your -``Procfile``. Here's an example for a Django project with a Celery worker: +To have your processes connect through the Tailscale proxy, you need to use +the `socks5` proxy provided by `tailscaled`. ``` -web: proxychains4 -f vendor/proxychains-ng/conf/proxychains.conf uvicorn --host 0.0.0.0 --port "$PORT" myproject.project.asgi:application -worker: proxychains4 -f vendor/proxychains-ng/conf/proxychains.conf celery -A myproject.project worker +curl --socks5-hostname localhost:1055 +``` + +```ruby + TCPSocket.socks_server = "localhost" + TCPSocket.socks_port = 1055 ``` ## Testing the integration -To test a connection, you can add the ``hello.ts.net`` machine into your network. +To test a connection, you can add the `hello.ts.net` machine into your network. [Follow the instructions here](https://tailscale.com/kb/1073/hello/?q=testing). You may need to modify your ACLs to allow access to the test machine. For example, I have -a separate Tailscale token that is tagged with ``tag:test``. My ACL looks like: +a separate Tailscale token that is tagged with `tag:test`. My ACL looks like: ```json { "hosts": { - "hello-test": "100.101.102.103" + "hello-test": "100.101.102.103" }, - + // Access control lists. "acls": [ - // Only allow the test tag to access anything. - {"action": "accept", "src": ["tag:test"], "dst": ["hello-test:*"]} + // Only allow the test tag to access anything. + { "action": "accept", "src": ["tag:test"], "dst": ["hello-test:*"] } ] } ``` @@ -61,175 +49,36 @@ To verify the connection works run: heroku run -- heroku-tailscale-test.sh ``` -You should see curl respond with ``Found.`` - +You should see curl respond with `Found.` ## Configuration The following settings are available for configuration via environment variables: -- ``TAILSCALE_ACCEPT_DNS`` - Accept DNS configuration from the admin console. Defaults +- `TAILSCALE_ACCEPT_DNS` - Accept DNS configuration from the admin console. Defaults to accepting DNS settings. -- ``TAILSCALE_ACCEPT_ROUTES`` - Accept subnet routes that other nodes advertise. Linux devices - default to not accepting routes. Defaults to accepting. -- ``TAILSCALE_ADVERTISE_EXIT_NODES`` - Offer to be an exit node for outbound internet traffic +- `TAILSCALE_ACCEPT_ROUTES` - Accept subnet routes that other nodes advertise. Defaults + to accepting subnet routes. +- `TAILSCALE_ADVERTISE_EXIT_NODES` - Offer to be an exit node for outbound internet traffic from the Tailscale network. Defaults to not advertising. -- ``TAILSCALE_ADVERTISE_TAGS`` - Give tagged permissions to this device. You must be listed in +- `TAILSCALE_ADVERTISE_TAGS` - Give tagged permissions to this device. You must be listed in \"TagOwners\" to be able to apply tags. Defaults to none. -- ``TAILSCALE_AUTH_KEY`` - Provide an auth key to automatically authenticate the node as your +- `TAILSCALE_AUTH_KEY` - Provide an auth key[^1] to automatically authenticate the node as your user account. **This must be set.** -- ``TAILSCALE_HOSTNAME`` - Provide a hostname to use for the device instead of the one provided - by the OS. Note that this will change the machine name used in MagicDNS. Defaults to the +- `TAILSCALE_HOSTNAME` - Provide a hostname to use for the device instead of the one provided + by the OS. Note that this will change the machine name used in MagicDNS. Defaults to the hostname of the application (a guid). If you have [Heroku Labs runtime-dyno-metadata](https://devcenter.heroku.com/articles/dyno-metadata) - enabled, it defaults to ``[commit]-[dyno]-[appname]``. -- ``TAILSCALE_SHIELDS_UP"`` - Block incoming connections from other devices on your Tailscale + enabled, it defaults to `[commit]-[dyno]-[appname]`. +- `TAILSCALE_SHIELDS_UP"` - Block incoming connections from other devices on your Tailscale network. Useful for personal devices that only make outgoing connections. Defaults to off. -- ``TAILSCALED_VERBOSE`` - Controls verbosity for the tailscaled command. Defaults to 0. +- `TAILSCALED_VERBOSE` - Controls verbosity for the tailscaled command. Defaults to 0. The following settings are for the compile process for the buildpack. If you change these, you must trigger a new build to see the change. Simply changing the environment variables in Heroku will not cause a rebuild. These are all optional and will default to the latest values. -- ``TAILSCALE_BUILD_TS_VERSION`` - The target version Tailscale package. -- ``TAILSCALE_BUILD_TS_TARGETARCH`` - The target architecture for the Tailscale package. -- ``TAILSCALE_BUILD_EXCLUDE_START_SCRIPT_FROM_PROFILE_D`` - Excludes the start script from the - [buildpack's ``.profile.d/`` folder](https://devcenter.heroku.com/articles/buildpack-api#profile-d-scripts). - If you set this to true, you must call ``vendor/tailscale/heroku-tailscale-start.sh``. This likely should go - into your ``.profile`` script ([see Heroku docs](https://devcenter.heroku.com/articles/dynos#the-profile-file)). - Starting the script in your ``.profile`` file would allow you to better control environment - variables in respect to the executables. For example, a specific dyno could change - ``TAILSCALE_HOSTNAME`` before tailscale starts. -- ``TAILSCALE_BUILD_PROXYCHAINS_REPO`` - The repository to install the proxychains-ng library from. - - -### Customizing proxychains.conf - -If you decide you want to customize the ``proxychains.conf`` configuration file, you can copy the -file from conf into your project. If you copy it to the base directory of your application, -ProxyChains will find it automatically. If you copy it to a specific directory, such as conf, -you'll need to specify the path. - -For example, if your conf file exists at ``/conf/proxychains.conf`` your web command -would need to be: - -```shell -proxychains4 -f conf/proxychains.conf -``` - -## Deployment considerations - -Switching to a Tailscale database or service can be troublesome. Especially if you interact -with the resource during the [Release phase of Heroku's deployments](https://devcenter.heroku.com/articles/release-phase) -such as basic SQL migrations. This is because you don't want to use the ``proxychains4`` -wrapper if you don't have Tailscale running, and you can't have Tailscale running if you -don't have a valid Tailscale auth key and the database/resource configured in your tailnet. - -I suggest working these problems out in reverse allowing for a fallback to a connection -outside of your tailnet. Once you've done the final switch over, you can remove access -to your database/resource from outside of the tailnet. - -1. Configure database/resource to be accessible in and outside of your tailnet -2. Create a Tailscale auth key (reusuable[^1], not ephemeral, and appropriately tagged) -3. Add the auth key and the Tailscale database/resource url to your Heroku app's environment variables. - -```shell -heroku config:set TAILSCALE_AUTH_KEY= \ - TAILSCALE_DATABASE_URL= -``` - -4. Add the heroku-tailscale-buildpack - -```shell -heroku buildpacks:add https://github.com/aspiredu/heroku-tailscale-buildpack -``` - -5. (Optional) Test your integration. - 1. Add the [Tailscale test machine in your tailnet](https://tailscale.com/kb/1073/hello/?q=test) - 2. Create a test tag that can only access the hello.ts.net machine via your ACLs - 3. Create a reusable ephemeral auth token that has the test tag applied to it. - 4. Temporarily change your application to use the test auth key. - 5. Trigger a build. This should include this buildpack. - 6. Run a one-off dyno to confirm that the setup is correct. - - ```shell - heroku run heroku-tailscale-start.sh - ``` - 7. Restore the previous version of Tailscale auth key. - -6. Modify your application to try to use the Tailscale database/resource and fallback to - the non-tailnet version. If you're using python, the following script may help: - -```python -import os -import dj_database_url - -def tailscale_resource_key(base_key): - """Fetch the resource key for a Tailscale service. - - It checks for an environment variable with the TAILSCALE_ prefix - and if it exists and TAILSCALE_AUTH_KEY is defined, it uses that key. - Else it returns the value that was passed in. - - This is useful for configuring different services to use tailscale - without having to do everything all at once. - """ - tailscale_auth_key = "TAILSCALE_AUTH_KEY" - tailscale_resource_key = f"TAILSCALE_{base_key}" - return ( - tailscale_resource_key - if os.environ.get(tailscale_resource_key) and os.environ.get(tailscale_auth_key) - else base_key - ) - -DATABASES = { - "default": dj_database_url.config(env=tailscale_resource_key("DATABASE_URL")) -} -``` -7. Push your code to your Heroku application, triggering a new build. - -```shell -git push heroku -``` -8. You're now running your application connecting to your resources via Tailscale. - -## Limit access to web app to Tailscale users - -It is possible to serve your web application on Heroku to only users in your tailnet, -but that is outside the scope of this particular buildpack. - -That said, this buildpack makes it possible to do so. We solved this by -creating a separate dyno in the ``Procfile`` called `admin_web` which runs a script -that does the following: - -1. Attempt to restore certificate files from cache. -2. Revoke previous machine with the desired hostname. -3. Update current tailscale process to use the desired hostname. -4. Validate and potentially re-issue certificates for hostname. -5. Store certificate files in cache. -6. Serve localhost process on Tailnet for the hostname. -7. Start web process to serve requests on localhost. - -The certificates need to be persisted beyond instances of the dyno to avoid requesting -certificates for the same full DNS path from Let's Encrypt. Let's Encrypt will limit -you to 5 requests per week. - -The certificate files you'll need to persist are: - -- ``.local/share/tailscale/certs/$TAILSCALE_HOSTNAME.crt`` -- ``.local/share/tailscale/certs/$TAILSCALE_HOSTNAME.key`` - -To serve your application your ``admin_web`` script should do something similar to: - -```shell -# Expose the local 8000 port to the tailnet. -# The URL will be https://..ts.net -tailscale serve https / http://127.0.0.1:8000 -# Generate the current serve status so the logs include the URL. -tailscale serve status -# Start the web server process -exec proxychains4 -f vendor/proxychains-ng/conf/proxychains.conf uvicorn --host 127.0.0.1 --port "8000" project.asgi:application -``` - -[^1]: You want reusable auth keys here because it will be used across all of your dynos - in the application. +- `TAILSCALE_VERSION` - The Tailscale package version. +[^1]: + You want reusable auth keys here because it will be used across all of your dynos + in the application. diff --git a/bin/compile b/bin/compile index 3766de2..131416f 100755 --- a/bin/compile +++ b/bin/compile @@ -17,10 +17,6 @@ set -euo pipefail # clean up leaking environment unset GIT_DIR -function log() { - echo "-----> $*" -} - function indent() { sed -e 's/^/ /' } @@ -31,93 +27,34 @@ CACHE_DIR=$2 ENV_DIR=$3 BUILDPACK_DIR="$(dirname "$(dirname "$0")")" -PC_BASE_DIR=$CACHE_DIR/proxychains-ng -PC_SOURCE_DIR=$CACHE_DIR/proxychains-ng/source -mkdir -p $PC_SOURCE_DIR +# load dependencies +source "$BUILDPACK_DIR/lib/environment.sh" -BUILDPACK_VARIABLES="TAILSCALE_BUILD_TS_VERSION TAILSCALE_BUILD_TS_TARGETARCH" +BUILDPACK_VARIABLES="TAILSCALE_VERSION" shopt -s nullglob -# Load any tailscale build environment variables for the application -# into the actual environment variables. -for env_file in $BUILDPACK_VARIABLES ; do - [ -f "$ENV_DIR/$env_file" ] && export "$(basename "$env_file")=$(cat "$ENV_DIR/$env_file" 2>/dev/null)" -done - -if [ -z "${TAILSCALE_BUILD_TS_TARGETARCH:-}" ] ; then - export TAILSCALE_BUILD_TS_TARGETARCH=amd64 - log "No Tailscale architecture specified in TAILSCALE_BUILD_TS_TARGETARCH config var. Defaulting to $TAILSCALE_BUILD_TS_TARGETARCH." -else - log "Using Tailscale architecture from TAILSCALE_BUILD_TS_TARGETARCH config var: $TAILSCALE_BUILD_TS_TARGETARCH" -fi - -if [ -z "${TAILSCALE_BUILD_TS_VERSION:-}" ] ; then - export TAILSCALE_BUILD_TS_VERSION=1.42.0 - log "No Tailscale version specified in TAILSCALE_BUILD_TS_VERSION config var. Defaulting to $TAILSCALE_BUILD_TS_VERSION." -else - log "Using Tailscale version from TAILSCALE_BUILD_TS_VERSION config var: $TAILSCALE_BUILD_TS_VERSION" -fi - -if [ -z "${TAILSCALE_BUILD_PROXYCHAINS_REPO:-}" ] ; then - export TAILSCALE_BUILD_PROXYCHAINS_REPO="https://github.com/rofl0r/proxychains-ng.git" - log "No ProxyChains repo specified in TAILSCALE_BUILD_PROXYCHAINS_REPO config var. Defaulting to $TAILSCALE_BUILD_PROXYCHAINS_REPO." -else - log "Using ProxyChains repo from TAILSCALE_BUILD_PROXYCHAINS_REPO config var: $TAILSCALE_BUILD_PROXYCHAINS_REPO" -fi - - -log "Install Tailscale" -log "Add Tailscale to the PATH" -mkdir -p "$BUILD_DIR/vendor/tailscale" -export PATH="$BUILD_DIR/vendor/tailscale:$PATH" - -log "Fetch Tailscale" -curl -sL "https://pkgs.tailscale.com/stable/tailscale_${TAILSCALE_BUILD_TS_VERSION}_${TAILSCALE_BUILD_TS_TARGETARCH}.tgz" \ - | tar -zxf - -C "${BUILD_DIR}/vendor/tailscale" --strip=1 tailscale_${TAILSCALE_BUILD_TS_VERSION}_${TAILSCALE_BUILD_TS_TARGETARCH}/tailscaled tailscale_${TAILSCALE_BUILD_TS_VERSION}_${TAILSCALE_BUILD_TS_TARGETARCH}/tailscale -# Mark the scripts as executable. -chmod +x "$BUILD_DIR/vendor/tailscale/tailscale" -chmod +x "$BUILD_DIR/vendor/tailscale/tailscaled" -cp "$BUILDPACK_DIR/bin/heroku-tailscale-start.sh" "$BUILD_DIR/vendor/tailscale/heroku-tailscale-start.sh" -cp "$BUILDPACK_DIR/bin/heroku-tailscale-test.sh" "$BUILD_DIR/vendor/tailscale/heroku-tailscale-test.sh" -chmod +x "$BUILD_DIR/vendor/tailscale/heroku-tailscale-start.sh" -chmod +x "$BUILD_DIR/vendor/tailscale/heroku-tailscale-test.sh" +export_env_dir "$ENV_DIR" + +: ${TAILSCALE_VERSION:=1.56.1} && echo "-----> Using Tailscale version: $TAILSCALE_VERSION" + +mkdir -p "$BUILD_DIR/.heroku/tailscale/bin" +export PATH="$BUILD_DIR/.heroku/tailscale/bin:$PATH" + +echo "-----> Downloading Tailscale" +curl -sL "https://pkgs.tailscale.com/stable/tailscale_${TAILSCALE_VERSION}_amd64.tgz" \ + | tar -zxf - -C "${BUILD_DIR}/.heroku/tailscale/bin" --strip=1 tailscale_${TAILSCALE_VERSION}_amd64/tailscaled tailscale_${TAILSCALE_VERSION}_amd64/tailscale + +chmod +x "$BUILD_DIR/.heroku/tailscale/bin/tailscale" +chmod +x "$BUILD_DIR/.heroku/tailscale/bin/tailscaled" + +cp "$BUILDPACK_DIR/bin/heroku-tailscale-start.sh" "$BUILD_DIR/.heroku/tailscale/bin/heroku-tailscale-start.sh" +cp "$BUILDPACK_DIR/bin/heroku-tailscale-test.sh" "$BUILD_DIR/.heroku/tailscale/bin/heroku-tailscale-test.sh" + +chmod +x "$BUILD_DIR/.heroku/tailscale/bin/heroku-tailscale-start.sh" +chmod +x "$BUILD_DIR/.heroku/tailscale/bin/heroku-tailscale-test.sh" mkdir -p $BUILD_DIR/.profile.d 2>&1 | indent -rm -f $BUILD_DIR/.profile.d/heroku-tailscale-buildpack.sh 2>&1 | indent -echo 'export PATH="/app/vendor/tailscale:$PATH"' >> $BUILD_DIR/.profile.d/heroku-tailscale-buildpack.sh 2>&1 | indent - -log "Install ProxyChains-ng" - -log "Clone ProxyChains repo" -rm -r $PC_SOURCE_DIR -git clone $TAILSCALE_BUILD_PROXYCHAINS_REPO $PC_SOURCE_DIR 2>&1 | indent - -pushd $PC_SOURCE_DIR > /dev/null -PC_VERSION_TAG=$(git describe --tags| cut -d- -f1) -CACHED_BUILD_DIR=$PC_BASE_DIR/proxychains-ng-$PC_VERSION_TAG - -if [[ ! -d $CACHED_BUILD_DIR ]]; then - log "Building ProxyChains $PC_VERSION_TAG" - make clean 2>&1 | indent - git checkout $PC_VERSION_TAG 2>&1 | indent - ./configure --prefix=/app/vendor/proxychains-ng 2>&1 | indent - make 2>&1 | indent - DESTDIR=$CACHED_BUILD_DIR make install 2>&1 | indent -fi -popd > /dev/null - -log "Installing ProxyChains into the slug" -mkdir -p "$BUILD_DIR/vendor/proxychains-ng" -cp -r "$BUILDPACK_DIR/conf" "$BUILD_DIR/vendor/proxychains-ng/conf" -echo 'export PATH="/app/vendor/proxychains-ng/bin:$PATH"' >> $BUILD_DIR/.profile.d/heroku-tailscale-buildpack.sh 2>&1 | indent -echo 'export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/app/vendor/proxychains-ng/lib";' >> $BUILD_DIR/.profile.d/heroku-tailscale-buildpack.sh 2>&1 | indent - -if [[ "${TAILSCALE_BUILD_EXCLUDE_START_SCRIPT_FROM_PROFILE_D:-}" != "True" ]]; then - # Add the line to start tailscale to the end of the file - echo "/app/vendor/tailscale/heroku-tailscale-start.sh" >> $BUILD_DIR/.profile.d/heroku-tailscale-buildpack.sh 2>&1 | indent -fi - -pushd $CACHED_BUILD_DIR/app > /dev/null -cp -rv ./ $BUILD_DIR 2>&1 | indent -popd > /dev/null +rm -f $BUILD_DIR/.profile.d/heroku-buildpack-tailscale.sh 2>&1 | indent +echo 'export PATH="/app/.heroku/tailscale/bin:$PATH"' >> $BUILD_DIR/.profile.d/heroku-buildpack-tailscale.sh 2>&1 | indent +echo "/app/.heroku/tailscale/bin/heroku-tailscale-start.sh" >> $BUILD_DIR/.profile.d/heroku-buildpack-tailscale.sh 2>&1 | indent diff --git a/bin/detect b/bin/detect index b34379a..a9ed65f 100755 --- a/bin/detect +++ b/bin/detect @@ -1,5 +1,5 @@ #!/usr/bin/env bash # bin/detect -echo 'tailscale' +echo 'Tailscale' exit 0 diff --git a/bin/heroku-tailscale-start.sh b/bin/heroku-tailscale-start.sh index 3c57c30..2317d81 100755 --- a/bin/heroku-tailscale-start.sh +++ b/bin/heroku-tailscale-start.sh @@ -45,6 +45,5 @@ else sleep 5 done - export ALL_PROXY=socks5://localhost:1055/ log "Tailscale started" fi diff --git a/bin/heroku-tailscale-test.sh b/bin/heroku-tailscale-test.sh index 0216e5f..176b6f1 100755 --- a/bin/heroku-tailscale-test.sh +++ b/bin/heroku-tailscale-test.sh @@ -14,9 +14,9 @@ else log "Running `tailscale status` You should see your accessible machines on your tailnet." tailscale status - log "Running `proxychains4 -f vendor/proxychains-ng/conf/proxychains.conf curl hello.ts.net` " - log 'Things are working if you see Found.' - proxychains4 -f vendor/proxychains-ng/conf/proxychains.conf curl hello.ts.net - log "If you didn't see the Found message, then you may need to add the hello.ts.net machine into your tailnet or configure your auth key to have access to it." + log "Running `curl --socks5-hostname localhost:1055 raspberrypi` " + log 'Things are working if you see Found.' + curl --socks5-hostname localhost:1055 raspberrypi + log "If you didn't see the Found message, then you may need to add the tail3c015.ts.net machine into your tailnet or configure your auth key to have access to it." log "Test complete. I hope you had your fingers crossed!" fi diff --git a/buildpack.toml b/buildpack.toml index 316f326..9645408 100644 --- a/buildpack.toml +++ b/buildpack.toml @@ -1,11 +1,5 @@ [buildpack] -name = "heroku-tailscale-buildpack" +name = "heroku-buildpack-tailscale" - [publish.Ignore] - files = [ - ".github/", - "test/", - ".gitignore", - "Dockerfile", - "run_tests.sh", - ] +[publish.Ignore] +files = [".github/", "test/", ".gitignore", "Dockerfile", "run_tests.sh"] diff --git a/conf/proxychains.conf b/conf/proxychains.conf deleted file mode 100644 index a51aae0..0000000 --- a/conf/proxychains.conf +++ /dev/null @@ -1,159 +0,0 @@ -# proxychains.conf VER 4.x -# -# HTTP, SOCKS4a, SOCKS5 tunneling proxifier with DNS. - - -# The option below identifies how the ProxyList is treated. -# only one option should be uncommented at time, -# otherwise the last appearing option will be accepted -# -#dynamic_chain -# -# Dynamic - Each connection will be done via chained proxies -# all proxies chained in the order as they appear in the list -# at least one proxy must be online to play in chain -# (dead proxies are skipped) -# otherwise EINTR is returned to the app -# -strict_chain -# -# Strict - Each connection will be done via chained proxies -# all proxies chained in the order as they appear in the list -# all proxies must be online to play in chain -# otherwise EINTR is returned to the app -# -#round_robin_chain -# -# Round Robin - Each connection will be done via chained proxies -# of chain_len length -# all proxies chained in the order as they appear in the list -# at least one proxy must be online to play in chain -# (dead proxies are skipped). -# the start of the current proxy chain is the proxy after the last -# proxy in the previously invoked proxy chain. -# if the end of the proxy chain is reached while looking for proxies -# start at the beginning again. -# otherwise EINTR is returned to the app -# These semantics are not guaranteed in a multithreaded environment. -# -#random_chain -# -# Random - Each connection will be done via random proxy -# (or proxy chain, see chain_len) from the list. -# this option is good to test your IDS :) - -# Make sense only if random_chain or round_robin_chain -#chain_len = 2 - -# Quiet mode (no output from library) -#quiet_mode - -## Proxy DNS requests - no leak for DNS data -# (disable all of the 3 items below to not proxy your DNS requests) - -# method 1. this uses the proxychains4 style method to do remote dns: -# a thread is spawned that serves DNS requests and hands down an ip -# assigned from an internal list (via remote_dns_subnet). -# this is the easiest (setup-wise) and fastest method, however on -# systems with buggy libcs and very complex software like webbrowsers -# this might not work and/or cause crashes. -#proxy_dns - -# method 2. use the old proxyresolv script to proxy DNS requests -# in proxychains 3.1 style. requires `proxyresolv` in $PATH -# plus a dynamically linked `dig` binary. -# this is a lot slower than `proxy_dns`, doesn't support .onion URLs, -# but might be more compatible with complex software like webbrowsers. -#proxy_dns_old - -# method 3. use proxychains4-daemon process to serve remote DNS requests. -# this is similar to the threaded `proxy_dns` method, however it requires -# that proxychains4-daemon is already running on the specified address. -# on the plus side it doesn't do malloc/threads so it should be quite -# compatible with complex, async-unsafe software. -# note that if you don't start proxychains4-daemon before using this, -# the process will simply hang. -#proxy_dns_daemon 127.0.0.1:1053 - -# set the class A subnet number to use for the internal remote DNS mapping -# we use the reserved 224.x.x.x range by default, -# if the proxified app does a DNS request, we will return an IP from that range. -# on further accesses to this ip we will send the saved DNS name to the proxy. -# in case some control-freak app checks the returned ip, and denies to -# connect, you can use another subnet, e.g. 10.x.x.x or 127.x.x.x. -# of course you should make sure that the proxified app does not need -# *real* access to this subnet. -# i.e. dont use the same subnet then in the localnet section -#remote_dns_subnet 127 -#remote_dns_subnet 10 -remote_dns_subnet 224 - -# Some timeouts in milliseconds -tcp_read_time_out 15000 -tcp_connect_time_out 8000 - -### Examples for localnet exclusion -## localnet ranges will *not* use a proxy to connect. -## note that localnet works only when plain IP addresses are passed to the app, -## the hostname resolves via /etc/hosts, or proxy_dns is disabled or proxy_dns_old used. - -## Exclude connections to 192.168.1.0/24 with port 80 -# localnet 192.168.1.0:80/255.255.255.0 - -## Exclude connections to 192.168.100.0/24 -# localnet 192.168.100.0/255.255.255.0 - -## Exclude connections to ANYwhere with port 80 -# localnet 0.0.0.0:80/0.0.0.0 -# localnet [::]:80/0 - -## RFC6890 Loopback address range -## if you enable this, you have to make sure remote_dns_subnet is not 127 -## you'll need to enable it if you want to use an application that -## connects to localhost. -# localnet 127.0.0.0/255.0.0.0 -# localnet ::1/128 - -## RFC1918 Private Address Ranges -# localnet 10.0.0.0/255.0.0.0 -# localnet 172.16.0.0/255.240.0.0 -# localnet 192.168.0.0/255.255.0.0 - -### Examples for dnat -## Trying to proxy connections to destinations which are dnatted, -## will result in proxying connections to the new given destinations. -## Whenever I connect to 1.1.1.1 on port 1234 actually connect to 1.1.1.2 on port 443 -# dnat 1.1.1.1:1234 1.1.1.2:443 - -## Whenever I connect to 1.1.1.1 on port 443 actually connect to 1.1.1.2 on port 443 -## (no need to write :443 again) -# dnat 1.1.1.2:443 1.1.1.2 - -## No matter what port I connect to on 1.1.1.1 port actually connect to 1.1.1.2 on port 443 -# dnat 1.1.1.1 1.1.1.2:443 - -## Always, instead of connecting to 1.1.1.1, connect to 1.1.1.2 -# dnat 1.1.1.1 1.1.1.2 - -# ProxyList format -# type ip port [user pass] -# (values separated by 'tab' or 'blank') -# -# only numeric ipv4 addresses are valid -# -# -# Examples: -# -# socks5 192.168.67.78 1080 lamer secret -# http 192.168.89.3 8080 justu hidden -# socks4 192.168.1.49 1080 -# http 192.168.39.93 8080 -# -# -# proxy types: http, socks4, socks5, raw -# * raw: The traffic is simply forwarded to the proxy without modification. -# ( auth types supported: "basic"-http "user/pass"-socks ) -# - -[ProxyList] -socks5 127.0.0.1 1055 diff --git a/lib/environment.sh b/lib/environment.sh new file mode 100644 index 0000000..b5cbe02 --- /dev/null +++ b/lib/environment.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +export_env_dir() { + local env_dir=$1 + if [ -d "$env_dir" ]; then + local whitelist_regex=${2:-''} + local blacklist_regex=${3:-'^(PATH|GIT_DIR|CPATH|CPPATH|LD_PRELOAD|LIBRARY_PATH|LANG|BUILD_DIR)$'} + # shellcheck disable=SC2164 + pushd "$env_dir" >/dev/null + for e in *; do + [ -e "$e" ] || continue + echo "$e" | grep -E "$whitelist_regex" | grep -qvE "$blacklist_regex" && + export "$e=$(cat "$e")" + : + done + # shellcheck disable=SC2164 + popd >/dev/null + fi +} \ No newline at end of file diff --git a/test/fixtures/compile-sanity-1.stderr.txt b/test/fixtures/compile-sanity-1.stderr.txt index 6c5b5d9..12d6a03 100644 --- a/test/fixtures/compile-sanity-1.stderr.txt +++ b/test/fixtures/compile-sanity-1.stderr.txt @@ -1 +1 @@ -../bin/compile: line 29: $1: unbound variable +../bin/compile: line 25: $1: unbound variable diff --git a/test/fixtures/compile-sanity-2.stderr.txt b/test/fixtures/compile-sanity-2.stderr.txt index 8a9684a..e29cf5c 100644 --- a/test/fixtures/compile-sanity-2.stderr.txt +++ b/test/fixtures/compile-sanity-2.stderr.txt @@ -1 +1 @@ -../bin/compile: line 30: $2: unbound variable +../bin/compile: line 26: $2: unbound variable diff --git a/test/fixtures/compile-sanity-3.stderr.txt b/test/fixtures/compile-sanity-3.stderr.txt index be7b62a..6785790 100644 --- a/test/fixtures/compile-sanity-3.stderr.txt +++ b/test/fixtures/compile-sanity-3.stderr.txt @@ -1 +1 @@ -../bin/compile: line 31: $3: unbound variable +../bin/compile: line 27: $3: unbound variable diff --git a/test/fixtures/detect-sanity.stdout.txt b/test/fixtures/detect-sanity.stdout.txt index 0d52153..0e7ff02 100644 --- a/test/fixtures/detect-sanity.stdout.txt +++ b/test/fixtures/detect-sanity.stdout.txt @@ -1 +1 @@ -tailscale +Tailscale diff --git a/test/stack-test.sh b/test/stack-test.sh index 586ff0c..b0199c7 100755 --- a/test/stack-test.sh +++ b/test/stack-test.sh @@ -22,7 +22,7 @@ docker build \ -t "$OUTPUT_IMAGE" \ . -LOAD_ENV_VARS="source .profile.d/heroku-tailscale-buildpack.sh" +LOAD_ENV_VARS="source .profile.d/heroku-buildpack-tailscale.sh" TEST_COMMAND="$LOAD_ENV_VARS && heroku-tailscale-test.sh" docker run \