Secrets usage in docker-compose #105
Replies: 3 comments 8 replies
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Secrets aren't very intuitive in compose. Here's the official docs: https://docs.docker.com/compose/how-tos/use-secrets/ Each secret is mounted as a file inside the container. So I'd need code in ControlR that explicitly reads each file and adds them to I haven't implemented this because I think the pattern would be highly error prone for self-hosting and result in a lot of support requests. Currently, passing them in via the host's environment variables or via a .env file are the only options. I've also thought about adding support for a single secret that should point to a json file in the format of appsettings.json, then these values would get merged with those passed in via env vars. That might end up creating confusion too, though. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
@bitbound So, I was doing some research and I think I may have found an alternative solution to the secrets debacle. There is a tool called "age" (ahge) and it essentially uses a public private key pair to encrypt and decrypt files. (Its a tool heavily used with Mozilla SOPS for Git, but can also be used locally with just the binary file). The thought process is, if you add this binary to your container build, this would give flexibility and security. If you build your appsettings.json code, you can add an env variable to say [ CONTROLR_AGE_KEY = value / null ] and that will determine if the appsettings.json takes the plain route of just directly passing the json file to your code, or if age need to decrypt that file before passing the values to the code. This prevents the settings from being passed as direct env variables to the host, adds a layer of security that the user can choose at runtime and the only requirement for them is to get the age tool an run a simple command to encrypt the file (this is no different than using something like (openssl rand -base64 32) to generate tokens). Then, they can pass the private key to the CONTROLR_AGE_KEY and mount the appsettings.json as RO and your container sees that the CONTROLR_AGE_KEY is not empty and uses that key value to decrypt the settings json. This is a solution that I believe would work for Docker (non-swarm), Docker Swarm and K3S and even Podman. Give you the ability to not just utilize it with your appsettings.json file idea, but also have a way to secure the whole thing if a user wants to. Im defintiely no cryptography or docker expert so this is only a theory based on research and conversing with AI 😅 |
I actually took a different approach to setting up compose for controlr using env_file for everything and traefik as the reverse proxy: docker-compose.yml name: controlr-beardedtekservices:
controlr:
image: bitbound/controlr:latestcontainer_name: controlrrestart: unless-stoppeddepends_on:
- postgres
- aspirenetworks:
- controlr-network
- proxyenv_file:
- .envlabels:
- "traefik.enable=true"
- "traefik.http.routers.controlr.rule=Host(`${TRAEFIK_DOMAIN_NAME:-controlr.example.com}`)"
- "traefik.http.routers.controlr.entryPoints=https"
- "traefik.http.routers.controlr.tls=true"
- "traefik.http.routers.controlr.tls.certresolver=le"
- "traefik.http.routers.controlr.service=controlr-entrypoint"
- "traefik.http.services.controlr-entrypoint.loadbalancer.server.port=8080"postgres:
image: postgres:18container_name: postgresrestart: unless-stoppednetworks:
- controlr-networkvolumes:
- postgres-data:/var/lib/postgresqlenv_file:
- .envaspire:
image: mcr.microsoft.com/dotnet/aspire-dashboard:13.1container_name: aspirerestart: unless-stoppedports:
- "18888:18888"expose:
- "18889"networks:
- controlr-networkenv_file:
- .envvolumes:
postgres-data:
name: "postgres-data"networks:
controlr-network:
driver: bridgetraefik:
external: true.env # Traefik domain nameTRAEFIK_DOMAIN_NAME=controlr.example.com# Core database and Aspire settingsControlR_POSTGRES_USER=postgresControlR_POSTGRES_PASSWORD=change_meControlR_POSTGRES_HOST=postgresControlR_POSTGRES_PORT=5432ControlR_POSTGRES_DB=controlrControlR_ASPIRE_BROWSER_TOKEN=change_me# ASP.NET Core hostingASPNETCORE_ENVIRONMENT=ProductionASPNETCORE_HTTP_PORTS=8080# ControlR server optionsControlR_AspireDashboard__Token=${ControlR_ASPIRE_BROWSER_TOKEN}ControlR_AspireDashboard__PublicWebUrl=http://localhost:18888ControlR_AppOptions__EnablePublicRegistration=falseControlR_AppOptions__AllowAgentsToSelfBootstrap=falseControlR_AppOptions__AuthenticatorIssuerName=ControlRControlR_AppOptions__PersistPasskeyLogin=falseControlR_AppOptions__EnableCloudflareProxySupport=falseControlR_AppOptions__EnableNetworkTrust=falseControlR_AppOptions__DockerGatewayIp=::ffff:172.29.0.1ControlR_AppOptions__MaxFileTransferSize=104857600ControlR_AppOptions__RequireUserEmailConfirmation=trueControlR_AppOptions__DisableEmailSending=false# Logging and telemetryControlR_OTLP_ENDPOINT_URL=http://aspire:18889ControlR_Logging__LogLevel__Default=InformationControlR_Logging__LogLevel__Microsoft.AspNetCore.HttpLogging=InformationControlR_Logging__LogLevel__Microsoft.AspNetCore.HttpOverrides=DebugControlR_AppOptions__UseHttpLogging=false# SMTP (leave empty or configure as needed)ControlR_AppOptions__SmtpDisplayName=ControlR_AppOptions__SmtpEmail=ControlR_AppOptions__SmtpHost=ControlR_AppOptions__SmtpLocalDomain=ControlR_AppOptions__SmtpCheckCertificateRevocation=trueControlR_AppOptions__SmtpPassword=ControlR_AppOptions__SmtpPort=587ControlR_AppOptions__SmtpUserName=# Optional proxy configuration (uncomment and set as needed)#ControlR_AppOptions__KnownProxies__0=ControlR_AppOptions__KnownNetworks__0=172.18.0.0/16# Optional external auth (leave empty unless configured)#ControlR_AppOptions__MicrosoftClientId=#ControlR_AppOptions__MicrosoftClientSecret=#ControlR_AppOptions__GitHubClientId=#ControlR_AppOptions__GitHubClientSecret=# Postgres container variablesPOSTGRES_USER=${ControlR_POSTGRES_USER}POSTGRES_PASSWORD=${ControlR_POSTGRES_PASSWORD}POSTGRES_DB=${ControlR_POSTGRES_DB} |


Uh oh!
There was an error while loading. Please reload this page.
How do I properly use docker secrets with controlr?
Postgres sets up just fine, but when trying to present the secrets to Controlr, it thinks they are empty. Ive used secrets in other containers this way and the docs say secrets are supported, did something change?
All reactions