Skip to content
Back to skills

Op Service Accounts

BSecurity

Use this skill when the user is setting up 1Password for headless / CI / production environments — anything involving service accounts (`op service-account create`), service account tokens, `OP_SERVICE_ACCOUNT_TOKEN`, Connect servers (`op connect`), `OP_CONNECT_HOST`/`OP_CONNECT_TOKEN`, GitHub Actions integration, deploying with 1Password secrets, the events-api integration, or scoping 1Password access for automation.

  • 4 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 12, 2026
devopsgoshellbashnodedockerkubernetesgitapidatabasedevops

Works with

  • cli
  • api

Security analysis

B84/100
  • mediumUses curl or wget to download content
  • criticalExfiltrates credentials via HTTP — exact pattern from Snyk ToxicSkills study

Pro scans all 2 files and shows the line behind each finding

Scanned September 12, 2026

npx -y skills add aibot88/sec_skill_store --skill op-service-accounts --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Op Service Accounts?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Op Service Accounts
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/aibot88-op-service-accounts/badge)](https://www.skillsdirectory.com/skills/aibot88-op-service-accounts)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: op-service-accounts
description: Use this skill when the user is setting up 1Password for headless / CI / production environments — anything involving service accounts (`op service-account create`), service account tokens, `OP_SERVICE_ACCOUNT_TOKEN`, Connect servers (`op connect`), `OP_CONNECT_HOST`/`OP_CONNECT_TOKEN`, GitHub Actions integration, deploying with 1Password secrets, the events-api integration, or scoping 1Password access for automation.
version: 1.0.0
---

# Service accounts and Connect servers

Two ways to give automation access to 1Password without a human:

| | Service Accounts | Connect (self-hosted) |
|---|---|---|
| Where it runs | 1Password.com | Your infra (Docker/K8s) |
| Setup | One CLI command | Run a server, generate creds |
| Network egress to 1Password.com | Per-call | Once at server boot |
| Best for | CI/CD, scripts, small-to-medium | High-throughput, on-prem, regulated |
| Vault scope | Selected vaults, granular permissions | Selected vaults |
| Personal/Private/Employee vault | **No access** | **No access** |

For most cases, **service accounts**. Connect when you have throughput, latency, or compliance reasons to keep the secrets path inside your network.

## Service accounts

### Create

```bash
op service-account create <name> [flags]
```

| Flag | Purpose |
|---|---|
| `--vault <vault>:<perms>` | Repeatable. Permissions: `read_items`, `write_items`, `share_items`. `write_items` and `share_items` require `read_items`. Default if no perms: `read_items`. |
| `--expires-in <duration>` | Token TTL — e.g., `90d`, `24h`, `4w`. No expiry if omitted. |
| `--can-create-vaults` | Allow the SA to create new vaults. |
| `--raw` | Print only the token (for piping into a secret store). |

The token is shown **once**. Store it immediately; you can't retrieve it again.

```bash
op service-account create "ci-prod-deploy" \
  --vault Prod:read_items \
  --vault "CI Tokens":read_items,write_items \
  --expires-in 90d
```

```bash
TOKEN=$(op service-account create "ci-build" --vault Build:read_items --expires-in 30d --raw)
gh secret set OP_SERVICE_ACCOUNT_TOKEN --body "$TOKEN" --repo myorg/myrepo
unset TOKEN
```

### Use

```bash
export OP_SERVICE_ACCOUNT_TOKEN="ops_..."
op vault list                # works without any signin
op read op://Prod/db/password
op run --env-file=.env -- ./bin/app
```

The token bypasses interactive auth entirely. `op signin` is not needed and `op whoami` will report the service account identity.

### Limitations and rules

- **Cannot access Personal, Private, or Employee vaults** — these are user-only.
- **Cannot manage users, groups, or vaults' membership** — administrative ops require an interactive admin.
- **Cannot enroll in shell plugins** (`op plugin init` requires desktop biometric).
- **Token rotation:** create a new SA + token, swap it in CI, then delete or expire the old one.
- **Rate limits:**
  ```bash
  op service-account ratelimit       # show current limit + usage
  ```

### List service accounts

```bash
op service-account list
```

(Then drill in via the desktop app for full audit history.)

## CI / production patterns

### GitHub Actions

Use the official action when possible:

```yaml
- uses: 1password/load-secrets-action@v2
  with:
    export-env: true
  env:
    OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
    DATABASE_URL: op://Prod/db/connection_string
    STRIPE_KEY: op://Prod/stripe/api-key
- run: ./bin/migrate && ./bin/start
```

Or install `op` and use `op run`:

```yaml
- uses: 1password/install-cli-action@v1
- run: op run --env-file=.env -- ./bin/migrate
  env:
    OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
```

### Other CI (CircleCI, GitLab, Jenkins, etc.)

```bash
# Install op
curl -sSf https://cache.agilebits.com/dist/1P/op2/pkg/v2.34.0/op_linux_amd64_v2.34.0.zip | \
  busybox unzip -o - -d /usr/local/bin op
chmod +x /usr/local/bin/op

# Use it
export OP_SERVICE_ACCOUNT_TOKEN="$OP_SERVICE_ACCOUNT_TOKEN"
op run --env-file=.env -- ./build.sh
```

(Pin to a known version. Always set `OP_SERVICE_ACCOUNT_TOKEN` from the CI's secret store, never inline.)

### Docker

```dockerfile
FROM 1password/op:2 AS op
FROM node:20-slim
COPY --from=op /usr/local/bin/op /usr/local/bin/op
COPY .env package.json ./
RUN npm ci
COPY . .
ENTRYPOINT ["op", "run", "--env-file=.env", "--"]
CMD ["node", "server.js"]
```

```bash
docker run --rm -e OP_SERVICE_ACCOUNT_TOKEN myapp
```

### Kubernetes — 1Password Operator

Install the operator, create `OnePasswordItem` CRDs that reference items, and the operator creates corresponding `Secret` resources. Cleaner than running `op` inside containers. See <https://developer.1password.com/docs/k8s/>.

Alternative without the operator: render manifests at deploy time:

```bash
op inject -i deploy.yaml.tpl | kubectl apply -f -
```

## Connect (self-hosted secrets API)

Run a Connect server in your infra, then `op` (and the SDKs) talk to it instead of 1Password.com.

### Provision

```bash
# Create the server config (downloads 1password-credentials.json)
op connect server create "us-east-1" --vaults Prod,Staging
# Issue a token for the server
op connect token create "us-east-1" "deploy-token" --vaults Prod
```

Two artifacts:
- `1password-credentials.json` — server's identity. Mount into the Connect container.
- The **token** (printed once) — what clients send.

### Run the server

```yaml
# docker-compose.yml
services:
  op-connect-api:
    image: 1password/connect-api:latest
    ports: ["8080:8080"]
    volumes:
      - ./1password-credentials.json:/home/opuser/.op/1password-credentials.json
      - data:/home/opuser/.op/data
  op-connect-sync:
    image: 1password/connect-sync:latest
    volumes:
      - ./1password-credentials.json:/home/opuser/.op/1password-credentials.json
      - data:/home/opuser/.op/data
volumes:
  data:
```

### Use Connect from `op`

```bash
export OP_CONNECT_HOST="http://op-connect.internal:8080"
export OP_CONNECT_TOKEN="eyJ..."
op vault list                            # talks to Connect, not 1Password.com
op read op://Prod/db/password
op run --env-file=.env -- ./bin/app
```

### Connect management

```bash
op connect server list
op connect server get "us-east-1"
op connect server edit "us-east-1" --name "us-east-1-prod"
op connect server delete "us-east-1"          # invalidates all its tokens

op connect token list
op connect token create "us-east-1" "deploy" --vaults Prod
op connect token edit   "us-east-1" "deploy" --name "deploy-2026"
op connect token delete "us-east-1" "deploy"

op connect vault grant  "us-east-1" --vault Staging
op connect vault revoke "us-east-1" --vault OldVault

op connect group grant  --group "DevOps"
op connect group revoke --group "DevOps"
```

### Token scoping

Token permissions inherit from the server's vault grants by default. Restrict per-token to read-only or write-only:

```bash
op connect token create "us-east-1" "read-only" --vaults Prod:r
op connect token create "us-east-1" "writer"    --vaults Audit:w
```

`r` = read items, `w` = write items, `r,w` = both.

## Events API

Audit/event integrations (sign-in attempts, item usages, audit events) use a separate token type:

```bash
op events-api create "Splunk-prod" \
  --features signinattempts,itemusages,auditevents \
  [--expires-in 1y]
```

The token is printed once. Configure your SIEM (Splunk, Elastic, Datadog, etc.) with the 1Password Events API integration using this token. Available features: `signinattempts`, `itemusages`, `auditevents`.

## Decision tree

- **Local dev (interactive)** → desktop app integration + `op signin`. No service account needed.
- **CI/CD pipelines** → service account. Cheapest, simplest.
- **Production app reading secrets at startup** → service account; if throughput >10/s sustained or you're in a regulated environment, Connect.
- **K8s production** → 1Password Operator (uses Connect under the hood).
- **SIEM ingestion** → events-api token.

## Gotchas

1. **`OP_SERVICE_ACCOUNT_TOKEN` and `op signin` shouldn't both be set.** The token wins, but it's confusing. Pick one mode per shell.
2. **SA tokens have no expiry by default.** Pass `--expires-in` and rotate. Treat them like long-lived API keys.
3. **Connect's `1password-credentials.json` is the server's identity** — losing it means re-creating the Connect server. Back it up to a secure store.
4. **Connect tokens are tied to a server.** Deleting `op connect server delete` invalidates every token issued for it.
5. **Events API tokens are read-only and feature-scoped.** They cannot read item contents or do anything except stream the configured event types.
6. **Service accounts can't run `op item template`** in some early CLI versions — if you hit `unauthorized`, check version and consider using a JSON file you produced once interactively as your template.

Files in this skill

  • SKILL.md8.7 KB
  • source.json960 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.