Node-RED SSL reverse proxy w/ Google Oauth

There is a risk (although minimal) - with something like this (particularly with you having written such easy to follow directions !) there is a set and forget mentality (plus probably a lot of not really understanding and followign by rote)

If a security issue is discovered in the Web terminating proxy, it COULD lead to a compromise of the underlying Docker host due to the elevated privilege levels that Docker uses.

Now does someone running this at home have anything to worry about from a State Based bad actor - not really - there are much bigger fish for them to fry - but if something like this is left just running (forever) - it becomes a larger and larger issue (like home based IP cameras, baby monitors and the like from 5 years ago.

But - we are going off track - great write up by you - and yes Colin/Bart definitely worth investing the time and effort into getting on top of container technology - regardless of the underlying engine you use for deployment today (just don't set it and forget it for 5 years !!)

Craig

Oh boy ...

I just run through a similar exercise with nginx as reverse proxy. It is really cool to see every single port locked to docker only and dealing with nodered and grafana via https without further mangling for each of these services in terms of ssl or so.

However, as a home user I yet did not look into letsencrypt. I set everything up with a self-signed certificate, since it is in my LAN, in a subnet that has no internet access, accessible only from selected devices from my HOME subnet, with looong password protection. The network side I manage with pfsense as well. Super easy and provides transparent control.

The struggle I have is that a) I yet have to find out, how to get chrome and opera on macos accepting self-signed certificates at all (it works with accepting on safari and firefox) AND b) how to passthrough favicon (apple-touch-icon.png to be precise) to IOS to allow nice looking home screen webclips.

At least for a) I was considering digging into letsencrypt as well. Although it feels like a bit of overkill for a home setup. But yes, once you have sorted things out with docker, it is almost set and forget.

b) seems up in the air, until I come accross a new idea :slight_smile:

@VinistoisR: This is really, really cool stuff. Thanks for putting all of this together. And thanks also to all the other well known fellows who transformed this announcement into a great source of knowlege regarding this topic.

3 Likes

The problem with self-signed certs is that each release of browsers seems to be locking things down.

The problem with Let's Encrypt (other than some complexities on initial setup that is made a lot easier by using the acme.sh script) is that you really need an IP name not just an address and you can only register against a publicly recognised (sub)domain. I have my router configured using "hairpin" DNS so that I can use the same URL whether internal or external (though nothing is actually externally accessible). I actually get certs for 2 domains from LE and I use wildcards so that I can use any sub-domain on those two domains. Everything updates automatically and you can use the acme.sh script to deploy certs as well.

1 Like

I will definitely look into letsencrypt again. And I will also play around with the docker stack provided by VinistoisR. Thanks guys.

@VinistoisR (or anyone else) this question isn't a node-red issue but hopefully you can help me overcome my lack of experience in the DNS system.

I currently have my domain ( mydomain.org.uk) with names.co.uk and they provide email redirection to myself and my wife's gmail accounts based on the specific email address used (me@mydomain.org.uk and she@mydomain.co.uk for example). In addition names.co.uk redirect some subdomains to a VPS I rent.

In order to move the domain to cloudflare as suggested I have opened an account with them and added my domain and it has magically come up with a set of DNS records.
It has A records for mydomain.org.uk, * and www pointing back to names.co.uk ip address, CNAME records for the subdomains pointing to my VPS, an MX record pointing to the names.co.uk mail server and various TXT and and SRV that I don't really know what they do.

Am I right in thinking that if I just leave those as they are and switch the name servers in the names.co.uk control panel to the cloudflare servers that my websites, email etc should just carry on as they do at the moment, with the mail redirection still being handled by names.co.uk?

I am reasonably confident that is right, but I don't want to kill my email or web servers so would be grateful if someone could confirm that, before I hit the big red button that says don't do this unless you know what you are doing :slight_smile:

Yes, that is correct. To be sure, just double check - as you may already have done - that the addresses are correct but I've always found them to be.

Some of the TXT entries are probably for mail security, DKIM, SPF, etc. You won't need to mess with those unless you want to increase the security of your email.

Great thanks. I had checked, and there were a couple missing so I have added those.
I will hit the button then.

Absolute worse case would be that some parts of the world wouldn't be able access one of your end points for a couple of hours. Email will cope with that as the sending server will retry for at least a week.

