falcondev-oss / github-actions-cache-server

Self-hosted GitHub Actions cache server implementation. Compatible with official 'actions/cache' action
https://gha-cache-server.falcondev.io
MIT License
131 stars 10 forks source link

Binary patching alternative #26

Closed caquino closed 5 months ago

caquino commented 6 months ago

Hi, I'm evaluating some local caching options for self-hosted runners and ended up here, one requirement that worries me a little bit is the requirement to patch the runner binary to allow the environment variable to be set to what is required.

As far as I understand the ACTIONS_CACHE_URL return different values based in your geolocation, like for example https://acghubeus1.actions.githubusercontent.com/ would it be possible instead of patching to provide within the runners the either of the following solutions:

Option 1 hijack the domain *.actions.githubusercontent.com

possible issues: Is anything else other than cache using this domains? can it break something else

Options 2 abuse the proxy support on the runner to hijack the cache functionality

Option 3 remap system fuctions using LD_PRELOAD

I haven't tested any of the options as I don't have a lab available at the moment but I will try to put a POC in place when I get some spare time and report back.

Thanks!

EDIT

I can confirm the LD_PRELOAD approach works you can point to HTTP or https endpoints and it will respect the protocol:

As you can see here I pointed to a local HTTP server and it was able to identify the 404 error.

and I could also confirm in the logs:

127.0.0.1 - - [08/Apr/2024:18:16:00 +0000] "GET /_apis/artifactcache/cache?keys=Linux-my-cache&version=8a1a35c329bc005ec3aa86e16d05dde409e80ca147480a4f22f31c778450b077 HTTP/1.1" 404 162 "-" "actions/cache"

You can check the source code I used here: https://github.com/caquino/runner/tree/main/envinject

Obviously this code can be improved to allow configuration, or even better to allow the override of ANY environment by adding a prefix OVERRIDE_* which would make it a more generic tool.

I did the bare minimum to test it locally, sorry for the dumb code.

To start the self-hosted runner I used the following command: LD_PRELOAD=/path/to/envinject/envinject.so ./run.sh

I also tested overriding the environment variable to a local version of this repo running on docker which worked successfully.

LouisHaftmann commented 6 months ago

Thanks for opening this issue :heart:

Patching the binary is a bit of a hacky solution and I appreciate the time you took to try out other solutions.

I believe the proxy approach would be the easiest to set up, as it only requires some env vars and no files or additional binaries.

We'll definitely look into it!

caquino commented 6 months ago

I would say that you listed pretty much the pros for the proxy approach. If we try to list the cons we have:

Both other options have more granularity, but you also have downsides on option 1:

For option 3:

LouisHaftmann commented 6 months ago

We'll try out the proxy approach. Adding proxy functionality shouldn't introduce breaking changes so you could still use option 3 on your setup.

LouisHaftmann commented 5 months ago

Unfortunately the proxy approach doesn't work. We cannot catch the action runner's requests because it uses https.

joh-klein commented 4 months ago

I just came across this and found this drop-in replacement for actions/cache – did you see that? They expose export CIRRUS_HTTP_CACHE_HOST=cache.internal:8080 which would then work with your server.