Workplace Structure
Learn how to structure your projects and configs most effectively inside a workplace.
There are many ways you could potentially model your project structure inside your workplace. This guide will walk you through the most typical way to structure your projects inside your workplace to make sure you're taking advantage of our features most effectively.
Project Naming
The best way to think of a project is to think of it as an encapsulated application service. For example, you might have two applications (e.g., AcmeWidgets and OmniCommerce) β each with two services: worker and backend. Each of those services should map to a separate project. Rather than using the overarching application name as the project name, you would use that in the project name as a namespace along with the service name. In this scenario, you might have projects named as follows:
acme-widgets-worker
acme-widgets-backend
omni-commerce-worker
omni-commerce-backend
Doing this allows you to have more fine-grained access controls over your secrets.
A common mistake when structuring projects is to name them after a company department, overarching application name, or even third-party service and then use environments under the project to hold secrets for different services related to that category or application. An example of this anti-pattern would be a situation where you have an application named AcmeWidgets that was comprised of a Worker and Backend service. Creating a project named
acme-widgets
and then having environments namedworker
andbackend
would be a textbook example of setting this up incorrectly.
Environment Naming
Environments should typically map to some kind of deployment environment (e.g., dev, stg, ci, qa, prd, etc.). The general design behind environments is that the project owning an environment maps to a single application and the majority of the secret keys in each config (e.g., STRIPE_API_KEY
) will be the same across the configs in that environment (e.g., STRIPE_API_KEY
will be one value in dev
, another value in stg
, and yet another in prd
). This design is what drives our config compare feature and the features that allow you to copy a secret to other configs when saving. The further outside this model you go when structuring your projects, the more rough-edges you'll likely run into further down the road.
If you find yourself naming environments after application or service names or end up needing more than our limit of 15 environments per project, that's a good sign that you may be structuring things wrong!
Shared Projects
In many cases, you might find that you need to share certain secrets across many applications. The best way to accomplish this is to create shared projects that contain those secrets. You can name these either after the application that has secrets you need to share to multiple other services or after a third-party service (e.g., AWS credentials, GitHub credentials, etc.).
Shared Application Secrets
Let's say you have an application called AcmeWidgets. As before, that application has two separate services: worker and backend. Those two services each have a set of secrets that they share (e.g., STRIPE_API_KEY
). The best way to handle this is to create four projects:
acme-widgets-worker
acme-widgets-backend
acme-widgets-shared
Inside the acme-widgets-shared
project, add the appropriate STRIPE_API_KEY
secret for each environment (e.g., dev
, stg
, prd
). Now, in each of the other acme-widgets-*
projects, create a new STRIPE_API_KEY
secret and use cross-project secret referencing (e.g., so the value for STRIPE_API_KEY
in the dev
environment for acme-widgets-worker
would be ${acme-widgets-shared.dev.STRIPE_API_KEY}
).
Using this approach will allow you to easily update the secret values in the shared project without needing to manually update each of your other projects. If you want more access control over these, you might have an acme-widgets-shared
and acme-widgets-credentials
project where everything under the shared
project is less sensitive and everything under the credentials
project is more sensitive.
Keep in mind that when updating a secret you can only reference secrets for projects/environments you have access to. However, when reading secrets, any configured references will be resolved regardless of the reader's permissions.
For example, a user who performs a
doppler secrets download
on a config they have access to (let's sayacme-widgets-worker.dev
) would see the resolved values of all secret references in that config regardless of whether they're to projects or configs that user has access to.
Shared Third-party Credentials
In some scenarios, you might have some third-party credentials that are used across many different applications. In a scenarios like that, it's common to create projects with a global-
namespace (e.g., global-credentials
). This allows you to use a similar approach as described above, but across many applications.
Alternate Naming Pattern
Another naming convention that might work better for you than what's described above would be having a single project per application and then naming branch configs after the services that compose that application. For example, you might have an application named AcmeWidgets that's composed of a worker and backend service.
Under this pattern, you would have a single acme-widgets
project. Under that project, you would have a dev
, stg
, ci
, and prd
environment. Under each of those environments, you would have a branch config for each service. For example, you might have dev_worker
and dev_backend
along with prd_worker
and prd_backend
. You would then put any shared secrets in the root config (i.e., dev
, stg
, prd
, etc.). Those secrets would be inherited by the branch configs. In those branch configs you can then override or add any additional secrets that you may need. If you have cross-project secrets (e.g., STRIPE_API_KEY
), then you might still use a global-credentials
project that you would reference via secret references in the root configs of your acme-widgets
project.
The downside to this approach is that you lose some access control granularity since project permissions are setup on a per environment level β so there would be no way to provide someone access to a single service's secrets. You could provide them access to the dev
environment and then they'd have access to all services with branch configs under that environment.
Updated 8 months ago