Skip to main content

Docker Installation

BugPin is a self-hosted visual bug reporting tool that can be installed with Docker in under 2 minutes. This guide covers Docker Compose setup, bind mounts and named volumes, file permissions, data persistence, backup, and updating to new releases.

Prerequisites

  • Docker Engine 20.10+ and Docker Compose v2+ installed
  • CPU: 1 core minimum (2 cores recommended for production)
  • RAM: 512MB minimum, 1GB recommended for production
  • Disk: 1GB minimum for the application; additional space depends on screenshot and attachment volume (plan for 10–50MB per 1,000 reports)
  • A Linux, macOS, or Windows host

Quick Start

mkdir bugpin && cd bugpin
curl -O https://raw.githubusercontent.com/aranticlabs/bugpin/main/docker-compose.yml
docker compose up -d

BugPin is now running at http://localhost:7300

Docker Command

docker run -d --restart=always -p 7300:7300 -v bugpin-data:/data --name bugpin registry.arantic.cloud/bugpin/bugpin:latest

Bun

Requirements:

  • Bun v1.1 or later
  • Git
git clone https://github.com/aranticlabs/bugpin.git
cd bugpin
bun install
bun run build
bun run start

BugPin is now running at http://localhost:7300

File Permissions for Bind Mounts

If you're using a bind mount (./data:/data), you need to set proper permissions for the data directory:

# Option 1: If you know the UID (usually 1000 for bun user)
sudo chown -R 1000:1000 ./data
# Option 2: Check the exact UID first (to be sure)
docker run --rm registry.arantic.cloud/bugpin/bugpin:main id bun
# This will show: uid=1000(bun) gid=1000(bun) groups=1000(bun)
# Then use that UID:
sudo chown -R 1000:1000 ./data
Alternative: Use Named Volumes

If you don't want to manage permissions, use a named volume instead of a bind mount in your docker-compose.yml:

volumes:
- bugpin-data:/data

volumes:
bugpin-data:
driver: local

Named volumes are managed by Docker and don't require manual permission setup.

Manual Docker Compose Setup

1. Create the Docker Compose file

Create a file named docker-compose.yml:

docker-compose.yml
services:
bugpin:
image: registry.arantic.cloud/bugpin/bugpin:latest
container_name: bugpin
restart: unless-stopped
ports:
- "7300:7300"
volumes:
- ./data:/data
environment:
- LOG_LEVEL=info
healthcheck:
test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://localhost:7300/health"]
interval: 30s
timeout: 3s
retries: 3
start_period: 10s

2. Start BugPin

docker compose up -d

3. Login and change password

Open http://localhost:7300 and login with:

  • Email: admin@example.com
  • Password: changeme123
warning

Change the default password immediately after first login in Settings → Users.

That's it! BugPin is now running.

What's Configured Automatically

  • Session key: Generated automatically and stored in the data volume
  • Database: SQLite, stored in the data volume
  • Admin account: Created on first run with default credentials

Data Persistence

BugPin uses Docker volumes to persist data. Understanding how volumes work is important for backups, migrations, and troubleshooting.

Volume Configuration

The default configuration uses a bind mount:

volumes:
- ./data:/data

What this means:

  • ./data - Directory on your host machine (same location as docker-compose.yml)
  • /data - Directory inside the container where BugPin stores data

Example: If you place docker-compose.yml in /home/user/bugpin/, Docker will create /home/user/bugpin/data/ and mount it to /data inside the container.

What Gets Stored

Inside the ./data directory, you'll find:

./data/
├── bugpin.db # SQLite database (all reports, users, settings)
├── .secret # Auto-generated session encryption key
└── uploads/ # User-uploaded files
├── screenshots/ # Bug report screenshots
├── attachments/ # File attachments
└── branding/ # Custom logo and branding assets

Bind Mount vs Named Volume

Option 1: Bind Mount (Default, Recommended)

volumes:
- ./data:/data

