1Password Connect Operator on a Homelab: Secrets Without ConfigMap Drift

Sep 7, 2026

Article cover: 1Password Connect Operator on a Homelab: Secrets Without ConfigMap Drift

Why Homelab Secrets Rot Faster Than Cloud

Why Homelab Secrets Rot Faster Than Cloud
Why Homelab Secrets Rot Faster Than Cloud

In a single-admin homelab, secrets management is a constant battle against the inevitable drift between your git repository and your Kubernetes cluster. Unlike cloud teams that have dedicated DevOps engineers and workflows, homelab operators often find themselves manually patching secrets, editing ConfigMaps, and restarting pods to keep everything in sync. This process is error-prone and time-consuming, especially when you have multiple applications running across different namespaces.

Consider the scenario where you have a homelab with several applications: Immich for photo management, Strapi for content management, a private registry for Docker images, and monitoring tools. Each application might require different secrets, and keeping track of them all can be a nightmare. For example, you might have a PostgreSQL database for Immich, and you need to update the password every few months. If you manage this via a ConfigMap, you might forget to update the Secret in the cluster, or you might accidentally commit the wrong value to your git repository.

In a cloud environment, you might use a secrets management tool like HashiCorp Vault or AWS Secrets Manager to handle these secrets. However, in a homelab, you often find yourself relying on manual processes, which can lead to drift and security vulnerabilities. For instance, you might have a kubectl command that you run to update a Secret, but you might forget to run it, or you might run it in the wrong namespace. This can lead to unexpected behavior, such as a pod failing to start because it can't connect to the database.

To address this issue, we can use the 1Password Connect Operator to manage our secrets in a more automated and secure way. The Connect Operator allows us to sync secrets from 1Password to Kubernetes Secrets, ensuring that our secrets are always up-to-date and consistent across the cluster.

Connect vs Operator vs Plain Secrets

Before we dive into the details of the 1Password Connect Operator, let's compare it to other methods of managing secrets in a homelab environment.

When Kubectl Secrets Are Enough

For simple applications that don't require frequent secret updates, using plain Kubernetes Secrets might be sufficient. For example, if you have a small application that only needs a single secret, you can create a Secret and manage it manually. However, this approach becomes cumbersome when you have multiple secrets and multiple applications.

When 1Password Connect Is Enough

If you have a few secrets that you need to update occasionally, you can use 1Password Connect to sync these secrets to Kubernetes Secrets. This is a good option if you don't need the full power of a dedicated secrets management tool.

When the Operator Pays Off

The 1Password Connect Operator is particularly useful when you have a large number of secrets that need to be updated frequently. It automates the process of syncing secrets from 1Password to Kubernetes Secrets, ensuring that your secrets are always up-to-date and consistent. This is especially useful in a homelab environment where you might have multiple namespaces and applications.

For example, in our homelab, we use the 1Password Connect Operator to sync PostgreSQL credentials for the Immich application. This ensures that the PostgreSQL database is always accessible, and the credentials are always up-to-date. We also use the Operator to sync secrets for the private registry, monitoring tools, and other applications.

Operator Install Pattern

To install the 1Password Connect Operator, we follow a specific pattern that ensures the Operator is always up-to-date and running correctly. Here are the steps:

  1. Namespace Watch: The Operator watches a specific namespace for OnePasswordItem custom resource definitions (CRDs).
  2. Connect Token Secret: The Operator requires a Secret that contains the Connect token. This token is used to authenticate with 1Password.
  3. OnePasswordItem CRD: The OnePasswordItem CRD is used to define the secrets that need to be synced.
  4. Deployment secretKeyRef: The Operator's Deployment is configured to use secretKeyRef to access the Connect token Secret.

Let's go through each step in detail.

Namespace Watch

The Operator watches a specific namespace for OnePasswordItem CRDs. This ensures that any new secrets added to this namespace are automatically synced to Kubernetes Secrets.

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: onepassworditems.1password.com
spec:
  group: 1password.com
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                itemID:
                  type: string
                itemUUID:
                  type: string
                itemTitle:
                  type: string
                itemFields:
                  type: array
                  items:
                    type: object
                    properties:
                      name:
                        type: string
                      value:
                        type: string
  scope: Namespaced
  names:
    plural: onepassworditems
    singular: onepassworditem
    kind: OnePasswordItem
    shortNames:
    - opitem

