home / skills / jeremylongshore / claude-code-plugins-plus-skills / documenso-deploy-integration

This skill helps you deploy Documenso integrations across Docker, Kubernetes, and cloud environments with automated, scalable infrastructure.

npx playbooks add skill jeremylongshore/claude-code-plugins-plus-skills --skill documenso-deploy-integration

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
10.3 KB
---
name: documenso-deploy-integration
description: |
  Deploy Documenso integrations across different platforms and environments.
  Use when deploying to cloud platforms, containerizing applications,
  or setting up infrastructure for Documenso integrations.
  Trigger with phrases like "deploy documenso", "documenso docker",
  "documenso kubernetes", "documenso cloud deployment".
allowed-tools: Read, Write, Edit, Bash(docker:*), Bash(kubectl:*)
version: 1.0.0
license: MIT
author: Jeremy Longshore <[email protected]>
---

# Documenso Deploy Integration

## Overview
Deploy Documenso integrations to various platforms including Docker, Kubernetes, and serverless environments.

## Prerequisites
- Application ready for deployment
- Cloud platform account (AWS, GCP, Azure)
- Container runtime (Docker)
- Kubernetes cluster (for K8s deployment)

## Docker Deployment

### Dockerfile

```dockerfile
# Dockerfile
FROM node:20-alpine AS base

# Install dependencies only when needed
FROM base AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

# Build the application
FROM base AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Production image
FROM base AS runner
WORKDIR /app

ENV NODE_ENV=production

# Create non-root user
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 appuser

# Copy built assets
COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./package.json

USER appuser

EXPOSE 3000

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1

CMD ["node", "dist/index.js"]
```

### Docker Compose

```yaml
# docker-compose.yml
version: '3.8'

services:
  signing-service:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DOCUMENSO_API_KEY=${DOCUMENSO_API_KEY}
      - DOCUMENSO_BASE_URL=${DOCUMENSO_BASE_URL:-https://app.documenso.com/api/v2/}
      - DOCUMENSO_WEBHOOK_SECRET=${DOCUMENSO_WEBHOOK_SECRET}
    healthcheck:
      test: ["CMD", "wget", "--spider", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    restart: unless-stopped
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

  # Optional: Redis for caching
  redis:
    image: redis:7-alpine
    volumes:
      - redis-data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3

volumes:
  redis-data:
```

## Kubernetes Deployment

### Deployment Manifest

```yaml
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: signing-service
  labels:
    app: signing-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: signing-service
  template:
    metadata:
      labels:
        app: signing-service
    spec:
      containers:
        - name: signing-service
          image: your-registry/signing-service:latest
          ports:
            - containerPort: 3000
          env:
            - name: NODE_ENV
              value: "production"
            - name: DOCUMENSO_API_KEY
              valueFrom:
                secretKeyRef:
                  name: documenso-secrets
                  key: api-key
            - name: DOCUMENSO_WEBHOOK_SECRET
              valueFrom:
                secretKeyRef:
                  name: documenso-secrets
                  key: webhook-secret
          resources:
            requests:
              memory: "128Mi"
              cpu: "100m"
            limits:
              memory: "512Mi"
              cpu: "500m"
          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 10
            periodSeconds: 30
          readinessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 10
      imagePullSecrets:
        - name: registry-credentials
```

### Service & Ingress

```yaml
# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: signing-service
spec:
  selector:
    app: signing-service
  ports:
    - port: 80
      targetPort: 3000
  type: ClusterIP

---
# k8s/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: signing-service
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
    - hosts:
        - signing.yourapp.com
      secretName: signing-tls
  rules:
    - host: signing.yourapp.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: signing-service
                port:
                  number: 80
```

### Secrets

```yaml
# k8s/secrets.yaml
apiVersion: v1
kind: Secret
metadata:
  name: documenso-secrets
type: Opaque
stringData:
  api-key: ${DOCUMENSO_API_KEY}
  webhook-secret: ${DOCUMENSO_WEBHOOK_SECRET}
```

### Horizontal Pod Autoscaler

```yaml
# k8s/hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: signing-service
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: signing-service
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80
```

## AWS Lambda Deployment

```typescript
// handler.ts
import { Documenso } from "@documenso/sdk-typescript";
import { APIGatewayProxyHandler } from "aws-lambda";

const documenso = new Documenso({
  apiKey: process.env.DOCUMENSO_API_KEY ?? "",
});

export const createDocument: APIGatewayProxyHandler = async (event) => {
  try {
    const body = JSON.parse(event.body ?? "{}");

    const doc = await documenso.documents.createV0({
      title: body.title,
    });

    return {
      statusCode: 200,
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ documentId: doc.documentId }),
    };
  } catch (error: any) {
    return {
      statusCode: error.statusCode ?? 500,
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ error: error.message }),
    };
  }
};

export const webhookHandler: APIGatewayProxyHandler = async (event) => {
  const secret = event.headers["x-documenso-secret"];
  if (secret !== process.env.DOCUMENSO_WEBHOOK_SECRET) {
    return { statusCode: 401, body: "Unauthorized" };
  }

  const payload = JSON.parse(event.body ?? "{}");
  console.log("Webhook received:", payload.event);

  // Process webhook...

  return { statusCode: 200, body: JSON.stringify({ received: true }) };
};
```

### SAM Template

