Skip to main content
Change the default password before deploying publicly. The .env.example placeholder values for Auth__Jwt__Secret, Auth__BootstrapSuperAdmin__Password, and Auth__ApiKey__Keys__0 are not safe for production. Replace all of them with strong, randomly generated values.

Deployment topologies

Choose the topology that matches your setup. The key difference between them is how you point the frontend at the backend API.
The simplest option. Frontend and backend run on the same machine with their default ports. Use this for local testing, single-machine setups, or internal network deployments.
FRONTEND_VITE_API_BASE_URL=http://localhost:5121
Storage__PublicBaseUrl=http://localhost:5121/content
Default addresses after docker compose up -d --build:
ServiceAddress
Public galleryhttp://localhost:5173/gallery
Admin consolehttp://localhost:5173/login
Backend APIhttp://localhost:5121

Environment variables

These are the variables you configure in your .env file. The compose.yaml passes them into the containers automatically.

Required

VariableDescription
Persistence__Database__ConnectionStringPostgreSQL connection string. Example: Host=postgres;Port=5432;Database=nekohub;Username=nekohub;Password=yourpassword;Pooling=true
Auth__Jwt__SecretSecret key used to sign JWT tokens. Must be at least 32 characters. Use a strong random value.
Auth__BootstrapSuperAdmin__UsernameUsername for the initial SuperAdmin account. Created once when the database has no SuperAdmin.
Auth__BootstrapSuperAdmin__PasswordPassword for the initial SuperAdmin account.
Storage__ProviderActive storage backend. One of: local, s3, github-repo.
Storage__PublicBaseUrlBase URL for public asset URLs. Used by the gallery and public content links.

Frontend

VariableDescription
FRONTEND_VITE_API_BASE_URLURL the browser uses to reach the backend API. Leave empty if using a same-origin reverse proxy.
FRONTEND_VITE_ALLOWED_HOSTSHosts allowed to serve the frontend preview. Set to true to allow all, or a comma-separated list of domains.

API key (optional)

VariableDescription
Auth__ApiKey__EnabledSet to true to enable API key authentication. Required for MCP and script integrations.
Auth__ApiKey__Keys__0The API key value. Add more keys as Keys__1, Keys__2, etc.
Auth__BootstrapSuperAdmin__* only runs once — when the database has no SuperAdmin user. Subsequent restarts do not re-create or overwrite the account. Additional users are managed from the admin console /users page.

JWT tuning (optional)

VariableDefaultDescription
Auth__Jwt__IssuerNekoHubJWT issuer claim.
Auth__Jwt__AudienceNekoHub.AdminJWT audience claim.
Auth__Jwt__AccessTokenMinutes15Access token lifetime in minutes.
Auth__Jwt__RefreshTokenDays30Refresh token lifetime in days.

Verifying your deployment

After starting the containers, run these checks to confirm everything is working: Backend health:
curl http://localhost:5121/api/v1/system/ping
curl http://localhost:5121/api/v1/system/bootstrap
Public assets API:
curl "http://localhost:5121/api/v1/public/assets?page=1&pageSize=20"
Login endpoint:
curl -X POST "http://localhost:5121/api/v1/auth/login" \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"<your-superadmin-password>"}'
A successful login response includes an accessToken and a refreshToken.

Fixing the “host not allowed” error

If you access NekoHub via a custom domain and see an error like:
Request blocked. This host ("nekohub.example.com") is not allowed.
This is not a backend authentication error. It is the frontend container’s Vite preview server rejecting the Host header. Fix it by setting FRONTEND_VITE_ALLOWED_HOSTS in your .env:
# Allow all hosts (convenient, less strict):
FRONTEND_VITE_ALLOWED_HOSTS=true

# Or allow a specific domain only:
FRONTEND_VITE_ALLOWED_HOSTS=nekohub.example.com
Then rebuild the frontend container:
docker compose up -d --build nekohub-web

Production checklist

Before going live, verify each of these.
  • Replace all placeholder values in .env with strong, randomly generated secrets
  • Use a persistent PostgreSQL instance (not an ephemeral container for production data)
  • Enable HTTPS for the frontend, API, and /content URLs
  • If using split-domain, update both FRONTEND_VITE_API_BASE_URL and Storage__PublicBaseUrl to your HTTPS URLs
  • Set FRONTEND_VITE_ALLOWED_HOSTS to your actual domain
  • If you need MCP or script access, configure Auth__ApiKey__Enabled and Auth__ApiKey__Keys__0