It is hard to predict timeouts on DNS changes but it should never be more than a couple of hours. Often it is pretty well instantaneous.

OK, done. If you never hear from me again you will know I have fallen into a virtual black hole in the internet space/time continuum.

4 Likes

LOL, but keep hanging in, we do not wanna lose you

Well I seem to have made it across the abyss and my domain is now served by Cloudflare, with no apparent disruption to service (so far at least).

@VinistoisR I think I am nearly there with your example. I have installed docker and Traefik (on Ubuntu 20.04) and built the compose file, putting in my details where appropriate, and it nearly works. However, when I run docker-compose traefik starts up ok but for node red I get
ERROR: for nodered network-scoped alias is supported only for containers in user defined networks
I have googled and found some information, but unfortunately not enough to know what the problem is. Can you point me in the right direction please?

The other issue I have is that I am not sure which tokens I need in

      - CF_DNS_API_TOKEN=your_cloudflare_api_token
      - CF_ZONE_API_TOKEN=your_cloudflare_zone_token

the other link you posted was helpful in understanding some areas, but it seems to be using a slightly different system, at least the variable names are different.

The zone token you need (good thing you asked) needs to be "all zone". I'm using the same token for both fields, but if you want, you can create two separate ones. Here is my config:

This API token will affect the below accounts and zones, along with their respective permissions

* All zones - Zone Settings:Read, Zone:Read, DNS:Edit

For the network, you need to create the traefik overlay network before running your stack deploy command. Then as long as you have external: true on the stack network declaration, the stack will use the network as-is. If you deploy a stack with a network declaration for a network that doesn't exist yet, it will create it prefixed with the stack name. So if you end up with a network like nodered_traefik, that's why.

Are you using portainer to deploy, or command line?

Oh also, since you have a new DNS server, keep in mind that some dns servers in the world may not have propagated the change yet. Search for "dns propagation check" and make sure your dns points to the correct IP. Also use https://mxtoolbox.com/dnscheck.aspx to check your other dns information and make sure it looks correct.

When you do the stack deploy, keep a tab open on cloudflare and look for the txt records to show up. They have a 5 minute ttl so they are easy to miss. Also tail the logs of the traefik container (set to debug) so you can see what is happening.

It does not matter about the DNS propogation times - if anyone is still pointing to his old DNS servers (Cached) they will still be served the same records, all it appears he has done is update his authoritative DNS servers at his country registrar. Regardless of who clients try to resolve against they will receive the same records - until he starts adding new ones to the CLoudflare setup.

Craig

Never hurts to check!

I had done that, hopefully correctly:
sudo docker network create -d overlay --attachable traefik-public

After a bit more googling I removed the bridge network in the nodered service network spec, and the error went away. In portainer docker_nodered_1 is now showing healthy, but still doesn't say it is running, though I hope that 'healthy' means running and also healthy.

I am using the command line to deploy, but I am a bit confused about how exactly I should be doing that. I have been using sudo docker -compose -f <file>.yml up -d but I am getting warnings
"Some services (nodered, traefik) use the 'deploy' key, which will be ignored. Compose does not support 'deploy' configuration - use docker stack deploy to deploy to a swarm"
and don't know whether I am therefore using the wrong command.
I seem to be getting into more of a mess with Traefik though, I am now getting, for example

sudo docker-compose -f ~/docker/docker-compose.yml up -d traefik
WARNING: Some services (nodered, traefik) use the 'deploy' key, which will be ignored. Compose does not support 'deploy' configuration - use `docker stack deploy` to deploy to a swarm.
WARNING: The Docker Engine you're using is running in swarm mode.

Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node.

To deploy your application across the swarm, use `docker stack deploy`.

Starting docker_traefik_1 ... 
Starting docker_traefik_1 ... error

ERROR: for docker_traefik_1  Cannot start service traefik: container d15eff915e19d123a1664a5bb023720a9bfeb8f46e1afe3817d369fe5f9e3730: endpoint join on GW Network failed: driver failed programming external connectivity on endpoint gateway_2d5f75b70b99 (939f5ba19c46eed5c4fd7f4ceaeb519a3b625406d1628cd9009605b0406b51c2): Bind for 0.0.0.0:443 failed: port is already allocated