```yaml
# template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Globals:
  Function:
    Timeout: 30
    Runtime: nodejs20.x
    Environment:
      Variables:
        DOCUMENSO_API_KEY: !Ref DocumensoApiKey
        DOCUMENSO_WEBHOOK_SECRET: !Ref DocumensoWebhookSecret

Parameters:
  DocumensoApiKey:
    Type: AWS::SSM::Parameter::Value<String>
    Default: /signing-service/documenso-api-key
  DocumensoWebhookSecret:
    Type: AWS::SSM::Parameter::Value<String>
    Default: /signing-service/documenso-webhook-secret

Resources:
  CreateDocumentFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: dist/
      Handler: handler.createDocument
      Events:
        Api:
          Type: Api
          Properties:
            Path: /documents
            Method: post

  WebhookFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: dist/
      Handler: handler.webhookHandler
      Events:
        Api:
          Type: Api
          Properties:
            Path: /webhooks/documenso
            Method: post
```

## Google Cloud Run

```yaml
# cloudbuild.yaml
steps:
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'gcr.io/$PROJECT_ID/signing-service:$COMMIT_SHA', '.']

  - name: 'gcr.io/cloud-builders/docker'
    args: ['push', 'gcr.io/$PROJECT_ID/signing-service:$COMMIT_SHA']

  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: gcloud
    args:
      - 'run'
      - 'deploy'
      - 'signing-service'
      - '--image=gcr.io/$PROJECT_ID/signing-service:$COMMIT_SHA'
      - '--region=us-central1'
      - '--platform=managed'
      - '--set-env-vars=NODE_ENV=production'
      - '--set-secrets=DOCUMENSO_API_KEY=documenso-api-key:latest,DOCUMENSO_WEBHOOK_SECRET=documenso-webhook-secret:latest'
      - '--min-instances=1'
      - '--max-instances=10'

images:
  - 'gcr.io/$PROJECT_ID/signing-service:$COMMIT_SHA'
```

## Environment Configuration

```typescript
// src/config.ts
interface Config {
  nodeEnv: string;
  port: number;
  documenso: {
    apiKey: string;
    baseUrl: string;
    webhookSecret: string;
  };
}

export function loadConfig(): Config {
  const config: Config = {
    nodeEnv: process.env.NODE_ENV ?? "development",
    port: parseInt(process.env.PORT ?? "3000"),
    documenso: {
      apiKey: requireEnv("DOCUMENSO_API_KEY"),
      baseUrl:
        process.env.DOCUMENSO_BASE_URL ??
        "https://app.documenso.com/api/v2/",
      webhookSecret: process.env.DOCUMENSO_WEBHOOK_SECRET ?? "",
    },
  };

  return config;
}

function requireEnv(name: string): string {
  const value = process.env[name];
  if (!value) {
    throw new Error(`Missing required environment variable: ${name}`);
  }
  return value;
}
```

## Output
- Dockerized application
- Kubernetes manifests ready
- Serverless functions configured
- Environment variables managed

## Error Handling
| Deployment Issue | Cause | Solution |
|-----------------|-------|----------|
| Container crash | Missing env vars | Check secret mounting |
| Health check fail | App not ready | Increase startup time |
| Network timeout | Firewall rules | Allow egress to Documenso |
| OOM killed | Memory limit | Increase resources |

## Resources
- [Docker Best Practices](https://docs.docker.com/develop/dev-best-practices/)
- [Kubernetes Documentation](https://kubernetes.io/docs/)
- [AWS Lambda](https://docs.aws.amazon.com/lambda/)
- [Google Cloud Run](https://cloud.google.com/run/docs)

## Next Steps
For webhook configuration, see `documenso-webhooks-events`.

Overview

This skill helps you deploy Documenso integrations across Docker, Kubernetes, serverless platforms, and managed cloud services. It packages the signing service, produces deployment manifests, and wires environment secrets so integrations run reliably in production. Use it to standardize deployments across environments and speed up delivery.

How this skill works

The skill provides ready-to-use Dockerfiles and Docker Compose for container builds, Kubernetes manifests (Deployment, Service, Ingress, Secrets, HPA) for cluster deployments, and serverless handlers plus SAM/Cloud Build templates for AWS Lambda and Google Cloud Run. It centralizes environment configuration and health checks, and includes resource and probe recommendations to reduce runtime failures.

When to use it

  • Deploying a Documenso signing service to Docker or Docker Compose for local or small production environments
  • Launching the service on Kubernetes clusters with secure secrets, autoscaling, and ingress
  • Deploying serverless endpoints on AWS Lambda or Cloud Run for event-driven workloads
  • Containerizing and pushing images to registries as part of CI/CD pipelines
  • Standardizing environment variable management (API keys, webhook secrets) before production rollouts

Best practices

  • Store sensitive values in secrets or a parameter store; never hard-code Documenso API keys
  • Include health, liveness, and readiness probes to enable graceful rolling updates
  • Start with conservative resource requests and scale limits; tune using HPA metrics
  • Use non-root application users inside containers and limit image layers for security
  • Validate webhooks with the webhook secret and log events for observability

Example use cases

  • Build a multi-stage Docker image and deploy a signing service behind an NGINX ingress with TLS
  • Deploy to Kubernetes with secrets for DOCUMENSO_API_KEY and DOCUMENSO_WEBHOOK_SECRET and enable autoscaling
  • Run the signing endpoints as AWS Lambda functions behind API Gateway using SAM for infrastructure as code
  • Use Cloud Build to build, push, and deploy the service to Google Cloud Run with secret bindings
  • Run Docker Compose locally with Redis caching to reproduce production behavior during development

FAQ

What environment variables are required?

DOCUMENSO_API_KEY is required; DOCUMENSO_WEBHOOK_SECRET and DOCUMENSO_BASE_URL are recommended. Use secret management for production.

Why is the container crashing after deployment?

Common causes are missing environment variables, failing health checks, or insufficient memory. Check logs, mount secrets, and increase resource limits.