Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Docker Deployment

The easiest way to run FsPulse is with Docker. The container runs FsPulse as a background service with the web UI accessible on port 8080. You can manage roots, initiate scans, query data, and view results—all from your browser.


Quick Start

Get FsPulse running in three simple steps:

# 1. Pull the image
docker pull gtunesdev/fspulse:latest

# 2. Run the container
docker run -d \
  --name fspulse \
  -p 8080:8080 \
  -v fspulse-data:/data \
  gtunesdev/fspulse:latest

# 3. Access the web UI
open http://localhost:8080

That's it! The web UI is now running.

This basic setup stores all FsPulse data (database, config, logs) in a Docker volume and uses default settings. If you need to customize settings (like running as a specific user for NAS deployments, or changing the port), see the Configuration and NAS Deployments sections below.


Scanning Your Files

To scan directories on your host machine, you need to mount them into the container. FsPulse can then scan these mounted paths.

Mounting Directories

Add -v flags to mount host directories into the container. We recommend mounting them under /roots for clarity:

docker run -d \
  --name fspulse \
  -p 8080:8080 \
  -v fspulse-data:/data \
  -v ~/Documents:/roots/documents:ro \
  -v ~/Photos:/roots/photos:ro \
  gtunesdev/fspulse:latest

The :ro (read-only) flag is recommended for safety—FsPulse only reads files during scans and never modifies them.

Creating Roots in the Web UI

After mounting directories:

  1. Open http://localhost:8080 in your browser
  2. Navigate to Manage Roots in the sidebar
  3. Click Add Root
  4. Enter the container path: /roots/documents (not the host path ~/Documents)
  5. Click Create Root

Important: Always use the container path (e.g., /roots/documents), not the host path. The container doesn't know about host paths.

Once roots are created, you can scan them from the web UI and monitor progress in real-time.


For persistent deployments, Docker Compose is cleaner and easier to manage:

version: '3.8'

services:
  fspulse:
    image: gtunesdev/fspulse:latest
    container_name: fspulse
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      # Persistent data storage - REQUIRED
      # Must map /data to either a Docker volume (shown here) or a host path
      # Must support read/write access for database, config, and logs
      - fspulse-data:/data

      # Alternative: use a host path instead
      # - /path/on/host/fspulse-data:/data

      # Directories to scan (read-only recommended for safety)
      - ~/Documents:/roots/documents:ro
      - ~/Photos:/roots/photos:ro
    environment:
      # Optional: override any configuration setting
      # See Configuration section below and https://gtunes-dev.github.io/fspulse/configuration.html
      - TZ=America/New_York

volumes:
  fspulse-data:

Save as docker-compose.yml and run:

docker-compose up -d

Configuration

FsPulse creates a default config.toml on first run with sensible defaults. Most users won't need to change anything, but when you do, there are three ways to customize settings.

Option 1: Use Environment Variables (Easiest)

Override any setting using environment variables. This works with both docker run and Docker Compose.

Docker Compose example:

services:
  fspulse:
    image: gtunesdev/fspulse:latest
    environment:
      - FSPULSE_SERVER_PORT=9090      # Change web UI port
      - FSPULSE_LOGGING_FSPULSE=debug # Enable debug logging
      - FSPULSE_ANALYSIS_THREADS=16   # Use 16 analysis threads
    ports:
      - "9090:9090"

Command line example (equivalent to above):

docker run -d \
  --name fspulse \
  -p 9090:9090 \
  -e FSPULSE_SERVER_PORT=9090 \
  -e FSPULSE_LOGGING_FSPULSE=debug \
  -e FSPULSE_ANALYSIS_THREADS=16 \
  -v fspulse-data:/data \
  gtunesdev/fspulse:latest

Environment variables follow the pattern FSPULSE_<SECTION>_<FIELD> and override any settings in config.toml. See the Configuration chapter for a complete list of available variables and their purposes.

Option 2: Edit the Config File

If you prefer editing the config file directly:

  1. Extract the auto-generated config:

    docker exec fspulse cat /data/config.toml > config.toml
    
  2. Edit config.toml with your preferred settings

  3. Copy back and restart:

    docker cp config.toml fspulse:/data/config.toml
    docker restart fspulse
    

Option 3: Pre-Mount Your Own Config (Advanced)

If you want custom settings before first launch, create your own config.toml and mount it:

volumes:
  - fspulse-data:/data
  - ./my-config.toml:/data/config.toml:ro

Most users should start with Option 1 (environment variables) or Option 2 (edit after first run).


NAS Deployments (TrueNAS, Unraid)

NAS systems often have specific user IDs for file ownership. By default, FsPulse runs as user 1000, but you may need it to match your file ownership.

Setting User and Group IDs

Use PUID and PGID environment variables to run FsPulse as a specific user:

TrueNAS Example (apps user = UID 34):

docker run -d \
  --name fspulse \
  -p 8080:8080 \
  -e PUID=34 \
  -e PGID=34 \
  -e TZ=America/New_York \
  -v /mnt/pool/fspulse/data:/data \
  -v /mnt/pool/documents:/roots/docs:ro \
  gtunesdev/fspulse:latest

Unraid Example (custom UID 1001):

docker run -d \
  --name fspulse \
  -p 8080:8080 \
  -e PUID=1001 \
  -e PGID=100 \
  -v /mnt/user/appdata/fspulse:/data \
  -v /mnt/user/photos:/roots/photos:ro \
  gtunesdev/fspulse:latest

Why PUID/PGID Matters

Even though you mount directories as read-only (:ro), Linux permissions still apply. If your files are owned by UID 34 and aren't world-readable, FsPulse (running as UID 1000 by default) won't be able to scan them. Setting PUID=34 makes FsPulse run as the same user that owns the files.