ERROR: for traefik  Cannot start service traefik: container d15eff915e19d123a1664a5bb023720a9bfeb8f46e1afe3817d369fe5f9e3730: endpoint join on GW Network failed: driver failed programming external connectivity on endpoint gateway_2d5f75b70b99 (939f5ba19c46eed5c4fd7f4ceaeb519a3b625406d1628cd9009605b0406b51c2): Bind for 0.0.0.0:443 failed: port is already allocated
ERROR: Encountered errors while bringing up the project.

plus I can't seem to work out how to get rid of everything in order to deploy from scratch. If I run
sudo docker-compose -f ~/docker/docker-compose.yml down --rmi all
it looks as if it is removing everything, but if I then immediately run docker ps -a I see

 sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                      NAMES
fc41a8b7fafa        traefik:v2.2        "/entrypoint.sh --loā€¦"   17 minutes ago      Up 17 minutes       0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   traefik_traefik.2acu8otaoc2s4kjl1ovmlyyp0.wa91azzjp7jk0jows3hf645wi

A further question on Cloudflare, I have added a new cname for the subdomain I want to use here, vps02.mydomain.org.uk, and directed that to my IP. In the compose file I have - "traefik.http.routers.nodered.rule=Host(vps02.mydomain.org.uk`)". Is that right, and what do I use to access nodered? Perhaps I can't even do what I want on thinking about it.

Some further information, I rebooted and on initial look all appears as if it might be working. However, when I go to vps02.mydomain.org.uk I get an error saying the certificate is not valid for the domain, and is only valid for e859..verylongnumber.traefik.default. Does that mean I have got a certificate but it is not registered for the correct domain?

Another thing that is confusing me is that in Portainer I see


so to see the traefik logs I have to use
traefik_traefik.2acu8otaoc2s4kjl1ovmlyyp0.x62dyeyr4ti04xfldawaaht9e
which is a bit of a pain. The start of the log shows

