OwnMaily Docs

Troubleshooting

Maintenance

Common issues and how to fix them. If the problem is not listed here, check the app container logs first - they usually tell you exactly what is wrong.

docker logs ownmaily-app-1 --tail 50

App container keeps restarting

The container starts, crashes, and Docker restarts it in a loop. This almost always means a configuration problem, not a bug.

Check the logs:

docker logs ownmaily-app-1

Common causes:

  • Missing or invalid DB_URL - the app cannot connect to Postgres. Check that your .env has a valid database URL and that the Postgres container is running (docker compose ps).
  • Missing required environment variable - the log will say something like "required env var X is not set". Check your .env file against the expected variables.
  • Port conflict - another process is using port 4400. Check with sudo lsof -i :4400 and either stop the conflicting process or change the port in your docker-compose.yml.

Page not found or blank page after install

You reach the server but get a 404 or a blank white page. This usually means the frontend assets are not loading correctly.

Open your browser developer tools (F12) and check the Console tab for errors. Common causes:

  • MIME type errors - the browser is refusing to execute JavaScript files because they are being served with the wrong content-type. This can happen if your reverse proxy (Nginx/Caddy) is not passing requests through to the app correctly.
  • Proxy configuration issue - make sure your Nginx or Caddy config is proxying all requests to localhost:4400, not just some paths.

SMTP test fails with a 403 or domain error

You try to send a test email and get a 403 or a message about your domain not being authorized.

This means your sending domain is not verified with your SMTP provider. Go to your provider's dashboard and check the domain verification status:

  • Resend: check Domains - it should show "Verified"
  • Mailgun: check Sending > Domains - it should show a green checkmark
  • SES: check Verified identities - it should show "Verified"

If verification is pending, wait a few minutes for DNS to propagate and check again. If it has been more than an hour, double-check that you added the DNS records to the correct domain.

Subscribers click unsubscribe or tracking links in emails and get a "site can't be reached" error or land on the wrong page.

This means your INSTALLATION_URL is wrong. The URL stored in your .env is what OwnMaily uses to build every link in every email.

Check the current value:

grep INSTALLATION_URL ~/ownmaily/.env

It should be the publicly reachable URL for your instance, including the protocol (https://). See What is the Installation URL? for guidance on setting it correctly.

After fixing the value, restart the stack:

cd ~/ownmaily && docker compose up -d

Health check timed out during install

The install script ran the health check but the app never responded in time, and the script exited with an error.

Check what the app is doing:

docker logs ownmaily-app-1

If the logs show database migration errors, the Postgres container may have started slowly and the app tried to connect before it was ready. Try restarting:

cd ~/ownmaily && docker compose restart

If the logs show the app started and is listening on port 4400 but the health check still failed, there may be a firewall issue. Check that your server's firewall allows traffic on port 4400 (or 80/443 if you have a reverse proxy in front).

Forgot your password

There is no password reset flow yet. To reset your password, connect to the database directly and update the owner record.

Get a shell inside the Postgres container:

docker exec -it ownmaily-db-1 psql -U ownmaily -d ownmaily

Generate a bcrypt hash of your new password using a tool like bcrypt.online (cost factor 12), then update the record:

UPDATE users SET password_hash = '$2a$12$...' WHERE email = '[email protected]';

Exit with \q and log in with your new password.

Password reset is on the roadmap. This workaround will not be needed in a future version. For now, it is a reliable way to regain access.