When to use PUID/PGID:

  • Files have restrictive permissions (not world-readable)
  • Using NAS with specific user accounts (TrueNAS, Unraid, Synology)
  • You need the /data directory to match specific host ownership

Using the CLI

While the web UI provides full functionality, you can also use CLI commands via docker exec:

# Run a query
docker exec fspulse fspulse query "items where scan:(5)"

# View reports
docker exec fspulse fspulse report scans --last 10

# Interactive menu (requires -it flags)
docker exec -it fspulse fspulse interact

# Data explorer TUI (requires -it flags)
docker exec -it fspulse fspulse explore

The -it flags are required for interactive modes (interact and explore) to properly handle terminal input.

Helper script (optional): Create fspulse-docker.sh to simplify CLI access:

#!/bin/bash
docker exec fspulse fspulse "$@"

Then use it: ./fspulse-docker.sh query "items limit 10"


Advanced Topics

Custom Network Settings

If you're using macvlan or host networking, ensure the server binds to all interfaces:

services:
  fspulse:
    image: gtunesdev/fspulse:latest
    network_mode: host
    environment:
      - FSPULSE_SERVER_HOST=0.0.0.0  # Required for non-bridge networking
      - FSPULSE_SERVER_PORT=8080

Note: The Docker image sets FSPULSE_SERVER_HOST=0.0.0.0 by default, so this is only needed if your config.toml overrides it to 127.0.0.1.

Reverse Proxy Setup

For public access with authentication, use a reverse proxy like nginx:

server {
    listen 80;
    server_name fspulse.example.com;

    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;

        # WebSocket support for scan progress
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Using Bind Mounts Instead of Volumes

By default, we use Docker volumes (-v fspulse-data:/data) which Docker manages automatically. For NAS deployments, you might prefer bind mounts to integrate with your existing backup schemes:

# Create directory on host
mkdir -p /mnt/pool/fspulse/data

# Use bind mount
docker run -d \
  --name fspulse \
  -p 8080:8080 \
  -v /mnt/pool/fspulse/data:/data \  # Bind mount to host path
  gtunesdev/fspulse:latest

Benefits of bind mounts for NAS:

  • Included in your NAS snapshot schedule
  • Backed up with your existing backup system
  • Directly accessible for manual inspection

Trade-off: You need to manage permissions yourself (use PUID/PGID if needed).


Troubleshooting

Cannot Access Web UI

Problem: http://localhost:8080 doesn't respond

Solutions:

  1. Check the container is running:

    docker ps | grep fspulse
    
  2. Check logs for errors:

    docker logs fspulse
    

    Look for "Server started" message.

  3. Verify port mapping:

    docker port fspulse
    

    Should show 8080/tcp -> 0.0.0.0:8080

Permission Denied Errors

Problem: "Permission denied" when scanning or accessing /data

Solutions:

  1. Check file ownership:

    ls -ln /path/to/your/files
    
  2. Set PUID/PGID to match file owner:

    docker run -e PUID=1000 -e PGID=1000 ...
    
  3. For bind mounts, ensure host directory is writable:

    chown -R 1000:1000 /mnt/pool/fspulse/data
    

Interactive Mode Doesn't Work

Problem: fspulse interact or fspulse explore looks broken in docker exec

Solution: Use -it flags for proper terminal:

# Wrong (missing -it)
docker exec fspulse fspulse interact

# Correct
docker exec -it fspulse fspulse interact

Configuration Changes Don't Persist

Problem: Settings revert after container restart

Solution: Verify /data volume is mounted:

docker inspect fspulse | grep -A 10 Mounts

If missing, recreate container with volume:

docker stop fspulse
docker rm fspulse
docker run -d --name fspulse -v fspulse-data:/data ...

Database Locked Errors

Problem: "Database is locked" errors

Cause: Multiple containers accessing the same database

Solution: Only run one FsPulse container per database. Don't mount the same /data volume to multiple containers.


Data Backup

Backing Up Your Data

For Docker volumes:

# Stop container
docker stop fspulse

# Backup volume
docker run --rm \
  -v fspulse-data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/fspulse-backup.tar.gz /data

# Restart container
docker start fspulse

For bind mounts:

# Simply backup the host directory
tar czf fspulse-backup.tar.gz /mnt/pool/fspulse/data

Restoring from Backup

For Docker volumes:

# Create volume
docker volume create fspulse-data-restored

# Restore data
docker run --rm \
  -v fspulse-data-restored:/data \
  -v $(pwd):/backup \
  alpine sh -c "cd / && tar xzf /backup/fspulse-backup.tar.gz"

# Use restored volume
docker run -d --name fspulse -v fspulse-data-restored:/data ...

For bind mounts:

tar xzf fspulse-backup.tar.gz -C /mnt/pool/fspulse/data

Image Tags and Updates

FsPulse provides multiple tags for different update strategies:

TagDescriptionWhen to Use
latestLatest stable releaseProduction (pinned versions)
1.2.3Specific versionProduction (exact control)
1.2Latest patch of minor versionProduction (auto-patch updates)
mainDevelopment buildsTesting new features

Recommendation: Use specific version tags (1.2.3) or minor version tags (1.2) for production. Avoid latest in production to prevent unexpected updates.

Updating to a new version:

docker pull gtunesdev/fspulse:1.2.3
docker stop fspulse
docker rm fspulse
docker run -d --name fspulse -v fspulse-data:/data ... gtunesdev/fspulse:1.2.3

Your data persists in the volume across updates.


Platform Support

FsPulse images support multiple architectures—Docker automatically pulls the correct one for your platform:

  • linux/amd64 - Intel/AMD processors (most common)
  • linux/arm64 - ARM processors (Apple Silicon, Raspberry Pi 4, ARM servers)

Next Steps


Getting Help