2020-04-30T13:35:31.535533523Z time="2020-04-30T13:35:31Z" level=info msg="Configuration loaded from flags."
2020-04-30T13:35:31.535606443Z time="2020-04-30T13:35:31Z" level=info msg="Traefik version 2.2.1 built on 2020-04-29T18:02:09Z"
2020-04-30T13:35:31.537006003Z time="2020-04-30T13:35:31Z" level=debug msg="Static configuration loaded {\"global\":{\"checkNewVersion\":true,\"sendAnonymousUsage\":true},\"serversTransport\":{\"maxIdleConnsPerHost\":200},\"entryPoints\":{\"web\":{\"address\":\":80\",\"transport\":{\"lifeCycle\":{\"graceTimeOut\":10000000000},\"respondingTimeouts\":{\"idleTimeout\":180000000000}},\"forwardedHeaders\":{},\"http\":{}},\"websecure\":{\"address\":\":443\",\"transport\":{\"lifeCycle\":{\"graceTimeOut\":10000000000},\"respondingTimeouts\":{\"idleTimeout\":180000000000}},\"forwardedHeaders\":{},\"http\":{}}},\"providers\":{\"providersThrottleDuration\":2000000000,\"docker\":{\"watch\":true,\"endpoint\":\"unix:///var/run/docker.sock\",\"defaultRule\":\"Host(`{{ normalize .Name }}`)\",\"swarmMode\":true,\"network\":\"traefik-public\",\"swarmModeRefreshSeconds\":15000000000},\"file\":{\"directory\":\"/etc\",\"watch\":true}},\"api\":{\"dashboard\":true},\"metrics\":{},\"log\":{\"level\":\"DEBUG\",\"format\":\"common\"},\"accessLog\":{\"filePath\":\"/var/log/docker/traefik.log\",\"format\":\"common\",\"filters\":{},\"fields\":{\"defaultMode\":\"keep\",\"headers\":{\"defaultMode\":\"drop\"}},\"bufferingSize\":100},\"certificatesResolvers\":{\"letsencryptresolver\":{\"acme\":{\"email\":\"me@mydomain.org.uk\",\"caServer\":\"https://acme-staging-v02.api.letsencrypt.org/directory\",\"storage\":\"/letsencrypt/acme.json\",\"keyType\":\"RSA4096\",\"dnsChallenge\":{\"provider\":\"cloudflare\",\"delayBeforeCheck\":90000000000,\"resolvers\":[\"1.1.1.1:53\",\"1.0.0.1:53\"]}}}}}"
2020-04-30T13:35:31.537074234Z time="2020-04-30T13:35:31Z" level=info msg="Stats collection is enabled."
2020-04-30T13:35:31.537083040Z time="2020-04-30T13:35:31Z" level=info msg="Many thanks for contributing to Traefik's improvement by allowing us to receive anonymous information from your configuration."
2020-04-30T13:35:31.537090821Z time="2020-04-30T13:35:31Z" level=info msg="Help us improve Traefik by leaving this feature on :)"
2020-04-30T13:35:31.537097849Z time="2020-04-30T13:35:31Z" level=info msg="More details on: https://docs.traefik.io/contributing/data-collection/"
2020-04-30T13:35:31.638609161Z time="2020-04-30T13:35:31Z" level=debug msg="Start TCP Server" entryPointName=websecure
2020-04-30T13:35:31.638654796Z time="2020-04-30T13:35:31Z" level=info msg="Starting provider aggregator.ProviderAggregator {}"
2020-04-30T13:35:31.638671793Z time="2020-04-30T13:35:31Z" level=debug msg="Start TCP Server" entryPointName=web
2020-04-30T13:35:31.638760990Z time="2020-04-30T13:35:31Z" level=info msg="Starting provider *file.Provider {\"directory\":\"/etc\",\"watch\":true}"
2020-04-30T13:35:31.740196820Z time="2020-04-30T13:35:31Z" level=info msg="Starting provider *docker.Provider {\"watch\":true,\"endpoint\":\"unix:///var/run/docker.sock\",\"defaultRule\":\"Host(`{{ normalize .Name }}`)\",\"swarmMode\":true,\"network\":\"traefik-public\",\"swarmModeRefreshSeconds\":15000000000}"
2020-04-30T13:35:31.740256553Z time="2020-04-30T13:35:31Z" level=info msg="Starting provider *traefik.Provider {}"
2020-04-30T13:35:31.740268719Z time="2020-04-30T13:35:31Z" level=info msg="Starting provider *acme.Provider {\"email\":\"me@mydomain.org.uk\",\"caServer\":\"https://acme-staging-v02.api.letsencrypt.org/directory\",\"storage\":\"/letsencrypt/acme.json\",\"keyType\":\"RSA4096\",\"dnsChallenge\":{\"provider\":\"cloudflare\",\"delayBeforeCheck\":90000000000,\"resolvers\":[\"1.1.1.1:53\",\"1.0.0.1:53\"]},\"ResolverName\":\"letsencryptresolver\",\"store\":{},\"ChallengeStore\":{}}"
2020-04-30T13:35:31.740281092Z time="2020-04-30T13:35:31Z" level=info msg="Testing certificate renew..." providerName=letsencryptresolver.acme
2020-04-30T13:35:31.741417989Z time="2020-04-30T13:35:31Z" level=debug msg="Configuration received from provider file: {\"http\":{},\"tcp\":{},\"udp\":{},\"tls\":{}}" providerName=file
2020-04-30T13:35:31.741775968Z time="2020-04-30T13:35:31Z" level=debug msg="Configuration received from provider internal: {\"http\":{\"services\":{\"api\":{},\"dashboard\":{},\"noop\":{}}},\"tcp\":{},\"tls\":{}}" providerName=internal
2020-04-30T13:35:31.756531602Z time="2020-04-30T13:35:31Z" level=debug msg="Configuration received from provider letsencryptresolver.acme: {\"http\":{},\"tls\":{}}" providerName=letsencryptresolver.acme
2020-04-30T13:35:31.774234887Z time="2020-04-30T13:35:31Z" level=debug msg="No default certificate, generating one"
2020-04-30T13:35:31.839146632Z time="2020-04-30T13:35:31Z" level=debug msg="Provider connection established with docker 19.03.8 (API 1.40)" providerName=docker
2020-04-30T13:35:31.865788824Z time="2020-04-30T13:35:31Z" level=debug msg="Network not found, id: s79msp9gdl2xbppxdk0bfhudx" providerName=docker
2020-04-30T13:35:31.867280749Z time="2020-04-30T13:35:31Z" level=debug msg="Filtering disabled container" providerName=docker container=traefik-traefik-x62dyeyr4ti04xfldawaaht9e
2020-04-30T13:35:31.867417388Z time="2020-04-30T13:35:31Z" level=debug msg="Configuration received from provider docker: {\"http\":{},\"tcp\":{},\"udp\":{}}" providerName=docker
2020-04-30T13:35:32.007376409Z time="2020-04-30T13:35:32Z" level=debug msg="No default certificate, generating one"
2020-04-30T13:35:32.339703544Z time="2020-04-30T13:35:32Z" level=debug msg="No default certificate, generating one"
2020-04-30T13:35:33.034959401Z time="2020-04-30T13:35:33Z" level=debug msg="No default certificate, generating one"
2020-04-30T13:35:46.910432524Z time="2020-04-30T13:35:46Z" level=debug msg="Network not found, id: s79msp9gdl2xbppxdk0bfhudx" providerName=docker
2020-04-30T13:35:46.912187737Z time="2020-04-30T13:35:46Z" level=debug msg="Filtering disabled container" providerName=docker container=traefik-traefik-x62dyeyr4ti04xfldawaaht9e
2020-04-30T13:35:46.912266491Z time="2020-04-30T13:35:46Z" level=debug msg="Configuration received from provider docker: {\"http\":{},\"tcp\":{},\"udp\":{}}" providerName=docker
2020-04-30T13:35:46.912410351Z time="2020-04-30T13:35:46Z" level=info msg="Skipping same configuration" providerName=docker
2020-04-30T13:36:01.910137097Z time="2020-04-30T13:36:01Z" level=debug msg="Network not found, id: s79msp9gdl2xbppxdk0bfhudx" providerName=docker
2020-04-30T13:36:01.912000222Z time="2020-04-30T13:36:01Z" level=debug msg="Filtering disabled container" providerName=docker container=traefik-traefik-x62dyeyr4ti04xfldawaaht9e
2020-04-30T13:36:01.912058212Z time="2020-04-30T13:36:01Z" level=debug msg="Configuration received from provider docker: {\"http\":{},\"tcp\":{},\"udp\":{}}" providerName=docker
2020-04-30T13:36:01.912129686Z time="2020-04-30T13:36:01Z" level=info msg="Skipping same configuration" providerName=docker

