Vulnsy Docs
Self-hosted

Troubleshooting

Fix common problems with a self-hosted Vulnsy installation, from startup errors and license status to file downloads, email delivery, sign-in and AI endpoints.

This page covers problems specific to running Vulnsy yourself. For problems inside the app, such as report exports, see the general Troubleshooting section.

Collect Information

sudo /opt/vulnsy/install.sh status    # containers, health, version and license status
sudo /opt/vulnsy/install.sh logs app  # follow the app log (Ctrl+C to stop)
curl -sS https://reports.example.com/api/health
curl -sS https://reports.example.com/api/version

Every run of the installer is logged in /opt/vulnsy/install.log. To run docker compose commands yourself, such as docker compose ps, run them as root from /opt/vulnsy, the directory that holds docker-compose.yml and .env.

Useful text to look for in the app log:

Log textMeaning
[self-hosted]Startup steps: instance ID, organization and first administrator
[health]A failed health check, with the error
S3 storage:The storage settings in use
Email:The email settings in use

Installer

SymptomCauseFix
./install.sh fails with Permission deniedThe package was extracted on a file system mounted without execute permission, often /tmpExtract the package somewhere else, such as your home directory, or run sudo bash install.sh ...
the package does not match its SHA256SUMSA file of the package is damaged or was changed, often by an incomplete downloadDownload the package again, and check it with sha256sum -c against its .sha256 file before extracting it
is not supported for the operating systemThe server does not run a supported distributionUse a supported server, or add --force to try anyway
ports in useAnother service listens on port 80, 443, 3000 or 9000Stop that service, or choose other ports with --app-port and --minio-port. For 80 and 443, use --no-tls with your own reverse proxy.
is built for linux/amd64 but this server is linux/arm64The package is for 64-bit x86 serversInstall on an x86-64 (amd64) server
Vulnsy data volumes exist but /opt/vulnsy/.env does notAn earlier installation left its data behind, without its .envPut that installation's .env back in the install directory, or restore a backup with install.sh restore. To delete the old data instead, run the docker volume rm command the message shows.
Vulnsy is already installed in another directoryOnly one installation can run on a serverPass that directory with --home, or uninstall it first

Startup

SymptomCauseFix
docker compose stops with run docker/generate-env.sh to create .env or required variable VULNSY_VERSION is missing a valueThe command was not run from the install directory, or .env is missing or damagedRun docker compose from /opt/vulnsy, which holds docker-compose.yml and .env. If VULNSY_VERSION is missing from .env, run sudo ./install.sh upgrade from the package of the installed version.
Starting the app fails with No such image: vulnsy/vulnsyVULNSY_VERSION in .env names a version whose package was never loadedSet VULNSY_VERSION back, or run sudo ./install.sh upgrade from the package of the version you want
The browser shows Vulnsy is not ready. An administrator should check the server logs for [self-hosted] errors. (HTTP 503)The first start has not finished, or a startup step failed: for example, INITIAL_ADMIN_EMAIL or INITIAL_ADMIN_PASSWORD is missing, or a database cannot be reachedRead the app log. If startup is still running, wait for it. If a [self-hosted] line reports an error, fix the setting it names in .env and run docker compose up -d app.
docker compose ps shows the app as health: starting or unhealthy during the first startThe first start applies the schema and loads the Vulnsy library before it serves requests. The healthcheck allows 60 seconds before failures count, and the first start can take longer.Wait, and follow the app log. The status changes to healthy once startup has finished and /api/health returns 200.
/api/health returns HTTP 503 with "status":"degraded"A database check failed. The checks field names it (controlPlane, shared or tenant), and a log line starting with [health] gives the error.Check that the postgres container is running and healthy, and that POSTGRES_PASSWORD and the database URLs in .env match the database
The browser shows 502 Bad Gateway, with the bundled CaddyThe app container is not running, or has not finished startingCheck docker compose ps and the app log
The app keeps restarting, and its log says the database was last run by a newer versionAn older version was started against a database that a newer version already usedRun sudo ./install.sh upgrade from the package of the newer version, or restore a backup taken with the older one. See Downgrading.

License

When a license is not valid, the License page explains why, and the app log records the reason.

SymptomCauseFix
After sign-in, every page redirects to /licenseNo license is installed, or the license has expired and its grace period has endedAn administrator installs a license or a renewal. See Licensing.
The license is invalid, with the reason instance_mismatchThe token was issued for a different installation, for example before a reinstall or a move to a new serverRequest a new license for the instance ID shown on the License page at vulnsy.com/offline-licensing, and install it
The license is invalid, with the reason clock_rollbackThe server clock was set back by more than a dayCorrect the system time, and keep it synchronized with NTP. The license is valid again once the clock is right.
A pasted token is rejectedThe token was changed when it was copied, for example cut short or split across linesCopy the whole token again, exactly as you received it
The license shows as not installed although VULNSY_LICENSE_FILE is setThe file is not mounted into the app container, or the app's user (UID 1001) cannot read itCheck the volume mount and the file's permissions. See Install a License.

