中文 | English
KUNO /ˈkuːnoʊ/ — a lightweight, i18n-first CMS built with Go and Next.js. The name comes from "坤" (kūn, earth in the I Ching), meaning to carry and support all things.
A full-stack blog system containerized with Docker for easy deployment.
- Markdown editor with live preview and Mermaid diagram support
- 70+ language interface (i18n powered by next-intl)
- Dark / light theme toggle
- Responsive, mobile-first layout
- Category and tag management
- Admin panel for content management
- Customizable site title, subtitle, and branding
- SEO optimization with LLMs.txt support for AI search engines
- Usage analytics and performance monitoring
- Docker one-click deployment with blue-green strategy (< 2s downtime)
- Health checks and automatic rollback on failed deployments
| Region | Languages |
|---|---|
| Core | Chinese, English |
| Asian | Japanese, Korean, Thai, Vietnamese, Indonesian, Malay, Filipino, Myanmar, Khmer, Lao |
| European | Spanish, French, German, Russian, Portuguese, Italian, Dutch, Swedish, Danish, Norwegian, Finnish, Polish, Czech, Slovak, Hungarian, Romanian, Bulgarian, Croatian, Serbian, Slovenian, Estonian, Latvian, Lithuanian, Ukrainian, Belarusian, Turkish, Greek, Albanian, Armenian, Azerbaijani, Georgian |
| Middle Eastern & African | Arabic, Hebrew, Persian, Urdu, Amharic, Swahili, Zulu, Afrikaans |
| South Asian | Hindi, Bengali, Tamil, Telugu, Malayalam, Kannada, Gujarati, Punjabi, Marathi, Nepali, Sinhala |
| Pacific & Others | Māori, Samoan, Tongan, Fijian, Irish, Icelandic, Maltese, Basque, Catalan |
sudo mkdir -p /opt/kuno && cd /opt/kuno
curl -sSL "https://raw.githubusercontent.com/xuemian168/kuno/main/deploy-from-hub.sh?$(date +%s)" \
-o deploy.sh && chmod +x deploy.sh && sudo ./deploy.shThe script will ask you to:
- Choose HTTP or HTTPS
- Enter your domain (e.g.
qut.edu.kg) - Pick standard or blue-green deployment
- API URL is generated automatically
Note: Don't pipe the script with
curl | bash— download it first, then run. Deploy under/opt/kunoto keep things tidy.
./quick-deploy.sh [image] [port] [container-name]
# Example:
./quick-deploy.sh ictrun/kuno:latest 80 kunoPulls the new image while the old container keeps serving, then swaps with < 2s downtime. Rolls back automatically if the new container fails health checks.
sudo mkdir -p /opt/kuno && cd /opt/kuno
mkdir -p ./blog-data
docker run -d \
--name kuno \
--restart unless-stopped \
-p 80:80 \
-v /opt/kuno/blog-data:/app/data \
-e NEXT_PUBLIC_API_URL="http://localhost/api" \
-e DB_PATH="/app/data/blog.db" \
-e GIN_MODE="release" \
-e NODE_ENV="production" \
-e JWT_SECRET="your-secure-secret-key" \
ictrun/kuno:latestNEXT_PUBLIC_API_URL to match your actual environment:
- Local:
http://localhost/api - LAN:
http://192.168.1.100/api - Public:
https://yourdomain.com/api - Non-80 port:
http://localhost:8080/api
JWT_SECRET — set a 32+ character string for production. If omitted, a random key is generated (resets on restart).
curl -O https://raw.githubusercontent.com/xuemian168/kuno/main/docker-compose.hub.yml
cp .env.hub.example .env
# Edit .env with your settings
docker-compose -f docker-compose.hub.yml up -dictrun/kuno:latest— latest stableictrun/kuno:v1.0.0— specific versionictrun/kuno:develop— development branch
| Variable | Default | Description |
|---|---|---|
NEXT_PUBLIC_API_URL |
https://your-domain.com/api |
API endpoint URL |
DB_PATH |
/app/data/blog.db |
SQLite database path |
UPLOAD_DIR |
/app/data/uploads |
Upload directory |
GIN_MODE |
release |
Gin mode (release/debug) |
NODE_ENV |
production |
Node.js environment |
RECOVERY_MODE |
false |
Password recovery mode |
JWT_SECRET |
(auto-generated) | JWT signing secret |
The API URL can be changed at runtime — just restart the container, no rebuild needed.
- URL:
http://localhost/admin - Username:
admin - Password:
xuemian168
/opt/kuno/
├── blog-data/
│ ├── blog.db # SQLite database
│ └── uploads/
│ ├── images/
│ ├── videos/
│ └── branding/
└── deploy.sh
cd /opt/kuno
./deploy.sh # choose blue-green
# or
./quick-deploy.sh ictrun/kuno:latest 80 kunodocker stop kuno && docker rm kuno
docker pull ictrun/kuno:latest
cd /opt/kuno
docker run -d \
--name kuno \
--restart unless-stopped \
-p 80:80 \
-v /opt/kuno/blog-data:/app/data \
-e NEXT_PUBLIC_API_URL=https://your-domain.com/api \
-e DB_PATH=/app/data/blog.db \
ictrun/kuno:latestcd /opt/kuno
sudo tar -czf blog-backup-$(date +%Y%m%d).tar.gz ./blog-datadocker stop kuno && docker rm kuno
# Restore data if needed
sudo tar -xzf blog-backup-YYYYMMDD.tar.gz
# Run previous version
docker run -d --name kuno --restart unless-stopped \
-p 80:80 -v /opt/kuno/blog-data:/app/data \
-e NEXT_PUBLIC_API_URL=https://your-domain.com/api \
ictrun/kuno:PREVIOUS_TAGIf you forget the admin password:
# 1. Stop the running container
docker stop kuno
# 2. Run a recovery container
docker run -d --name kuno_recovery \
-p 80:80 \
-v /opt/kuno/blog-data:/app/data \
-e NEXT_PUBLIC_API_URL="http://localhost/api" \
-e DB_PATH="/app/data/blog.db" \
-e RECOVERY_MODE="true" \
ictrun/kuno:latest
# 3. Check logs — password resets to xuemian168, then the container refuses to start (by design)
docker logs kuno_recovery
docker rm -f kuno_recovery
# 4. Start normally
docker run -d --name kuno --restart unless-stopped \
-p 80:80 \
-v /opt/kuno/blog-data:/app/data \
-e NEXT_PUBLIC_API_URL="http://localhost/api" \
-e DB_PATH="/app/data/blog.db" \
-e RECOVERY_MODE="false" \
ictrun/kuno:latest
# 5. Log in with admin / xuemian168 and change the password immediatelyRecovery mode requires server access to set the env var, and the system won't serve traffic while it's active.
# Backend
cd backend
go mod download
go run cmd/server/main.go
# Frontend
cd frontend
npm install
npm run devAccess at: frontend http://localhost:3000, API http://localhost:8080/api, admin http://localhost:3000/admin.
# Dev
docker-compose up --build -d
# Production (with Nginx)
docker-compose -f docker-compose.prod.yml up --build -ddocker ps | grep kuno # status
docker logs kuno # logs
docker restart kuno # restart
docker stop kuno # stop- Port conflict: Change
-p 80:80to-p 8080:80 - API URL not taking effect: Restart the container. Check logs for "Setting runtime API URL to: ..."
- Deploy script syntax error: Don't use
curl | bash. Download first, then run. - Build failures:
docker system prune -fto clear cache
Health check endpoints: backend http://localhost:8080/api/categories, frontend http://localhost:3000.
This project is sponsored by TIKHUB.IO
TikHub.io provides social media data APIs and tools for developers, creators, and businesses.


