Pb Deploy Smart
Enterprise-grade skill for production, deployment, pocketbase, deploying. Includes structured workflows, validation checks, and reusable patterns for pocketbase.
PB Deploy Smart
A comprehensive skill for deploying PocketBase to production — covering single-binary deployment, systemd service configuration, reverse proxy setup with Nginx/Caddy, SSL certificates, backup strategies, and monitoring for PocketBase applications.
When to Use This Skill
Choose PB Deploy Smart when you need to:
- Deploy PocketBase to a production Linux server
- Configure systemd for automatic startup and restart
- Set up reverse proxy with Nginx or Caddy for SSL
- Implement automated backup strategies for PocketBase data
- Monitor PocketBase health and performance
Consider alternatives when:
- You need PocketBase schema design (use a PB collections skill)
- You need API rules configuration (use a PB API rules skill)
- You need general cloud infrastructure (use a cloud/DevOps skill)
Quick Start
# Download PocketBase binary wget https://github.com/pocketbase/pocketbase/releases/download/v0.23.0/pocketbase_0.23.0_linux_amd64.zip unzip pocketbase_0.23.0_linux_amd64.zip -d /opt/pocketbase # Create data directory mkdir -p /opt/pocketbase/pb_data # Test run /opt/pocketbase/pocketbase serve --http=0.0.0.0:8090 # Create admin account (first run) # Navigate to: http://your-server:8090/_/
# systemd service file # /etc/systemd/system/pocketbase.service [Unit] Description=PocketBase After=network.target [Service] Type=simple User=pocketbase Group=pocketbase WorkingDirectory=/opt/pocketbase ExecStart=/opt/pocketbase/pocketbase serve --http=0.0.0.0:8090 Restart=always RestartSec=5 StandardOutput=journal StandardError=journal SyslogIdentifier=pocketbase # Security hardening NoNewPrivileges=true ProtectSystem=strict ProtectHome=true ReadWritePaths=/opt/pocketbase/pb_data PrivateTmp=true [Install] WantedBy=multi-user.target
# Enable and start sudo systemctl enable pocketbase sudo systemctl start pocketbase sudo systemctl status pocketbase
Core Concepts
Deployment Architecture
| Component | Purpose | Tool/Service |
|---|---|---|
| PocketBase | Application server + database | Single binary |
| Reverse Proxy | SSL termination, load balancing | Nginx or Caddy |
| Process Manager | Auto-restart, logging | systemd |
| Backup | Data protection | cron + rsync/rclone |
| Monitoring | Health checks, alerting | UptimeRobot, Grafana |
Nginx Reverse Proxy Configuration
# /etc/nginx/sites-available/pocketbase server { listen 80; server_name api.yourdomain.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name api.yourdomain.com; ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem; client_max_body_size 50M; location / { proxy_pass http://127.0.0.1:8090; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; 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 (for real-time subscriptions) proxy_read_timeout 86400; } }
Caddy Reverse Proxy (Simpler Alternative)
# /etc/caddy/Caddyfile
api.yourdomain.com {
reverse_proxy 127.0.0.1:8090
}
Backup Strategy
#!/bin/bash # /opt/pocketbase/backup.sh BACKUP_DIR="/opt/backups/pocketbase" TIMESTAMP=$(date +%Y%m%d_%H%M%S) PB_DATA="/opt/pocketbase/pb_data" mkdir -p "$BACKUP_DIR" # Create backup using PocketBase's built-in backup /opt/pocketbase/pocketbase backup "$BACKUP_DIR/pb_backup_$TIMESTAMP.zip" # Alternatively, copy the SQLite database (requires stopping PB briefly) # systemctl stop pocketbase # cp "$PB_DATA/data.db" "$BACKUP_DIR/data_$TIMESTAMP.db" # systemctl start pocketbase # Upload to remote storage rclone copy "$BACKUP_DIR/pb_backup_$TIMESTAMP.zip" remote:backups/pocketbase/ # Clean up local backups older than 7 days find "$BACKUP_DIR" -name "pb_backup_*.zip" -mtime +7 -delete echo "Backup completed: pb_backup_$TIMESTAMP.zip"
# Cron job for daily backups # crontab -e 0 3 * * * /opt/pocketbase/backup.sh >> /var/log/pocketbase-backup.log 2>&1
Configuration
| Parameter | Description | Example |
|---|---|---|
http_addr | HTTP listen address | "0.0.0.0:8090" |
data_dir | PocketBase data directory | "/opt/pocketbase/pb_data" |
domain | Public domain for the API | "api.yourdomain.com" |
proxy | Reverse proxy type | "nginx" / "caddy" |
backup_schedule | Cron expression for backups | "0 3 * * *" (3am daily) |
backup_retention | Days to keep local backups | 7 |
Best Practices
-
Run PocketBase behind a reverse proxy, never expose directly — A reverse proxy (Nginx/Caddy) handles SSL termination, request rate limiting, and WebSocket upgrades properly. Exposing PocketBase directly on port 8090 to the internet skips these security layers.
-
Use Caddy if you want zero-config SSL — Caddy automatically provisions Let's Encrypt certificates and renews them. Two lines of Caddyfile configuration gives you HTTPS with zero maintenance. Nginx requires separate certbot setup and renewal cron jobs.
-
Create a dedicated system user for PocketBase — Don't run PocketBase as root. Create a
pocketbaseuser with minimal permissions:useradd -r -s /bin/false pocketbase. The systemd service runs as this user for security isolation. -
Test your backup restoration process quarterly — A backup that can't be restored is worthless. Every quarter, restore a backup to a test environment and verify the data is complete. PocketBase's built-in backup creates a ZIP containing the SQLite database and uploaded files.
-
Set
client_max_body_sizein Nginx to match your file upload limits — PocketBase may allow 50MB uploads, but if Nginx defaults to 1MB, large uploads fail at the proxy level with a 413 error. Setclient_max_body_size 50M(or your desired limit) in the Nginx config.
Common Issues
WebSocket connections fail for real-time subscriptions — The reverse proxy must support WebSocket upgrades. In Nginx, add proxy_set_header Upgrade $http_upgrade and proxy_set_header Connection "upgrade". Without these headers, real-time subscriptions connect over HTTP polling (slower) or fail entirely.
PocketBase runs out of file descriptors under load — The default ulimit on Linux is 1024 open files, which PocketBase can exhaust with many concurrent connections. Add LimitNOFILE=65535 to the systemd service file to increase the limit.
SQLite database locks under concurrent writes — PocketBase uses SQLite, which handles one writer at a time. Under heavy write load, requests may fail with "database is locked." Enable WAL mode (PocketBase does this by default) and consider reducing write-heavy API calls by batching operations or using a queue.
Reviews
No reviews yet. Be the first to review this template!
Similar Templates
Full-Stack Code Reviewer
Comprehensive code review skill that checks for security vulnerabilities, performance issues, accessibility, and best practices across frontend and backend code.
Test Suite Generator
Generates comprehensive test suites with unit tests, integration tests, and edge cases. Supports Jest, Vitest, Pytest, and Go testing.
Pro Architecture Workspace
Battle-tested skill for architectural, decision, making, framework. Includes structured workflows, validation checks, and reusable patterns for development.