Documentation Index Fetch the complete documentation index at: https://mintlify.com/pinchtab/pinchtab/llms.txt
Use this file to discover all available pages before exploring further.
PinchTab includes a Docker image with bundled Chromium for easy deployment in containerized environments.
Quick Start
Using Docker Compose
Clone Repository
git clone https://github.com/pinchtab/pinchtab.git
cd pinchtab
Start with Docker Compose
Test Connection
curl http://localhost:9867/health
Using Docker CLI
Build Image
Run Container
Run with Auth
# Build from source
docker build -t pinchtab .
Configuration
Environment Variables
Variable Description Default BRIDGE_BINDAddress to bind to 0.0.0.0 (Docker)BRIDGE_PORTHTTP port 9867BRIDGE_TOKENAuth token (optional) - BRIDGE_HEADLESSRun Chrome headless true (Docker)BRIDGE_STATE_DIRState directory /dataBRIDGE_STEALTHStealth level lightBRIDGE_BLOCK_IMAGESBlock image loading falseBRIDGE_BLOCK_MEDIABlock all media falseBRIDGE_NO_ANIMATIONSDisable CSS animations falseCHROME_BINARYChrome binary path /usr/bin/chromium-browserCHROME_FLAGSChrome launch flags --no-sandbox --disable-gpu
Example docker-compose.yml
services :
pinchtab :
build : .
container_name : pinchtab
ports :
- "9867:9867"
volumes :
- pinchtab-data:/data
environment :
- BRIDGE_BIND=0.0.0.0
- BRIDGE_PORT=9867
- BRIDGE_HEADLESS=true
- BRIDGE_TOKEN=${PINCHTAB_TOKEN:-}
- BRIDGE_STATE_DIR=/data
- BRIDGE_PROFILE=/data/chrome-profile
restart : unless-stopped
# Shared memory is critical for Chrome stability
shm_size : '2gb'
# Required for Chrome to work in container
security_opt :
- seccomp:unconfined
# Limit resources
mem_limit : 2g
cpus : '2.0'
volumes :
pinchtab-data :
The container requires --security-opt seccomp=unconfined for Chrome to function properly. This is a limitation of running Chrome in containers.
Dockerfile Breakdown
The official Dockerfile uses a multi-stage build:
# Build stage
FROM golang:1.26-alpine AS builder
RUN apk add --no-cache git
WORKDIR /build
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -ldflags= "-s -w" -o pinchtab ./cmd/pinchtab
# Runtime stage
FROM alpine:latest
LABEL org.opencontainers.image.source= "https://github.com/pinchtab/pinchtab"
LABEL org.opencontainers.image.description= "High-performance browser automation bridge"
# Install Chromium and dependencies
RUN apk add --no-cache \
chromium \
nss \
freetype \
harfbuzz \
ca-certificates \
ttf-freefont \
dumb-init
# Create non-root user and state directory
RUN adduser -D -g '' pinchtab && \
mkdir -p /data && \
chown pinchtab:pinchtab /data
# Copy binary from builder
COPY --from=builder /build/pinchtab /usr/local/bin/pinchtab
# Switch to non-root user
USER pinchtab
WORKDIR /data
# Environment variables
ENV BRIDGE_BIND=0.0.0.0 \
BRIDGE_PORT=9867 \
BRIDGE_HEADLESS=true \
BRIDGE_STATE_DIR=/data \
BRIDGE_PROFILE=/data/chrome-profile \
CHROME_BINARY=/usr/bin/chromium-browser \
CHROME_FLAGS= "--no-sandbox --disable-gpu"
# Expose port
EXPOSE 9867
# Use dumb-init to properly handle signals
ENTRYPOINT [ "/usr/bin/dumb-init" , "--" ]
# Run pinchtab
CMD [ "pinchtab" ]
The image uses Alpine Linux for minimal size and includes all necessary dependencies for running Chrome.
Architecture
The Docker image:
Uses Alpine Linux for minimal size (~200MB total)
Includes Chromium browser (bundled)
Runs as non-root user for security
Uses dumb-init for proper signal handling
Persists state in /data volume
Listens on 0.0.0.0 (accessible from host)
Profiles & Dashboard Mode
Docker runs PinchTab in bridge mode — a single headless Chrome instance with one default profile. This is the intended setup for containers.
The profile management feature (dashboard mode, multiple named Chrome profiles) is designed for desktop/workstation use where you might manage multiple browser identities from a GUI. It doesn’t apply to Docker deployments.
Why Not Use Profiles in Docker?
Containers are ephemeral — profiles don’t persist unless you mount /data
There’s no user desktop or personal Chrome to coexist with
One container = one browser instance, which is the right model for automation
If you need multiple isolated browser instances, run multiple containers rather than using the dashboard’s profile system.
Production Deployment
With Reverse Proxy (nginx)
upstream pinchtab {
server localhost:9867;
}
server {
listen 443 ssl http2;
server_name pinchtab.example.com;
ssl_certificate /etc/ssl/certs/pinchtab.crt;
ssl_certificate_key /etc/ssl/private/pinchtab.key;
location / {
proxy_pass http://pinchtab;
proxy_set_header Host $ host ;
proxy_set_header X-Real-IP $ remote_addr ;
proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for ;
proxy_set_header X-Forwarded-Proto $ scheme ;
# WebSocket support
proxy_http_version 1.1 ;
proxy_set_header Upgrade $ http_upgrade ;
proxy_set_header Connection "upgrade" ;
# Increase timeouts for long operations
proxy_connect_timeout 60s ;
proxy_send_timeout 60s ;
proxy_read_timeout 60s ;
}
}
Kubernetes Deployment
apiVersion : apps/v1
kind : Deployment
metadata :
name : pinchtab
spec :
replicas : 3
selector :
matchLabels :
app : pinchtab
template :
metadata :
labels :
app : pinchtab
spec :
containers :
- name : pinchtab
image : pinchtab/pinchtab:latest
ports :
- containerPort : 9867
env :
- name : BRIDGE_TOKEN
valueFrom :
secretKeyRef :
name : pinchtab-secret
key : token
- name : BRIDGE_HEADLESS
value : "true"
resources :
requests :
memory : "512Mi"
cpu : "500m"
limits :
memory : "2Gi"
cpu : "2000m"
volumeMounts :
- name : data
mountPath : /data
- name : dshm
mountPath : /dev/shm
securityContext :
capabilities :
add :
- SYS_ADMIN
volumes :
- name : data
emptyDir : {}
- name : dshm
emptyDir :
medium : Memory
sizeLimit : 2Gi
---
apiVersion : v1
kind : Service
metadata :
name : pinchtab
spec :
selector :
app : pinchtab
ports :
- protocol : TCP
port : 9867
targetPort : 9867
type : LoadBalancer
Security Best Practices
Set Authentication Token
Always set BRIDGE_TOKEN in production: docker run -d \
-e BRIDGE_TOKEN= $( openssl rand -hex 32 ) \
pinchtab
Use TLS
Put PinchTab behind a reverse proxy with TLS: # Use nginx, Caddy, or Traefik
# Never expose port 9867 directly to the internet
Limit Resources
Set memory and CPU limits: mem_limit : 2g
cpus : '2.0'
Network Isolation
Run on isolated networks:
Troubleshooting
Chrome crashes
Increase shared memory:
Or use /dev/shm mount:
docker run -d \
--shm-size=2g \
pinchtab
Font issues
The image includes basic fonts. For specific fonts:
FROM pinchtab/pinchtab:latest
USER root
RUN apk add --no-cache ttf-liberation ttf-dejavu
USER pinchtab
For better performance:
Shared Memory
Resource Limits
Volume Mounts
shm_size : '2gb' # Critical for Chrome stability
mem_limit : 4g
cpus : '4.0'
volumes :
- type : tmpfs
target : /tmp
tmpfs :
size : 1073741824 # 1GB
Container won’t start
Check logs:
Common issues:
Missing --security-opt seccomp=unconfined
Insufficient memory
Port already in use
Chrome binary not found
Verify Chrome is installed in container:
docker exec pinchtab which chromium-browser
# Should output: /usr/bin/chromium-browser
Resource Planning
Memory Requirements
Scenario Recommended Memory Single instance, light use 512 MB Single instance, heavy use 2 GB Multiple tabs (10+) 4 GB High concurrency 8 GB+
CPU Requirements
Scenario Recommended CPUs Light automation 0.5 cores Standard use 1-2 cores Heavy rendering 2-4 cores
Storage Requirements
Base image : ~200 MB
Chrome profile : 50-200 MB per profile
Temp files : 100-500 MB
Recommended : 1 GB minimum
Monitor actual usage with docker stats pinchtab and adjust limits accordingly.