Possibly the certificate problem is related to the No default certificate, generating one messages which rather suggests to me that I am not getting a certificate.
The last four messages are repeated every 15 seconds, but I don't know whether they are errors or not.

This is a swarm stack. You have to do a docker swarm init. And then you use

Docker stack deploy -c nodered.yml nodered

Delete the containers to start over. Also you're still using the staging server, so you'll expect to see a "not secure" message still, but when you click on it, will show a let's encrypt staging cert. If it's not working, the certificate will be called "traefik default cert".

Yes, I have just noticed you said to do that right at the start. That's wasted a couple of hours. Actually it hasn't, you learn a lot trying to understand what is happening.

Well a bit more progress, now at least I am getting an error indication in the logs:

2020-04-30T15:20:53.472060249Z time="2020-04-30T15:20:53Z" level=debug msg="Try to challenge certificate for domain [vps02.mydomain.org.uk] found in HostSNI rule" providerName=letsencryptresolver.acme routerName=nodered@docker rule="Host(`vps02.mydomain.org.uk`)"
2020-04-30T15:20:53.472111984Z time="2020-04-30T15:20:53Z" level=debug msg="Looking for provided certificate(s) to validate [\"vps02.mydomain.org.uk\"]..." rule="Host(`vps02.mydomain.org.uk`)" providerName=letsencryptresolver.acme routerName=nodered@docker
2020-04-30T15:20:53.472234984Z time="2020-04-30T15:20:53Z" level=debug msg="Domains [\"vps02.mydomain.org.uk\"] need ACME certificates generation for domains \"vps02.mydomain.org.uk\"." providerName=letsencryptresolver.acme routerName=nodered@docker rule="Host(`vps02.mydomain.org.uk`)"
2020-04-30T15:20:53.472252804Z time="2020-04-30T15:20:53Z" level=debug msg="Loading ACME certificates [vps02.mydomain.org.uk]..." providerName=letsencryptresolver.acme routerName=nodered@docker rule="Host(`vps02.mydomain.org.uk`)"
2020-04-30T15:20:53.472310603Z time="2020-04-30T15:20:53Z" level=debug msg="Building ACME client..." providerName=letsencryptresolver.acme
2020-04-30T15:20:53.472324104Z time="2020-04-30T15:20:53Z" level=debug msg="https://acme-staging-v02.api.letsencrypt.org/directory" providerName=letsencryptresolver.acme
2020-04-30T15:20:54.164042392Z time="2020-04-30T15:20:54Z" level=debug msg="Using DNS Challenge provider: cloudflare" providerName=letsencryptresolver.acme
2020-04-30T15:20:54.164224319Z time="2020-04-30T15:20:54Z" level=debug msg="legolog: [INFO] [vps02.mydomain.org.uk] acme: Obtaining bundled SAN certificate"
2020-04-30T15:20:54.737593103Z time="2020-04-30T15:20:54Z" level=debug msg="legolog: [INFO] [vps02.mydomain.org.uk] AuthURL: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/52740190"
2020-04-30T15:20:54.737649813Z time="2020-04-30T15:20:54Z" level=debug msg="legolog: [INFO] [vps02.mydomain.org.uk] acme: Could not find solver for: tls-alpn-01"
2020-04-30T15:20:54.737671861Z time="2020-04-30T15:20:54Z" level=debug msg="legolog: [INFO] [vps02.mydomain.org.uk] acme: Could not find solver for: http-01"
2020-04-30T15:20:54.737695522Z time="2020-04-30T15:20:54Z" level=debug msg="legolog: [INFO] [vps02.mydomain.org.uk] acme: use dns-01 solver"
2020-04-30T15:20:54.737717464Z time="2020-04-30T15:20:54Z" level=debug msg="legolog: [INFO] [vps02.mydomain.org.uk] acme: Preparing to solve DNS-01"
2020-04-30T15:20:55.184884453Z time="2020-04-30T15:20:55Z" level=debug msg="legolog: [INFO] [vps02.mydomain.org.uk] acme: Cleaning DNS-01 challenge"
2020-04-30T15:20:55.392065173Z time="2020-04-30T15:20:55Z" level=debug msg="legolog: [WARN] [vps02.mydomain.org.uk] acme: cleaning up failed: cloudflare: failed to find zone mydomain.org.uk.: ListZonesContext command failed: error from makeRequest: HTTP status 400: content \"{\\\"success\\\":false,\\\"errors\\\":[{\\\"code\\\":6003,\\\"message\\\":\\\"Invalid request headers\\\",\\\"error_chain\\\":[{\\\"code\\\":6111,\\\"message\\\":\\\"Invalid format for Authorization header\\\"}]}],\\\"messages\\\":[],\\\"result\\\":null}\" "
2020-04-30T15:20:55.575840102Z time="2020-04-30T15:20:55Z" level=debug msg="legolog: [INFO] Deactivating auth: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/52740190"
2020-04-30T15:20:55.760518817Z time="2020-04-30T15:20:55Z" level=error msg="Unable to obtain ACME certificate for domains \"vps02.mydomain.org.uk\": unable to generate a certificate for the domains [vps02.mydomain.org.uk]: error: one or more domains had a problem:\n[vps02.mydomain.org.uk] [vps02.mydomain.org.uk] acme: error presenting token: cloudflare: failed to find zone mydomain.org.uk.: ListZonesContext command failed: error from makeRequest: HTTP status 400: content \"{\\\"success\\\":false,\\\"errors\\\":[{\\\"code\\\":6003,\\\"message\\\":\\\"Invalid request headers\\\",\\\"error_chain\\\":[{\\\"code\\\":6111,\\\"message\\\":\\\"Invalid format for Authorization header\\\"}]}],\\\"messages\\\":[],\\\"result\\\":null}\"\n" rule="Host(`vps02.mydomain.org.uk`)" providerName=letsencryptresolver.acme routerName=nodered@docker

Does 'Invalid format for Authorization header' mean there is a problem with the token or something more significant?
You said to delete the containers but I can't work out how to do that. If I remove them in portainer they just keep re-appearing.