Advantages:

  • Easy to find and access (right next to docker-compose.yml)
  • Simple to backup (just copy the folder)
  • Easy to inspect files directly
  • Simple to migrate (move the entire directory)

Disadvantages:

  • Can be accidentally deleted
  • Permissions can be tricky on some systems

Option 2: Named Volume

volumes:
- bugpin-data:/data

volumes:
bugpin-data:
driver: local

Advantages:

  • Managed by Docker (stored in /var/lib/docker/volumes/)
  • Better isolation and permissions
  • Less likely to be accidentally deleted

Disadvantages:

  • Harder to find and access directly
  • More complex backup process
  • Need to use docker volume commands

Backup

For bind mounts (default):

# Stop the container
docker compose down

# Backup the data directory
tar -czf bugpin-backup-$(date +%Y%m%d).tar.gz ./data

# Restart
docker compose up -d

For named volumes:

# Stop the container
docker compose down

# Backup the named volume
docker run --rm \
-v bugpin-data:/data \
-v $(pwd):/backup \
alpine tar -czf /backup/bugpin-backup-$(date +%Y%m%d).tar.gz /data

# Restart
docker compose up -d

Restore

For bind mounts:

docker compose down
rm -rf ./data
tar -xzf bugpin-backup-20260103.tar.gz
docker compose up -d

For named volumes:

docker compose down
docker volume rm bugpin-data
docker volume create bugpin-data
docker run --rm \
-v bugpin-data:/data \
-v $(pwd):/backup \
alpine tar -xzf /backup/bugpin-backup-20260103.tar.gz -C /
docker compose up -d

Migration to Another Server

With bind mount (easiest):

# On old server
docker compose down
tar -czf bugpin-full.tar.gz docker-compose.yml data/

# Copy to new server
scp bugpin-full.tar.gz user@newserver:/opt/bugpin/

# On new server
tar -xzf bugpin-full.tar.gz
docker compose up -d

Custom Data Location

To store data in a different location:

volumes:
- /path/to/your/data:/data

For example, to use a dedicated data partition:

volumes:
- /mnt/data/bugpin:/data

Troubleshooting Volumes

Check what's stored in the volume:

# For bind mount
ls -lah ./data

# For named volume
docker run --rm -v bugpin-data:/data alpine ls -lah /data

Check disk usage:

# For bind mount
du -sh ./data

# For named volume
docker system df -v | grep bugpin

Fix permissions (if container can't write to bind mount):

sudo chown -R 1000:1000 ./data

Update

Before updating, make sure to back up your data so you can roll back if needed.

Pull and Restart

docker compose pull && docker compose up -d
note

Database migrations run automatically on startup — no manual steps are needed.

Verify the Update

Check the container is running and healthy

docker compose ps

Check logs for any migration or startup errors

docker compose logs --tail 50

Rolling Back

If something goes wrong, revert to the previous image:

docker compose down
# Restore your data backup
cp -r ./data-backup-YYYYMMDD ./data

Pin the previous version in docker-compose.yml and restart

docker compose up -d

Custom Port

To use a different port, edit the ports section:

ports:
- "8080:7300" # Access on port 8080

Reverse Proxy

For production deployments, place BugPin behind a reverse proxy with SSL.

Nginx Example

server {
listen 443 ssl http2;
server_name bugs.yourdomain.com;

ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;

location / {
proxy_pass http://localhost:7300;
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;
client_max_body_size 10M;
}
}

Traefik Example

Add labels to your docker-compose.yml:

services:
bugpin:
# ... existing configuration ...
labels:
- "traefik.enable=true"
- "traefik.http.routers.bugpin.rule=Host(`bugs.yourdomain.com`)"
- "traefik.http.routers.bugpin.entrypoints=websecure"
- "traefik.http.routers.bugpin.tls.certresolver=letsencrypt"
- "traefik.http.services.bugpin.loadbalancer.server.port=7300"

Health Check

BugPin includes automatic health monitoring:

docker inspect --format='{{.State.Health.Status}}' bugpin

Next Steps

We use cookies for analytics to improve our website. More information in our Privacy Policy.