Deploy Kan with PostgreSQL and MinIO (S3-compatible storage) using Docker Compose, with clear steps and production notes.Documentation Index
Fetch the complete documentation index at: https://docs.kan.bn/llms.txt
Use this file to discover all available pages before exploring further.
What you’ll set up
Kan
Kan web app (Next.js), on port 3000.
PostgreSQL 15
PostgreSQL database for Kan.
MinIO (S3-compatible)
MinIO object storage (console port 9001, S3 API port 9000).
How it works
- Kan stores data in PostgreSQL.
- Kan uploads files (e.g., avatars) to MinIO over the S3 API.
- The browser fetches public files directly from MinIO’s public URL.
- The Next.js image optimizer in Kan must be explicitly allowed to fetch from your storage host.
NEXT_PUBLIC_BASE_URL→ the Kan siteNEXT_PUBLIC_STORAGE_URL→ the public S3 base URLNEXT_PUBLIC_STORAGE_DOMAIN→ the exact S3 hostname (no scheme)
Prerequisites
- Docker and Docker Compose
- Open local ports: 3000 (Kan), 5432 (Postgres), 9000/9001 (MinIO)
- A long random string for
BETTER_AUTH_SECRET(32+ chars)
For production you’ll want a reverse proxy (Traefik/Nginx/Caddy), valid TLS
certificates, and DNS for your domains (e.g.,
kan.example.com,
s3.example.com).Quick start
Set environment variables
Provide the minimum required configuration (local example):Optional (see README for full list): Email (
Issue #109 fix: make sure
NEXT_PUBLIC_STORAGE_DOMAIN exactly
equals the hostname that serves your images (no scheme, no port).EMAIL_FROM, SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD, SMTP_SECURE), OAuth/OIDC (GOOGLE_*, GITHUB_*, OIDC_*), auth toggles, Trello import, etc.Create or review Docker Compose files
You can start from the minimal compose at the repository root (
docker-compose.yml) and review the production-oriented settings in cloud/docker-compose.yml.Start with the minimal setup (web + postgres + minio) and ensure environment variables are passed to the web service.Docker Compose example
Docker Compose example
Ensure your
.env contains values that match this compose file.
For example:POSTGRES_URL=postgresql://kan:changeme@postgres:5432/kan_dbS3_ENDPOINT=http://s3.localtest.me:9000S3_ACCESS_KEY_ID=minioandS3_SECRET_ACCESS_KEY=minio123456789S3_FORCE_PATH_STYLE=trueNEXT_PUBLIC_STORAGE_URL=http://s3.localtest.me:9000NEXT_PUBLIC_STORAGE_DOMAIN=s3.localtest.meNEXT_PUBLIC_AVATAR_BUCKET_NAME=kan
Start services
- Kan: http://kan.localtest.me:3000
- MinIO Console: http://minio.localtest.me:9001
- MinIO S3 API: http://s3.localtest.me:9000
Initialize MinIO
- Log into the MinIO Console (http://minio.localtest.me:9001).
-
Create a bucket (e.g.,
kan). - For simple public avatars, apply a read-only policy so GET requests are allowed for objects:
Alternatively, keep the bucket private and use presigned URLs. In that case,
ensure your server and browser access paths are correctly configured.
Verify the setup
- Sign in to Kan and upload an avatar (Settings).
- Confirm the object is created in your MinIO bucket.
- The avatar should render without errors.
/_next/image with “url parameter is not allowed”:NEXT_PUBLIC_STORAGE_DOMAINmust exactly match the S3 hostname that serves images.NEXT_PUBLIC_STORAGE_URLshould use the same host (with scheme/port).- Ensure you’re using the latest Kan image.
Production setup
- Local
- Production
NEXT_PUBLIC_BASE_URL=http://kan.localtest.me:3000S3_ENDPOINT=http://s3.localtest.me:9000NEXT_PUBLIC_STORAGE_URL=http://s3.localtest.me:9000NEXT_PUBLIC_STORAGE_DOMAIN=s3.localtest.me- Keep
S3_FORCE_PATH_STYLE=truefor MinIO.
Troubleshooting
Files upload but don’t display
Files upload but don’t display
- If public: confirm GET is allowed on objects (bucket policy).
- If private: ensure presigned URLs are generated and valid.
- 403 AccessDenied indicates permissions, not CORS. CORS is not required for simple
<img>GETs.
Make the bucket public (read-only) with mc
Make the bucket public (read-only) with mc
Use your MinIO root credentials to allow anonymous reads:
Alternative: S3 bucket policy (AWS CLI)
Alternative: S3 bucket policy (AWS CLI)
If you prefer a bucket policy, apply a public-read policy for objects:
policy.json
Next.js optimizer 400 — url parameter is not allowed
Next.js optimizer 400 — url parameter is not allowed
- Exact match on
NEXT_PUBLIC_STORAGE_DOMAINwith your storage host. - Same host in
NEXT_PUBLIC_STORAGE_URL. - Update to the latest Kan image.
Next/Image: “url parameter is valid but upstream response is invalid”
Next/Image: “url parameter is valid but upstream response is invalid”
- This means Next.js accepted the URL, but the upstream returned a non-image (e.g., 403 HTML/XML).
- Fix: make the bucket/object publicly readable (see above), or use presigned URLs.
- Sanity test from the web network (replace with your image URL):
Connectivity checks
Connectivity checks
- The Kan container must reach
S3_ENDPOINT. - Verify DNS/ports inside the container (e.g.,
docker exec -it <kan-container> sh).