-
Notifications
You must be signed in to change notification settings - Fork 845
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow passing tunnel token via the file system. #645
Comments
You can see in:
that it is also possible to pass the token as an environment variable. Those should be manageable as secrets in docker (compose, k8s, etc...) easily. If you really want a file, then you can:
And then you have All in all, I think there are enough ways to do this, and I would skip yet another way. Free free to open back and discuss further. |
The purpose of docker secrets is to avoid putting secrets as environment variables. From my understanding of I admit that this is an edge case, but the goal is to be able to use remote managed tunnels via docker secrets. |
But that's my whole point: docker secrets can be injected into the container via both files as well as environment variables. The values still come from the secret storage. The way they are made available to the container is what differs. |
How do you inject secrets as environment variables? From the documentation I have seen, it is only possible as a file As an example, I have this compose file with a file called version: "3.9"
secrets:
cloudflare_token:
file: "token.secret"
services:
cloudflared:
image: cloudflare/cloudflared:2022.5.1
command: tunnel run
secrets:
- cloudflare_token
environment:
- TUNNEL_TOKEN=/run/secrets/cloudflare_token Running
If I replace with version: "3.9"
secrets:
cloudflare_token:
file: "token.secret"
services:
cloudflared:
image: cloudflare/cloudflared:2022.5.1
command: tunnel run --token /run/secrets/cloudflare_token
secrets:
- cloudflare_token I get the same output |
The problem is that you are setting the TUNNEL_TOKEN To the file path, not to the token itself. Maybe you want to use something like https://builtin.com/software-engineering-perspectives/docker-compose-environment-variables instead? |
The way that docker secrets work is that the secret info, in this case, the token, is passed to the container via a file.
Other images typically use an environment variable that ends in |
To reiterate, docker secrets allows us to have encrypted secrets at transit and at rest and makes it easier to keep tokens out of version control since it is not in the .env file. To the best of my (limited) knowledge, environment variables do not give us the same benefits of encryption at transit and rest. In my opinion, unless there is a more secure way to pass the token to a docker container, this should not be closed and should be worked on as a security enhancement. |
I want to reiterate on my comment in #645 (comment) above, where I said:
So there's a way to rely on a file, which is why I closed the issue, regardless of the discussion around the environment variables. |
Doesn't this require having a With a docker-compose of version: "3.9"
secrets:
tunnel_file:
file: "tunnel_info"
services:
cloudflared:
image: cloudflare/cloudflared:2022.5.1
command: tunnel token --cred-file /run/secrets/tunnel_file 8be772befd147a8df540aae0fa15c047
secrets:
- tunnel_file
volumes:
- ./cloudflared:/etc/cloudflared/:ro
With Right now to get a connector online you run |
This would be done once per tunnel only, as part of your setup that would generate/handle/manage the secret so that it would be available in the future for your container to use.
Let me make it extra clear:
Steps 1/2 can be skipped if you create the Tunnel via the CLI and manage it that way. No need for the |
Ah, this is the step that I was missing. I was attempting to do it all in the container 😅. Thanks for staying with me on this |
Thanks for the explanation, got it working this way. |
Following the conversation above and specially @nmldiegues last answer I understood that cert.pem would only be required to generate the tunnel.json file but that after that it's not needed anymore and only tunnel.json needs to be mounted into the Docker container. However, if I do so the container complains at startup about the missing cert.pem.
Apologies if this question might sound dumb - but why does it still ask for the cert.pem? Shouldn't the tunnel.json have all the credential information? After all, if I would not run the service in a stack but just as a single container with |
For anyone running into this later and a bit confused like I was, here is what you need to do (Replace <TUNNEL> with the name of your Tunnel as shown in the cloudflare dashboard)
|
I will post my experience to encourage others not to worry about the process. secrets:
tunneltoken:
external: true
networks:
cloud-overlay:
external: true
services:
cloudflared:
image: cloudflare/cloudflared
secrets:
- tunneltoken
command: tunnel --credentials-file /run/secrets/tunneltoken run my-cloudflare-tunnel
deploy:
replicas: 2
networks:
- cloud-overlay I thank you all for the discussion and solution. |
I'm still confused because this doesn't work
|
the Docker container still complains about lack of an origin certificate & will not run how do you get the origin certificate into the container? |
Did you generate the cert.perm file and the .JSON cred-file and pass the JSON to the container? |
@catharsis71 I had the same issue but I figured out that it was a permissions issue for the secret file. I was not able to figure out what uid the cloudflared user was running so I change my permissions to 404 (read for owner and others) on the tunneltoken secret file and it worked fine without the cert.pem. |
Adding another vote for being able to read the token directly from a file, rather than going through the steps to get the cert, JSON, UUID, etc - doing so kind of defeats the purpose of the one-shot remote setup process. For reference, it is a convention for Docker env vars to have a TUNNEL_TOKEN_FILE=/run/secret/cf_tunnel_token would basically translate to something like: TUNNEL_TOKEN=$(cat /run/secret/cf_tunnel_token) although of course this is just a convention and this type of translation isn't built into Docker - it needs explicit application support, hence this issue. [1] Source - very last note on the bottom of the page |
It outputs 1 in stdin. |
Hi, I came across this discussion while trying to pass the token as a secret in my docker-compose file. Should I install and use docker swarm, just for this? So far I went through the different steps to get the json file with the 1- Create a temporary folder in $DOCKERDIR and give it chmod 777, as to not get permissions issues when generating the json file 3- Generate and save the json cred-file 4- Not sure what to do from there install docker swarm to use it as a secret or load it from the json file with the I did not use docker swarm yet, would it change much to my single host orchestration to |
@ZJohnAsZ Not to derail this topic but this gist shows my approach with Docker Compose. Basically invoke cloudflared in a shell (via multi-stage busybox build) and read the secrets file into a TUNNEL_TOKEN env var prior to execution. |
@j0sh Thank you for the reply. I am fairly new to docker/containers, I will explore the multi-stage way. New things to learn. :) |
Thanks @j0sh for the workaround, it worked well for me. +1 to address this the right way with a |
+1 for TUNNEL_TOKEN_FILE |
Using Google Secret Manager with Google Kubernetes Engine has limitations - secrets can be only read from file. It will be very nice to read tunnel_token from the file. |
If anyone stumbes on this thread while researching it for NixOS, you can use the {
pkgs,
config,
...
}: {
age.secrets.cloudflared_env = {
file = ./secrets/cloudflared_env.age;
owner = "cloudflared";
group = "cloudflared";
};
# https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes
boot.kernel.sysctl."net.core.rmem_max" = 7500000;
boot.kernel.sysctl."net.core.wmem_max" = 7500000;
users.users.cloudflared = {
group = "cloudflared";
isSystemUser = true;
};
users.groups.cloudflared = {};
systemd.services.cloudflared = {
wantedBy = ["multi-user.target"];
requires = ["network-online.target"];
after = ["network-online.target"];
serviceConfig = {
Restart = "always";
EnvironmentFile = config.age.secrets.cloudflared_env.path;
User = "cloudflared";
Group = "cloudflared";
};
script = ''
${pkgs.unstable.cloudflared}/bin/cloudflared --no-autoupdate tunnel run
'';
};
} with TUNNEL_TOKEN=<your actual token> So this technically is not needed for this, even though it would still be a nice addition to be able to 'easily' inject it without utilizing the |
I'm uncertain why there is so much push-back to making this more ergonomic by following the "standards" established by other docker containers. Is there something I'm missing that makes adding this painful or insecure? The provided workarounds are serviceable, but all have drawbacks and are varying degrees of unfriendly to use. Please reconsider making this nicer by implementing |
WTF it is 2024 and there is still no support for |
This should really be reopened. Cloudflare tunnels are widely used and not having |
Describe the feature you'd like
I currently use named tunnels and run in docker containers. I would like to be able to use docker secrets with the containers. This is currently not possible because docker secrets are passed as a file and there is no way to read the file. It would be nice to be able to have
--secret-file
option, i.e.cloudflared tunnel run --token --secret-file
orcloudflared tunnel run --token </path/to/token/file>
.Describe alternatives you've considered
Typically, you use
cat
in containers to read the files, but the rootless container does not have the cat executable so unable to use secrets that wayAdditional context
Similar to #232.
I would be happy to work on this if it is something that is worth implementing.
The text was updated successfully, but these errors were encountered: