19 KiB
Environment variables — full reference
qiming-file-server can be configured entirely through environment variables. This document lists every supported variable.
Precedence
From highest to lowest:
- CLI arguments
- Process environment variables
- Env files (
.env.production,.env.development,.env.test— loaded according to project conventions; seesrc/env.*) - Built-in defaults
Env files
Files under src/ are selected based on NODE_ENV:
| Mode | File | Purpose |
|---|---|---|
| development | env.development |
Local development |
| production | env.production |
Production |
| test | env.test |
Tests |
Core settings
Server
| Variable | Default | Description |
|---|---|---|
NODE_ENV |
development |
development / production / test |
PORT |
60000 |
HTTP listen port |
REQUEST_BODY_LIMIT |
2000mb |
Express body size limit |
Logging
| Variable | Default | Description |
|---|---|---|
LOG_BASE_DIR |
— | Base directory for log files |
LOG_LEVEL |
debug |
error / warn / info / debug |
LOG_CONSOLE_ENABLED |
true |
Mirror logs to console |
LOG_PREFIX_API |
api |
Prefix for API logs |
LOG_PREFIX_BUILD |
build |
Prefix for build logs |
Project paths
| Variable | Default | Description |
|---|---|---|
INIT_PROJECT_NAME_REACT |
react-vite-template |
Built-in scaffold name for React projects |
INIT_PROJECT_NAME_VUE3 |
vue3-vite-template |
Built-in scaffold name for Vue3 projects |
INIT_PROJECT_DIR |
— | Scaffold / init project directory |
UPLOAD_PROJECT_DIR |
— | Directory for uploaded project archives |
PROJECT_SOURCE_DIR |
— | Unpacked / working project sources |
DIST_TARGET_DIR |
— | Build output directory (e.g. served by nginx) |
COMPUTER_WORKSPACE_DIR |
— | “Computer” feature workspace |
COMPUTER_LOG_DIR |
— | “Computer” feature logs |
Build
| Variable | Default | Description |
|---|---|---|
MAX_BUILD_CONCURRENCY |
20 |
Max concurrent builds |
DEV_SERVER_PORT_TIMEOUT |
5000 |
Dev-server port probe timeout (ms) |
DEV_SERVER_STOP_TIMEOUT |
5000 |
Dev-server stop timeout (ms) |
DEV_SERVER_STOP_CHECK_INTERVAL |
100 |
Poll interval while stopping dev server (ms) |
DEV_SERVER_STOP_MAX_ATTEMPTS |
50 |
Max stop retries |
Uploads
| Variable | Default | Description |
|---|---|---|
MAX_INLINE_FILE_SIZE_BYTES |
1048576 |
Max size (bytes) to return inline; larger files are not inlined |
UPLOAD_MAX_FILE_SIZE_BYTES |
1048576000 |
Max archive upload size (bytes) |
UPLOAD_ALLOWED_EXTENSIONS |
.zip |
Allowed extensions (comma-separated) |
UPLOAD_SINGLE_FILE_SIZE_BYTES |
1048576000 |
Max single upload size (bytes) |
Traversal / filters
| Variable | Default | Description |
|---|---|---|
TRAVERSE_EXCLUDE_DIRS |
dist,node_modules,.pnpm-store,__MACOSX,.attachments |
Comma-separated dirs to skip when traversing |
BACKUP_TRAVERSE_EXCLUDE_FILES |
pnpm-lock.yaml,yarn.lock,package-lock.json |
Comma-separated files to skip in backup traversal |
CONTENT_TRAVERSE_EXCLUDE_FILES |
AGENT.md,AGENTS.md,CLAUDE.md,pnpm-lock.yaml,yarn.lock,package-lock.json |
Comma-separated files to skip for content API |
INLINE_IMAGE_EXTENSIONS |
.png,.jpg,.jpeg,.gif,.bmp,.svg,.ico,.webp,.avif |
Image extensions eligible for inline serving |
TOP_LEVEL_NOISE_PATTERNS |
__MACOSX,Thumbs.db,node_modules,.pnpm-store,.attachments |
Comma-separated noise patterns for top-level flattening after unzip |
pnpm prune scheduler
| Variable | Default | Description |
|---|---|---|
PNPM_PRUNE_ENABLED |
true |
Enable scheduled pnpm store maintenance |
PNPM_PRUNE_SCHEDULE |
0 2 * * * |
Cron expression |
PNPM_PRUNE_TIMEZONE |
Asia/Shanghai |
Time zone for the schedule |
PNPM_PRUNE_RUN_ON_START |
false |
Run once immediately on startup |
Example cron expressions:
| Expression | Meaning |
|---|---|
0 2 * * 0 |
Every Sunday 02:00 |
0 3 * * * |
Every day 03:00 |
0 2 1 * * |
1st of month 02:00 |
0 */6 * * * |
Every 6 hours |
Log cache
| Variable | Default | Description |
|---|---|---|
LOG_CACHE_ENABLED |
true |
Enable in-memory log cache |
LOG_CACHE_DURATION |
180000 |
TTL (ms); default 3 minutes |
LOG_CACHE_MAX_ENTRIES |
100 |
Max cached entries |
LOG_CACHE_MAX_FILE_SIZE |
2097152 |
Max cached file size (bytes); default 2 MB |
CLI-only
| Variable | Default | Description |
|---|---|---|
CLI_PID_DIR |
system temp | Directory for PID file |
CLI_PID_FILE |
server.pid |
PID filename |
CLI_STOP_TIMEOUT |
30000 |
Graceful stop timeout (ms) |
CLI_CHECK_INTERVAL |
500 |
Poll interval when stopping (ms) |
CLI_LOG_DIR |
system temp | CLI log directory |
Extra CLI environment
| Variable | Description |
|---|---|
CONFIG_FILE |
Optional path to an extra env file (CLI) |
Examples
Use production defaults but override paths
In real deployments you often keep env.production as the base and only override paths:
Example A: production + custom paths
qiming-file-server start \
--env production \
--port 60000 \
PROJECT_SOURCE_DIR=/data/my-projects \
DIST_TARGET_DIR=/var/www/my-app \
UPLOAD_PROJECT_DIR=/data/uploads \
LOG_BASE_DIR=/var/log/qiming
Example B: multiple instances on one host
# Instance 1 — main
qiming-file-server start \
--env production \
--port 60001 \
PROJECT_SOURCE_DIR=/data/main-site \
DIST_TARGET_DIR=/var/www/main-site
# Instance 2 — staging
qiming-file-server start \
--env production \
--port 60002 \
PROJECT_SOURCE_DIR=/data/test-site \
DIST_TARGET_DIR=/var/www/test-site
# Instance 3 — internal
qiming-file-server start \
--env production \
--port 60003 \
PROJECT_SOURCE_DIR=/data/internal \
DIST_TARGET_DIR=/var/www/internal
Only pass
--portand the paths you need; everything else comes fromenv.production.
Example C: override file
cat > env.override << 'EOF'
# Path overrides for production
PROJECT_SOURCE_DIR=/data/override-projects
DIST_TARGET_DIR=/var/www/override-nginx
UPLOAD_PROJECT_DIR=/data/override-uploads
LOG_BASE_DIR=/var/log/override
EOF
qiming-file-server start --env production --env-file ./env.override
Example D: Kubernetes ConfigMap
kubectl create configmap qiming-overrides \
--from-literal=PROJECT_SOURCE_DIR=/data/k8s-projects \
--from-literal=DIST_TARGET_DIR=/usr/share/nginx/apps \
--from-literal=UPLOAD_PROJECT_DIR=/data/k8s-uploads \
--from-literal=LOG_BASE_DIR=/var/log/qiming
Reference it in the Deployment:
envFrom:
- configMapRef:
name: qiming-overrides
Example E: full path set (illustrative)
Below lists path-related variables you might set. Trim to what you actually need:
# Production with defaults from env.production, paths overridden
qiming-file-server start \
--env production \
--port 60000
# Or set paths explicitly
qiming-file-server start \
--env production \
--port 60000 \
INIT_PROJECT_NAME_REACT=react-vite-template \
INIT_PROJECT_NAME_VUE3=vue3-vite-template \
INIT_PROJECT_DIR=/app/project_init \
UPLOAD_PROJECT_DIR=/app/project_zips \
PROJECT_SOURCE_DIR=/app/project_workspace \
DIST_TARGET_DIR=/app/project_nginx \
LOG_BASE_DIR=/app/logs/project_logs \
COMPUTER_WORKSPACE_DIR=/app/computer-project-workspace \
COMPUTER_LOG_DIR=/app/logs/computer_logs
Path variables as documented for env.production
| Variable | Example default | Description |
|---|---|---|
INIT_PROJECT_NAME_REACT |
react-vite-template |
Built-in scaffold name for React projects |
INIT_PROJECT_NAME_VUE3 |
vue3-vite-template |
Built-in scaffold name for Vue3 projects |
INIT_PROJECT_DIR |
/app/project_init |
Init project directory |
UPLOAD_PROJECT_DIR |
/app/project_zips |
Uploaded zips |
PROJECT_SOURCE_DIR |
/app/project_workspace |
Project workspace |
DIST_TARGET_DIR |
/app/project_nginx |
Build output (nginx root) |
LOG_BASE_DIR |
/app/logs/project_logs |
Log root |
COMPUTER_WORKSPACE_DIR |
/app/computer-project-workspace |
Computer workspace |
COMPUTER_LOG_DIR |
/app/logs/computer_logs |
Computer logs |
Path-only snippets
# 1) Only change project sources
qiming-file-server start \
--env production \
--port 60000 \
PROJECT_SOURCE_DIR=/data/my-projects
# 2) Several paths
qiming-file-server start \
--env production \
--port 60000 \
PROJECT_SOURCE_DIR=/data/projects \
DIST_TARGET_DIR=/var/www/html \
UPLOAD_PROJECT_DIR=/data/uploads
# 3) Full path set
qiming-file-server start \
--env production \
--port 60000 \
INIT_PROJECT_NAME_REACT=my-react-template \
INIT_PROJECT_NAME_VUE3=my-vue3-template \
INIT_PROJECT_DIR=/data/init \
UPLOAD_PROJECT_DIR=/data/zips \
PROJECT_SOURCE_DIR=/data/workspace \
DIST_TARGET_DIR=/var/www/nginx \
LOG_BASE_DIR=/var/logs/project_logs \
COMPUTER_WORKSPACE_DIR=/data/computer \
COMPUTER_LOG_DIR=/var/logs/computer
--portselects the HTTP port; unset path keys keep their values fromenv.production.
Verify overrides
qiming-file-server status
curl http://localhost:60000/health | jq
# Check startup logs for loaded env (messages are in English, e.g. "Loaded environment files: ...")
grep -E "Loaded environment|Environment configuration file" /var/log/qiming/server.log
CLI overrides precedence
CLI wins over env files and plain env:
qiming-file-server start --port 8080
qiming-file-server start --env production
qiming-file-server start --env production --port 8080
Shell environment
Linux / macOS
export PORT=8080
export NODE_ENV=production
export LOG_LEVEL=info
# Persist in ~/.bashrc or ~/.zshrc
echo 'export PORT=8080' >> ~/.bashrc
source ~/.bashrc
Windows
set PORT=8080
set NODE_ENV=production
setx PORT 8080
setx NODE_ENV production
Docker / Compose
docker-compose.yml
version: '3.8'
services:
qiming-file-server:
image: qiming-file-server:latest
container_name: qiming-file-server
restart: unless-stopped
environment:
- NODE_ENV=production
- PORT=60000
- LOG_BASE_DIR=/app/logs
- LOG_LEVEL=info
- LOG_CONSOLE_ENABLED=false
- PROJECT_SOURCE_DIR=/app/projects
- DIST_TARGET_DIR=/app/nginx
- UPLOAD_PROJECT_DIR=/app/uploads
- INIT_PROJECT_DIR=/app/init
- COMPUTER_WORKSPACE_DIR=/app/computer
- COMPUTER_LOG_DIR=/app/computer-logs
- MAX_BUILD_CONCURRENCY=20
- PNPM_PRUNE_ENABLED=true
- PNPM_PRUNE_SCHEDULE=0 3 * * *
- PNPM_PRUNE_TIMEZONE=Asia/Shanghai
- LOG_CACHE_ENABLED=true
- LOG_CACHE_DURATION=180000
- LOG_CACHE_MAX_ENTRIES=100
- LOG_CACHE_MAX_FILE_SIZE=2097152
volumes:
- ./projects:/app/projects
- ./logs:/app/logs
- ./nginx:/app/nginx
- ./uploads:/app/uploads
- ./init:/app/init
- ./computer:/app/computer
ports:
- "60000:60000"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:60000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install -g pnpm && pnpm install --frozen-lockfile
COPY . .
RUN mkdir -p /app/logs /app/projects /app/nginx /app/uploads /app/init /app/computer
EXPOSE 60000
CMD ["node", "scripts/start-cli.js"]
Sample env files
.env.production
# ==================== Server ====================
NODE_ENV=production
PORT=60000
REQUEST_BODY_LIMIT=2000mb
# ==================== Logging ====================
LOG_BASE_DIR=/app/logs
LOG_LEVEL=info
LOG_CONSOLE_ENABLED=false
LOG_PREFIX_API=api
LOG_PREFIX_BUILD=build
# ==================== Paths ====================
INIT_PROJECT_NAME_REACT=react-vite-template
INIT_PROJECT_NAME_VUE3=vue3-vite-template
INIT_PROJECT_DIR=/app/project_init
UPLOAD_PROJECT_DIR=/app/project_zips
PROJECT_SOURCE_DIR=/app/project_workspace
DIST_TARGET_DIR=/app/project_nginx
COMPUTER_WORKSPACE_DIR=/app/computer-project-workspace
COMPUTER_LOG_DIR=/app/logs/computer_logs
# ==================== Build ====================
MAX_BUILD_CONCURRENCY=20
DEV_SERVER_PORT_TIMEOUT=5000
DEV_SERVER_STOP_TIMEOUT=5000
DEV_SERVER_STOP_CHECK_INTERVAL=100
DEV_SERVER_STOP_MAX_ATTEMPTS=50
# ==================== Uploads ====================
MAX_INLINE_FILE_SIZE_BYTES=1048576
UPLOAD_MAX_FILE_SIZE_BYTES=1048576000
UPLOAD_ALLOWED_EXTENSIONS=.zip
UPLOAD_SINGLE_FILE_SIZE_BYTES=1048576000
# ==================== Traversal / filters ====================
TRAVERSE_EXCLUDE_DIRS=dist,node_modules,.pnpm-store,__MACOSX,.attachments
BACKUP_TRAVERSE_EXCLUDE_FILES=pnpm-lock.yaml,yarn.lock,package-lock.json
CONTENT_TRAVERSE_EXCLUDE_FILES=AGENT.md,AGENTS.md,CLAUDE.md,pnpm-lock.yaml,yarn.lock,package-lock.json
INLINE_IMAGE_EXTENSIONS=.png,.jpg,.jpeg,.gif,.bmp,.svg,.ico,.webp,.avif
TOP_LEVEL_NOISE_PATTERNS=__MACOSX,Thumbs.db,node_modules,.pnpm-store,.attachments
# ==================== pnpm prune ====================
PNPM_PRUNE_ENABLED=true
PNPM_PRUNE_SCHEDULE=0 2 * * *
PNPM_PRUNE_TIMEZONE=Asia/Shanghai
PNPM_PRUNE_RUN_ON_START=false
# ==================== Log cache ====================
LOG_CACHE_ENABLED=true
LOG_CACHE_DURATION=180000
LOG_CACHE_MAX_ENTRIES=100
LOG_CACHE_MAX_FILE_SIZE=2097152
# ==================== CLI ====================
CLI_PID_DIR=/tmp/qiming-file-server
CLI_STOP_TIMEOUT=30000
CLI_CHECK_INTERVAL=500
CLI_LOG_DIR=/tmp/qiming-file-server/logs
.env.development
# ==================== Server ====================
NODE_ENV=development
PORT=60000
REQUEST_BODY_LIMIT=2000mb
# ==================== Logging ====================
LOG_BASE_DIR=./logs
LOG_LEVEL=debug
LOG_CONSOLE_ENABLED=true
LOG_PREFIX_API=api
LOG_PREFIX_BUILD=build
# ==================== Paths ====================
INIT_PROJECT_NAME_REACT=react-vite-template
INIT_PROJECT_NAME_VUE3=vue3-vite-template
INIT_PROJECT_DIR=./project_init
UPLOAD_PROJECT_DIR=./project_zips
PROJECT_SOURCE_DIR=./project_workspace
DIST_TARGET_DIR=./project_nginx
COMPUTER_WORKSPACE_DIR=./computer-project-workspace
COMPUTER_LOG_DIR=./computer_logs
# ==================== Build ====================
MAX_BUILD_CONCURRENCY=20
DEV_SERVER_PORT_TIMEOUT=5000
DEV_SERVER_STOP_TIMEOUT=5000
DEV_SERVER_STOP_CHECK_INTERVAL=100
DEV_SERVER_STOP_MAX_ATTEMPTS=50
# ==================== Uploads ====================
MAX_INLINE_FILE_SIZE_BYTES=1048576
UPLOAD_MAX_FILE_SIZE_BYTES=1048576000
UPLOAD_ALLOWED_EXTENSIONS=.zip
UPLOAD_SINGLE_FILE_SIZE_BYTES=1048576000
# ==================== Traversal / filters ====================
TRAVERSE_EXCLUDE_DIRS=dist,node_modules,.pnpm-store,__MACOSX,.attachments
BACKUP_TRAVERSE_EXCLUDE_FILES=pnpm-lock.yaml,yarn.lock,package-lock.json
CONTENT_TRAVERSE_EXCLUDE_FILES=AGENT.md,AGENTS.md,CLAUDE.md,pnpm-lock.yaml,yarn.lock,package-lock.json
INLINE_IMAGE_EXTENSIONS=.png,.jpg,.jpeg,.gif,.bmp,.svg,.ico,.webp,.avif
TOP_LEVEL_NOISE_PATTERNS=__MACOSX,Thumbs.db,node_modules,.pnpm-store,.attachments
# ==================== pnpm prune ====================
PNPM_PRUNE_ENABLED=false
PNPM_PRUNE_SCHEDULE=0 2 * * *
PNPM_PRUNE_TIMEZONE=Asia/Shanghai
PNPM_PRUNE_RUN_ON_START=false
# ==================== Log cache ====================
LOG_CACHE_ENABLED=true
LOG_CACHE_DURATION=180000
LOG_CACHE_MAX_ENTRIES=100
LOG_CACHE_MAX_FILE_SIZE=2097152
# ==================== CLI ====================
CLI_PID_DIR=./tmp
CLI_STOP_TIMEOUT=30000
CLI_CHECK_INTERVAL=500
CLI_LOG_DIR=./tmp/logs
Kubernetes example
apiVersion: v1
kind: ConfigMap
metadata:
name: qiming-file-server-config
data:
NODE_ENV: "production"
PORT: "60000"
LOG_BASE_DIR: "/app/logs"
LOG_LEVEL: "info"
LOG_CONSOLE_ENABLED: "false"
PROJECT_SOURCE_DIR: "/app/projects"
DIST_TARGET_DIR: "/app/nginx"
UPLOAD_PROJECT_DIR: "/app/uploads"
INIT_PROJECT_DIR: "/app/init"
COMPUTER_WORKSPACE_DIR: "/app/computer"
COMPUTER_LOG_DIR: "/app/computer-logs"
MAX_BUILD_CONCURRENCY: "20"
PNPM_PRUNE_ENABLED: "true"
PNPM_PRUNE_SCHEDULE: "0 3 * * *"
PNPM_PRUNE_TIMEZONE: "Asia/Shanghai"
LOG_CACHE_ENABLED: "true"
LOG_CACHE_DURATION: "180000"
LOG_CACHE_MAX_ENTRIES: "100"
LOG_CACHE_MAX_FILE_SIZE: "2097152"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: qiming-file-server
spec:
replicas: 1
selector:
matchLabels:
app: qiming-file-server
template:
metadata:
labels:
app: qiming-file-server
spec:
containers:
- name: qiming-file-server
image: qiming-file-server:latest
ports:
- containerPort: 60000
envFrom:
- configMapRef:
name: qiming-file-server-config
volumeMounts:
- name: projects
mountPath: /app/projects
- name: logs
mountPath: /app/logs
- name: nginx
mountPath: /app/nginx
- name: uploads
mountPath: /app/uploads
- name: init
mountPath: /app/init
- name: computer
mountPath: /app/computer
livenessProbe:
httpGet:
path: /health
port: 60000
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 60000
initialDelaySeconds: 5
periodSeconds: 10
volumes:
- name: projects
hostPath:
path: /data/projects
- name: logs
hostPath:
path: /data/logs
- name: nginx
hostPath:
path: /data/nginx
- name: uploads
hostPath:
path: /data/uploads
- name: init
hostPath:
path: /data/init
- name: computer
hostPath:
path: /data/computer
Verifying configuration
curl http://localhost:60000/health
The JSON body includes the active environment name (e.g. "env": "production").
Troubleshooting
Changes not applied
- Confirm the correct env file path and
NODE_ENV. - Variable names are case-sensitive.
- Validate YAML/JSON if you embed config in manifests.
- Read server logs for load errors.
Port already in use
If PORT is taken, startup fails. Pick another port or free the listener.
Permissions
Ensure log and data directories are writable:
chmod -R 755 /path/to/logs
mkdir -p /path/to/logs /path/to/projects
Docker env not visible
Pass variables with environment: or envFrom::
environment:
- NODE_ENV=production
- PORT=60000
envFrom:
- configMapRef:
name: my-config
Related docs
- README.md — Overview
- PNPM_CHECK.md — pnpm disk usage helper