Author: Anton Gulin · Tool: opencode-skill-creator · GitHub: @antongulin · Registry: skills.sh
Paperclip Coolify Deployer
Deploy Paperclip on a self-hosted Coolify v4 server.
Paperclip is an open-source platform for managing AI agents in an org chart, tracking tasks and budgets. This skill automates or guides every step of deploying it on Coolify — a self-hosted PaaS (Platform as a Service).
Prerequisites
- A running Coolify v4 server with a reachable Server in its sidebar (green dot)
- Docker / Buildx available on that server
- At least 2 GB RAM, 2 CPU cores, 10 GB disk
- OpenCode must have access to the Coolify MCP tools (
coolify_*)
Workflow Overview
The deployment has 8 phases. The agent should execute them sequentially, pausing for user confirmation only where indicated.
- Discover Coolify infrastructure
- Create/select a Project and Environment
- Add Paperclip Application
- Configure Environment Variables
- Configure Persistent Storage
- Preempt known issues (permissions, health check)
- Deploy
- Post-deployment onboarding
Important: This workflow is specifically for Paperclip on Coolify v4. Other PaaS (Railway, Heroku) are not covered.
Phase 1: Discover Coolify Infrastructure
First, figure out where everything goes.
Ask the user (or infer from context) for:
- Their Coolify server's public IP address (e.g.,
YOUR_SERVER_IP) - Whether they use
sslip.ioor a custom domain - Whether they prefer creating a new project or using an existing one
- Their Coolify server's public IP address (e.g.,
If the IP is not given, try to find it:
- Use
coolify_list_serversto discover servers - Use
coolify_server_domainsorcoolify_get_serverto inspect them
- Use
Pick the FQDN for Paperclip:
- Default:
http://paperclip.<SERVER_IP>.sslip.io - If the user has a custom domain, substitute accordingly
- Ensure the scheme (
http://vshttps://) matches what the user actually types in their browser
- Default:
Phase 2: Create Project & Environment
In Coolify, every app lives in a Project inside an Environment (typically production).
If creating a new project:
- Call
coolify_projectswithaction: "create"name:"AI Infrastructure"(or user preference)- Optionally set
description
- The result contains
uuid— save this for later
If using an existing project:
- Call
coolify_projectswithaction: "list" - Ask the user to pick one, or use context to infer which
- Save its
uuid
Then get the environment:
- Call
coolify_environmentswithaction: "list"and the project UUID - Look for the environment named
production - Save its
uuid
Edge case: If
productiondoesn't exist, either use another environment or create one. Ask the user.
Phase 3: Add the Paperclip Application
This is the crucial step with several known failure modes.
Step 3a: Create Application Resource
Call coolify_application with:
action: "create"project_uuid: (from Phase 2)environment_uuid: (from Phase 2)name:"paperclip"description:"Paperclip AI - Open-source orchestration for zero-human companies"build_pack:"dockerfile"git_repository:"https://github.com/paperclipai/paperclip"git_branch:"master"— CRITICAL: Paperclip usesmaster, notmainports_exposes:"3100"server_uuid: (from Phase 1)
Common failure: Wrong branch
If git_branch is set to "main", deployment will fail with:
fatal: Remote branch main not found in upstream origin
If this error appears in logs later, immediately switch branch to "master" and redeploy.
Step 3b: Set FQDN
Call coolify_application with action: "update" and:
fqdn: The FQDN chosen in Phase 1 (e.g.,"http://paperclip.YOUR_SERVER_IP.sslip.io")
Step 3c: Ensure non-static deployment
Make sure the app is not marked as a static site. If the Coolify UI shows a static-site toggle, ensure it is unchecked.
Phase 4: Configure Environment Variables
Paperclip requires several environment variables to start correctly.
Required variables
Call coolify_env_vars in batch or individually for these:
| Key | Value | Notes |
|---|---|---|
HOST |
0.0.0.0 |
Accept connections from outside the container |
PAPERCLIP_HOME |
/paperclip |
Persistent data folder inside the container |
PAPERCLIP_PUBLIC_URL |
http://paperclip.<IP>.sslip.io |
Must match FQDN exactly, including http:// or https:// |
BETTER_AUTH_SECRET |
<64-char-hex> |
See below for how to generate |
PAPERCLIP_ALLOWED_HOSTNAMES |
paperclip.<IP>.sslip.io |
Without http:// prefix |
Generating BETTER_AUTH_SECRET
This must be a 64-character hex string. The agent should either:
- Ask the user to run
openssl rand -hex 32on the server, or - If there is a trusted way to execute commands on the server (e.g., Coolify terminal, local terminal with SSH access), run it and capture the output.
Why this matters: Paperclip uses this secret for authentication token encryption. A weak or missing secret prevents login.
Optional variable
| Key | Value | Notes |
|---|---|---|
PAPERCLIP_TELEMETRY_DISABLED |
1 |
Disables usage telemetry if desired |
After setting all variables, call coolify_application_logs or ask the user to verify the Environment Variables tab in Coolify.
Phase 5: Configure Persistent Storage
Without persistent storage, all Paperclip data (companies, agents, tasks) is lost on container restart.
Using Coolify Storage tab
- Navigate to the app's Storage (or Volumes) tab
- Click "+ Add Volume"
- Set Mount Type to "Directory Mount"
- Configure:
- Source Directory: auto-filled host path (e.g.,
/data/coolify/applications/YOUR_APP_UUID) - Destination Directory:
/paperclip
- Source Directory: auto-filled host path (e.g.,
- Save
Why this host path matters: Coolify generates a unique UUID folder per application under
/data/coolify/applications/on the host. Accept the auto-filled path unless the user intentionally customized their Coolify data directory.
Phase 6: Preempt Known Issues
Two issues will almost certainly happen if not handled proactively.
Issue A: Permission Denied on Volume
Root cause: The host directory is owned by root, but Paperclip runs inside the container as user node (UID 1000). It tries to write to /paperclip and gets EACCES permission denied.
Proactive fix (recommended):
- Find the exact host directory for this app's volume from Coolify
- Execute (or provide to the user):
sudo chown -R 1000:1000 /data/coolify/applications/YOUR_APP_UUID sudo chmod -R u+rwX /data/coolify/applications/YOUR_APP_UUID
Reactive fix: If the first deployment fails with the EACCES error, apply the chown commands above, redeploy, and it should work.
Issue B: Health Check Failures
Root cause: The container doesn't have curl, and Paperclip's startup takes longer than the default Coolify health-check interval.
Fix: Disable the health check.
- In Coolify, go to the app's Health Check tab
- Toggle "Health Check Enabled" to OFF
- Save
Alternatively, if the user wants to keep it on, increase:
- Retries:
10 - Start Period:
60 - Interval:
10
Recommendation: For first-time deployers, turn health check OFF to avoid the container being rolled back prematurely. Re-enable later once stable.
Phase 7: Deploy
- Call
coolify_deploywith the application tag or UUID - Wait for deployment logs
Expected success pattern in logs
Building docker image completed.
Rolling update started.
New container started.
Attempt 3 of 10 | Healthcheck status: "healthy"
New container is healthy.
Removing old containers.
Rolling update completed.
If deployment fails
| Symptom | Cause | Fix |
|---|---|---|
Remote branch main not found |
Wrong branch | Set branch to master, redeploy |
EACCES permission denied, mkdir '/paperclip/instances/default/logs' |
Host volume owned by root | Run chown -R 1000:1000 /data/coolify/applications/UUID |
New container is unhealthy |
Health check timing out | Turn health check OFF in Coolify, redeploy |
Build step skipped |
Coolify cached stale image | Force rebuild from deployment settings |
Phase 8: Post-Deployment Onboarding
Paperclip is running, but it's not fully configured until you run two interactive commands inside the container.
Step 8a: Find the container
Use one of these approaches:
Option 1 (agent-friendly):
docker ps -q --filter "publish=3100"
Option 2 (human-friendly, on the server):
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
Look for the one with port 3100 exposed. Copy that full name or ID.
Step 8b: Onboard Paperclip
Run inside the container (replace CONTAINER_ID with actual ID or UUID):
docker exec -it --user node CONTAINER_ID pnpm paperclipai onboard
What happens:
- Corepack may ask to download
pnpm— confirmY - Select "Quickstart" via arrow keys
- When asked if you want to start Paperclip now, say NO (Coolify already started it)
- Look for the server info screen — this confirms configuration
- Copy the CEO invite URL immediately. Example:
Invite URL: http://paperclip.YOUR_SERVER_IP.sslip.io/invite/pcp_bootstrap_0db2f2d2bc5610d3acaa3f47c58334607cd84d9f90697532 - Exit the container (
exitorCtrl+D)
Why "Quickstart"? It pre-configures an embedded PostgreSQL database and default company setup. Other options (like manual) are for advanced users.
Step 8c: Bootstrap CEO (if onboard didn't give an invite URL)
If onboarding did not output an invite link, run:
docker exec -it --user node CONTAINER_ID pnpm paperclipai auth bootstrap-ceo
Copy the resulting invite URL.
Step 8d: User opens invite URL
- Instruct the user to open the invite URL in their browser
- Fill in name, email, password
- They are now logged in as the CEO — top-level admin
Verification
Once complete, test with:
curl http://paperclip.<IP>.sslip.io
Expected: HTML from Paperclip's frontend.
Quick Reference: All Commands
Check containers
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
View Paperclip logs
docker logs $(docker ps -q --filter "publish=3100")
SSH into container as node user
docker exec -it --user node $(docker ps -q --filter "publish=3100") bash
Restart from Coolify CLI
coolify restart paperclip
Troubleshooting Summary
"Remote branch main not found"
- Cause: Branch set to
main - Fix: Change to
master, redeploy
"EACCES permission denied, mkdir '/paperclip/instances/default/logs'"
- Cause: Host volume owned by root, Paperclip runs as UID 1000
- Fix:
chown -R 1000:1000 /data/coolify/applications/UUID && chmod -R u+rwX ...
"New container is unhealthy"
- Cause: Health check timing or missing curl
- Fix: Turn Health Check OFF, redeploy
Can't access URL in browser
- DNS delay: Wait 2-3 minutes for
sslip.ioto propagate - Firewall: Ensure ports 80/443 are open
- FQDN mismatch: Verify
PAPERCLIP_PUBLIC_URLexactly matches browser URL - App crashed: Check deployment logs in Coolify
Invite URL doesn't work
- Cause:
PAPERCLIP_PUBLIC_URLorPAPERCLIP_ALLOWED_HOSTNAMESmismatched with actual browser URL - Fix: Ensure both match exactly (including
httpvshttps)
Version & Compatibility
- Tested on: Coolify v4 (latest stable / 4.x beta as of 2026-04)
- Paperclip source:
https://github.com/paperclipai/paperclip(branch:master) - Required ports: 3100 (container internal), 80/443 (host ingress)
- Required storage:
/paperclipinside container → host directory mount