ScanopyScanopy

Troubleshooting

Common issues and solutions for self-hosted Scanopy server deployments.

For daemon-related issues, see Daemon Troubleshooting. If an image pull or download fails, see Docker Pull or Download Fails.

Server Issues

Port Already in Use

Symptoms: Server fails to start with "address already in use"

Solution: Change the port mapping in your compose file:

ports:
  - '8080:60072' # Change 8080 to any available port

Browser Shows "SSL Protocol Error"

Symptoms: Browser displays "ERR_SSL_PROTOCOL_ERROR" when accessing Scanopy

Cause: Using https:// instead of http://. Scanopy doesn't handle TLS directly.

http://your-server:60072

Solution: Use http:// to access Scanopy directly. For HTTPS, put a reverse proxy (Traefik, Nginx, Caddy) in front to handle TLS termination.

PostgreSQL "Could not create any Unix-domain sockets" (Proxmox)

Symptoms: PostgreSQL container fails to start on Proxmox host with socket creation error

Cause: AppArmor security policy blocking socket creation.

Solution: Add to both the postgres and server services in your compose file:

security_opt:
  - apparmor:unconfined

See issue #87 for details.

Integrated Daemon Not Initializing

Symptoms: Integrated daemon shows in UI but doesn't start discovery

Diagnosis:

# Check daemon logs
docker logs scanopy-daemon

# Check that the server can reach the daemon
docker compose exec server curl http://host.docker.internal:60073/api/health

Solutions:

  1. Check the server's route to the daemon: The daemon runs with host networking, and the server reaches it at http://host.docker.internal:60073. The server service needs extra_hosts: ["host.docker.internal:host-gateway"] for that name to resolve, as in the shipped compose file. If you changed the daemon's port or network mode, update SCANOPY_INTEGRATED_DAEMON_URL to match.

  2. Check the daemon record: Server setup provisions the integrated daemon and its API key. Confirm the daemon appears in Discover > Daemons and that its daemon-config volume still holds the key — a wiped volume leaves the daemon with no identity to present.

Daemon Waits for /api/initialize After a Restart or Recreate

Symptoms: After pulling and recreating the containers, or any other container recreate, the daemon log shows:

Missing site ID — waiting for server to hit /api/initialize...

A daemon that authenticates with a shared site key instead logs 403 errors on every startup attempt, while its container still reports healthy.

Cause: Daemon images from v0.16.1 through v0.17.21 wrote config.json outside the daemon-config volume, so a recreate discarded the daemon's API key and identity. v0.17.22 and later write to the volume at either mount path, /root/.config/scanopy/daemon or /root/.config/daemon. The server provisions the integrated daemon only once, when the first user registers, so it never sends the key again.

Before upgrading from v0.17.21 or earlier, copy the config onto the volume while the old container is still running, then pull and recreate:

docker compose exec daemon sh -c 'mkdir -p /root/.config/scanopy/daemon && cp -rn /root/.config/daemon/. /root/.config/scanopy/daemon/'
docker compose pull
docker compose up -d

If the daemon already lost its config, upgrade to v0.17.22 or later first, then:

  • Integrated daemon: In Discover > Daemons, click Edit on the daemon, open the API Key tab and click Rotate Key. Add the new key to the daemon's environment in your compose file as SCANOPY_DAEMON_API_KEY=<key>, then recreate the containers. The daemon reconnects as the same daemon, with its host and history.

  • Daemon installed from the UI's compose file: Its compose file already sets SCANOPY_DAEMON_API_KEY, so it reconnects on its own. If the key is missing from the compose file, rotate it as above.

  • Daemon on a shared site key (installed before v0.17.5): Click Edit, open the API Key tab and click Bind a Key, then use the compose file it generates. The daemon keeps its record, host and history.

    To keep the shared key instead, add SCANOPY_ID=<daemon id> to the daemon's environment. The daemon id is the id field in the metadata section at the bottom of the Edit dialog. A config.json on the volume overrides SCANOPY_ID, so delete it as you recreate the container:

    docker compose exec daemon rm -f /root/.config/scanopy/daemon/config.json
    docker compose up -d

Integrated Daemon Still Shows Outdated After an Upgrade

Symptoms: After you upgrade the containers, the integrated daemon still shows Outdated. For any other daemon, see Upgrading Daemons.

Solutions:

  1. Verify the daemon is running the new image: the startup log prints the daemon version.

    docker compose logs daemon | head -20

    If it still shows the old version, the image wasn't pulled. Pull it and recreate the container:

    docker compose pull daemon
    docker compose up -d daemon
  2. Check that the daemon can reach the server: a daemon that can't connect can't report its version. Look for connection errors in the daemon logs.

    docker compose logs daemon

Emails Aren't Being Sent

Symptoms: Password reset, invite, or install-command emails never arrive. The UI reports only that Scanopy could not send the email and asks you to check the server logs.

Diagnosis: The server logs the mail server's reply, with its reply code and whether the failure was TLS or a timeout.

docker compose logs server 2>&1 | grep -i smtp

Check the log from startup as well. A partial SMTP configuration, or a relay the server could not build a transport for, disables email and says so at boot.

Solutions:

  1. Fill in every SMTP setting: relay, username, password, and sender email must all be set together. With any of them missing, email stays disabled. See SMTP Configuration.

  2. Check the port: SCANOPY_SMTP_PORT defaults to 465, which is implicit TLS. Providers that accept authenticated submission only on 587 with STARTTLS — Microsoft 365 among them — do not listen on 465, and the connection fails before authentication.

  1. Confirm the settings reach the container: the published compose files pass a .env beside them through to the server. In a compose file of your own, the server service needs its own env_file entry, or the variables set under environment.
  1. Trust a relay with a private certificate: if the log says the relay's certificate is signed by a CA the server doesn't trust, set SCANOPY_TRUSTED_CA_BUNDLE to a PEM file containing that CA. Encryption can't be turned off, so this is the only way to send through such a relay. See Trusted CA Certificates.

Database Issues

How to Backup Data

Scanopy stores all data in PostgreSQL. To back up and restore:

# Backup
docker compose exec -T postgres pg_dump -U postgres scanopy > scanopy_backup.sql

# Restore
docker compose exec -T postgres psql -U postgres scanopy < scanopy_backup.sql

How to Reset Password

If SMTP is configured, use the "Forgot Password" link on the login page.

If SMTP is not configured:

  1. Generate a new password hash using bcrypt
  2. Update the users table with the new hash
  3. Or, ask another Owner to delete and re-invite you

How to Delete All Data

To start fresh:

docker compose down -v  # Removes all volumes including database
docker compose up -d    # Start fresh

Reverse Proxy Setup

Configure your reverse proxy (Nginx, Traefik, Caddy) to forward traffic to port 60072. Forward every path, not only /api: the server also serves the web UI and share links.

For HTTPS, enable secure cookies in your compose file:

environment:
  - SCANOPY_USE_SECURE_SESSION_COOKIES=true

See Server Configuration for details.

Getting Help

If your issue isn't covered here:

On this page