migrate from github

This commit is contained in:
2026-07-15 23:28:04 +08:00
commit eb25aa19d9
17 changed files with 1433 additions and 0 deletions
+68
View File
@@ -0,0 +1,68 @@
# host exposed ports
NGINX_HTTP_PORT=8080
NGINX_HTTPS_PORT=8443
BACKEND_GRPC_HOST_PORT=9090
BACKEND_DEBUG_HOST_PORT=2345
POSTGRES_HOST_PORT=5432
REDIS_HOST_PORT=6379
RABBITMQ_AMQP_HOST_PORT=5672
CONSUL_HOST_PORT=8500
ELASTICSEARCH_HOST_PORT=9200
# internal service ports
BACKEND_GRPC_PORT=9090
BACKEND_GRPC_WEB_PORT=8080
POSTGRES_PORT=5432
REDIS_PORT=6379
RABBITMQ_AMQP_PORT=5672
RABBITMQ_MANAGEMENT_PORT=15672
CONSUL_PORT=8500
COLLAB_CORE_PORT=1234
COLLAB_GATEWAY_PORT=1234
MINIO_API_PORT=9000
MINIO_CONSOLE_PORT=9001
ELASTICSEARCH_PORT=9200
REDIS_DB=0
# internal service hosts
POSTGRES_HOST=postgres
REDIS_HOST=redis
CONSUL_HOST=consul
RABBITMQ_HOST=rabbitmq
BACKEND_HOST=backend
FRONTEND_HOST=frontend
COLLAB_HOST=collab
COLLAB_CORE_HOST=collab-core
MINIO_HOST=minio
ELASTICSEARCH_HOST=elasticsearch
# credentials & secrets
POSTGRES_USER=root
POSTGRES_PASSWORD=your_password
POSTGRES_DB=yoresee_doc_db
REDIS_PASSWORD=your_redis_password
RABBITMQ_DEFAULT_USER=guest
RABBITMQ_DEFAULT_PASS=guest
CONSUL_ROOT_TOKEN=yoresee_doc_root_token
BACKEND_INTERNAL_RPC_KEY=yoresee_doc_internal_key
JWT_SECRET=yoresee_doc_jwt_secret_key
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=minioadmin
# application config
VITE_API_BASE_URL=http://localhost:8080
VITE_GRPC_WEB_ENDPOINT=/grpc
MINIO_BUCKET=yoresee-doc
# Keep this aligned with VITE_API_BASE_URL. configure.sh will derive it as ${VITE_API_BASE_URL}/minio.
MINIO_BROWSER_REDIRECT_URL=http://localhost:8080/minio
DIRTY_DOC_TOPIC=collab.dirty_docs
DIRTY_DOC_MQ=rabbitmq
NOTIFICATION_MQ=rabbitmq
SEARCH_SYNC_MQ=rabbitmq
DIRTY_DOC_NOTIFY_THRESHOLD=5
# elasticsearch
ELASTICSEARCH_ENABLED=true
ELASTICSEARCH_USERNAME=
ELASTICSEARCH_PASSWORD=
ELASTICSEARCH_INDEX_PREFIX=yoresee_doc
+12
View File
@@ -0,0 +1,12 @@
# ignore config files
nginx/nginx.conf
nginx/conf.d/default.conf
redis/redis.conf
rabbitmq/rabbitmq.conf
.env
# ignore log files by suffix
*.logs
*.log
+11
View File
@@ -0,0 +1,11 @@
FROM bufbuild/buf:latest
WORKDIR /workspace/proto
ENTRYPOINT ["sh", "-c", "\
buf generate --template buf.gen.backend.yaml && \
buf generate --template buf.gen.collab-go.yaml && \
buf generate --template buf.gen.frontend.yaml && \
buf generate --template buf.gen.node.yaml && \
echo 'Proto generation complete.' \
"]
+324
View File
@@ -0,0 +1,324 @@
services:
proto-gen:
build:
context: ../proto
dockerfile: ../deploy/Dockerfile.proto-gen
image: yoresee_doc_proto_gen:latest
container_name: yoresee_doc_proto_gen
volumes:
- ../proto:/workspace/proto
- ../backend/pkg/gen:/workspace/backend/pkg/gen
- ../collab-go/pkg/gen:/workspace/collab-go/pkg/gen
- ../frontend/src/gen:/workspace/frontend/src/gen
- ../collab/src/gen:/workspace/collab/src/gen
nginx:
image: nginx:alpine
container_name: yoresee_doc_nginx
ports:
- "${NGINX_HTTP_PORT:-8080}:80"
- "${NGINX_HTTPS_PORT:-8443}:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
- ./logs/nginx:/var/log/nginx
depends_on:
- frontend
- backend
- collab
- minio
networks:
- yoresee_doc_network
restart: unless-stopped
frontend:
build:
context: ../frontend
dockerfile: Dockerfile
target: dev
image: yoresee_doc_frontend_dev:latest
container_name: yoresee_doc_frontend
volumes:
- ../frontend:/app
- /app/node_modules
environment:
- NODE_ENV=development
- VITE_API_BASE_URL=${VITE_API_BASE_URL:-http://localhost:8080}
- VITE_GRPC_WEB_ENDPOINT=${VITE_GRPC_WEB_ENDPOINT:-/grpc}
networks:
- yoresee_doc_network
restart: unless-stopped
postgres:
image: postgres:15-alpine
container_name: yoresee_doc_postgres
environment:
POSTGRES_USER: ${POSTGRES_USER:-root}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-your_password}
POSTGRES_DB: ${POSTGRES_DB:-yoresee_doc_db}
ports:
- "${POSTGRES_HOST_PORT:-5432}:${POSTGRES_PORT:-5432}"
volumes:
- yoresee_doc_postgres_data:/var/lib/postgresql/data
networks:
- yoresee_doc_network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-root} -d ${POSTGRES_DB:-yoresee_doc_db}"]
interval: 5s
timeout: 3s
retries: 5
restart: unless-stopped
redis:
image: redis:7-alpine
container_name: yoresee_doc_redis
environment:
REDIS_PASSWORD: ${REDIS_PASSWORD:-your_redis_password}
ports:
- "${REDIS_HOST_PORT:-6379}:${REDIS_PORT:-6379}"
volumes:
- yoresee_doc_redis_data:/data
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
command: redis-server /usr/local/etc/redis/redis.conf
networks:
- yoresee_doc_network
healthcheck:
test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
interval: 5s
timeout: 3s
retries: 5
restart: unless-stopped
consul:
image: hashicorp/consul:1.16
container_name: yoresee_doc_consul
command: "agent -dev -client=0.0.0.0 -ui"
environment:
CONSUL_LOCAL_CONFIG: >-
{"acl":{"enabled":true,"default_policy":"deny","down_policy":"extend-cache","enable_token_persistence":true,"tokens":{"initial_management":"${CONSUL_ROOT_TOKEN:-yoresee_doc_root_token}"}}}
ports:
- "${CONSUL_HOST_PORT:-8500}:${CONSUL_PORT:-8500}"
volumes:
- yoresee_doc_consul_data:/consul/data
networks:
- yoresee_doc_network
restart: unless-stopped
rabbitmq:
image: rabbitmq:3-management
container_name: yoresee_doc_rabbitmq
environment:
RABBITMQ_DEFAULT_USER: ${RABBITMQ_DEFAULT_USER:-guest}
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_DEFAULT_PASS:-guest}
ports:
- "${RABBITMQ_AMQP_HOST_PORT:-5672}:${RABBITMQ_AMQP_PORT:-5672}"
volumes:
- yoresee_doc_rabbitmq_data:/var/lib/rabbitmq
- ./rabbitmq/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf:ro
- ./logs/rabbitmq:/var/log/rabbitmq
networks:
- yoresee_doc_network
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"]
interval: 5s
timeout: 3s
retries: 5
restart: unless-stopped
minio:
image: minio/minio:latest
container_name: yoresee_doc_minio
command: server /data --console-address ":${MINIO_CONSOLE_PORT:-9001}"
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin}
MINIO_BROWSER_REDIRECT_URL: ${MINIO_BROWSER_REDIRECT_URL:-http://localhost:8080/minio}
volumes:
- yoresee_doc_minio_data:/data
networks:
- yoresee_doc_network
restart: unless-stopped
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.15.3
container_name: yoresee_doc_elasticsearch
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- xpack.security.enrollment.enabled=false
- ES_JAVA_OPTS=-Xms512m -Xmx512m
ports:
- "${ELASTICSEARCH_HOST_PORT:-9200}:${ELASTICSEARCH_PORT:-9200}"
volumes:
- yoresee_doc_elasticsearch_data:/usr/share/elasticsearch/data
networks:
- yoresee_doc_network
restart: unless-stopped
backend:
build:
context: ../backend
dockerfile: Dockerfile
target: dev
image: yoresee_doc_backend_dev:latest
container_name: yoresee_doc_backend
volumes:
- ../backend:/app
ports:
- "${BACKEND_DEBUG_HOST_PORT:-2345}:2345"
- "${BACKEND_GRPC_HOST_PORT:-9090}:${BACKEND_GRPC_PORT:-9090}"
environment:
- BACKEND_INTERNAL_RPC_KEY=${BACKEND_INTERNAL_RPC_KEY:-yoresee_doc_internal_key}
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
rabbitmq:
condition: service_healthy
minio:
condition: service_started
elasticsearch:
condition: service_started
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://${BACKEND_HOST:-backend}:${BACKEND_GRPC_PORT:-9090}/health"]
interval: 5s
timeout: 3s
retries: 20
start_period: 30s
networks:
- yoresee_doc_network
restart: unless-stopped
collab-core:
build:
context: ..
dockerfile: collab/Dockerfile
image: yoresee_doc_collab_core:latest
container_name: yoresee_doc_collab_core
environment:
- REDIS_HOST=${REDIS_HOST:-redis}
- REDIS_PORT=${REDIS_PORT:-6379}
- REDIS_PASSWORD=${REDIS_PASSWORD:-your_redis_password}
- REDIS_DB=${REDIS_DB:-0}
- BACKEND_ADDR=${BACKEND_HOST:-backend}:${BACKEND_GRPC_PORT:-9090}
- DIRTY_DOC_MQ=${DIRTY_DOC_MQ:-rabbitmq}
- DIRTY_DOC_TOPIC=${DIRTY_DOC_TOPIC:-collab.dirty_docs}
- RABBITMQ_URL=amqp://${RABBITMQ_DEFAULT_USER:-guest}:${RABBITMQ_DEFAULT_PASS:-guest}@${RABBITMQ_HOST:-rabbitmq}:${RABBITMQ_AMQP_PORT:-5672}/
- INTERNAL_RPC_KEY=${BACKEND_INTERNAL_RPC_KEY:-yoresee_doc_internal_key}
- DIRTY_DOC_NOTIFY_THRESHOLD=${DIRTY_DOC_NOTIFY_THRESHOLD:-5}
depends_on:
redis:
condition: service_healthy
backend:
condition: service_healthy
rabbitmq:
condition: service_healthy
networks:
- yoresee_doc_network
volumes:
- ../collab:/app
restart: unless-stopped
collab:
build:
context: ../collab-go
dockerfile: Dockerfile
image: yoresee_doc_collab_gateway:latest
container_name: yoresee_doc_collab
environment:
- ADDR=:${COLLAB_GATEWAY_PORT:-1234}
- JWT_SECRET=${JWT_SECRET:-yoresee_doc_jwt_secret_key}
- COLLAB_CORE_URL=ws://${COLLAB_CORE_HOST:-collab-core}:${COLLAB_CORE_PORT:-1234}
- BACKEND_GRPC_ADDR=${BACKEND_HOST:-backend}:${BACKEND_GRPC_PORT:-9090}
- INTERNAL_RPC_KEY=${BACKEND_INTERNAL_RPC_KEY:-yoresee_doc_internal_key}
volumes:
- ../collab-go:/app
depends_on:
- collab-core
networks:
- yoresee_doc_network
restart: unless-stopped
snapshot-worker:
build:
context: ../backend
dockerfile: Dockerfile
target: dev
image: yoresee_doc_snapshot_worker_dev:latest
container_name: yoresee_doc_snapshot_worker
volumes:
- ../backend:/app
environment:
- COLLAB_CORE_HTTP=http://${COLLAB_CORE_HOST:-collab-core}:${COLLAB_CORE_PORT:-1234}
command: sh -c "go mod download && go run ./cmd/snapshot-worker"
depends_on:
rabbitmq:
condition: service_healthy
redis:
condition: service_healthy
elasticsearch:
condition: service_started
networks:
- yoresee_doc_network
restart: unless-stopped
notification-worker:
build:
context: ../backend
dockerfile: Dockerfile
target: dev
image: yoresee_doc_notification_worker_dev:latest
container_name: yoresee_doc_notification_worker
volumes:
- ../backend:/app
environment:
- NOTIFICATION_MQ=${NOTIFICATION_MQ:-rabbitmq}
command: sh -c "go mod download && go run ./cmd/notification-worker"
depends_on:
rabbitmq:
condition: service_healthy
redis:
condition: service_healthy
postgres:
condition: service_healthy
networks:
- yoresee_doc_network
restart: unless-stopped
search-sync-worker:
build:
context: ../backend
dockerfile: Dockerfile
target: dev
image: yoresee_doc_search_sync_worker_dev:latest
container_name: yoresee_doc_search_sync_worker
volumes:
- ../backend:/app
environment:
- SEARCH_SYNC_MQ=${SEARCH_SYNC_MQ:-rabbitmq}
command: sh -c "go mod download && go run ./cmd/search-sync-worker"
depends_on:
rabbitmq:
condition: service_healthy
redis:
condition: service_healthy
postgres:
condition: service_healthy
elasticsearch:
condition: service_started
networks:
- yoresee_doc_network
restart: unless-stopped
volumes:
yoresee_doc_postgres_data:
yoresee_doc_redis_data:
yoresee_doc_consul_data:
yoresee_doc_rabbitmq_data:
yoresee_doc_minio_data:
yoresee_doc_elasticsearch_data:
networks:
yoresee_doc_network:
driver: bridge
+251
View File
@@ -0,0 +1,251 @@
services:
nginx:
image: nginx:alpine
container_name: yoresee_doc_nginx
ports:
- "${NGINX_HTTP_PORT:-8080}:80"
- "${NGINX_HTTPS_PORT:-8443}:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
- ./logs/nginx:/var/log/nginx
depends_on:
- frontend
- backend
- collab
- minio
networks:
- yoresee_doc_network
restart: unless-stopped
frontend:
build:
context: ..
dockerfile: frontend/Dockerfile.prod
target: runner
image: yoresee_doc_frontend_runner:latest
container_name: yoresee_doc_frontend
environment:
- NODE_ENV=production
- VITE_API_BASE_URL=${VITE_API_BASE_URL:-http://localhost:8080}
- VITE_GRPC_WEB_ENDPOINT=${VITE_GRPC_WEB_ENDPOINT:-/grpc}
networks:
- yoresee_doc_network
restart: unless-stopped
postgres:
image: postgres:15-alpine
container_name: yoresee_doc_postgres
environment:
POSTGRES_USER: ${POSTGRES_USER:-root}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-your_password}
POSTGRES_DB: ${POSTGRES_DB:-yoresee_doc_db}
volumes:
- yoresee_doc_postgres_data:/var/lib/postgresql/data
networks:
- yoresee_doc_network
restart: unless-stopped
redis:
image: redis:7-alpine
container_name: yoresee_doc_redis
environment:
REDIS_PASSWORD: ${REDIS_PASSWORD:-your_redis_password}
volumes:
- yoresee_doc_redis_data:/data
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
command: redis-server /usr/local/etc/redis/redis.conf
networks:
- yoresee_doc_network
restart: unless-stopped
consul:
image: hashicorp/consul:1.16
container_name: yoresee_doc_consul
command: "agent -dev -client=0.0.0.0 -ui"
environment:
CONSUL_LOCAL_CONFIG: >-
{"acl":{"enabled":true,"default_policy":"deny","down_policy":"extend-cache","enable_token_persistence":true,"tokens":{"initial_management":"${CONSUL_ROOT_TOKEN:-yoresee_doc_root_token}"}}}
ports:
- "${CONSUL_HOST_PORT:-8500}:${CONSUL_PORT:-8500}"
volumes:
- yoresee_doc_consul_data:/consul/data
networks:
- yoresee_doc_network
restart: unless-stopped
rabbitmq:
image: rabbitmq:3-management
container_name: yoresee_doc_rabbitmq
environment:
RABBITMQ_DEFAULT_USER: ${RABBITMQ_DEFAULT_USER:-guest}
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_DEFAULT_PASS:-guest}
volumes:
- yoresee_doc_rabbitmq_data:/var/lib/rabbitmq
- ./rabbitmq/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf:ro
- ./logs/rabbitmq:/var/log/rabbitmq
networks:
- yoresee_doc_network
restart: unless-stopped
minio:
image: minio/minio:latest
container_name: yoresee_doc_minio
command: server /data --console-address ":${MINIO_CONSOLE_PORT:-9001}"
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin}
MINIO_BROWSER_REDIRECT_URL: ${MINIO_BROWSER_REDIRECT_URL:-http://localhost:8080/minio}
volumes:
- yoresee_doc_minio_data:/data
networks:
- yoresee_doc_network
restart: unless-stopped
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.15.3
container_name: yoresee_doc_elasticsearch
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- xpack.security.enrollment.enabled=false
- ES_JAVA_OPTS=-Xms512m -Xmx512m
volumes:
- yoresee_doc_elasticsearch_data:/usr/share/elasticsearch/data
networks:
- yoresee_doc_network
restart: unless-stopped
backend:
build:
context: ..
dockerfile: backend/Dockerfile.prod
target: runner
image: yoresee_doc_backend_runner:latest
container_name: yoresee_doc_backend
volumes:
- ../backend/config.toml:/app/config.toml
environment:
- BACKEND_INTERNAL_RPC_KEY=${BACKEND_INTERNAL_RPC_KEY:-yoresee_doc_internal_key}
ports:
- "${BACKEND_GRPC_HOST_PORT:-9090}:${BACKEND_GRPC_PORT:-9090}"
depends_on:
- postgres
- redis
- consul
- rabbitmq
- minio
- elasticsearch
networks:
- yoresee_doc_network
restart: unless-stopped
collab-core:
build:
context: ..
dockerfile: collab/Dockerfile.prod
image: yoresee_doc_collab_core:latest
container_name: yoresee_doc_collab_core
environment:
- REDIS_HOST=${REDIS_HOST:-redis}
- REDIS_PORT=${REDIS_PORT:-6379}
- REDIS_PASSWORD=${REDIS_PASSWORD:-your_redis_password}
- REDIS_DB=${REDIS_DB:-0}
- BACKEND_ADDR=${BACKEND_HOST:-backend}:${BACKEND_GRPC_PORT:-9090}
- DIRTY_DOC_MQ=${DIRTY_DOC_MQ:-rabbitmq}
- DIRTY_DOC_TOPIC=${DIRTY_DOC_TOPIC:-collab.dirty_docs}
- RABBITMQ_URL=amqp://${RABBITMQ_DEFAULT_USER:-guest}:${RABBITMQ_DEFAULT_PASS:-guest}@${RABBITMQ_HOST:-rabbitmq}:${RABBITMQ_AMQP_PORT:-5672}/
- INTERNAL_RPC_KEY=${BACKEND_INTERNAL_RPC_KEY:-yoresee_doc_internal_key}
- DIRTY_DOC_NOTIFY_THRESHOLD=${DIRTY_DOC_NOTIFY_THRESHOLD:-200}
depends_on:
- redis
- backend
- rabbitmq
networks:
- yoresee_doc_network
restart: unless-stopped
collab:
build:
context: ..
dockerfile: collab-go/Dockerfile.prod
image: yoresee_doc_collab_gateway:latest
container_name: yoresee_doc_collab
environment:
- ADDR=:${COLLAB_GATEWAY_PORT:-1234}
- JWT_SECRET=${JWT_SECRET:-yoresee_doc_jwt_secret_key}
- COLLAB_CORE_URL=ws://${COLLAB_CORE_HOST:-collab-core}:${COLLAB_CORE_PORT:-1234}
- BACKEND_GRPC_ADDR=${BACKEND_HOST:-backend}:${BACKEND_GRPC_PORT:-9090}
- INTERNAL_RPC_KEY=${BACKEND_INTERNAL_RPC_KEY:-yoresee_doc_internal_key}
depends_on:
- collab-core
networks:
- yoresee_doc_network
restart: unless-stopped
snapshot-worker:
build:
context: ..
dockerfile: backend/Dockerfile.snapshot.prod
image: yoresee_doc_snapshot_worker:latest
container_name: yoresee_doc_snapshot_worker
volumes:
- ../backend/config.toml:/app/config.toml
environment:
- COLLAB_CORE_HTTP=http://${COLLAB_CORE_HOST:-collab-core}:${COLLAB_CORE_PORT:-1234}
depends_on:
- rabbitmq
- redis
- elasticsearch
networks:
- yoresee_doc_network
restart: unless-stopped
notification-worker:
build:
context: ..
dockerfile: backend/Dockerfile.notification.prod
image: yoresee_doc_notification_worker:latest
container_name: yoresee_doc_notification_worker
volumes:
- ../backend/config.toml:/app/config.toml
environment:
- NOTIFICATION_MQ=${NOTIFICATION_MQ:-rabbitmq}
depends_on:
- rabbitmq
- redis
- postgres
networks:
- yoresee_doc_network
restart: unless-stopped
search-sync-worker:
build:
context: ..
dockerfile: backend/Dockerfile.search-sync.prod
image: yoresee_doc_search_sync_worker:latest
container_name: yoresee_doc_search_sync_worker
volumes:
- ../backend/config.toml:/app/config.toml
environment:
- SEARCH_SYNC_MQ=${SEARCH_SYNC_MQ:-rabbitmq}
depends_on:
- rabbitmq
- redis
- postgres
- elasticsearch
networks:
- yoresee_doc_network
restart: unless-stopped
volumes:
yoresee_doc_postgres_data:
yoresee_doc_redis_data:
yoresee_doc_consul_data:
yoresee_doc_rabbitmq_data:
yoresee_doc_minio_data:
yoresee_doc_elasticsearch_data:
networks:
yoresee_doc_network:
driver: bridge
+130
View File
@@ -0,0 +1,130 @@
server {
listen 80;
server_name localhost;
client_max_body_size 5m;
# Uncomment the following block (Line6 to Line24) to enable redirect HTTP to HTTPS
# Redirect HTTP to HTTPS
# Using 8443 port because that is what is exposed in docker-compose
# location / {
# return 301 https://$host:8443$request_uri;
# }
# }
# server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate /etc/nginx/ssl/server.crt;
# ssl_certificate_key /etc/nginx/ssl/server.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# gRPC endpoint
location /grpc/ {
if ($request_method = OPTIONS) {
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'POST,GET,OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Accept,Accept-Language,Content-Type,Content-Length,X-Grpc-Web,X-User-Agent,Grpc-Timeout,Authorization,Connect-Protocol-Version' always;
return 204;
}
proxy_pass http://${BACKEND_HOST}:${BACKEND_GRPC_WEB_PORT}/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Grpc-Web $http_x_grpc_web;
proxy_set_header X-User-Agent $http_x_user_agent;
}
# MinIO Console
location = /minio {
return 301 /minio/;
}
location /minio/ {
rewrite ^/minio/(.*)$ /$1 break;
proxy_pass http://${MINIO_HOST}:${MINIO_CONSOLE_PORT};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Prefix /minio;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
# Public storage path
location = /storage {
return 301 /storage/;
}
location /storage/ {
rewrite ^/storage/(.*)$ /${MINIO_BUCKET}/$1 break;
proxy_pass http://${MINIO_HOST}:${MINIO_API_PORT};
proxy_set_header Host ${MINIO_HOST}:${MINIO_API_PORT};
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Frontend (dev/prod on same port)
location / {
proxy_pass http://${FRONTEND_HOST}:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Vite HMR WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
# New collab WebSocket path
location = /ws/doc {
return 301 /ws/doc/;
}
location /ws/doc/ {
proxy_pass http://${COLLAB_HOST}:${COLLAB_GATEWAY_PORT};
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
# RabbitMQ Management Interface
location /rabbitmq/ {
proxy_pass http://${RABBITMQ_HOST}:${RABBITMQ_MANAGEMENT_PORT}/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
# Handle WebSocket connections for management UI
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
+34
View File
@@ -0,0 +1,34 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
include /etc/nginx/conf.d/*.conf;
}
+19
View File
@@ -0,0 +1,19 @@
# RabbitMQ Configuration File - Template
# Default user and password
default_user = ${RABBITMQ_DEFAULT_USER}
default_pass = ${RABBITMQ_DEFAULT_PASS}
# Management plugin
management.tcp.port = ${RABBITMQ_MANAGEMENT_PORT}
# Networking
listeners.tcp.default = ${RABBITMQ_AMQP_PORT}
# Memory-based DB configuration
vm_memory_high_watermark.relative = 0.6
# Logging
log.file.level = info
# Keep RabbitMQ default auth mechanisms (PLAIN/AMQPLAIN) for broad client compatibility.
+3
View File
@@ -0,0 +1,3 @@
bind 0.0.0.0
protected-mode yes
requirepass ${REDIS_PASSWORD}
+111
View File
@@ -0,0 +1,111 @@
#Requires -Version 5.1
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
$BasePath = (Resolve-Path "$ScriptDir\..\.." ).Path
$DeployDir = "$BasePath\deploy"
$EnvFile = "$DeployDir\.env"
$EnvExampleFile = "$DeployDir\.env.example"
if (-not (Test-Path $EnvExampleFile)) {
Write-Error "Missing required file: $EnvExampleFile"
exit 1
}
if (-not (Test-Path $EnvFile)) {
Copy-Item $EnvExampleFile $EnvFile
}
# Load key=value pairs from a .env file into a hashtable (last value wins)
function Read-EnvFile([string]$Path) {
$map = @{}
foreach ($line in (Get-Content $Path)) {
if ($line -match '^\s*#' -or $line.Trim() -eq '') { continue }
$idx = $line.IndexOf('=')
if ($idx -lt 1) { continue }
$map[$line.Substring(0, $idx).Trim()] = $line.Substring($idx + 1)
}
return $map
}
# Write or update a single key in the .env file
function Update-EnvKey([string]$Key, [string]$Value) {
$lines = Get-Content $EnvFile
$updated = $false
$result = foreach ($line in $lines) {
if ($line -match "^$Key=") { "$Key=$Value"; $updated = $true }
else { $line }
}
if (-not $updated) { $result += "$Key=$Value" }
$result | Set-Content $EnvFile
}
# Prompt the user for a value, showing the current default in brackets
function Prompt-Value([string]$Key, [string]$Label, [string]$Fallback) {
$current = if ($script:cfg.ContainsKey($Key) -and $script:cfg[$Key] -ne '') {
$script:cfg[$Key]
} else { $Fallback }
$input = Read-Host "$Label [$current]"
if ([string]::IsNullOrEmpty($input)) { $input = $current }
$script:cfg[$Key] = $input
Update-EnvKey $Key $input
}
# Merge example defaults then overlay with actual .env values
$script:cfg = Read-EnvFile $EnvExampleFile
foreach ($kv in (Read-EnvFile $EnvFile).GetEnumerator()) {
$script:cfg[$kv.Key] = $kv.Value
}
Write-Host "== Yoresee Deploy Config Init =="
Write-Host "Press Enter to keep the default value in brackets."
# Host exposed ports
Prompt-Value 'NGINX_HTTP_PORT' 'Host port for Nginx HTTP' '8080'
Prompt-Value 'NGINX_HTTPS_PORT' 'Host port for Nginx HTTPS' '8443'
Prompt-Value 'BACKEND_GRPC_HOST_PORT' 'Host port for backend gRPC' '9090'
Prompt-Value 'BACKEND_DEBUG_HOST_PORT' 'Host port for backend debug (dev only)' '2345'
Prompt-Value 'POSTGRES_HOST_PORT' 'Host port for Postgres (dev only)' '5432'
Prompt-Value 'REDIS_HOST_PORT' 'Host port for Redis (dev only)' '6379'
Prompt-Value 'RABBITMQ_AMQP_HOST_PORT' 'Host port for RabbitMQ AMQP (dev only)' '5672'
Prompt-Value 'CONSUL_HOST_PORT' 'Host port for Consul UI/API' '8500'
Prompt-Value 'ELASTICSEARCH_HOST_PORT' 'Host port for Elasticsearch (dev only)' '9200'
# Credentials and app secrets
Prompt-Value 'POSTGRES_USER' 'Postgres user' 'root'
Prompt-Value 'POSTGRES_PASSWORD' 'Postgres password' 'your_password'
Prompt-Value 'POSTGRES_DB' 'Postgres database' 'yoresee_doc_db'
Prompt-Value 'REDIS_PASSWORD' 'Redis password' 'your_redis_password'
Prompt-Value 'RABBITMQ_DEFAULT_USER' 'RabbitMQ user' 'guest'
Prompt-Value 'RABBITMQ_DEFAULT_PASS' 'RabbitMQ password' 'guest'
Prompt-Value 'MINIO_ROOT_USER' 'MinIO root user' 'minioadmin'
Prompt-Value 'MINIO_ROOT_PASSWORD' 'MinIO root password' 'minioadmin'
Prompt-Value 'CONSUL_ROOT_TOKEN' 'Consul root token' 'yoresee_doc_root_token'
Prompt-Value 'BACKEND_INTERNAL_RPC_KEY' 'Internal RPC key' 'yoresee_doc_internal_key'
Prompt-Value 'JWT_SECRET' 'JWT secret' 'yoresee_doc_jwt_secret_key'
# App behaviour
$defaultApiUrl = "http://localhost:$($script:cfg['NGINX_HTTP_PORT'])"
Prompt-Value 'VITE_API_BASE_URL' 'Frontend API base URL' $defaultApiUrl
Prompt-Value 'VITE_GRPC_WEB_ENDPOINT' 'Frontend gRPC-web endpoint' '/grpc'
Prompt-Value 'DIRTY_DOC_NOTIFY_THRESHOLD' 'Dirty doc notify threshold' '5'
# Derived value — keep MinIO redirect bound to API base URL
$minioRedirect = "$($script:cfg['VITE_API_BASE_URL'].TrimEnd('/'))/minio"
Update-EnvKey 'MINIO_BROWSER_REDIRECT_URL' $minioRedirect
Write-Host "MinIO browser redirect URL (derived): $minioRedirect"
Prompt-Value 'ELASTICSEARCH_ENABLED' 'Enable Elasticsearch' 'true'
Prompt-Value 'ELASTICSEARCH_INDEX_PREFIX' 'Elasticsearch index prefix' 'yoresee_doc'
Prompt-Value 'ELASTICSEARCH_USERNAME' 'Elasticsearch username (optional)' ''
Prompt-Value 'ELASTICSEARCH_PASSWORD' 'Elasticsearch password (optional)' ''
Write-Host "Written: $EnvFile"
& powershell -ExecutionPolicy Bypass -File "$ScriptDir\prepare.ps1"
Write-Host "Initialization completed."
Write-Host "You can start services with: powershell -ExecutionPolicy Bypass -File deploy/script/start.ps1 dev up"
+119
View File
@@ -0,0 +1,119 @@
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BASE_PATH="$(cd "$SCRIPT_DIR/../.." && pwd)"
DEPLOY_DIR="$BASE_PATH/deploy"
ENV_FILE="$DEPLOY_DIR/.env"
ENV_EXAMPLE_FILE="$DEPLOY_DIR/.env.example"
if [ ! -t 0 ]; then
echo "Interactive terminal is required."
echo "Fallback: copy deploy/.env.example to deploy/.env then run bash deploy/script/prepare.sh"
exit 1
fi
if [ ! -f "$ENV_EXAMPLE_FILE" ]; then
echo "Missing required file: $ENV_EXAMPLE_FILE"
exit 1
fi
if [ ! -f "$ENV_FILE" ]; then
cp "$ENV_EXAMPLE_FILE" "$ENV_FILE"
fi
set -a
# shellcheck disable=SC1090
source "$ENV_EXAMPLE_FILE"
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a
update_env_key() {
local key="$1"
local value="$2"
local tmp_file=""
tmp_file="$(mktemp)"
awk -v key="$key" -v val="$value" '
BEGIN { updated = 0 }
$0 ~ "^" key "=" {
print key "=" val
updated = 1
next
}
{ print }
END {
if (!updated) {
print key "=" val
}
}
' "$ENV_FILE" > "$tmp_file"
mv "$tmp_file" "$ENV_FILE"
}
prompt_value() {
local key="$1"
local label="$2"
local fallback="$3"
local current_value=""
local input=""
current_value="${!key:-$fallback}"
read -r -p "$label [$current_value]: " input
if [ -z "$input" ]; then
input="$current_value"
fi
printf -v "$key" '%s' "$input"
update_env_key "$key" "$input"
}
echo "== Yoresee Deploy Config Init =="
echo "Press Enter to keep the default value in brackets."
# Host exposed ports
prompt_value NGINX_HTTP_PORT "Host port for Nginx HTTP" "8080"
prompt_value NGINX_HTTPS_PORT "Host port for Nginx HTTPS" "8443"
prompt_value BACKEND_GRPC_HOST_PORT "Host port for backend gRPC" "9090"
prompt_value BACKEND_DEBUG_HOST_PORT "Host port for backend debug (dev only)" "2345"
prompt_value POSTGRES_HOST_PORT "Host port for Postgres (dev only)" "5432"
prompt_value REDIS_HOST_PORT "Host port for Redis (dev only)" "6379"
prompt_value RABBITMQ_AMQP_HOST_PORT "Host port for RabbitMQ AMQP (dev only)" "5672"
prompt_value CONSUL_HOST_PORT "Host port for Consul UI/API" "8500"
prompt_value ELASTICSEARCH_HOST_PORT "Host port for Elasticsearch (dev only)" "9200"
# Credentials and app secrets
prompt_value POSTGRES_USER "Postgres user" "root"
prompt_value POSTGRES_PASSWORD "Postgres password" "your_password"
prompt_value POSTGRES_DB "Postgres database" "yoresee_doc_db"
prompt_value REDIS_PASSWORD "Redis password" "your_redis_password"
prompt_value RABBITMQ_DEFAULT_USER "RabbitMQ user" "guest"
prompt_value RABBITMQ_DEFAULT_PASS "RabbitMQ password" "guest"
prompt_value MINIO_ROOT_USER "MinIO root user" "minioadmin"
prompt_value MINIO_ROOT_PASSWORD "MinIO root password" "minioadmin"
prompt_value CONSUL_ROOT_TOKEN "Consul root token" "yoresee_doc_root_token"
prompt_value BACKEND_INTERNAL_RPC_KEY "Internal RPC key" "yoresee_doc_internal_key"
prompt_value JWT_SECRET "JWT secret" "yoresee_doc_jwt_secret_key"
# App behavior
prompt_value VITE_API_BASE_URL "Frontend API base URL" "http://localhost:${NGINX_HTTP_PORT}"
prompt_value VITE_GRPC_WEB_ENDPOINT "Frontend gRPC-web endpoint" "/grpc"
prompt_value DIRTY_DOC_NOTIFY_THRESHOLD "Dirty doc notify threshold" "5"
# Keep MinIO browser redirect bound to API base URL to avoid host drift in deployments.
MINIO_BROWSER_REDIRECT_URL="${VITE_API_BASE_URL%/}/minio"
update_env_key MINIO_BROWSER_REDIRECT_URL "$MINIO_BROWSER_REDIRECT_URL"
echo "MinIO browser redirect URL (derived): $MINIO_BROWSER_REDIRECT_URL"
prompt_value ELASTICSEARCH_ENABLED "Enable Elasticsearch" "true"
prompt_value ELASTICSEARCH_INDEX_PREFIX "Elasticsearch index prefix" "yoresee_doc"
prompt_value ELASTICSEARCH_USERNAME "Elasticsearch username (optional)" ""
prompt_value ELASTICSEARCH_PASSWORD "Elasticsearch password (optional)" ""
echo "Written: $ENV_FILE"
bash "$SCRIPT_DIR/prepare.sh"
echo "Initialization completed."
echo "You can start services with: bash deploy/script/start.sh dev up"
+20
View File
@@ -0,0 +1,20 @@
#Requires -Version 5.1
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
$DeployDir = Resolve-Path "$ScriptDir\.."
if (Get-Command buf -ErrorAction SilentlyContinue) {
Write-Host "buf found locally, generating directly..."
Push-Location "$DeployDir\..\proto"
buf generate --template buf.gen.backend.yaml
buf generate --template buf.gen.collab-go.yaml
buf generate --template buf.gen.frontend.yaml
buf generate --template buf.gen.node.yaml
Pop-Location
Write-Host "Proto generation complete."
} else {
Write-Host "buf not found locally, using proto-gen container..."
docker compose -f "$DeployDir\docker-compose.dev.yml" run --rm proto-gen
}
+18
View File
@@ -0,0 +1,18 @@
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEPLOY_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
if command -v buf &>/dev/null; then
echo "buf found locally, generating directly..."
cd "$DEPLOY_DIR/../proto"
buf generate --template buf.gen.backend.yaml
buf generate --template buf.gen.collab-go.yaml
buf generate --template buf.gen.frontend.yaml
buf generate --template buf.gen.node.yaml
echo "Proto generation complete."
else
echo "buf not found locally, using proto-gen container..."
docker compose -f "$DEPLOY_DIR/docker-compose.dev.yml" run --rm proto-gen
fi
+86
View File
@@ -0,0 +1,86 @@
#Requires -Version 5.1
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
$BasePath = (Resolve-Path "$ScriptDir\..\.." ).Path
$DeployDir = "$BasePath\deploy"
$EnvExampleFile = "$DeployDir\.env.example"
$EnvFile = "$DeployDir\.env"
if (-not (Test-Path $EnvExampleFile)) {
Write-Error "Missing required file: $EnvExampleFile"
exit 1
}
if (-not (Test-Path $EnvFile)) {
Write-Host "deploy\.env not found, creating from .env.example"
Copy-Item $EnvExampleFile $EnvFile
}
# Load key=value pairs from a .env file into a hashtable (last value wins)
function Read-EnvFile([string]$Path) {
$map = @{}
foreach ($line in (Get-Content $Path)) {
if ($line -match '^\s*#' -or $line.Trim() -eq '') { continue }
$idx = $line.IndexOf('=')
if ($idx -lt 1) { continue }
$map[$line.Substring(0, $idx).Trim()] = $line.Substring($idx + 1)
}
return $map
}
# Expand ${VAR} placeholders in a template string using the provided env hashtable
function Expand-Template([string]$Text, [hashtable]$Env) {
return [regex]::Replace($Text, '\$\{([A-Z0-9_]+)\}', {
param($m)
$key = $m.Groups[1].Value
if ($Env.ContainsKey($key)) { $Env[$key] } else { '' }
})
}
# Render a template file to an output path, substituting ${VAR} with env values
function Render-Template([string]$Template, [string]$Output, [hashtable]$Env) {
if (-not (Test-Path $Template)) {
Write-Error "Template not found: $Template"
return
}
$outDir = Split-Path -Parent $Output
if (-not (Test-Path $outDir)) { New-Item -ItemType Directory -Force -Path $outDir | Out-Null }
# If a directory exists at the output path, back it up
if (Test-Path $Output -PathType Container) {
$backup = "$Output.backup.$([DateTimeOffset]::UtcNow.ToUnixTimeSeconds())"
Move-Item $Output $backup
Write-Host "Detected directory at $Output, moved to $backup"
}
$content = Get-Content $Template -Raw
$rendered = Expand-Template $content $Env
[System.IO.File]::WriteAllText($Output, $rendered)
}
# Merge example defaults then overlay with actual .env values
$env_map = Read-EnvFile $EnvExampleFile
foreach ($kv in (Read-EnvFile $EnvFile).GetEnumerator()) {
$env_map[$kv.Key] = $kv.Value
}
$templateMappings = @(
@{ Template = "$BasePath\backend\config.toml.tmpl"; Output = "$BasePath\backend\config.toml" }
@{ Template = "$BasePath\frontend\nginx.conf.tmpl"; Output = "$BasePath\frontend\nginx.conf" }
@{ Template = "$DeployDir\nginx\nginx.conf.tmpl"; Output = "$DeployDir\nginx\nginx.conf" }
@{ Template = "$DeployDir\nginx\conf.d\default.conf.tmpl"; Output = "$DeployDir\nginx\conf.d\default.conf" }
@{ Template = "$DeployDir\redis\redis.conf.tmpl"; Output = "$DeployDir\redis\redis.conf" }
@{ Template = "$DeployDir\rabbitmq\rabbitmq.conf.tmpl"; Output = "$DeployDir\rabbitmq\rabbitmq.conf" }
)
Write-Host "Rendering configuration files from templates..."
foreach ($m in $templateMappings) {
Render-Template $m.Template $m.Output $env_map
$rel = $m.Output.Replace("$BasePath\", '')
Write-Host " - $rel"
}
Write-Host "Configuration preparation completed!"
+75
View File
@@ -0,0 +1,75 @@
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BASE_PATH="$(cd "$SCRIPT_DIR/../.." && pwd)"
DEPLOY_DIR="$BASE_PATH/deploy"
ENV_EXAMPLE_FILE="$DEPLOY_DIR/.env.example"
ENV_FILE="$DEPLOY_DIR/.env"
if [ ! -f "$ENV_EXAMPLE_FILE" ]; then
echo "Missing required file: $ENV_EXAMPLE_FILE"
exit 1
fi
if [ ! -f "$ENV_FILE" ]; then
echo "deploy/.env not found, creating from .env.example"
cp "$ENV_EXAMPLE_FILE" "$ENV_FILE"
fi
set -a
# shellcheck disable=SC1090
source "$ENV_EXAMPLE_FILE"
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a
prepare_target_file() {
local target="$1"
if [ -d "$target" ]; then
local backup="${target}.backup.$(date +%s)"
mv "$target" "$backup"
echo "Detected directory at $target, moved to $backup"
fi
}
render_template() {
local template="$1"
local output="$2"
local tmp_file=""
if [ ! -f "$template" ]; then
echo "Template not found: $template"
return 1
fi
mkdir -p "$(dirname "$output")"
prepare_target_file "$output"
tmp_file="$(mktemp)"
perl -pe 's/\$\{([A-Z0-9_]+)\}/defined $ENV{$1} ? $ENV{$1} : ""/ge' "$template" > "$tmp_file"
mv "$tmp_file" "$output"
}
TEMPLATE_MAPPINGS=(
"$BASE_PATH/backend/config.toml.tmpl:$BASE_PATH/backend/config.toml"
"$BASE_PATH/frontend/nginx.conf.tmpl:$BASE_PATH/frontend/nginx.conf"
"$DEPLOY_DIR/nginx/nginx.conf.tmpl:$DEPLOY_DIR/nginx/nginx.conf"
"$DEPLOY_DIR/nginx/conf.d/default.conf.tmpl:$DEPLOY_DIR/nginx/conf.d/default.conf"
"$DEPLOY_DIR/redis/redis.conf.tmpl:$DEPLOY_DIR/redis/redis.conf"
"$DEPLOY_DIR/rabbitmq/rabbitmq.conf.tmpl:$DEPLOY_DIR/rabbitmq/rabbitmq.conf"
)
echo "Rendering configuration files from templates..."
for mapping in "${TEMPLATE_MAPPINGS[@]}"; do
template="${mapping%%:*}"
output="${mapping#*:}"
render_template "$template" "$output"
rel_output="${output#$BASE_PATH/}"
if [ "$rel_output" = "$output" ]; then
rel_output="$output"
fi
echo " - $rel_output"
done
echo "Configuration preparation completed!"
+61
View File
@@ -0,0 +1,61 @@
#Requires -Version 5.1
param(
[Parameter(Mandatory)][ValidateSet('dev','release')][string]$Environment,
[Parameter(Mandatory)][ValidateSet('rebuild','clear','restart','up','build')][string]$Action
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
$BasePath = (Resolve-Path "$ScriptDir\..\.." ).Path
$DeployDir = "$BasePath\deploy"
Write-Host "Environment: $Environment"
Write-Host "Action: $Action"
Write-Host "Base path: $BasePath"
$ComposeFile = if ($Environment -eq 'dev') { 'docker-compose.dev.yml' } else { 'docker-compose.yml' }
Write-Host "Compose file: $ComposeFile"
if ($Environment -eq 'dev') {
Write-Host "Generating proto code..."
docker compose -f "$DeployDir\$ComposeFile" run --rm proto-gen
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
}
Push-Location $DeployDir
try {
switch ($Action) {
'rebuild' {
Write-Host "Rebuilding and starting services..."
docker compose -f $ComposeFile down -v
docker compose -f $ComposeFile up -d --build
}
'clear' {
Write-Host "Clearing containers and volumes..."
docker compose -f $ComposeFile down -v
}
'restart' {
Write-Host "Restarting services..."
docker compose -f $ComposeFile down
docker compose -f $ComposeFile up -d
}
'up' {
Write-Host "Starting services..."
docker compose -f $ComposeFile up -d
}
'build' {
Write-Host "Building images..."
docker compose -f $ComposeFile build
}
}
} finally {
Pop-Location
}
if ($LASTEXITCODE -ne 0) {
Write-Error "Operation failed."
exit $LASTEXITCODE
}
Write-Host "Operation completed successfully."
+91
View File
@@ -0,0 +1,91 @@
#!/bin/bash
# Check parameter count
if [ $# -lt 2 ]; then
echo "Usage: $0 <dev|release> <rebuild|clear|restart|up|build>"
echo " dev|release: Use docker-compose.dev.yml or docker-compose.yml"
echo " rebuild: Clean containers and volumes, then rebuild and start"
echo " clear: Clean containers and volumes"
echo " restart: Stop and restart services"
echo " up: Start services"
echo " build: Build images without starting"
exit 1
fi
ENVIRONMENT=$1
ACTION=$2
# Parameter validation
if [[ "$ENVIRONMENT" != "dev" && "$ENVIRONMENT" != "release" ]]; then
echo "Error: First argument must be 'dev' or 'release'"
exit 1
fi
if [[ "$ACTION" != "rebuild" && "$ACTION" != "clear" && "$ACTION" != "restart" && "$ACTION" != "up" && "$ACTION" != "build" ]]; then
echo "Error: Second argument must be 'rebuild', 'clear', 'restart', 'up', or 'build'"
exit 1
fi
ORIGINAL_DIR=$(pwd)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BASE_PATH="$(cd "$SCRIPT_DIR/../.." && pwd)"
echo "Environment: $ENVIRONMENT"
echo "Action: $ACTION"
echo "Script directory: $SCRIPT_DIR"
echo "Base path: $BASE_PATH"
cd "$BASE_PATH"/deploy/
# Select compose file based on environment
if [ "$ENVIRONMENT" = "dev" ]; then
COMPOSE_FILE="docker-compose.dev.yml"
else
COMPOSE_FILE="docker-compose.yml"
fi
echo "Using compose file: $COMPOSE_FILE"
if [ "$ENVIRONMENT" = "dev" ]; then
echo "Generating proto code..."
docker compose -f "$COMPOSE_FILE" run --rm proto-gen
fi
case "$ACTION" in
"rebuild")
echo "Rebuilding and starting services..."
docker compose -f "$COMPOSE_FILE" down -v
docker compose -f "$COMPOSE_FILE" up -d --build
;;
"clear")
echo "Clearing containers and volumes..."
docker compose -f "$COMPOSE_FILE" down -v
;;
"restart")
echo "Restarting services..."
docker compose -f "$COMPOSE_FILE" down
docker compose -f "$COMPOSE_FILE" up -d
;;
"up")
echo "Starting services..."
docker compose -f "$COMPOSE_FILE" up -d
;;
"build")
echo "Building images..."
docker compose -f "$COMPOSE_FILE" build
;;
*)
echo "Unknown action: $ACTION"
cd "$ORIGINAL_DIR"
exit 1
;;
esac
cd "$ORIGINAL_DIR"
if [ $? -eq 0 ]; then
echo "Operation completed successfully."
else
echo "Operation failed."
exit 1
fi