Connect Token Secret

The Operator requires a Secret that contains the Connect token. This token is used to authenticate with 1Password. Here is an example of how to create the Connect token Secret:

apiVersion: v1
kind: Secret
metadata:
  name: 1password-connect-token
  namespace: <app-namespace>
type: Opaque
data:
  connect_token: <base64-encoded-connect-token>

OnePasswordItem CRD

The OnePasswordItem CRD is used to define the secrets that need to be synced. Here is an example of how to create a OnePasswordItem CRD:

apiVersion: 1password.com/v1
kind: OnePasswordItem
metadata:
  name: immich-postgres-credentials
  namespace: <app-namespace>
spec:
  itemID: <item-id>
  itemUUID: <item-uuid>
  itemTitle: PostgreSQL Credentials
  itemFields:
    - name: Password
      value: <password>

Deployment secretKeyRef

The Operator's Deployment is configured to use secretKeyRef to access the Connect token Secret. Here is an example of how to configure the Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: 1password-connect-operator
  namespace: <app-namespace>
spec:
  replicas: 1
  selector:
    matchLabels:
      app: 1password-connect-operator
  template:
    metadata:
      labels:
        app: 1password-connect-operator
    spec:
      containers:
        - name: 1password-connect-operator
          image: <connect-operator-image>
          env:
            - name: CONNECT_TOKEN
              valueFrom:
                secretKeyRef:
                  name: 1password-connect-token
                  key: connect_token
          volumeMounts:
            - name: config-volume
              mountPath: /config
      volumes:
        - name: config-volume
          secret:
            secretName: 1password-connect-token

Verification Loop

Verification Loop
Verification Loop

To ensure that the 1Password Connect Operator is working correctly, we use a verification loop. This loop checks that the secrets are correctly synced and that the applications are using the correct secrets.

./scripts/verify-infra-secrets-1password.sh

We have a script called ./scripts/verify-infra-secrets-1password.sh that verifies the secrets in the cluster. This script checks that the secrets are correctly synced and that the applications are using the correct secrets.

Here is an example of how to use the script:

#!/bin/bash

# Verify PostgreSQL credentials for Immich
echo "Verifying Immich PostgreSQL credentials..."
kubectl get secret immich-postgres-credentials -n <app-namespace> -o yaml | grep -q "password: <expected-password>"
if [ $? -eq 0 ]; then
  echo "Immich PostgreSQL credentials are correct."
else
  echo "Immich PostgreSQL credentials are incorrect."
  exit 1
fi

Immich PostgreSQL Case Study

Let's take a closer look at the Immich PostgreSQL case study. In this case, we have a PostgreSQL database for the Immich application, and we need to ensure that the credentials are correctly synced.

Here is an example of the OnePasswordItem CRD for the Immich PostgreSQL credentials:

apiVersion: 1password.com/v1
kind: OnePasswordItem
metadata:
  name: immich-postgres-credentials
  namespace: immich
spec:
  itemID: <item-id>
  itemUUID: <item-uuid>
  itemTitle: PostgreSQL Credentials
  itemFields:
    - name: Password
      value: <password>

We can use the ./scripts/verify-infra-secrets-1password.sh script to verify that the credentials are correctly synced:

#!/bin/bash

# Verify PostgreSQL credentials for Immich
echo "Verifying Immich PostgreSQL credentials..."
kubectl get secret immich-postgres-credentials -n immich -o yaml | grep -q "password: <expected-password>"
if [ $? -eq 0 ]; then
  echo "Immich PostgreSQL credentials are correct."
else
  echo "Immich PostgreSQL credentials are incorrect."
  exit 1
fi

Rotation Without Downtime

One of the key benefits of using the 1Password Connect Operator is that it allows us to rotate secrets without downtime. This is particularly useful when you have applications that rely on secrets, such as database credentials or API keys.

Update Vault Item → Reconcile → kubectl rollout restart

To rotate a secret, we update the corresponding item in 1Password, and the Operator will automatically sync the updated secret to Kubernetes. We can then use kubectl rollout restart to restart the application pods, ensuring that they use the updated secret.

Here is an example of how to update the PostgreSQL credentials for Immich:

  1. Update Vault Item: Update the PostgreSQL credentials in 1Password.
  2. Reconcile: The Operator will automatically sync the updated credentials to Kubernetes.
  3. Restart Pods: Use kubectl rollout restart to restart the Immich pods.
