feat: CI/CD pipeline + Learning/Medicine/Travel services
Some checks failed
Build and Deploy GooSeek / build-backend (push) Failing after 1m4s
Build and Deploy GooSeek / build-webui (push) Failing after 1m2s
Build and Deploy GooSeek / deploy (push) Has been skipped

- Add Gitea Actions workflow for automated build & deploy
- Add K8s manifests: webui, travel-svc, medicine-svc, sandbox-svc
- Update kustomization for localhost:5000 registry
- Add ingress for gooseek.ru and api.gooseek.ru
- Learning cabinet with onboarding, courses, sandbox integration
- Medicine service with symptom analysis and doctor matching
- Travel service with itinerary planning
- Server setup scripts (NVIDIA/CUDA, K3s, Gitea runner)

Made-with: Cursor
This commit is contained in:
home
2026-03-02 20:25:44 +03:00
parent 08bd41e75c
commit ab48a0632b
92 changed files with 15562 additions and 2198 deletions

View File

@@ -24,7 +24,9 @@ RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /bin/file-svc ./cmd/fi
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /bin/thread-svc ./cmd/thread-svc
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /bin/finance-heatmap-svc ./cmd/finance-heatmap-svc
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /bin/learning-svc ./cmd/learning-svc
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /bin/sandbox-svc ./cmd/sandbox-svc
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /bin/travel-svc ./cmd/travel-svc
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /bin/medicine-svc ./cmd/medicine-svc
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /bin/labs-svc ./cmd/labs-svc
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /bin/podcast-svc ./cmd/podcast-svc
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /bin/admin-svc ./cmd/admin-svc
@@ -43,7 +45,7 @@ COPY --from=builder /bin/* /app/
ENV SERVICE=api-gateway
ENV PORT=3015
EXPOSE 3015 3018 3005 3001 3020 3021 3002 3025 3026 3027 3035 3040
EXPOSE 3015 3018 3005 3001 3020 3021 3002 3025 3026 3027 3034 3035 3036 3037 3040
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:${PORT}/health || exit 1

View File

@@ -5,11 +5,11 @@ services:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.all
env_file: ../../../.env
environment:
- SERVICE=auth-svc
- PORT=3050
- DATABASE_URL=postgres://gooseek:gooseek@postgres:5432/gooseek?sslmode=disable
- JWT_SECRET=${JWT_SECRET}
- AUTH_SVC_URL=http://auth-svc:3050
ports:
- "3050:3050"
depends_on:
@@ -26,6 +26,7 @@ services:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.all
env_file: ../../../.env
environment:
- SERVICE=api-gateway
- PORT=3015
@@ -39,9 +40,10 @@ services:
- DISCOVER_SVC_URL=http://discover-svc:3002
- FINANCE_HEATMAP_SVC_URL=http://finance-heatmap-svc:3033
- LEARNING_SVC_URL=http://learning-svc:3034
- SANDBOX_SVC_URL=http://sandbox-svc:3036
- TRAVEL_SVC_URL=http://travel-svc:3035
- MEDICINE_SVC_URL=http://medicine-svc:3037
- ADMIN_SVC_URL=http://admin-svc:3040
- JWT_SECRET=${JWT_SECRET}
- REDIS_URL=redis://redis:6379
ports:
- "3015:3015"
@@ -52,6 +54,7 @@ services:
- thread-svc
- admin-svc
- travel-svc
- medicine-svc
- redis
networks:
- gooseek
@@ -60,10 +63,10 @@ services:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.chat-svc
env_file: ../../../.env
environment:
- SERVICE=chat-svc
- PORT=3005
- JWT_SECRET=${JWT_SECRET}
- AUTH_SVC_URL=http://auth-svc:3050
- MASTER_AGENTS_SVC_URL=http://agent-svc:3018
- DISCOVER_SVC_URL=http://discover-svc:3002
@@ -79,23 +82,15 @@ services:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.agent-svc
env_file: ../../../.env
environment:
- SERVICE=agent-svc
- PORT=3018
- JWT_SECRET=${JWT_SECRET}
- AUTH_SVC_URL=http://auth-svc:3050
- SEARXNG_URL=http://searxng:8080
- DISCOVER_SVC_URL=http://discover-svc:3002
- CRAWL4AI_URL=http://crawl4ai:11235
- TRAVEL_SVC_URL=http://travel-svc:3035
- TRAVELPAYOUTS_TOKEN=${TRAVELPAYOUTS_TOKEN}
- TRAVELPAYOUTS_MARKER=${TRAVELPAYOUTS_MARKER}
- OPENAI_API_KEY=${OPENAI_API_KEY}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- GEMINI_API_KEY=${GEMINI_API_KEY}
- TIMEWEB_API_BASE_URL=${TIMEWEB_API_BASE_URL}
- TIMEWEB_AGENT_ACCESS_ID=${TIMEWEB_AGENT_ACCESS_ID}
- TIMEWEB_API_KEY=${TIMEWEB_API_KEY}
ports:
- "3018:3018"
depends_on:
@@ -111,6 +106,7 @@ services:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.search-svc
env_file: ../../../.env
environment:
- SERVICE=search-svc
- PORT=3001
@@ -126,12 +122,10 @@ services:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.all
env_file: ../../../.env
environment:
- SERVICE=llm-svc
- PORT=3020
- OPENAI_API_KEY=${OPENAI_API_KEY}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- GEMINI_API_KEY=${GEMINI_API_KEY}
ports:
- "3020:3020"
networks:
@@ -141,6 +135,7 @@ services:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.all
env_file: ../../../.env
environment:
- SERVICE=scraper-svc
- PORT=3021
@@ -154,6 +149,7 @@ services:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.discover-svc
env_file: ../../../.env
environment:
- SERVICE=discover-svc
- PORT=3002
@@ -173,12 +169,12 @@ services:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.all
env_file: ../../../.env
environment:
- SERVICE=collection-svc
- PORT=3025
- DATABASE_URL=postgres://gooseek:gooseek@postgres:5432/gooseek?sslmode=disable
- JWT_SECRET=${JWT_SECRET}
- AUTH_SVC_URL=${AUTH_SVC_URL}
- AUTH_SVC_URL=http://auth-svc:3050
ports:
- "3025:3025"
depends_on:
@@ -190,13 +186,11 @@ services:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.all
env_file: ../../../.env
environment:
- SERVICE=file-svc
- PORT=3026
- DATABASE_URL=postgres://gooseek:gooseek@postgres:5432/gooseek?sslmode=disable
- OPENAI_API_KEY=${OPENAI_API_KEY}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- JWT_SECRET=${JWT_SECRET}
- FILE_STORAGE_PATH=/data/files
ports:
- "3026:3026"
@@ -211,13 +205,12 @@ services:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.all
env_file: ../../../.env
environment:
- SERVICE=thread-svc
- PORT=3027
- DATABASE_URL=postgres://gooseek:gooseek@postgres:5432/gooseek?sslmode=disable
- OPENAI_API_KEY=${OPENAI_API_KEY}
- JWT_SECRET=${JWT_SECRET}
- AUTH_SVC_URL=${AUTH_SVC_URL}
- AUTH_SVC_URL=http://auth-svc:3050
ports:
- "3027:3027"
depends_on:
@@ -229,12 +222,11 @@ services:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.all
env_file: ../../../.env
environment:
- SERVICE=labs-svc
- PORT=3031
- LABS_SVC_PORT=3031
- OPENAI_API_KEY=${OPENAI_API_KEY}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
ports:
- "3031:3031"
networks:
@@ -244,13 +236,11 @@ services:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.all
env_file: ../../../.env
environment:
- SERVICE=podcast-svc
- PORT=3032
- PODCAST_SVC_PORT=3032
- OPENAI_API_KEY=${OPENAI_API_KEY}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- ELEVENLABS_API_KEY=${ELEVENLABS_API_KEY}
ports:
- "3032:3032"
volumes:
@@ -262,12 +252,11 @@ services:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.all
env_file: ../../../.env
environment:
- SERVICE=finance-heatmap-svc
- PORT=3033
- REDIS_URL=redis://redis:6379
# MOEX, Крипто, Валюты работают без URL (встроенные провайдеры). Для своих рынков — URL сервиса, GET ?market=...&range=...
- FINANCE_DATA_PROVIDER_URL=${FINANCE_DATA_PROVIDER_URL:-}
ports:
- "3033:3033"
depends_on:
@@ -279,16 +268,12 @@ services:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.all
env_file: ../../../.env
environment:
- SERVICE=learning-svc
- PORT=3034
- LEARNING_SVC_PORT=3034
- TIMEWEB_API_BASE_URL=${TIMEWEB_API_BASE_URL}
- TIMEWEB_AGENT_ACCESS_ID=${TIMEWEB_AGENT_ACCESS_ID}
- TIMEWEB_API_KEY=${TIMEWEB_API_KEY}
- DEFAULT_LLM_MODEL=${DEFAULT_LLM_MODEL:-gpt-4o-mini}
- OPENAI_API_KEY=${OPENAI_API_KEY}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- AUTH_SVC_URL=http://auth-svc:3050
- DATABASE_URL=postgres://gooseek:gooseek@postgres:5432/gooseek?sslmode=disable
ports:
- "3034:3034"
@@ -297,31 +282,37 @@ services:
networks:
- gooseek
sandbox-svc:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.all
env_file: ../../../.env
environment:
- SERVICE=sandbox-svc
- PORT=3036
- SANDBOX_SVC_PORT=3036
- AUTH_SVC_URL=http://auth-svc:3050
- DATABASE_URL=postgres://gooseek:gooseek@postgres:5432/gooseek?sslmode=disable
- OPENSANDBOX_URL=http://opensandbox-server:8080
ports:
- "3036:3036"
depends_on:
- postgres
networks:
- gooseek
travel-svc:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.all
env_file: ../../../.env
environment:
- SERVICE=travel-svc
- PORT=3035
- DATABASE_URL=postgres://gooseek:gooseek@postgres:5432/gooseek?sslmode=disable
- JWT_SECRET=${JWT_SECRET}
- AUTH_SVC_URL=http://auth-svc:3050
# Российские API (по умолчанию)
- USE_RUSSIAN_APIS=true
- TRAVELPAYOUTS_TOKEN=${TRAVELPAYOUTS_TOKEN}
- TRAVELPAYOUTS_MARKER=${TRAVELPAYOUTS_MARKER}
- TWOGIS_API_KEY=${TWOGIS_API_KEY}
# Международные API (опционально)
- AMADEUS_API_KEY=${AMADEUS_API_KEY}
- AMADEUS_API_SECRET=${AMADEUS_API_SECRET}
- OPENROUTE_API_KEY=${OPENROUTE_API_KEY}
# LLM (TimeWeb)
- LLM_PROVIDER=timeweb
- LLM_MODEL=${DEFAULT_LLM_MODEL:-gpt-4o-mini}
- TIMEWEB_API_BASE_URL=${TIMEWEB_API_BASE_URL}
- TIMEWEB_AGENT_ACCESS_ID=${TIMEWEB_AGENT_ACCESS_ID}
- TIMEWEB_API_KEY=${TIMEWEB_API_KEY}
ports:
- "3035:3035"
depends_on:
@@ -330,17 +321,36 @@ services:
networks:
- gooseek
medicine-svc:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.all
env_file: ../../../.env
environment:
- SERVICE=medicine-svc
- PORT=3037
- AUTH_SVC_URL=http://auth-svc:3050
- SEARXNG_URL=http://searxng:8080
- LLM_PROVIDER=timeweb
ports:
- "3037:3037"
depends_on:
- auth-svc
- searxng
networks:
- gooseek
admin-svc:
build:
context: ../..
dockerfile: deploy/docker/Dockerfile.all
env_file: ../../../.env
environment:
- SERVICE=admin-svc
- PORT=3040
- ADMIN_SVC_PORT=3040
- DATABASE_URL=postgres://gooseek:gooseek@postgres:5432/gooseek?sslmode=disable
- JWT_SECRET=${JWT_SECRET}
- AUTH_SVC_URL=${AUTH_SVC_URL}
- AUTH_SVC_URL=http://auth-svc:3050
- MINIO_ENDPOINT=minio:9000
- MINIO_ACCESS_KEY=minioadmin
- MINIO_SECRET_KEY=minioadmin
@@ -378,12 +388,12 @@ services:
context: ../../webui
dockerfile: Dockerfile
args:
- NEXT_PUBLIC_DISABLED_ROUTES=${NEXT_PUBLIC_DISABLED_ROUTES:-/medicine}
NEXT_PUBLIC_ENABLED_ROUTES: ${NEXT_PUBLIC_ENABLED_ROUTES:-}
NEXT_PUBLIC_TWOGIS_API_KEY: ${NEXT_PUBLIC_TWOGIS_API_KEY:-}
env_file: ../../../.env
environment:
- NODE_ENV=production
- API_URL=http://api-gateway:3015
- NEXT_PUBLIC_API_URL=
- NEXT_PUBLIC_DISABLED_ROUTES=${NEXT_PUBLIC_DISABLED_ROUTES:-/medicine}
ports:
- "3000:3000"
depends_on:

View File

@@ -16,6 +16,27 @@ data:
COLLECTION_SVC_URL: "http://collection-svc:3025"
FILE_SVC_URL: "http://file-svc:3026"
THREAD_SVC_URL: "http://thread-svc:3027"
LEARNING_SVC_URL: "http://learning-svc:3034"
MEDICINE_SVC_URL: "http://medicine-svc:3037"
SANDBOX_SVC_URL: "http://sandbox-svc:3036"
OPENSANDBOX_URL: "http://opensandbox-server:8080"
AUTH_SVC_URL: "http://auth-svc:3050"
TRAVEL_SVC_URL: "http://travel-svc:3035"
ADMIN_SVC_URL: "http://admin-svc:3040"
DEFAULT_LLM_MODEL: "${DEFAULT_LLM_MODEL}"
DEFAULT_LLM_PROVIDER: "${DEFAULT_LLM_PROVIDER}"
TIMEWEB_API_BASE_URL: "${TIMEWEB_API_BASE_URL}"
TIMEWEB_AGENT_ACCESS_ID: "${TIMEWEB_AGENT_ACCESS_ID}"
TRAVELPAYOUTS_TOKEN: "${TRAVELPAYOUTS_TOKEN}"
NEXT_PUBLIC_ENABLED_ROUTES: "${NEXT_PUBLIC_ENABLED_ROUTES}"
NEXT_PUBLIC_TWOGIS_API_KEY: "${NEXT_PUBLIC_TWOGIS_API_KEY}"
S3_ENDPOINT: "${S3_ENDPOINT}"
S3_ACCESS_KEY: "${S3_ACCESS_KEY}"
S3_SECRET_KEY: "${S3_SECRET_KEY}"
S3_BUCKET: "${S3_BUCKET}"
S3_USE_SSL: "${S3_USE_SSL}"
S3_REGION: "${S3_REGION}"
S3_PUBLIC_URL: "${S3_PUBLIC_URL}"
---
apiVersion: v1
kind: Secret
@@ -28,5 +49,6 @@ stringData:
ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY}"
GEMINI_API_KEY: "${GEMINI_API_KEY}"
JWT_SECRET: "${JWT_SECRET}"
TIMEWEB_API_KEY: "${TIMEWEB_API_KEY}"
POSTGRES_USER: "gooseek"
POSTGRES_PASSWORD: "gooseek"

View File

@@ -3,9 +3,24 @@ set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BACKEND_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
ROOT_DIR="$(cd "$BACKEND_DIR/.." && pwd)"
ENV_FILE="$ROOT_DIR/.env"
echo "=== GooSeek Go Backend K8s Deployment ==="
REGISTRY="localhost:5000"
IMAGE_TAG="${IMAGE_TAG:-latest}"
echo "=== GooSeek K8s Deployment ==="
echo "Backend dir: $BACKEND_DIR"
echo "Registry: $REGISTRY"
echo "Tag: $IMAGE_TAG"
# Load .env
if [ -f "$ENV_FILE" ]; then
echo "Loading env from $ENV_FILE"
set -a
source "$ENV_FILE"
set +a
fi
# Check kubectl
if ! command -v kubectl &> /dev/null; then
@@ -13,17 +28,40 @@ if ! command -v kubectl &> /dev/null; then
exit 1
fi
# Build Docker image
# Build and push backend image
echo ""
echo "=== Building Docker image ==="
echo "=== Building Go backend image ==="
cd "$BACKEND_DIR"
docker build -f deploy/docker/Dockerfile.all -t gooseek/backend:latest .
docker build -f deploy/docker/Dockerfile.all \
-t "$REGISTRY/gooseek/backend:$IMAGE_TAG" \
-t "$REGISTRY/gooseek/backend:latest" \
.
# Load to k3s (if using k3s)
if command -v k3s &> /dev/null; then
echo ""
echo "=== Loading image to k3s ==="
docker save gooseek/backend:latest | sudo k3s ctr images import -
echo "=== Pushing backend to registry ==="
docker push "$REGISTRY/gooseek/backend:$IMAGE_TAG"
docker push "$REGISTRY/gooseek/backend:latest"
# Build and push webui image
echo ""
echo "=== Building webui image ==="
docker build \
-f "$BACKEND_DIR/webui/Dockerfile" \
--build-arg "NEXT_PUBLIC_ENABLED_ROUTES=${NEXT_PUBLIC_ENABLED_ROUTES:-}" \
--build-arg "NEXT_PUBLIC_TWOGIS_API_KEY=${NEXT_PUBLIC_TWOGIS_API_KEY:-}" \
-t "$REGISTRY/gooseek/webui:$IMAGE_TAG" \
-t "$REGISTRY/gooseek/webui:latest" \
"$BACKEND_DIR/webui"
echo "=== Pushing webui to registry ==="
docker push "$REGISTRY/gooseek/webui:$IMAGE_TAG"
docker push "$REGISTRY/gooseek/webui:latest"
# Generate configmap/secrets from .env via envsubst
echo ""
echo "=== Generating K8s manifests from .env ==="
if command -v envsubst &> /dev/null && [ -f "$ENV_FILE" ]; then
envsubst < "$SCRIPT_DIR/configmap.yaml" > "$SCRIPT_DIR/_generated_configmap.yaml"
kubectl apply -f "$SCRIPT_DIR/_generated_configmap.yaml" -n gooseek
fi
# Apply kustomization
@@ -32,20 +70,31 @@ echo "=== Applying K8s manifests ==="
cd "$SCRIPT_DIR"
kubectl apply -k .
# Rolling restart to pull new images
echo ""
echo "=== Rolling restart deployments ==="
kubectl -n gooseek rollout restart deployment/api-gateway
kubectl -n gooseek rollout restart deployment/webui
kubectl -n gooseek rollout restart deployment/chat-svc
kubectl -n gooseek rollout restart deployment/agent-svc
kubectl -n gooseek rollout restart deployment/discover-svc
kubectl -n gooseek rollout restart deployment/search-svc
kubectl -n gooseek rollout restart deployment/learning-svc
kubectl -n gooseek rollout restart deployment/medicine-svc
kubectl -n gooseek rollout restart deployment/travel-svc
kubectl -n gooseek rollout restart deployment/sandbox-svc
# Wait for rollout
echo ""
echo "=== Waiting for deployments ==="
kubectl -n gooseek rollout status deployment/api-gateway --timeout=120s || true
echo "=== Waiting for rollouts ==="
kubectl -n gooseek rollout status deployment/api-gateway --timeout=180s || true
kubectl -n gooseek rollout status deployment/chat-svc --timeout=120s || true
kubectl -n gooseek rollout status deployment/agent-svc --timeout=120s || true
kubectl -n gooseek rollout status deployment/discover-svc --timeout=120s || true
kubectl -n gooseek rollout status deployment/search-svc --timeout=120s || true
kubectl -n gooseek rollout status deployment/redis --timeout=60s || true
# Show status
echo ""
echo "=== Deployment Status ==="
kubectl -n gooseek get pods
kubectl -n gooseek get pods -o wide
echo ""
kubectl -n gooseek get svc
echo ""
@@ -53,4 +102,5 @@ kubectl -n gooseek get ingress
echo ""
echo "=== Done ==="
echo "API Gateway: http://localhost:3015 (NodePort) or via Ingress"
echo "API: https://api.gooseek.ru"
echo "Web: https://gooseek.ru"

View File

@@ -0,0 +1,44 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: gitea
namespace: gitea
spec:
replicas: 1
selector:
matchLabels:
app: gitea
template:
metadata:
labels:
app: gitea
spec:
containers:
- name: gitea
image: gitea/gitea:1.22
ports:
- containerPort: 3000
name: http
- containerPort: 22
name: ssh
volumeMounts:
- name: data
mountPath: /data
env:
- name: GITEA__database__DB_TYPE
value: sqlite3
- name: GITEA__server__DOMAIN
value: git.gooseek.ru
- name: GITEA__server__ROOT_URL
value: https://git.gooseek.ru/
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
volumes:
- name: data
persistentVolumeClaim:
claimName: gitea-data

View File

@@ -4,7 +4,7 @@ metadata:
name: gooseek-ingress
namespace: gooseek
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
nginx.ingress.kubernetes.io/proxy-buffering: "off"
@@ -14,9 +14,20 @@ spec:
ingressClassName: nginx
tls:
- hosts:
- gooseek.ru
- api.gooseek.ru
secretName: gooseek-tls
rules:
- host: gooseek.ru
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: webui
port:
number: 3000
- host: api.gooseek.ru
http:
paths:
@@ -27,25 +38,3 @@ spec:
name: api-gateway
port:
number: 3015
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gooseek-ingress-local
namespace: gooseek
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
spec:
ingressClassName: nginx
rules:
- host: localhost
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-gateway
port:
number: 3015

View File

@@ -9,6 +9,7 @@ resources:
- postgres.yaml
- redis.yaml
- api-gateway.yaml
- webui.yaml
- chat-svc.yaml
- agent-svc.yaml
- search-svc.yaml
@@ -18,6 +19,11 @@ resources:
- collection-svc.yaml
- file-svc.yaml
- thread-svc.yaml
- learning-svc.yaml
- medicine-svc.yaml
- travel-svc.yaml
- sandbox-svc.yaml
- opensandbox.yaml
- ingress.yaml
commonLabels:
@@ -26,4 +32,8 @@ commonLabels:
images:
- name: gooseek/backend
newName: localhost:5000/gooseek/backend
newTag: latest
- name: gooseek/webui
newName: localhost:5000/gooseek/webui
newTag: latest

View File

@@ -0,0 +1,68 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: learning-svc
namespace: gooseek
labels:
app: learning-svc
app.kubernetes.io/name: learning-svc
app.kubernetes.io/part-of: gooseek
spec:
replicas: 2
selector:
matchLabels:
app: learning-svc
template:
metadata:
labels:
app: learning-svc
spec:
containers:
- name: learning-svc
image: gooseek/backend:latest
env:
- name: SERVICE
value: "learning-svc"
- name: PORT
value: "3034"
envFrom:
- configMapRef:
name: gooseek-config
- secretRef:
name: gooseek-secrets
ports:
- containerPort: 3034
name: http
livenessProbe:
httpGet:
path: /health
port: 3034
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /health
port: 3034
initialDelaySeconds: 10
periodSeconds: 15
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 1000m
memory: 512Mi
---
apiVersion: v1
kind: Service
metadata:
name: learning-svc
namespace: gooseek
spec:
type: ClusterIP
selector:
app: learning-svc
ports:
- port: 3034
targetPort: 3034
name: http

View File

@@ -0,0 +1,70 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: medicine-svc
namespace: gooseek
labels:
app: medicine-svc
app.kubernetes.io/name: medicine-svc
app.kubernetes.io/part-of: gooseek
spec:
replicas: 2
selector:
matchLabels:
app: medicine-svc
template:
metadata:
labels:
app: medicine-svc
spec:
containers:
- name: medicine-svc
image: gooseek/backend:latest
env:
- name: SERVICE
value: "medicine-svc"
- name: PORT
value: "3037"
- name: LLM_PROVIDER
value: "timeweb"
envFrom:
- configMapRef:
name: gooseek-config
- secretRef:
name: gooseek-secrets
ports:
- containerPort: 3037
name: http
livenessProbe:
httpGet:
path: /health
port: 3037
initialDelaySeconds: 10
periodSeconds: 20
readinessProbe:
httpGet:
path: /health
port: 3037
initialDelaySeconds: 5
periodSeconds: 15
resources:
requests:
cpu: 150m
memory: 192Mi
limits:
cpu: 700m
memory: 512Mi
---
apiVersion: v1
kind: Service
metadata:
name: medicine-svc
namespace: gooseek
spec:
type: ClusterIP
selector:
app: medicine-svc
ports:
- port: 3037
targetPort: 3037
name: http

View File

@@ -0,0 +1,165 @@
apiVersion: v1
kind: Namespace
metadata:
name: gooseek-sandbox
labels:
app.kubernetes.io/part-of: gooseek
purpose: user-sandboxes
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: opensandbox-sa
namespace: gooseek
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: opensandbox-role
namespace: gooseek-sandbox
rules:
- apiGroups: [""]
resources: ["pods", "pods/exec", "pods/log"]
verbs: ["create", "get", "list", "watch", "delete"]
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["create", "get", "list", "watch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: opensandbox-binding
namespace: gooseek-sandbox
subjects:
- kind: ServiceAccount
name: opensandbox-sa
namespace: gooseek
roleRef:
kind: Role
name: opensandbox-role
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: sandbox-quota
namespace: gooseek-sandbox
spec:
hard:
requests.cpu: "8"
requests.memory: "16Gi"
limits.cpu: "16"
limits.memory: "32Gi"
pods: "50"
---
apiVersion: v1
kind: LimitRange
metadata:
name: sandbox-limits
namespace: gooseek-sandbox
spec:
limits:
- default:
cpu: "500m"
memory: "512Mi"
defaultRequest:
cpu: "100m"
memory: "128Mi"
max:
cpu: "2"
memory: "2Gi"
type: Container
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: opensandbox-server
namespace: gooseek
labels:
app: opensandbox-server
app.kubernetes.io/name: opensandbox-server
app.kubernetes.io/part-of: gooseek
spec:
replicas: 1
selector:
matchLabels:
app: opensandbox-server
template:
metadata:
labels:
app: opensandbox-server
spec:
serviceAccountName: opensandbox-sa
containers:
- name: opensandbox
image: registry.cn-hangzhou.aliyuncs.com/open_sandbox/server:v1.0.1
ports:
- containerPort: 8080
name: http
env:
- name: SANDBOX_NAMESPACE
value: "gooseek-sandbox"
- name: SANDBOX_DEFAULT_TIMEOUT
value: "30m"
- name: SANDBOX_MAX_CONCURRENT
value: "20"
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 1000m
memory: 512Mi
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 15
---
apiVersion: v1
kind: Service
metadata:
name: opensandbox-server
namespace: gooseek
spec:
type: ClusterIP
selector:
app: opensandbox-server
ports:
- port: 8080
targetPort: 8080
name: http
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: sandbox-isolation
namespace: gooseek-sandbox
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
app.kubernetes.io/part-of: gooseek
egress:
- to:
- namespaceSelector:
matchLabels:
app.kubernetes.io/part-of: gooseek
- to: []
ports:
- protocol: TCP
port: 443
- protocol: TCP
port: 80

View File

@@ -0,0 +1,78 @@
apiVersion: v1
kind: Secret
metadata:
name: registry-auth
namespace: gooseek
type: Opaque
stringData:
htpasswd: |
admin:$2y$05$A6oxuQhSjFObdjDsbjiWee.FJ62XQrc6BhLfzCMofY.9A/qQ050v6
---
apiVersion: v1
kind: ConfigMap
metadata:
name: registry-config
namespace: gooseek
data:
config.yml: |
version: 0.1
log:
level: info
storage:
filesystem:
rootdirectory: /var/lib/registry
delete:
enabled: true
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
auth:
htpasswd:
realm: GooSeek Registry
path: /auth/htpasswd
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: registry
namespace: gooseek
spec:
replicas: 1
selector:
matchLabels:
app: registry
template:
metadata:
labels:
app: registry
spec:
containers:
- name: registry
image: registry:2
ports:
- containerPort: 5000
volumeMounts:
- name: registry-data
mountPath: /var/lib/registry
- name: registry-config
mountPath: /etc/docker/registry
- name: registry-auth
mountPath: /auth
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "256Mi"
cpu: "200m"
volumes:
- name: registry-data
persistentVolumeClaim:
claimName: registry-pvc
- name: registry-config
configMap:
name: registry-config
- name: registry-auth
secret:
secretName: registry-auth

View File

@@ -0,0 +1,70 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: sandbox-svc
namespace: gooseek
labels:
app: sandbox-svc
app.kubernetes.io/name: sandbox-svc
app.kubernetes.io/part-of: gooseek
spec:
replicas: 1
selector:
matchLabels:
app: sandbox-svc
template:
metadata:
labels:
app: sandbox-svc
spec:
containers:
- name: sandbox-svc
image: gooseek/backend:latest
env:
- name: SERVICE
value: "sandbox-svc"
- name: PORT
value: "3036"
- name: OPENSANDBOX_URL
value: "http://opensandbox-server:8080"
envFrom:
- configMapRef:
name: gooseek-config
- secretRef:
name: gooseek-secrets
ports:
- containerPort: 3036
name: http
livenessProbe:
httpGet:
path: /health
port: 3036
initialDelaySeconds: 10
periodSeconds: 20
readinessProbe:
httpGet:
path: /health
port: 3036
initialDelaySeconds: 5
periodSeconds: 15
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
name: sandbox-svc
namespace: gooseek
spec:
type: ClusterIP
selector:
app: sandbox-svc
ports:
- port: 3036
targetPort: 3036
name: http

View File

@@ -0,0 +1,68 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: travel-svc
namespace: gooseek
labels:
app: travel-svc
app.kubernetes.io/name: travel-svc
app.kubernetes.io/part-of: gooseek
spec:
replicas: 2
selector:
matchLabels:
app: travel-svc
template:
metadata:
labels:
app: travel-svc
spec:
containers:
- name: travel-svc
image: gooseek/backend:latest
env:
- name: SERVICE
value: "travel-svc"
- name: PORT
value: "3035"
envFrom:
- configMapRef:
name: gooseek-config
- secretRef:
name: gooseek-secrets
ports:
- containerPort: 3035
name: http
livenessProbe:
httpGet:
path: /health
port: 3035
initialDelaySeconds: 10
periodSeconds: 20
readinessProbe:
httpGet:
path: /health
port: 3035
initialDelaySeconds: 5
periodSeconds: 15
resources:
requests:
cpu: 150m
memory: 192Mi
limits:
cpu: 700m
memory: 512Mi
---
apiVersion: v1
kind: Service
metadata:
name: travel-svc
namespace: gooseek
spec:
type: ClusterIP
selector:
app: travel-svc
ports:
- port: 3035
targetPort: 3035
name: http

View File

@@ -0,0 +1,63 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: webui
namespace: gooseek
labels:
app: webui
app.kubernetes.io/name: webui
app.kubernetes.io/part-of: gooseek
spec:
replicas: 2
selector:
matchLabels:
app: webui
template:
metadata:
labels:
app: webui
spec:
containers:
- name: webui
image: gooseek/webui:latest
ports:
- containerPort: 3000
name: http
envFrom:
- configMapRef:
name: gooseek-config
- secretRef:
name: gooseek-secrets
livenessProbe:
httpGet:
path: /
port: 3000
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /
port: 3000
initialDelaySeconds: 5
periodSeconds: 10
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 1000m
memory: 512Mi
---
apiVersion: v1
kind: Service
metadata:
name: webui
namespace: gooseek
spec:
type: ClusterIP
selector:
app: webui
ports:
- port: 3000
targetPort: 3000
name: http

View File

@@ -0,0 +1,49 @@
# Установка NVIDIA + CUDA на сервере (Ubuntu 24.04)
Скрипт `setup-nvidia-cuda-ubuntu24.sh` ставит драйвер NVIDIA и CUDA Toolkit для работы с нейросетями (PyTorch, TensorFlow и т.д.).
## Что уже сделано на 192.168.31.59
- **Драйвер:** nvidia-driver-570-server (Open kernel module)
- **CUDA:** 12.6 в `/usr/local/cuda-12.6`
- **Окружение:** `/etc/profile.d/cuda.sh` — подключать: `source /etc/profile.d/cuda.sh`
## Обязательно после установки
**Перезагрузка** (без неё драйвер не загрузится):
```bash
sudo reboot
```
После перезагрузки проверка:
```bash
nvidia-smi
source /etc/profile.d/cuda.sh && nvcc --version
```
## Проверка для нейросетей (PyTorch)
```bash
source /etc/profile.d/cuda.sh
pip install torch --index-url https://download.pytorch.org/whl/cu124
python3 -c "import torch; print('CUDA:', torch.cuda.is_available()); print('Device:', torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'N/A')"
```
Для CUDA 12.6 подойдёт индекс `cu124` (PyTorch совместим с 12.4+).
## Запуск скрипта вручную
Если нужно переустановить или поставить на другом сервере:
```bash
scp backend/deploy/scripts/setup-nvidia-cuda-ubuntu24.sh user@server:/tmp/
ssh user@server "echo YOUR_SUDO_PASSWORD | sudo -S bash /tmp/setup-nvidia-cuda-ubuntu24.sh"
sudo reboot
```
## Железо на текущем сервере
- **GPU:** NVIDIA GeForce RTX 4060 Ti 16GB
- **ОС:** Ubuntu 24.04.4 LTS, ядро 6.8.0-101-generic

View File

@@ -0,0 +1,14 @@
[Unit]
Description=Gitea Actions Runner
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/gitea-runner
ExecStart=/usr/local/bin/act_runner daemon --config /opt/gitea-runner/config.yaml
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,55 @@
#!/bin/bash
set -e
echo "=== Installing Helm ==="
cd /tmp
curl -fsSL https://get.helm.sh/helm-v3.17.0-linux-amd64.tar.gz -o helm.tar.gz
tar -zxf helm.tar.gz
mv linux-amd64/helm /usr/local/bin/helm
rm -rf linux-amd64 helm.tar.gz
helm version
echo "=== Adding Helm repos ==="
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo add jetstack https://charts.jetstack.io
helm repo update
echo "=== Installing Nginx Ingress Controller ==="
helm upgrade --install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx --create-namespace \
--set controller.hostNetwork=true \
--set controller.kind=DaemonSet \
--set controller.service.type=ClusterIP \
--wait --timeout 300s
echo "=== Installing Cert-Manager ==="
helm upgrade --install cert-manager jetstack/cert-manager \
--namespace cert-manager --create-namespace \
--set crds.enabled=true \
--wait --timeout 300s
echo "=== Creating Let's Encrypt ClusterIssuer ==="
cat <<'EOF' | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@gooseek.ru
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
EOF
echo "=== Creating namespaces ==="
kubectl create namespace gooseek --dry-run=client -o yaml | kubectl apply -f -
kubectl create namespace gitea --dry-run=client -o yaml | kubectl apply -f -
echo "=== Done! Checking status ==="
kubectl get nodes
kubectl get pods -A

View File

@@ -0,0 +1,248 @@
#!/bin/bash
set -e
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
echo "=== Installing Gitea via manifests ==="
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gitea-data
namespace: gitea
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: ConfigMap
metadata:
name: gitea-config
namespace: gitea
data:
app.ini: |
APP_NAME = GooSeek Git
RUN_MODE = prod
[server]
DOMAIN = git.gooseek.ru
ROOT_URL = https://git.gooseek.ru/
HTTP_PORT = 3000
SSH_PORT = 22
SSH_DOMAIN = git.gooseek.ru
[database]
DB_TYPE = sqlite3
PATH = /data/gitea/gitea.db
[security]
INSTALL_LOCK = true
SECRET_KEY = $(openssl rand -hex 32)
[service]
DISABLE_REGISTRATION = false
REQUIRE_SIGNIN_VIEW = false
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: gitea
namespace: gitea
spec:
replicas: 1
selector:
matchLabels:
app: gitea
template:
metadata:
labels:
app: gitea
spec:
containers:
- name: gitea
image: gitea/gitea:1.22
ports:
- containerPort: 3000
name: http
- containerPort: 22
name: ssh
volumeMounts:
- name: data
mountPath: /data
- name: config
mountPath: /data/gitea/conf
env:
- name: GITEA__database__DB_TYPE
value: sqlite3
- name: GITEA__database__PATH
value: /data/gitea/gitea.db
- name: GITEA__server__DOMAIN
value: git.gooseek.ru
- name: GITEA__server__ROOT_URL
value: https://git.gooseek.ru/
- name: GITEA__security__INSTALL_LOCK
value: "false"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
volumes:
- name: data
persistentVolumeClaim:
claimName: gitea-data
- name: config
configMap:
name: gitea-config
---
apiVersion: v1
kind: Service
metadata:
name: gitea
namespace: gitea
spec:
selector:
app: gitea
ports:
- port: 3000
targetPort: 3000
name: http
- port: 22
targetPort: 22
name: ssh
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gitea-ingress
namespace: gitea
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- git.gooseek.ru
secretName: gitea-tls
rules:
- host: git.gooseek.ru
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: gitea
port:
number: 3000
EOF
echo "=== Installing Docker Registry ==="
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: registry-pvc
namespace: gooseek
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: registry
namespace: gooseek
spec:
replicas: 1
selector:
matchLabels:
app: registry
template:
metadata:
labels:
app: registry
spec:
containers:
- name: registry
image: registry:2
ports:
- containerPort: 5000
volumeMounts:
- name: registry-data
mountPath: /var/lib/registry
env:
- name: REGISTRY_STORAGE_DELETE_ENABLED
value: "true"
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "256Mi"
cpu: "200m"
volumes:
- name: registry-data
persistentVolumeClaim:
claimName: registry-pvc
---
apiVersion: v1
kind: Service
metadata:
name: registry
namespace: gooseek
spec:
selector:
app: registry
ports:
- port: 5000
targetPort: 5000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: registry-ingress
namespace: gooseek
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/proxy-body-size: "0"
spec:
ingressClassName: nginx
tls:
- hosts:
- registry.gooseek.ru
secretName: registry-tls
rules:
- host: registry.gooseek.ru
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: registry
port:
number: 5000
EOF
echo "=== Waiting for deployments ==="
kubectl -n gitea rollout status deployment/gitea --timeout=180s || true
kubectl -n gooseek rollout status deployment/registry --timeout=120s || true
echo "=== Status ==="
kubectl get pods -A
kubectl get ingress -A
kubectl get certificates -A
echo ""
echo "=== DONE ==="
echo "Gitea: https://git.gooseek.ru (first user to register will be admin)"
echo "Registry: https://registry.gooseek.ru"

View File

@@ -0,0 +1,130 @@
#!/bin/bash
set -e
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
echo "=== Adding Gitea Helm repo ==="
helm repo add gitea-charts https://dl.gitea.com/charts/
helm repo update
echo "=== Installing Gitea ==="
helm upgrade --install gitea gitea-charts/gitea \
--namespace gitea \
--set gitea.admin.username=admin \
--set gitea.admin.password=GooSeek2026! \
--set gitea.admin.email=admin@gooseek.ru \
--set persistence.enabled=true \
--set persistence.size=10Gi \
--set postgresql-ha.enabled=false \
--set postgresql.enabled=false \
--set redis-cluster.enabled=false \
--set redis.enabled=false \
--set gitea.config.database.DB_TYPE=sqlite3 \
--set gitea.config.server.ROOT_URL=https://git.gooseek.ru \
--set gitea.config.server.DOMAIN=git.gooseek.ru \
--set ingress.enabled=true \
--set ingress.className=nginx \
--set ingress.hosts[0].host=git.gooseek.ru \
--set ingress.hosts[0].paths[0].path=/ \
--set ingress.hosts[0].paths[0].pathType=Prefix \
--set ingress.tls[0].secretName=gitea-tls \
--set ingress.tls[0].hosts[0]=git.gooseek.ru \
--set ingress.annotations."cert-manager\.io/cluster-issuer"=letsencrypt-prod \
--wait --timeout 300s
echo "=== Installing Docker Registry ==="
cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: registry-pvc
namespace: gooseek
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: registry
namespace: gooseek
spec:
replicas: 1
selector:
matchLabels:
app: registry
template:
metadata:
labels:
app: registry
spec:
containers:
- name: registry
image: registry:2
ports:
- containerPort: 5000
volumeMounts:
- name: registry-data
mountPath: /var/lib/registry
env:
- name: REGISTRY_STORAGE_DELETE_ENABLED
value: "true"
volumes:
- name: registry-data
persistentVolumeClaim:
claimName: registry-pvc
---
apiVersion: v1
kind: Service
metadata:
name: registry
namespace: gooseek
spec:
selector:
app: registry
ports:
- port: 5000
targetPort: 5000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: registry-ingress
namespace: gooseek
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/proxy-body-size: "0"
spec:
ingressClassName: nginx
tls:
- hosts:
- registry.gooseek.ru
secretName: registry-tls
rules:
- host: registry.gooseek.ru
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: registry
port:
number: 5000
EOF
echo "=== Waiting for pods ==="
kubectl -n gitea wait --for=condition=Ready pod -l app.kubernetes.io/name=gitea --timeout=300s || true
kubectl -n gooseek wait --for=condition=Ready pod -l app=registry --timeout=120s || true
echo "=== Final status ==="
kubectl get pods -A
kubectl get ingress -A
kubectl get certificates -A
echo ""
echo "=== DONE ==="
echo "Gitea: https://git.gooseek.ru (admin / GooSeek2026!)"
echo "Registry: https://registry.gooseek.ru"

View File

@@ -0,0 +1,65 @@
#!/bin/bash
set -e
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
echo "=== Enabling Gitea Actions ==="
# Update Gitea config to enable actions
kubectl -n gitea exec deploy/gitea -- sh -c '
cat >> /data/gitea/conf/app.ini << EOF
[actions]
ENABLED = true
DEFAULT_ACTIONS_URL = https://github.com
EOF
'
echo "=== Restarting Gitea ==="
kubectl -n gitea rollout restart deploy/gitea
kubectl -n gitea rollout status deploy/gitea --timeout=120s
echo "=== Installing Act Runner ==="
cd /tmp
curl -sL https://gitea.com/gitea/act_runner/releases/download/v0.2.11/act_runner-0.2.11-linux-amd64 -o act_runner
chmod +x act_runner
mv act_runner /usr/local/bin/
echo "=== Creating runner service ==="
mkdir -p /opt/gitea-runner
cd /opt/gitea-runner
# Create config
cat > config.yaml << 'EOF'
log:
level: info
runner:
file: .runner
capacity: 2
timeout: 3h
insecure: false
fetch_timeout: 5s
fetch_interval: 2s
labels:
- ubuntu-latest:docker://node:20-bullseye
- ubuntu-22.04:docker://node:20-bullseye
cache:
enabled: true
dir: /opt/gitea-runner/cache
container:
network: host
privileged: true
options:
workdir_parent:
valid_volumes:
- /opt/gitea-runner/cache
host:
workdir_parent: /opt/gitea-runner/workspace
EOF
echo "=== Runner installed ==="
echo ""
echo "NEXT STEPS:"
echo "1. Go to https://git.gooseek.ru and register/login as admin"
echo "2. Go to Site Administration -> Actions -> Runners"
echo "3. Click 'Create new Runner' and copy the registration token"
echo "4. Run: act_runner register --config /opt/gitea-runner/config.yaml --instance https://git.gooseek.ru --token YOUR_TOKEN"
echo "5. Run: act_runner daemon --config /opt/gitea-runner/config.yaml"

View File

@@ -0,0 +1,60 @@
#!/bin/bash
set -e
echo "=== Installing K3s ==="
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--disable traefik --disable servicelb --tls-san gooseek.ru --tls-san 5.187.77.89" sh -
echo "=== Waiting for K3s to be ready ==="
sleep 10
sudo k3s kubectl wait --for=condition=Ready node --all --timeout=120s
echo "=== Setting up kubectl for user ==="
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $(id -u):$(id -g) ~/.kube/config
chmod 600 ~/.kube/config
echo "=== Installing Helm ==="
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
echo "=== Installing Nginx Ingress Controller ==="
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx \
--namespace ingress-nginx --create-namespace \
--set controller.service.type=NodePort \
--set controller.service.nodePorts.http=80 \
--set controller.service.nodePorts.https=443 \
--set controller.hostNetwork=true \
--set controller.kind=DaemonSet
echo "=== Installing Cert-Manager ==="
helm repo add jetstack https://charts.jetstack.io
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager --create-namespace \
--set crds.enabled=true
echo "=== Waiting for cert-manager ==="
kubectl -n cert-manager wait --for=condition=Available deployment --all --timeout=120s
echo "=== Creating Let's Encrypt ClusterIssuer ==="
cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@gooseek.ru
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
EOF
echo "=== K3s + Ingress + Cert-Manager installed ==="
kubectl get nodes
kubectl get pods -A

View File

@@ -0,0 +1,73 @@
#!/bin/bash
# Установка драйвера NVIDIA и CUDA на Ubuntu 24.04 для работы с нейросетями (RTX 40xx).
# Запуск: sudo bash setup-nvidia-cuda-ubuntu24.sh
# После выполнения нужна перезагрузка: sudo reboot
set -e
if [ "$(id -u)" -ne 0 ]; then
echo "Запустите скрипт с sudo."
exit 1
fi
echo "=== 1/6 Отключение драйвера Nouveau ==="
cat > /etc/modprobe.d/blacklist-nvidia-nouveau.conf << 'EOF'
blacklist nouveau
options nouveau modeset=0
EOF
update-initramfs -u 2>/dev/null || true
echo "=== 2/6 Обновление системы и установка зависимостей ==="
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y build-essential wget
echo "=== 3/6 Установка драйвера NVIDIA (рекомендуемый для железа) ==="
# Для RTX 4060 Ti подойдёт драйвер 550+; ubuntu-drivers выберет подходящий
apt-get install -y ubuntu-drivers-common
DRIVER=$(ubuntu-drivers list 2>/dev/null | grep -m1 "nvidia-driver-" || echo "nvidia-driver-560")
if apt-cache show "$DRIVER" &>/dev/null; then
apt-get install -y "$DRIVER"
else
apt-get install -y nvidia-driver-560 || apt-get install -y nvidia-driver-550 || ubuntu-drivers autoinstall
fi
echo "=== 4/6 Добавление репозитория CUDA и установка CUDA Toolkit 12 ==="
KEYRING_DEB="/tmp/cuda-keyring.deb"
wget -q -O "$KEYRING_DEB" "https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/cuda-keyring_1.1-1_all.deb" || {
echo "Ошибка загрузки cuda-keyring. Проверьте сеть."
exit 1
}
dpkg -i "$KEYRING_DEB"
rm -f "$KEYRING_DEB"
apt-get update -qq
apt-get install -y cuda-toolkit-12-6 || apt-get install -y cuda-toolkit-12-5 || apt-get install -y cuda
echo "=== 5/6 Настройка окружения CUDA (PATH и библиотеки) ==="
# Ubuntu/NVIDIA repo ставит в /usr/local/cuda-12.6, симлинк /usr/local/cuda создаётся пакетом cuda
for CUDA_ROOT in /usr/local/cuda /usr/local/cuda-12.6 /usr/local/cuda-12.5; do
if [ -d "$CUDA_ROOT" ]; then
cat > /etc/profile.d/cuda.sh << EOF
# CUDA for neural networks
export PATH=$CUDA_ROOT/bin:\$PATH
export LD_LIBRARY_PATH=$CUDA_ROOT/lib64:\${LD_LIBRARY_PATH:+:\$LD_LIBRARY_PATH}
EOF
chmod 644 /etc/profile.d/cuda.sh
echo "Файл /etc/profile.d/cuda.sh создан (CUDA_ROOT=$CUDA_ROOT)."
break
fi
done
if [ ! -f /etc/profile.d/cuda.sh ]; then
echo "Предупреждение: каталог CUDA не найден. После установки cuda-toolkit выполните: sudo bash -c 'echo \"export PATH=/usr/local/cuda/bin:\\\$PATH\" > /etc/profile.d/cuda.sh'"
fi
echo "=== 6/6 Готово ==="
echo ""
echo "Драйвер NVIDIA и CUDA Toolkit установлены."
echo "ОБЯЗАТЕЛЬНО перезагрузите сервер для загрузки драйвера:"
echo " sudo reboot"
echo ""
echo "После перезагрузки проверьте:"
echo " nvidia-smi"
echo " source /etc/profile.d/cuda.sh && nvcc --version"
echo " python3 -c 'import torch; print(torch.cuda.is_available())' # если ставите PyTorch"