Originally assigned to: @oschwartz10612 on GitHub.
Describe the Bug
I'm trying out Pangolin and want to get away from the hidden database-method of configuring things, I want everything with docker labels - enter blueprints.
Unfortunately when you do a configuration mistake and create duplicate names, all docker labels configured resources are deleted in the database, more specifically: subDomain is nulled and fullDomain is set to the base domain.
Environment
OS Type & Version: Debian & Ubuntu
Pangolin Version: 1.11.0
Gerbil Version: 1.2.1
Traefik Version: v3.5.3
Newt Version: 1.5.2
Restart newt on host1 & host2. There are no errors in either newt log and no errors in the Pangolin log
Everything is still working
Restart Pangolin on host0 - no errors in the log.
Observe that newt on host1&host2 are throwing errors:
ERROR: 2025/10/20 09:55:23 Failed to connect: failed to get token: failed to request new token: Post "https://cloud.gaida.biz/auth/resource/bdfd60bc-0193-409e-8a97-4bb0500b61ff?redirect=https%3A%2F%2Fsubdomain.example.com%2Fauth%2Fresource%2Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%3Fredirect%3Dhttps%253A%252F%252Fsubdomain.example.com%252Fauth%252Fresource%252Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%253Fredirect%253Dhttps%25253A%25252F%25252Fsubdomain.example.com%25252Fauth%25252Fresource%25252Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%25253Fredirect%25253Dhttps%2525253A%2525252F%2525252Fsubdomain.example.com%2525252Fauth%2525252Fresource%2525252Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%2525253Fredirect%2525253Dhttps%252525253A%252525252F%252525252Fsubdomain.example.com%252525252Fauth%252525252Fresource%252525252Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%252525253Fredirect%252525253Dhttps%25252525253A%25252525252F%25252525252Fsubdomain.example.com%25252525252Fauth%25252525252Fresource%25252525252Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%25252525253Fredirect%25252525253Dhttps%2525252525253A%2525252525252F%2525252525252Fsubdomain.example.com%2525252525252Fauth%2525252525252Fresource%2525252525252Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%2525252525253Fredirect%2525252525253Dhttps%252525252525253A%252525252525252F%252525252525252Fsubdomain.example.com%252525252525252Fauth%252525252525252Fresource%252525252525252Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%252525252525253Fredirect%252525252525253Dhttps%25252525252525253A%25252525252525252F%25252525252525252Fsubdomain.example.com%25252525252525252Fauth%25252525252525252Fresource%25252525252525252Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%25252525252525253Fredirect%25252525252525253Dhttps%2525252525252525253A%2525252525252525252F%2525252525252525252Fsubdomain.example.com%2525252525252525252Fapi%2525252525252525252Fv1%2525252525252525252Fauth%2525252525252525252Fnewt%2525252525252525252Fget-token": stopped after 10 redirects. Retrying in 3s...
Observe that synthing is now infinitely redirecting - I'll spare you the log, it looks similar to the newt log
The infinite redirect may be my specific use case as the base domain domain.example.org is the domain where Pangolin lives. Checking the database, I see that that several entries are nulled and I have to manually fix them in the database
(I anonymized the base domain in the above screenshot - so syncthing in this example has set the base domain of domain.example.org instead of the example of syncthing-host1.domain.example.org). Since there are now multiple entries in traefik with the same base domain, I assume that is why I get infinite redirects.
Given the above example from the screenshot, I need to set the subdomain for n8n, as well as the fullDomain (i.e. n8n.domain.example.org) in the database and the same goes for the other three nulled entries. Secondly the newt instances can't "fix themselves", since the newt endpoint as per documentation is https://domain.example.org and that right now is infinitely redirecting.
After fixing everything in the database and restarting Pangolin, everything is back in order. Of course I need to fix the non-unique names in host1 and host2 otherwise I can recreate the same problem when restarting.
Expected Behavior
A misconfiguration of newt / docker-labels should not result in a catastrophic failure. Documentation doesn't specify that the name needs to be unique (it makes sense, of course) - Pangolin should actually just add e.g. -1 suffix if the name already exists and not delete things.
Secondly when playing around with the docker labels, I figured out that the name within the key is also important, i.e. pangolin.proxy-resources.<name>.name: something. When having multiple pangolin.proxy-resources with the same <name> across multiple hosts, things also go awry. So the best practice seems to be (not documented) to have unique a <name> within the docker label key, as well as a unique name as the actual name. I guess you should always suffix your names with the host names or something like that and then again this could be something newt could be automatically doing.
As for newt not being able to "fix itself" due to the Pangolin endpoint being broken - can't i use another internal endpoint, so that newt <-> Pangolin always works? Right now I am using the public domain as the endpoint, but newt <-> Pangolin could also talk via VPN IP (e.g. Tailscale/Zerotier etc.), so the "safer" endpoint could be <VPN-IP>, couldn't it?
Originally created by @DennisGaida on GitHub (Oct 20, 2025).
Original GitHub issue: https://github.com/fosrl/pangolin/issues/1709
Originally assigned to: @oschwartz10612 on GitHub.
### Describe the Bug
I'm trying out Pangolin and want to get away from the hidden database-method of configuring things, I want everything with docker labels - enter blueprints.
Unfortunately when you do a configuration mistake and create duplicate names, **all** docker labels configured resources are deleted in the database, more specifically: `subDomain` is nulled and `fullDomain` is set to the base domain.
### Environment
OS Type & Version: Debian & Ubuntu
Pangolin Version: 1.11.0
Gerbil Version: 1.2.1
Traefik Version: v3.5.3
Newt Version: 1.5.2
### To Reproduce
1. Have host1 & host2
2. Configure host1 as follows:
```
labels:
pangolin.proxy-resources.syncthing.name: syncthing
pangolin.proxy-resources.syncthing.full-domain: syncthing-host1.domain.example.org
pangolin.proxy-resources.syncthing.protocol: http
pangolin.proxy-resources.syncthing.auth.sso-enabled: "true"
pangolin.proxy-resources.syncthing.targets[0].method: http
pangolin.proxy-resources.syncthing.targets[0].hostname: syncthing
pangolin.proxy-resources.syncthing.targets[0].port: 8384
```
3. Configure host2 as follows
```
labels:
pangolin.proxy-resources.syncthing.name: syncthing
pangolin.proxy-resources.syncthing.full-domain: syncthing-host2.domain.example.org
pangolin.proxy-resources.syncthing.protocol: http
pangolin.proxy-resources.syncthing.auth.sso-enabled: "true"
pangolin.proxy-resources.syncthing.targets[0].method: http
pangolin.proxy-resources.syncthing.targets[0].hostname: syncthing
pangolin.proxy-resources.syncthing.targets[0].port: 8384
```
3. Restart newt on host1 & host2. There are no errors in either newt log and no errors in the Pangolin log
4. Everything is still working
5. Restart Pangolin on host0 - no errors in the log.
6. Observe that newt on host1&host2 are throwing errors:
```
ERROR: 2025/10/20 09:55:23 Failed to connect: failed to get token: failed to request new token: Post "https://cloud.gaida.biz/auth/resource/bdfd60bc-0193-409e-8a97-4bb0500b61ff?redirect=https%3A%2F%2Fsubdomain.example.com%2Fauth%2Fresource%2Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%3Fredirect%3Dhttps%253A%252F%252Fsubdomain.example.com%252Fauth%252Fresource%252Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%253Fredirect%253Dhttps%25253A%25252F%25252Fsubdomain.example.com%25252Fauth%25252Fresource%25252Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%25253Fredirect%25253Dhttps%2525253A%2525252F%2525252Fsubdomain.example.com%2525252Fauth%2525252Fresource%2525252Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%2525253Fredirect%2525253Dhttps%252525253A%252525252F%252525252Fsubdomain.example.com%252525252Fauth%252525252Fresource%252525252Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%252525253Fredirect%252525253Dhttps%25252525253A%25252525252F%25252525252Fsubdomain.example.com%25252525252Fauth%25252525252Fresource%25252525252Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%25252525253Fredirect%25252525253Dhttps%2525252525253A%2525252525252F%2525252525252Fsubdomain.example.com%2525252525252Fauth%2525252525252Fresource%2525252525252Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%2525252525253Fredirect%2525252525253Dhttps%252525252525253A%252525252525252F%252525252525252Fsubdomain.example.com%252525252525252Fauth%252525252525252Fresource%252525252525252Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%252525252525253Fredirect%252525252525253Dhttps%25252525252525253A%25252525252525252F%25252525252525252Fsubdomain.example.com%25252525252525252Fauth%25252525252525252Fresource%25252525252525252Fbdfd60bc-0193-409e-8a97-4bb0500b61ff%25252525252525253Fredirect%25252525252525253Dhttps%2525252525252525253A%2525252525252525252F%2525252525252525252Fsubdomain.example.com%2525252525252525252Fapi%2525252525252525252Fv1%2525252525252525252Fauth%2525252525252525252Fnewt%2525252525252525252Fget-token": stopped after 10 redirects. Retrying in 3s...
```
8. Observe that synthing is now infinitely redirecting - I'll spare you the log, it looks similar to the newt log
The infinite redirect may be my specific use case as the base domain `domain.example.org` is the domain where Pangolin lives. Checking the database, I see that that several entries are nulled and I have to manually fix them in the database
<img width="999" height="214" alt="Image" src="https://github.com/user-attachments/assets/9bdd09d0-6943-4439-88f6-6b982f6908a9" />
(I anonymized the base domain in the above screenshot - so syncthing in this example has set the base domain of `domain.example.org` instead of the example of `syncthing-host1.domain.example.org`). Since there are now multiple entries in traefik with the same base domain, I assume that is why I get infinite redirects.
Given the above example from the screenshot, I need to set the subdomain for n8n, as well as the `fullDomain` (i.e. `n8n.domain.example.org`) in the database and the same goes for the other three nulled entries. Secondly the newt instances can't "fix themselves", since the newt endpoint as per documentation is `https://domain.example.org` and that right now is infinitely redirecting.
After fixing everything in the database and restarting Pangolin, everything is back in order. Of course I need to fix the non-unique names in host1 and host2 otherwise I can recreate the same problem when restarting.
### Expected Behavior
A misconfiguration of newt / docker-labels should not result in a catastrophic failure. Documentation doesn't specify that the name needs to be unique (it makes sense, of course) - Pangolin should actually just add e.g. `-1` suffix if the name already exists and not delete things.
Secondly when playing around with the docker labels, I figured out that the name within the key is also important, i.e. `pangolin.proxy-resources.<name>.name: something`. When having multiple `pangolin.proxy-resources` with the same `<name>` across multiple hosts, things also go awry. So the best practice seems to be (not documented) to have unique a `<name>` within the docker label key, as well as a unique name as the actual name. I guess you should always suffix your names with the host names or something like that and then again this could be something newt could be automatically doing.
As for newt not being able to "fix itself" due to the Pangolin endpoint being broken - can't i use another internal endpoint, so that newt <-> Pangolin always works? Right now I am using the public domain as the endpoint, but newt <-> Pangolin could also talk via VPN IP (e.g. Tailscale/Zerotier etc.), so the "safer" endpoint could be `<VPN-IP>`, couldn't it?
GiteaMirror
added the bug label 2026-04-30 04:46:13 -05:00
@github-actions[bot] commented on GitHub (Nov 4, 2025):
This issue has been automatically marked as stale due to 14 days of inactivity. It will be closed in 14 days if no further activity occurs.
<!-- gh-comment-id:3483186761 -->
@github-actions[bot] commented on GitHub (Nov 4, 2025):
This issue has been automatically marked as stale due to 14 days of inactivity. It will be closed in 14 days if no further activity occurs.
I would like a breaking change to be investigated or maybe I am doing something wrong.
<!-- gh-comment-id:3484676751 -->
@DennisGaida commented on GitHub (Nov 4, 2025):
I would like a breaking change to be investigated or maybe I am doing something wrong.
@oschwartz10612 commented on GitHub (Nov 9, 2025):
It seems like undefined behavior is taking place when you have duplicate blueprints around the subdomains so I will take a look into that but you will need to make a change to make this work: the "nice id" of the resource across resources needs to be unique and thats whats causing your issue.
The nice id is the ID of the resource in the table and on the lable here
Basically defining a new nice id here will create a new resource. So by defining two different newts they are fighting over this resource. If you want two different syncthing deployments you should call them with different nice ids.
<!-- gh-comment-id:3507188355 -->
@oschwartz10612 commented on GitHub (Nov 9, 2025):
It seems like undefined behavior is taking place when you have duplicate blueprints around the subdomains so I will take a look into that but you will need to make a change to make this work: the "nice id" of the resource across resources needs to be unique and thats whats causing your issue.
The nice id is the ID of the resource in the table and on the lable here
```
⌄
pangolin.proxy-resources.syncthing.targets[0].hostname: syncthing
```
Basically defining a new nice id here will create a new resource. So by defining two different newts they are fighting over this resource. If you want two different syncthing deployments you should call them with different nice ids.
I am aware as also stated in the OP, though such a user error (using duplicate ids) shouldn’t result in failure. Either check whether the ID already exists and err on the newt side or generate a completely new random ID or just add a suffix such as -1 if it already exists.
<!-- gh-comment-id:3508126338 -->
@DennisGaida commented on GitHub (Nov 9, 2025):
I am aware as also stated in the OP, though such a user error (using duplicate ids) shouldn’t result in failure. Either check whether the ID already exists and err on the newt side or generate a completely new random ID or just add a suffix such as -1 if it already exists.
Adding a Resource through the Blueprints interface (and also using labels in Docker Compose):
# Blueprintproxy-resources:nice-id-transmission:name:Transmission-Blueprint# subdomain: # this would be a missing equivalentfull-domain:transmission-blueprint.pangolin.openstudiolandscapes.cloud-ip.ccprotocol:httpauth:sso-enabled:truetargets:- site:serene-ords-kangaroo-rathostname:transmissionmethod:httpport:9091
The subdomain field seems missing when using Blueprints/Labels.
Both Resource resolve just fine, however, after adding the second Resource, Pangolin will not survive a system reboot.
traefik: 2025-11-13T17:46:32Z ERR Provider error, retrying in 757.480238ms error="cannot fetch configuration data: do fetch request: Get \"http://pangolin:3001/api/v1/traefik-config\": dial tcp 172.18.0.3:3001: connect: connection refused" providerName=http
traefik: 2025-11-13T17:46:33Z ERR Provider error, retrying in 915.605008ms error="cannot fetch configuration data: do fetch request: Get \"http://pangolin:3001/api/v1/traefik-config\": dial tcp 172.18.0.3:3001: connect: connection refused" providerName=http
traefik: 2025-11-13T17:46:34Z ERR Provider error, retrying in 1.229068454s error="cannot fetch configuration data: do fetch request: Get \"http://pangolin:3001/api/v1/traefik-config\": dial tcp 172.18.0.3:3001: connect: connection refused" providerName=http
traefik: 2025-11-13T17:46:35Z ERR Provider error, retrying in 2.365606955s error="cannot fetch configuration data: do fetch request: Get \"http://pangolin:3001/api/v1/traefik-config\": dial tcp 172.18.0.3:3001: connect: connection refused" providerName=http
As you can see here, I'm using DNS Challenge with a single certificate for pangolin.openstudiolandscapes.cloud-ip.cc and *.pangolin.openstudiolandscapes.cloud-ip.cc as opposed the default HTTP Challenge.
My traefik_config.yml:
# -- Configure your CertificateResolver here...certificatesResolvers:# # for HTTP Challenge (this was the shipped default)# letsencrypt:# acme:# httpChallenge:# entryPoint: web# email: email@example.com # REPLACE WITH YOUR EMAIL# storage: "/letsencrypt/acme.json"# caServer: "https://acme-v02.api.letsencrypt.org/directory"cloudns_staging:acme:email:<my@email.com> # <-- Change this to your emailstorage:/letsencrypt/acme.cloudns_staging.jsoncaServer:"https://acme-staging-v02.api.letsencrypt.org/directory"dnsChallenge:provider:cloudns # <-- (Optional) Change this to your DNS providerresolvers:- "8.8.4.4:53"- "8.8.8.8:53"cloudns_production:acme:email:<my@email.com> # <-- Change this to your emailstorage:/letsencrypt/acme.cloudns_production.jsoncaServer:"https://acme-v02.api.letsencrypt.org/directory"dnsChallenge:provider:cloudns # <-- (Optional) Change this to your DNS providerresolvers:- "8.8.4.4:53"- "8.8.8.8:53"entryPoints:web:address:":80"websecure:address:":443"transport:respondingTimeouts:readTimeout:"30m"http:tls:certResolver:"cloudns_production"
And my dynamic_config.yml
http:middlewares:redirect-to-https:redirectScheme:scheme:httpsrouters:# HTTP to HTTPS redirect routermain-app-router-redirect:rule:"Host(`pangolin.openstudiolandscapes.cloud-ip.cc`)"# REPLACE WITH YOUR DOMAINservice:next-serviceentryPoints:- webmiddlewares:- redirect-to-https# Next.js router (handles everything except API and WebSocket paths)next-router:rule:"Host(`pangolin.openstudiolandscapes.cloud-ip.cc`) && !PathPrefix(`/api/v1`)"# REPLACE WITH YOUR DOMAINservice:next-serviceentryPoints:- websecuretls:# certResolver: letsencryptcertResolver:cloudns_productiondomains:- main:"pangolin.openstudiolandscapes.cloud-ip.cc"sans:- "*.pangolin.openstudiolandscapes.cloud-ip.cc"# API router (handles /api/v1 paths)api-router:rule:"Host(`pangolin.openstudiolandscapes.cloud-ip.cc`) && PathPrefix(`/api/v1`)"# REPLACE WITH YOUR DOMAINservice:api-serviceentryPoints:- websecuretls:certResolver:cloudns_production# WebSocket routerws-router:rule:"Host(`pangolin.openstudiolandscapes.cloud-ip.cc`)"# REPLACE WITH YOUR DOMAINservice:api-serviceentryPoints:- websecuretls:certResolver:cloudns_productionservices:next-service:loadBalancer:servers:- url:"http://pangolin:3002"# Next.js serverapi-service:loadBalancer:servers:- url:"http://pangolin:3000"# API/WebSocket server
<!-- gh-comment-id:3529004161 -->
@michimussato commented on GitHub (Nov 13, 2025):
Stumbled across this issue as well today.
Creating a Resource through the web UI leads to the following entry in `db.sqlite:/db/main/tables/resources`:
```
1,e188c5e6-a587-421c-a28f-9f9f75ec32c7,openstudiolandscapes,medical-woodland-vole,Transmission-UI,transmission-ui,transmission-ui.pangolin.openstudiolandscapes.cloud-ip.cc,domain1,1,0,1,1,tcp,,0,0,1,0,,,1,,,0,1
```
which will work and resolve just fine.
Adding a Resource through the Blueprints interface (and also using `labels` in Docker Compose):
```yaml
# Blueprint
proxy-resources:
nice-id-transmission:
name: Transmission-Blueprint
# subdomain: # this would be a missing equivalent
full-domain: transmission-blueprint.pangolin.openstudiolandscapes.cloud-ip.cc
protocol: http
auth:
sso-enabled: true
targets:
- site: serene-ords-kangaroo-rat
hostname: transmission
method: http
port: 9091
```
```
2,956c72c2-2513-49e7-a69e-9417b89bfab8,openstudiolandscapes,nice-id-transmission,Transmission-Blueprint,,transmission-blueprint.pangolin.openstudiolandscapes.cloud-ip.cc,domain1,1,0,1,1,tcp,,0,0,1,0,,,1,,,0,1
```
The `subdomain` field seems missing when using Blueprints/Labels.
Both Resource resolve just fine, however, after adding the second Resource, Pangolin will not survive a system reboot.
Trying to open [https://pangolin.openstudiolandscapes.cloud-ip.cc]() - which worked fine with just the manually entered Resource - now leads to the following redirect URL:
[https://pangolin.openstudiolandscapes.cloud-ip.cc/auth/resource/956c72c2-2513-49e7-a69e-9417b89bfab8?redirect=https%3A%2F%2Fpangolin.openstudiolandscapes.cloud-ip.cc%2Fauth%2Fresource%2F956c72c2-2513-49e7-a69e-9417b89bfab8%3Fredirect%3Dhttps%253A%252F%252Fpangolin.openstudiolandscapes.cloud-ip.cc%252Fauth%252Fresource%252F956c72c2-2513-49e7-a69e-9417b89bfab8%253Fredirect%253Dhttps%25253A%25252F%25252Fpangolin.openstudiolandscapes.cloud-ip.cc%25252Fauth%25252Fresource%25252F956c72c2-2513-49e7-a69e-9417b89bfab8%25253Fredirect%25253Dhttps%2525253A%2525252F%2525252Fpangolin.openstudiolandscapes.cloud-ip.cc%2525252Fauth%2525252Fresource%2525252F956c72c2-2513-49e7-a69e-9417b89bfab8%2525253Fredirect%2525253Dhttps%252525253A%252525252F%252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%252525252Fauth%252525252Fresource%252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%252525253Fredirect%252525253Dhttps%25252525253A%25252525252F%25252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%25252525252Fauth%25252525252Fresource%25252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%25252525253Fredirect%25252525253Dhttps%2525252525253A%2525252525252F%2525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%2525252525252Fauth%2525252525252Fresource%2525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%2525252525253Fredirect%2525252525253Dhttps%252525252525253A%252525252525252F%252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%252525252525252Fauth%252525252525252Fresource%252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%252525252525253Fredirect%252525252525253Dhttps%25252525252525253A%25252525252525252F%25252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%25252525252525252Fauth%25252525252525252Fresource%25252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%25252525252525253Fredirect%25252525252525253Dhttps%2525252525252525253A%2525252525252525252F%2525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%2525252525252525252Fauth%2525252525252525252Fresource%2525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%2525252525252525253Fredirect%2525252525252525253Dhttps%252525252525252525253A%252525252525252525252F%252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%252525252525252525252Fauth%252525252525252525252Fresource%252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%252525252525252525253Fredirect%252525252525252525253Dhttps%25252525252525252525253A%25252525252525252525252F%25252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%25252525252525252525252Fauth%25252525252525252525252Fresource%25252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%25252525252525252525253Fredirect%25252525252525252525253Dhttps%2525252525252525252525253A%2525252525252525252525252F%2525252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%2525252525252525252525252Fauth%2525252525252525252525252Fresource%2525252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%2525252525252525252525253Fredirect%2525252525252525252525253Dhttps%252525252525252525252525253A%252525252525252525252525252F%252525252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%252525252525252525252525252Fauth%252525252525252525252525252Fresource%252525252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%252525252525252525252525253Fredirect%252525252525252525252525253Dhttps%25252525252525252525252525253A%25252525252525252525252525252F%25252525252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%25252525252525252525252525252Fauth%25252525252525252525252525252Fresource%25252525252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%25252525252525252525252525253Fredirect%25252525252525252525252525253Dhttps%2525252525252525252525252525253A%2525252525252525252525252525252F%2525252525252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%2525252525252525252525252525252Fauth%2525252525252525252525252525252Fresource%2525252525252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%2525252525252525252525252525253Fredirect%2525252525252525252525252525253Dhttps%252525252525252525252525252525253A%252525252525252525252525252525252F%252525252525252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%252525252525252525252525252525252Fauth%252525252525252525252525252525252Fresource%252525252525252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%252525252525252525252525252525253Fredirect%252525252525252525252525252525253Dhttps%25252525252525252525252525252525253A%25252525252525252525252525252525252F%25252525252525252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%25252525252525252525252525252525252Fauth%25252525252525252525252525252525252Fresource%25252525252525252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%25252525252525252525252525252525253Fredirect%25252525252525252525252525252525253Dhttps%2525252525252525252525252525252525253A%2525252525252525252525252525252525252F%2525252525252525252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%2525252525252525252525252525252525252Fauth%2525252525252525252525252525252525252Fresource%2525252525252525252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%2525252525252525252525252525252525253Fredirect%2525252525252525252525252525252525253Dhttps%252525252525252525252525252525252525253A%252525252525252525252525252525252525252F%252525252525252525252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%252525252525252525252525252525252525252Fopenstudiolandscapes%252525252525252525252525252525252525252Fsettings%252525252525252525252525252525252525252Fresources]()
<img width="834" height="310" alt="Image" src="https://github.com/user-attachments/assets/78e5fda0-0369-43f8-8336-eed7ed980467" />
A snippet from the `traefik` logs (maybe it helps):
```
traefik: 2025-11-13T17:46:32Z ERR Provider error, retrying in 757.480238ms error="cannot fetch configuration data: do fetch request: Get \"http://pangolin:3001/api/v1/traefik-config\": dial tcp 172.18.0.3:3001: connect: connection refused" providerName=http
traefik: 2025-11-13T17:46:33Z ERR Provider error, retrying in 915.605008ms error="cannot fetch configuration data: do fetch request: Get \"http://pangolin:3001/api/v1/traefik-config\": dial tcp 172.18.0.3:3001: connect: connection refused" providerName=http
traefik: 2025-11-13T17:46:34Z ERR Provider error, retrying in 1.229068454s error="cannot fetch configuration data: do fetch request: Get \"http://pangolin:3001/api/v1/traefik-config\": dial tcp 172.18.0.3:3001: connect: connection refused" providerName=http
traefik: 2025-11-13T17:46:35Z ERR Provider error, retrying in 2.365606955s error="cannot fetch configuration data: do fetch request: Get \"http://pangolin:3001/api/v1/traefik-config\": dial tcp 172.18.0.3:3001: connect: connection refused" providerName=http
```
---
As you can see here, I'm using DNS Challenge with a single certificate for `pangolin.openstudiolandscapes.cloud-ip.cc` and `*.pangolin.openstudiolandscapes.cloud-ip.cc` as opposed the default HTTP Challenge.
My `traefik_config.yml`:
```yaml
# -- Configure your CertificateResolver here...
certificatesResolvers:
# # for HTTP Challenge (this was the shipped default)
# letsencrypt:
# acme:
# httpChallenge:
# entryPoint: web
# email: email@example.com # REPLACE WITH YOUR EMAIL
# storage: "/letsencrypt/acme.json"
# caServer: "https://acme-v02.api.letsencrypt.org/directory"
cloudns_staging:
acme:
email: <my@email.com> # <-- Change this to your email
storage: /letsencrypt/acme.cloudns_staging.json
caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
dnsChallenge:
provider: cloudns # <-- (Optional) Change this to your DNS provider
resolvers:
- "8.8.4.4:53"
- "8.8.8.8:53"
cloudns_production:
acme:
email: <my@email.com> # <-- Change this to your email
storage: /letsencrypt/acme.cloudns_production.json
caServer: "https://acme-v02.api.letsencrypt.org/directory"
dnsChallenge:
provider: cloudns # <-- (Optional) Change this to your DNS provider
resolvers:
- "8.8.4.4:53"
- "8.8.8.8:53"
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
transport:
respondingTimeouts:
readTimeout: "30m"
http:
tls:
certResolver: "cloudns_production"
```
And my `dynamic_config.yml`
```yaml
http:
middlewares:
redirect-to-https:
redirectScheme:
scheme: https
routers:
# HTTP to HTTPS redirect router
main-app-router-redirect:
rule: "Host(`pangolin.openstudiolandscapes.cloud-ip.cc`)" # REPLACE WITH YOUR DOMAIN
service: next-service
entryPoints:
- web
middlewares:
- redirect-to-https
# Next.js router (handles everything except API and WebSocket paths)
next-router:
rule: "Host(`pangolin.openstudiolandscapes.cloud-ip.cc`) && !PathPrefix(`/api/v1`)" # REPLACE WITH YOUR DOMAIN
service: next-service
entryPoints:
- websecure
tls:
# certResolver: letsencrypt
certResolver: cloudns_production
domains:
- main: "pangolin.openstudiolandscapes.cloud-ip.cc"
sans:
- "*.pangolin.openstudiolandscapes.cloud-ip.cc"
# API router (handles /api/v1 paths)
api-router:
rule: "Host(`pangolin.openstudiolandscapes.cloud-ip.cc`) && PathPrefix(`/api/v1`)" # REPLACE WITH YOUR DOMAIN
service: api-service
entryPoints:
- websecure
tls:
certResolver: cloudns_production
# WebSocket router
ws-router:
rule: "Host(`pangolin.openstudiolandscapes.cloud-ip.cc`)" # REPLACE WITH YOUR DOMAIN
service: api-service
entryPoints:
- websecure
tls:
certResolver: cloudns_production
services:
next-service:
loadBalancer:
servers:
- url: "http://pangolin:3002" # Next.js server
api-service:
loadBalancer:
servers:
- url: "http://pangolin:3000" # API/WebSocket server
```
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @DennisGaida on GitHub (Oct 20, 2025).
Original GitHub issue: https://github.com/fosrl/pangolin/issues/1709
Originally assigned to: @oschwartz10612 on GitHub.
Describe the Bug
I'm trying out Pangolin and want to get away from the hidden database-method of configuring things, I want everything with docker labels - enter blueprints.
Unfortunately when you do a configuration mistake and create duplicate names, all docker labels configured resources are deleted in the database, more specifically:
subDomainis nulled andfullDomainis set to the base domain.Environment
OS Type & Version: Debian & Ubuntu
Pangolin Version: 1.11.0
Gerbil Version: 1.2.1
Traefik Version: v3.5.3
Newt Version: 1.5.2
To Reproduce
The infinite redirect may be my specific use case as the base domain
domain.example.orgis the domain where Pangolin lives. Checking the database, I see that that several entries are nulled and I have to manually fix them in the database(I anonymized the base domain in the above screenshot - so syncthing in this example has set the base domain of
domain.example.orginstead of the example ofsyncthing-host1.domain.example.org). Since there are now multiple entries in traefik with the same base domain, I assume that is why I get infinite redirects.Given the above example from the screenshot, I need to set the subdomain for n8n, as well as the
fullDomain(i.e.n8n.domain.example.org) in the database and the same goes for the other three nulled entries. Secondly the newt instances can't "fix themselves", since the newt endpoint as per documentation ishttps://domain.example.organd that right now is infinitely redirecting.After fixing everything in the database and restarting Pangolin, everything is back in order. Of course I need to fix the non-unique names in host1 and host2 otherwise I can recreate the same problem when restarting.
Expected Behavior
A misconfiguration of newt / docker-labels should not result in a catastrophic failure. Documentation doesn't specify that the name needs to be unique (it makes sense, of course) - Pangolin should actually just add e.g.
-1suffix if the name already exists and not delete things.Secondly when playing around with the docker labels, I figured out that the name within the key is also important, i.e.
pangolin.proxy-resources.<name>.name: something. When having multiplepangolin.proxy-resourceswith the same<name>across multiple hosts, things also go awry. So the best practice seems to be (not documented) to have unique a<name>within the docker label key, as well as a unique name as the actual name. I guess you should always suffix your names with the host names or something like that and then again this could be something newt could be automatically doing.As for newt not being able to "fix itself" due to the Pangolin endpoint being broken - can't i use another internal endpoint, so that newt <-> Pangolin always works? Right now I am using the public domain as the endpoint, but newt <-> Pangolin could also talk via VPN IP (e.g. Tailscale/Zerotier etc.), so the "safer" endpoint could be
<VPN-IP>, couldn't it?@github-actions[bot] commented on GitHub (Nov 4, 2025):
This issue has been automatically marked as stale due to 14 days of inactivity. It will be closed in 14 days if no further activity occurs.
@DennisGaida commented on GitHub (Nov 4, 2025):
I would like a breaking change to be investigated or maybe I am doing something wrong.
@oschwartz10612 commented on GitHub (Nov 4, 2025):
Thanks for the bump I will take a look asap
@oschwartz10612 commented on GitHub (Nov 9, 2025):
It seems like undefined behavior is taking place when you have duplicate blueprints around the subdomains so I will take a look into that but you will need to make a change to make this work: the "nice id" of the resource across resources needs to be unique and thats whats causing your issue.
The nice id is the ID of the resource in the table and on the lable here
Basically defining a new nice id here will create a new resource. So by defining two different newts they are fighting over this resource. If you want two different syncthing deployments you should call them with different nice ids.
@DennisGaida commented on GitHub (Nov 9, 2025):
I am aware as also stated in the OP, though such a user error (using duplicate ids) shouldn’t result in failure. Either check whether the ID already exists and err on the newt side or generate a completely new random ID or just add a suffix such as -1 if it already exists.
@michimussato commented on GitHub (Nov 13, 2025):
Stumbled across this issue as well today.
Creating a Resource through the web UI leads to the following entry in
db.sqlite:/db/main/tables/resources:which will work and resolve just fine.
Adding a Resource through the Blueprints interface (and also using
labelsin Docker Compose):The
subdomainfield seems missing when using Blueprints/Labels.Both Resource resolve just fine, however, after adding the second Resource, Pangolin will not survive a system reboot.
Trying to open https://pangolin.openstudiolandscapes.cloud-ip.cc - which worked fine with just the manually entered Resource - now leads to the following redirect URL:
https://pangolin.openstudiolandscapes.cloud-ip.cc/auth/resource/956c72c2-2513-49e7-a69e-9417b89bfab8?redirect=https%3A%2F%2Fpangolin.openstudiolandscapes.cloud-ip.cc%2Fauth%2Fresource%2F956c72c2-2513-49e7-a69e-9417b89bfab8%3Fredirect%3Dhttps%253A%252F%252Fpangolin.openstudiolandscapes.cloud-ip.cc%252Fauth%252Fresource%252F956c72c2-2513-49e7-a69e-9417b89bfab8%253Fredirect%253Dhttps%25253A%25252F%25252Fpangolin.openstudiolandscapes.cloud-ip.cc%25252Fauth%25252Fresource%25252F956c72c2-2513-49e7-a69e-9417b89bfab8%25253Fredirect%25253Dhttps%2525253A%2525252F%2525252Fpangolin.openstudiolandscapes.cloud-ip.cc%2525252Fauth%2525252Fresource%2525252F956c72c2-2513-49e7-a69e-9417b89bfab8%2525253Fredirect%2525253Dhttps%252525253A%252525252F%252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%252525252Fauth%252525252Fresource%252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%252525253Fredirect%252525253Dhttps%25252525253A%25252525252F%25252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%25252525252Fauth%25252525252Fresource%25252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%25252525253Fredirect%25252525253Dhttps%2525252525253A%2525252525252F%2525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%2525252525252Fauth%2525252525252Fresource%2525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%2525252525253Fredirect%2525252525253Dhttps%252525252525253A%252525252525252F%252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%252525252525252Fauth%252525252525252Fresource%252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%252525252525253Fredirect%252525252525253Dhttps%25252525252525253A%25252525252525252F%25252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%25252525252525252Fauth%25252525252525252Fresource%25252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%25252525252525253Fredirect%25252525252525253Dhttps%2525252525252525253A%2525252525252525252F%2525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%2525252525252525252Fauth%2525252525252525252Fresource%2525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%2525252525252525253Fredirect%2525252525252525253Dhttps%252525252525252525253A%252525252525252525252F%252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%252525252525252525252Fauth%252525252525252525252Fresource%252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%252525252525252525253Fredirect%252525252525252525253Dhttps%25252525252525252525253A%25252525252525252525252F%25252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%25252525252525252525252Fauth%25252525252525252525252Fresource%25252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%25252525252525252525253Fredirect%25252525252525252525253Dhttps%2525252525252525252525253A%2525252525252525252525252F%2525252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%2525252525252525252525252Fauth%2525252525252525252525252Fresource%2525252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%2525252525252525252525253Fredirect%2525252525252525252525253Dhttps%252525252525252525252525253A%252525252525252525252525252F%252525252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%252525252525252525252525252Fauth%252525252525252525252525252Fresource%252525252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%252525252525252525252525253Fredirect%252525252525252525252525253Dhttps%25252525252525252525252525253A%25252525252525252525252525252F%25252525252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%25252525252525252525252525252Fauth%25252525252525252525252525252Fresource%25252525252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%25252525252525252525252525253Fredirect%25252525252525252525252525253Dhttps%2525252525252525252525252525253A%2525252525252525252525252525252F%2525252525252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%2525252525252525252525252525252Fauth%2525252525252525252525252525252Fresource%2525252525252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%2525252525252525252525252525253Fredirect%2525252525252525252525252525253Dhttps%252525252525252525252525252525253A%252525252525252525252525252525252F%252525252525252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%252525252525252525252525252525252Fauth%252525252525252525252525252525252Fresource%252525252525252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%252525252525252525252525252525253Fredirect%252525252525252525252525252525253Dhttps%25252525252525252525252525252525253A%25252525252525252525252525252525252F%25252525252525252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%25252525252525252525252525252525252Fauth%25252525252525252525252525252525252Fresource%25252525252525252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%25252525252525252525252525252525253Fredirect%25252525252525252525252525252525253Dhttps%2525252525252525252525252525252525253A%2525252525252525252525252525252525252F%2525252525252525252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%2525252525252525252525252525252525252Fauth%2525252525252525252525252525252525252Fresource%2525252525252525252525252525252525252F956c72c2-2513-49e7-a69e-9417b89bfab8%2525252525252525252525252525252525253Fredirect%2525252525252525252525252525252525253Dhttps%252525252525252525252525252525252525253A%252525252525252525252525252525252525252F%252525252525252525252525252525252525252Fpangolin.openstudiolandscapes.cloud-ip.cc%252525252525252525252525252525252525252Fopenstudiolandscapes%252525252525252525252525252525252525252Fsettings%252525252525252525252525252525252525252Fresources
A snippet from the
traefiklogs (maybe it helps):As you can see here, I'm using DNS Challenge with a single certificate for
pangolin.openstudiolandscapes.cloud-ip.ccand*.pangolin.openstudiolandscapes.cloud-ip.ccas opposed the default HTTP Challenge.My
traefik_config.yml:And my
dynamic_config.yml@oschwartz10612 commented on GitHub (Dec 7, 2025):
I am hoping this is fixed by #1645 but LMK if not.