# Update PostgreSQL credentials in 1Password
1password update item <item-id> --field Password <new-password>

# Restart Immich pods
kubectl rollout restart deployment/immich -n immich

Avoiding Stale Env Vars

To avoid stale environment variables, we can use the OnePasswordItem CRD to define the secrets and use secretKeyRef in the application's deployment. This ensures that the application always uses the latest secret.

Here is an example of how to define the PostgreSQL credentials in the OnePasswordItem CRD:

apiVersion: 1password.com/v1
kind: OnePasswordItem
metadata:
  name: immich-postgres-credentials
  namespace: immich
spec:
  itemID: <item-id>
  itemUUID: <item-uuid>
  itemTitle: PostgreSQL Credentials
  itemFields:
    - name: Password
      value: <password>

And here is an example of how to use secretKeyRef in the application's deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: immich
  namespace: immich
spec:
  replicas: 1
  selector:
    matchLabels:
      app: immich
  template:
    metadata:
      labels:
        app: immich
    spec:
      containers:
        - name: immich
          image: <immich-image>
          env:
            - name: POSTGRES_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: immich-postgres-credentials
                  key: Password

What Not to Sync via Items

While the 1Password Connect Operator is a powerful tool for managing secrets, there are some scenarios where it might not be the best choice. Here are some examples of what not to sync via items:

Telegram Bot Tokens in ConfigMap

Telegram bot tokens are sensitive information that should not be stored in ConfigMaps. If you store a bot token in a ConfigMap, you risk exposing it to unauthorized users. Instead, you can use the 1Password Connect Operator to sync the bot token to a Kubernetes Secret.

Here is an example of how to define a bot token in a ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: telegram-bot-config
  namespace: monitoring
data:
  bot_token: <telegram-bot-token>

And here is an example of how to define the bot token in a OnePasswordItem CRD:

apiVersion: 1password.com/v1
kind: OnePasswordItem
metadata:
  name: telegram-bot-token
  namespace: monitoring
spec:
  itemID: <item-id>
  itemUUID: <item-uuid>
  itemTitle: Telegram Bot Token
  itemFields:
    - name: Bot Token
      value: <telegram-bot-token>

Committing Connect Credentials

Committing Connect credentials to your git repository is a bad practice. If you commit the Connect credentials, you risk exposing them to unauthorized users. Instead, you can use the 1Password Connect Operator to sync the Connect credentials to a Kubernetes Secret.

Here is an example of how to define the Connect credentials in a ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: 1password-connect-credentials
  namespace: <app-namespace>
data:
  connect_token: <connect-token>

And here is an example of how to define the Connect credentials in a OnePasswordItem CRD:

apiVersion: 1password.com/v1
kind: OnePasswordItem
metadata:
  name: 1password-connect-credentials
  namespace: <app-namespace>
spec:
  itemID: <item-id>
  itemUUID: <item-uuid>
  itemTitle: 1Password Connect Credentials
  itemFields:
    - name: Connect Token
      value: <connect-token>

Per-App Connect Sprawl

Using a separate Connect instance for each application can lead to per-app Connect sprawl. This can make it difficult to manage and rotate secrets. Instead, you can use a single Connect instance to manage all your secrets.

Here is an example of how to define the Connect credentials in a OnePasswordItem CRD:

apiVersion: 1password.com/v1
kind: OnePasswordItem
metadata:
  name: 1password-connect-credentials
  namespace: <app-namespace>
spec:
  itemID: <item-id>
  itemUUID: <item-uuid>
  itemTitle: 1Password Connect Credentials
  itemFields:
    - name: Connect Token
      value: <connect-token>

Runbook Pointer

Runbook Pointer
Runbook Pointer

For more detailed information on managing secrets in a homelab environment, please refer to the runbook available at [kb slug 1password-operator-homelab].

By following the steps outlined in this article, you can manage your secrets more securely and efficiently using the 1Password Connect Operator. This approach ensures that your secrets are always up-to-date and consistent, reducing the risk of drift and security vulnerabilities.

For more information on managing secrets in a homelab environment, please refer to the runbook available at [kb slug 1password-operator-homelab].


This article provides a comprehensive guide to using the 1Password Connect Operator in a homelab environment. By following the steps outlined, you can manage your secrets more securely and efficiently, reducing the risk of drift and security vulnerabilities.