Environment Variables
⚠️ BREAKING CHANGE — Tina4 v3.12.0
Every framework env var now requires the
TINA4_prefix. The legacy un-prefixed names (DATABASE_URL,SECRET,SMTP_HOST,HOST_NAME, etc.) no longer work. Setting them at startup makes the framework refuse to boot with a list of renames.Run
tina4 env --migrateto rewrite your existing.envautomatically, or rename manually using the table below. The runtime guard prints the same mapping if it detects legacy names.Conventional names stay un-prefixed:
PORT,HOST,NODE_ENV,RACK_ENV,RUBY_ENV,ENVIRONMENT. These are runtime/PaaS conventions, not framework config.
Tina4 is configured through environment variables, read from .env at the project root. Every variable has a sensible default — most projects set three or four values and leave the rest alone.
This chapter lists every variable the PHP framework reads, grouped by subsystem. Start with the minimum-config examples at the end, then come back here when you need to tune something specific.
Core Server
| Variable | Default | Description |
|---|---|---|
HOST | 0.0.0.0 | Bind address. 0.0.0.0 listens on every interface. 127.0.0.1 restricts to localhost. |
TINA4_HOST | 0.0.0.0 | Tina4-specific bind override consulted by App::serve() and Server when no $host argument is passed. Wins over the conventional HOST for the framework's own server. |
PORT | 7145 | HTTP server port. The Rust CLI prefers TINA4_PORT but falls back to PORT. |
TINA4_PORT | (inherits PORT) | Explicit Tina4-specific port override. Takes precedence over PORT when both are set. |
TINA4_WS_PORT | (inherits port) | Separate port for the WebSocket server. Leave unset to share the HTTP port. |
TINA4_HOST_NAME | localhost:7145 | Fully-qualified host used in generated absolute URLs (Swagger, OAuth redirects, emails). |
TINA4_DEBUG | false | Master debug toggle. Enables Swagger UI, dev dashboard, live reload, template dump filter, error overlay. Never set to true in production. |
TINA4_LOG_LEVEL | ERROR | Minimum message level shown when TINA4_DEBUG=true. Options: DEBUG, INFO, WARNING, ERROR, ALL. |
TINA4_NO_BROWSER | false | Stops tina4 serve from opening your browser on every restart. Recommended during active development. |
TINA4_NO_RELOAD | false | Disables the dev hot-reload signal from the Rust CLI. Use when you want a stable server for debugging. |
TINA4_SUPPRESS | false | Hides the Tina4 startup banner. Useful in CI and systemd units where stdout is ingested. |
TINA4_VERSION | (framework) | Override the version string reported by /__dev/api/system. Mostly for testing. |
TINA4_CLI_SERVE | (none) | Set internally by the Rust CLI to signal managed mode. Do not set manually. |
TINA4_PUBLIC_DIR | (empty) | Override directory served as static files at /. When unset, the static-file middleware searches src/public/ and the framework's bundled public assets. |
TINA4_TEMPLATE_ROUTING | on | Auto-routing of Twig templates from src/templates/. Set to off, false, 0, no, or disabled to require explicit Router::get() for every URL. |
TINA4_ALLOW_LEGACY_ENV | false | Bypass the v3.12 boot guard that rejects un-prefixed legacy env vars (DATABASE_URL, SECRET, SMTP_HOST, etc.). Use only in CI / migration scripts during the transition window. |
TINA4_ENV_FILE | .env | Alternate path for the dotenv file loaded at boot. Resolved relative to the project root unless absolute. Useful for per-environment files (e.g. .env.production) without symlinking. |
TINA4_HEALTH_PATH | /health | Path the built-in health-check route registers under. Set /__health to align with the v3 documented alias used by the other frameworks; the default keeps /health for back-compat with existing probes. |
Routing
| Variable | Default | Description |
|---|---|---|
TINA4_TRAILING_SLASH_REDIRECT | false | When truthy, any request path ending in / (other than the bare root) is 301-redirected to the slash-stripped form. The query string is preserved. Lets you normalise URLs without writing per-route handlers. |
Secrets and Authentication
| Variable | Default | Description |
|---|---|---|
TINA4_SECRET | (empty) | JWT signing secret. Must be long, random, and unique per environment. Never commit. |
TINA4_JWT_ALGORITHM | HS256 | JWT signing algorithm. Supports HS256, HS384, HS512. |
TINA4_TOKEN_LIMIT | 60 | JWT token lifetime in minutes. |
TINA4_API_KEY | (empty) | Static API key used by Auth::validateApiKey() as a fallback to JWT. |
Database
| Variable | Default | Description |
|---|---|---|
TINA4_DATABASE_URL | sqlite:///data/app.db | Connection URL. Scheme selects the driver: sqlite, postgres, mysql, mssql, sqlserver, firebird. |
TINA4_DATABASE_USERNAME | (empty) | Overrides the username embedded in TINA4_DATABASE_URL. |
TINA4_DATABASE_PASSWORD | (empty) | Overrides the password embedded in TINA4_DATABASE_URL. |
TINA4_DATABASE_FIREBIRD_PATH | (empty) | Overrides the database path/alias parsed from TINA4_DATABASE_URL for Firebird. Useful for Windows backslash paths and split-config setups. |
TINA4_DATABASE_URL | (empty) | Legacy alias for TINA4_DATABASE_URL. Prefer TINA4_DATABASE_URL in new projects. |
TINA4_AUTOCOMMIT | false | Auto-commit after every write. Default is off — call commit() explicitly. |
TINA4_DB_CACHE | false | Enables in-memory query-result caching for read queries. |
TINA4_DB_CACHE_TTL | 60 | Query cache TTL in seconds when TINA4_DB_CACHE=true. |
TINA4_DB_POOL | 0 | Default connection-pool size used when a caller constructs Database without passing $pool. 0 keeps the single-connection behaviour; values above zero enable pooled adapters lazily. An explicit constructor argument always wins. |
TINA4_MIGRATION_ID | (timestamp) | Override the migration ID used when recording applied migrations. |
CORS
| Variable | Default | Description |
|---|---|---|
TINA4_CORS_ORIGINS | * | Comma-separated allowed origins. Lock down to real domains in production. |
TINA4_CORS_METHODS | GET,POST,PUT,PATCH,DELETE,OPTIONS | Allowed request methods. |
TINA4_CORS_HEADERS | Content-Type,Authorization,X-Requested-With | Allowed request headers. |
TINA4_CORS_CREDENTIALS | false | Send Access-Control-Allow-Credentials: true. Required for cross-origin cookies. |
TINA4_CORS_MAX_AGE | 600 | Preflight cache lifetime in seconds. |
Security Headers
| Variable | Default | Description |
|---|---|---|
TINA4_CSP | default-src 'self' | Content-Security-Policy header. |
TINA4_CSRF | true | CSRF token validation on POST/PUT/PATCH/DELETE. Requires _csrf in the body or X-CSRF-Token header. |
TINA4_HSTS | (empty/off) | Strict-Transport-Security max-age in seconds. Set 31536000 in production with HTTPS. |
TINA4_FRAME_OPTIONS | DENY | X-Frame-Options header. Set SAMEORIGIN if you embed your own app in an iframe. |
TINA4_REFERRER_POLICY | strict-origin-when-cross-origin | Referrer-Policy header. |
TINA4_PERMISSIONS_POLICY | (empty) | Permissions-Policy header. Example: geolocation=(), microphone=(). |
Rate Limiting
| Variable | Default | Description |
|---|---|---|
TINA4_RATE_LIMIT | 100 | Maximum requests per window per IP. Set 0 to disable. |
TINA4_RATE_WINDOW | 60 | Rate-limit window in seconds. |
Sessions
| Variable | Default | Description |
|---|---|---|
TINA4_SESSION_BACKEND | file | Storage backend. Options: file, redis, valkey, mongo, database. |
TINA4_SESSION_HANDLER | (inherits _BACKEND) | Alternate handler class name. Overrides TINA4_SESSION_BACKEND. |
TINA4_SESSION_NAME | tina4_session | Cookie name written by the framework session manager. Distinct from TINA4_PHP_SESSION_NAME, which controls the native PHP session cookie. |
TINA4_SESSION_TTL | 3600 | Session expiry in seconds. |
TINA4_SESSION_SAMESITE | Lax | SameSite cookie attribute. Options: Strict, Lax, None. |
TINA4_SESSION_HTTPONLY | true | Emit the HttpOnly attribute on the session cookie. Leave on unless JavaScript genuinely needs to read the cookie. |
TINA4_SESSION_SECURE | false | Emit the Secure attribute on the session cookie. Setting TINA4_SESSION_SAMESITE=None forces this to true regardless of the value here. |
TINA4_SESSION_PATH | data/sessions | Filesystem path for the file backend. |
TINA4_PHP_SESSION_NAME | PHPSESSID | Cookie name used by native PHP $_SESSION (separate from the framework session). |
TINA4_PHP_SESSION_PATH | (system temp) | session.save_path for native PHP sessions. The framework configures it before session_start() so the SAPI and the built-in server share session storage. |
Redis/Valkey session backend
| Variable | Default | Description |
|---|---|---|
TINA4_SESSION_REDIS_HOST | localhost | Redis host. |
TINA4_SESSION_REDIS_PORT | 6379 | Redis port. |
TINA4_SESSION_REDIS_PASSWORD | (none) | Redis auth password. |
TINA4_SESSION_REDIS_DB | 0 | Redis database number. |
TINA4_SESSION_REDIS_URL | (none) | Full redis:// URL. Overrides the individual fields when set. |
TINA4_SESSION_VALKEY_HOST | localhost | Valkey host. |
TINA4_SESSION_VALKEY_PORT | 6379 | Valkey port. |
TINA4_SESSION_VALKEY_PASSWORD | (none) | Valkey auth password. |
TINA4_SESSION_VALKEY_DB | 0 | Valkey database number. |
MongoDB session backend
| Variable | Default | Description |
|---|---|---|
TINA4_SESSION_MONGO_URL | mongodb://localhost:27017 | MongoDB connection string. |
TINA4_SESSION_MONGO_DB | tina4 | MongoDB database name. |
Templates
| Variable | Default | Description |
|---|---|---|
TINA4_TEMPLATE_CACHE_TTL | 0 | Lifetime of compiled Frond templates in production, in seconds. 0 means cache forever (no filesystem checks per render); a positive value re-reads and re-tokenises a template once it has been cached for that long. Ignored when TINA4_DEBUG=true — debug mode always re-reads. |
Cache
| Variable | Default | Description |
|---|---|---|
TINA4_CACHE_BACKEND | memory | Response cache backend. Options: memory, file, redis. |
TINA4_CACHE_DIR | data/cache | Cache directory for the file backend. |
TINA4_CACHE_TTL | 60 | Default cache TTL in seconds. |
TINA4_CACHE_MAX_ENTRIES | 1000 | Maximum cache entries. Oldest entries evicted first. |
TINA4_CACHE_URL | (none) | Connection URL for remote cache backends (Redis, Memcached). |
Queues
| Variable | Default | Description |
|---|---|---|
TINA4_QUEUE_BACKEND | file | Queue backend. Options: file, kafka, rabbitmq, mongo, database. |
TINA4_QUEUE_PATH | data/queue | Filesystem path for the file backend. |
TINA4_QUEUE_URL | (none) | Connection URL for remote backends. |
Kafka queue backend
| Variable | Default | Description |
|---|---|---|
TINA4_KAFKA_BROKERS | localhost:9092 | Comma-separated broker list. |
TINA4_KAFKA_GROUP_ID | tina4_consumer_group | Kafka consumer group ID. |
RabbitMQ queue backend
| Variable | Default | Description |
|---|---|---|
TINA4_RABBITMQ_HOST | localhost | RabbitMQ host. |
TINA4_RABBITMQ_PORT | 5672 | RabbitMQ port. |
TINA4_RABBITMQ_USERNAME | guest | RabbitMQ username. |
TINA4_RABBITMQ_PASSWORD | guest | RabbitMQ password. |
TINA4_RABBITMQ_VHOST | / | RabbitMQ virtual host. |
MongoDB queue backend
| Variable | Default | Description |
|---|---|---|
TINA4_MONGO_URI | (none) | Full MongoDB connection string. Overrides host/port when set. |
TINA4_MONGO_HOST | localhost | MongoDB host. |
TINA4_MONGO_PORT | 27017 | MongoDB port. |
TINA4_MONGO_USERNAME | (none) | MongoDB username. |
TINA4_MONGO_PASSWORD | (none) | MongoDB password. |
TINA4_MONGO_DB | tina4 | MongoDB database name. |
TINA4_MONGO_COLLECTION | tina4_queue | MongoDB collection name for jobs. |
WebSocket Backplane
| Variable | Default | Description |
|---|---|---|
TINA4_WS_BACKPLANE | (none) | Backplane type. Set redis for multi-instance broadcasts. |
TINA4_WS_BACKPLANE_URL | redis://localhost:6379 | Connection URL for the backplane. |
Email
| Variable | Default | Description |
|---|---|---|
TINA4_MAIL_HOST | (none) | SMTP server hostname. |
TINA4_MAIL_PORT | 587 | SMTP server port. |
TINA4_MAIL_USERNAME | (none) | SMTP authentication username. |
TINA4_MAIL_PASSWORD | (none) | SMTP authentication password. |
TINA4_MAIL_FROM | (none) | Default sender email address. |
TINA4_MAIL_FROM_NAME | (none) | Default sender display name. |
TINA4_MAIL_ENCRYPTION | tls | Connection encryption. Options: tls, ssl, none. |
TINA4_MAIL_IMAP_HOST | (none) | IMAP server for inbound mail. |
TINA4_MAIL_IMAP_PORT | 993 | IMAP server port. |
TINA4_MAIL_IMAP_USERNAME | (none) | IMAP authentication username. |
TINA4_MAIL_IMAP_PASSWORD | (none) | IMAP authentication password. |
TINA4_MAIL_IMAP_ENCRYPTION | tls | IMAP transport encryption. Accepts tls, starttls, or none; any other value is silently coerced back to tls. Independent of TINA4_MAIL_ENCRYPTION so Gmail-style setups can use IMAPS on 993 alongside SMTP STARTTLS on 587. |
TINA4_MAILBOX_DIR | data/mailbox | Dev mailbox directory. All outbound mail lands here when TINA4_DEBUG=true. |
TINA4_MAIL_HOST,TINA4_MAIL_PORT,TINA4_MAIL_USERNAME,TINA4_MAIL_PASSWORDare also accepted as aliases for theTINA4_MAIL_*equivalents. New projects should use theTINA4_MAIL_*names.
Logging
| Variable | Default | Description |
|---|---|---|
TINA4_LOG_LEVEL | ERROR | Minimum log level written to files. Options: ALL, DEBUG, INFO, WARNING, ERROR. |
TINA4_LOG_DEBUG | 0 | Numeric flag for debug-level messages. Used internally by Debug::message(). |
TINA4_LOG_INFO | 1 | Numeric flag for info-level messages. |
TINA4_LOG_ERROR | 3 | Numeric flag for error-level messages. |
TINA4_LOG_MAX_SIZE | 10485760 | Per-file log size limit in bytes (10 MB). Rotated when exceeded. |
TINA4_LOG_KEEP | 5 | Number of rotated log files to retain. |
Log pipeline (sink, format, rotation)
Logs default to stdout. Set TINA4_LOG_OUTPUT=file plus TINA4_LOG_FILE=app.log to write to disk; the framework rotates at TINA4_LOG_ROTATE_SIZE bytes and keeps TINA4_LOG_ROTATE_KEEP backups.
| Variable | Default | Description |
|---|---|---|
TINA4_LOG_FILE | (empty = stdout only) | Primary log filename. A relative value is joined with TINA4_LOG_DIR; an absolute path overrides both directory and filename. Leave empty to skip file output entirely. |
TINA4_LOG_DIR | logs | Directory log files are written into when TINA4_LOG_OUTPUT includes file. Created on first write if missing. |
TINA4_LOG_FORMAT | text | Wire format for emitted lines. text is human-readable; json emits one structured object per line for ingestion by Loki, ELK, etc. |
TINA4_LOG_OUTPUT | stdout | Where lines are sent. stdout writes to the process stream (great for systemd / containers), file writes only to TINA4_LOG_FILE, both does both. |
TINA4_LOG_CRITICAL | false | Enable Log::critical() emission. Off by default so security-relevant criticals can be intentionally surfaced rather than buried in routine output. |
TINA4_LOG_ROTATE_SIZE | 10485760 | Rotation threshold in bytes (10 MB default). Set 0 to disable rotation entirely — useful when an external tool (logrotate, Docker driver) owns the file. |
TINA4_LOG_ROTATE_KEEP | 5 | Number of rotated backups to retain. Older files are pruned on rotation. |
Uploads
| Variable | Default | Description |
|---|---|---|
TINA4_MAX_UPLOAD_SIZE | 10485760 | Maximum multipart upload size in bytes (10 MB). |
Localisation
| Variable | Default | Description |
|---|---|---|
TINA4_LOCALE | en | Default locale for I18n. |
TINA4_LOCALE_DIR | src/locale | Directory containing locale JSON files. |
Services (background tasks)
| Variable | Default | Description |
|---|---|---|
TINA4_SERVICE_DIR | src/services | Directory scanned for service classes. |
TINA4_SERVICE_SLEEP | 1 | Default tick interval (seconds) when a service does not specify one. |
AI and MCP Tooling
The dashboard AI chat and the framework's RAG-based code search both default to a local qwen2.5-coder model served via Ollama. Nothing leaves your machine unless you point TINA4_AI_URL at a remote endpoint.
| Variable | Default | Description |
|---|---|---|
TINA4_AI_URL | http://localhost:11434 | OpenAI-compatible HTTP endpoint for the chat/completion model (Ollama by default). |
TINA4_AI_MODEL | qwen2.5-coder | Model identifier the endpoint should serve. |
TINA4_RAG_URL | (inherits TINA4_AI_URL) | Embedding endpoint for the framework RAG index. |
TINA4_RAG_TOPK | 4 | Number of nearest-neighbour matches the dev dashboard RAG search returns per query. |
TINA4_AI_MODEL | nomic-embed-text | Embedding model used to index the framework and src/. |
TINA4_VISION_URL | http://andrevanzuydam.com:11434 | Vision-model endpoint surfaced by the dev dashboard /__dev/api/vision probe. |
TINA4_EMBED_URL | http://andrevanzuydam.com:11435 | Embeddings endpoint surfaced by the dev dashboard /__dev/api/embed probe. |
TINA4_IMAGE_URL | http://andrevanzuydam.com:11436 | Image-generation endpoint (e.g. SDXL Turbo) for the dev dashboard image tools. |
TINA4_SUPERVISOR_URL | (framework port + 2000) | Override the URL of the Rust agent supervisor that the dev dashboard proxies for /__dev/api/supervise/* and /__dev/api/execute. Defaults to http://127.0.0.1:9145 when TINA4_PORT=7145. |
TINA4_MCP | (inherits TINA4_DEBUG) | Master switch for the MCP subsystem. When unset, follows TINA4_DEBUG — MCP is on in dev and off in prod. Set to false to keep MCP disabled while leaving debug mode on, or to true to expose MCP from a production server (combine with TINA4_MCP_REMOTE if binding off-localhost). |
TINA4_MCP_PORT | (framework port + 2000) | Port the MCP server listens on. Defaults to TINA4_PORT + 2000 (so 7145 → 9145). Set explicitly when running multiple Tina4 instances on the same host. |
TINA4_MCP_REMOTE | false | Allow the MCP server to bind on non-localhost interfaces. Never enable in production. |
TINA4_NO_AI_PORT | false | Disables the MCP port listener in dev mode. |
TINA4_OVERRIDE_CLIENT | false | Allow the framework to start without the Rust CLI (tina4 serve). Used in Docker images and CI runners; bypasses SCSS compilation, the file watcher, and live reload. |
Swagger / OpenAPI
| Variable | Default | Description |
|---|---|---|
TINA4_SWAGGER_TITLE | Tina4 API | OpenAPI spec title shown in the Swagger UI. |
TINA4_SWAGGER_DESCRIPTION | Auto-generated from Tina4 routes | OpenAPI spec description. |
TINA4_SWAGGER_VERSION | 1.0.0 | OpenAPI spec version. |
TINA4_SWAGGER_ENABLED | (inherits TINA4_DEBUG) | Master switch for Swagger UI and the /swagger//swagger.json routes. When unset, follows TINA4_DEBUG so Swagger is on in dev and off in prod automatically. Set explicitly to expose docs in production. |
TINA4_SWAGGER_CONTACT_EMAIL | (empty) | Contact email written into the generated OpenAPI info.contact block. |
TINA4_SWAGGER_LICENSE | (empty) | License name written into the generated OpenAPI info.license block. |
GraphQL
| Variable | Default | Description |
|---|---|---|
TINA4_GRAPHQL_ENDPOINT | /graphql | URL path the framework binds the GraphQL handler to. The same value is used when generating __schema links and the dev-dashboard query console URL. |
TINA4_GRAPHQL_AUTO_SCHEMA | true | Auto-generate the GraphQL schema from registered ORM models. Set to false to skip introspection scaffolding when you supply a hand-written schema. |
HTTP Status Constants
For use in route handlers instead of raw integers:
return $response->json($data, \Tina4\HTTP_CREATED);
return $response("<error/>", \Tina4\HTTP_BAD_REQUEST, \Tina4\APPLICATION_XML);See Chapter 3: Request and Response for the full table.
Log-Level Constants
Passed to Debug::message() to tag severity:
| Constant | Description |
|---|---|
TINA4_LOG_DEBUG | Verbose developer messages. |
TINA4_LOG_INFO | Normal operational messages. |
TINA4_LOG_WARNING | Non-fatal anomalies. |
TINA4_LOG_ERROR | Recoverable errors. |
TINA4_LOG_CRITICAL | Fatal or security-relevant events. |
\Tina4\Debug::message("User " . $id . " missed the cache", TINA4_LOG_INFO);Minimal .env for Development
TINA4_DEBUG=true
TINA4_LOG_LEVEL=DEBUG
TINA4_NO_BROWSER=trueThat is it. Debug mode lights up the Swagger UI, the dev dashboard, detailed error pages, and live reload. Keeping the browser flag on stops a new tab opening every time you save a file.
Minimal .env for Production
TINA4_SECRET=your-long-random-secret-here
TINA4_DATABASE_URL=postgresql://user:password@db-host:5432/myapp
TINA4_CORS_ORIGINS=https://myapp.com,https://www.myapp.com
TINA4_HSTS=31536000
TINA4_MAIL_HOST=smtp.example.com
TINA4_MAIL_PORT=587
TINA4_MAIL_USERNAME=noreply@myapp.com
TINA4_MAIL_PASSWORD=your-smtp-password
TINA4_MAIL_FROM=noreply@myapp.comNo TINA4_DEBUG. It defaults to false, which is what you want in production. Set a real secret, a real database, locked-down CORS origins, HSTS, and SMTP credentials if you send email. Everything else has a production-appropriate default.