Files and Downloads

The app log line starting with S3 storage: shows the storage endpoint and the URL used for download links.

SymptomCauseFix
Evidence images do not load and downloads failThe browser cannot reach the files host: its DNS record is missing, or the proxy does not forward it to MinIOCheck that FILES_HOST resolves to the server and that the proxy forwards it to MinIO (127.0.0.1:9000 with your own proxy)
The browser shows a certificate error for the files hostThere is no trusted certificate for FILES_HOST. Caddy could not obtain one (DNS, or ports 80 and 443 not reachable), a tls line was enabled in only one site block, your own certificate does not cover the files host, or users do not trust Caddy's root certificate (tls internal).Check docker compose logs caddy and fix the cause. See Install.
A download returns an XML error such as SignatureDoesNotMatchThe proxy changed the Host header, or serves the files host under a path prefix, so the request no longer matches its signatureForward the files host at its root, and pass the Host header through unchanged. S3_PUBLIC_ENDPOINT must be exactly https:// followed by FILES_HOST.
Download links point at minio:9000 or another internal addressS3_PUBLIC_ENDPOINT is emptySet S3_PUBLIC_ENDPOINT=https://${FILES_HOST} in .env and run docker compose up -d app
Large uploads failThe proxy in front of the app host limits request bodies to less than 50 MBAllow request bodies of at least 50 MB

Email

The app log line starting with Email: shows the SMTP server, port and TLS mode in use. Failed sends are also logged.

SymptomCauseFix
No email arrives at allSMTP_HOST is empty, so Vulnsy sends no email. The Email: log line reports that no transport is configured.Set the SMTP_* variables and run docker compose up -d app
Sending fails with connection, timeout or TLS errorsThe port and the TLS mode do not match. Port 465 needs SMTP_SECURE=true; ports 587 and 25 need SMTP_SECURE=false.Correct SMTP_PORT or SMTP_SECURE
The mail server rejects the sender or the loginEMAIL_FROM is empty or is not an address the server lets you send from (an empty value falls back to a vulnsy.com address), or the credentials are wrongSet EMAIL_FROM to an address your server accepts, and check SMTP_USER and SMTP_PASSWORD. For a relay without authentication, leave both empty.
Client portal emails go through a different serverAn SMTP server is set up under Admin > Email > Delivery, and it takes precedence for client emailsChange or turn off that setting

Emails sent to clients are also listed under Admin > Email > Logs.

Sign-in

SymptomCauseFix
The password from INITIAL_ADMIN_PASSWORD is rejectedINITIAL_ADMIN_PASSWORD is read only on the first start. After the first sign-in, the password you chose replaced it, and editing the variable later has no effect.Sign in with the password you chose, or have it reset as in the next row
An administrator has forgotten their passwordVulnsy stores only password hashes, so a password can be reset but not recoveredAnother administrator opens Admin > Users & Access, edits the account and enters a new password. The user must change it at the next sign-in. If email works, Forgot password? on the sign-in page emails a temporary password instead.
No administrator can sign inNo account with the Admin role is available to reset the othersContact Vulnsy support

Forgot password? replaces the current password immediately, and sends the temporary one by email only. Use it only when email delivery works. Otherwise the user is left without a working password until an administrator sets a new one.

AI Assistant

SymptomCauseFix
An endpoint is rejected with Endpoint must use HTTPS or Endpoint must be served on port 443 or 8443By default, an endpoint must use HTTPS on port 443 or 8443, at a public addressServe the model over HTTPS. For a model server on your own network, set AI_ALLOW_PRIVATE_ENDPOINTS=true and run docker compose up -d app.
An endpoint is rejected because it resolves to a private or reserved addressThe endpoint is on a private network, and AI_ALLOW_PRIVATE_ENDPOINTS is not trueSet AI_ALLOW_PRIVATE_ENDPOINTS=true and run docker compose up -d app
An endpoint is rejected because it resolves to a loopback or link-local addressThe URL uses localhost, 127.0.0.1 or another loopback or link-local address. These are always blocked: inside the container, localhost is the app itself.Use the server's LAN address or a Compose service name. See AI Options.
The AI assistant is not availableThe license does not include the AI assistant, or AI is turned offCheck the License page. An administrator turns AI on under Admin > Organization > AI Assistant.

Contacting Support

When you contact Vulnsy support, include the output of /api/version and the relevant log lines. Never send .env or a database dump: they contain your secrets and your data.

On this page