mirror of
https://github.com/ryankazokas/turbovault-app.git
synced 2026-04-16 22:12:53 +00:00
- Switch from Gitea to GitHub Container Registry (ghcr.io) - Add GitHub Actions workflow with Tailscale connectivity - Update k8s manifests for cloud nodes and Traefik ingress - Configure for turbo.kazcloud.dev domain - Test deployment with home page text change
321 lines
6.5 KiB
Markdown
321 lines
6.5 KiB
Markdown
# Initial Deployment Guide
|
|
|
|
Follow these steps to deploy TurboVault to Kubernetes for the first time.
|
|
|
|
## Prerequisites
|
|
|
|
- ✅ Code pushed to GitHub
|
|
- ✅ PostgreSQL database ready (host, user, password)
|
|
- ✅ kubectl configured for k3s cluster (100.101.31.99:6443)
|
|
- ✅ Docker installed locally
|
|
- ✅ Gitea account at gitea.kazcloud.dev
|
|
|
|
---
|
|
|
|
## Step 1: Build and Push Initial Image
|
|
|
|
Since GitHub Actions hasn't run yet, build the first image manually:
|
|
|
|
```bash
|
|
# Build image
|
|
docker build -t gitea.kazcloud.dev/ryan/turbovault-app:v1.0.0 .
|
|
|
|
# Login to Gitea registry
|
|
docker login gitea.kazcloud.dev
|
|
# Username: ryankazokas
|
|
# Password: <your-gitea-token>
|
|
|
|
# Push image
|
|
docker push gitea.kazcloud.dev/ryan/turbovault-app:v1.0.0
|
|
|
|
# Also tag as latest
|
|
docker tag gitea.kazcloud.dev/ryan/turbovault-app:v1.0.0 \
|
|
gitea.kazcloud.dev/ryan/turbovault-app:latest
|
|
docker push gitea.kazcloud.dev/ryan/turbovault-app:latest
|
|
```
|
|
|
|
✅ **Verify:** Check Gitea packages at `gitea.kazcloud.dev/ryankazokas/-/packages`
|
|
|
|
---
|
|
|
|
## Step 2: Configure Kubernetes Secrets
|
|
|
|
```bash
|
|
# Copy template
|
|
cp k8s/secrets.yaml.example k8s/secrets.yaml
|
|
|
|
# Generate Rails secret key
|
|
rails secret
|
|
# Copy the output
|
|
|
|
# Edit secrets file
|
|
nano k8s/secrets.yaml
|
|
```
|
|
|
|
**Add these values in `k8s/secrets.yaml`:**
|
|
|
|
```yaml
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: turbovault-secrets
|
|
namespace: turbovault
|
|
type: Opaque
|
|
stringData:
|
|
SECRET_KEY_BASE: "<paste-output-from-rails-secret>"
|
|
DATABASE_PASSWORD: "your-postgres-password"
|
|
|
|
# Optional: IGDB integration
|
|
IGDB_CLIENT_ID: "your-igdb-client-id"
|
|
IGDB_CLIENT_SECRET: "your-igdb-client-secret"
|
|
|
|
# Optional: Email (for password resets)
|
|
SMTP_ADDRESS: "smtp.example.com"
|
|
SMTP_PORT: "587"
|
|
SMTP_USERNAME: "user@example.com"
|
|
SMTP_PASSWORD: "smtp-password"
|
|
```
|
|
|
|
---
|
|
|
|
## Step 3: Configure Database Connection
|
|
|
|
Edit `k8s/configmap.yaml`:
|
|
|
|
```yaml
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: turbovault-config
|
|
namespace: turbovault
|
|
data:
|
|
RAILS_ENV: "production"
|
|
DATABASE_HOST: "your-postgres-host"
|
|
DATABASE_NAME: "turbovault_production"
|
|
DATABASE_USERNAME: "turbovault"
|
|
RAILS_LOG_TO_STDOUT: "true"
|
|
RAILS_SERVE_STATIC_FILES: "true"
|
|
```
|
|
|
|
**Replace:**
|
|
- `your-postgres-host` - Your PostgreSQL server hostname/IP
|
|
- Database name and username if different
|
|
|
|
---
|
|
|
|
## Step 4: Deploy to Kubernetes
|
|
|
|
Run the automated deployment script:
|
|
|
|
```bash
|
|
./scripts/deploy-k8s.sh
|
|
```
|
|
|
|
**When prompted for registry credentials:**
|
|
- Registry: `gitea.kazcloud.dev`
|
|
- Username: `ryankazokas`
|
|
- Password: `<your-gitea-token>`
|
|
|
|
**The script will:**
|
|
1. Create namespace
|
|
2. Apply configmap
|
|
3. Apply secrets
|
|
4. Run database migration job
|
|
5. Deploy application
|
|
6. Create service
|
|
7. Create ingress
|
|
|
|
---
|
|
|
|
## Step 5: Verify Deployment
|
|
|
|
```bash
|
|
# Check all resources
|
|
kubectl get all -n turbovault
|
|
|
|
# Check pods are running
|
|
kubectl get pods -n turbovault
|
|
|
|
# View logs
|
|
kubectl logs -f -l app=turbovault -n turbovault
|
|
|
|
# Check migration job completed
|
|
kubectl logs job/turbovault-migrate -n turbovault
|
|
```
|
|
|
|
**Expected output:**
|
|
```
|
|
NAME READY STATUS RESTARTS AGE
|
|
pod/turbovault-xxxxxxxxxx-xxxxx 1/1 Running 0 2m
|
|
pod/turbovault-xxxxxxxxxx-xxxxx 1/1 Running 0 2m
|
|
```
|
|
|
|
---
|
|
|
|
## Step 6: Access Application
|
|
|
|
### Option A: Port Forward (Testing)
|
|
|
|
```bash
|
|
kubectl port-forward svc/turbovault-service 3000:80 -n turbovault
|
|
```
|
|
|
|
Visit: http://localhost:3000
|
|
|
|
### Option B: Ingress (Production)
|
|
|
|
Edit `k8s/ingress.yaml` with your domain and apply:
|
|
|
|
```bash
|
|
kubectl apply -f k8s/ingress.yaml
|
|
```
|
|
|
|
Visit: https://your-domain.com
|
|
|
|
---
|
|
|
|
## Step 7: Configure GitHub Secrets
|
|
|
|
Now set up automated deployments for future updates.
|
|
|
|
See [docs/GITHUB_SECRETS.md](docs/GITHUB_SECRETS.md) for detailed instructions.
|
|
|
|
**Required secrets (add at https://github.com/ryankazokas/turbovault-app/settings/secrets/actions):**
|
|
|
|
1. `GITEA_USERNAME` - Your Gitea username
|
|
2. `GITEA_TOKEN` - Gitea access token (Settings → Applications)
|
|
3. `TAILSCALE_CLIENT_ID` - Tailscale OAuth client ID
|
|
4. `TAILSCALE_CLIENT_SECRET` - Tailscale OAuth client secret
|
|
5. `KUBECONFIG` - Base64-encoded kubeconfig (`cat ~/.kube/config | base64 -w 0`)
|
|
|
|
---
|
|
|
|
## Step 8: Test Automated Deployment
|
|
|
|
After GitHub secrets are configured:
|
|
|
|
```bash
|
|
# Create a test tag
|
|
git tag v1.0.1
|
|
git push origin v1.0.1
|
|
```
|
|
|
|
Watch at: https://github.com/ryankazokas/turbovault-app/actions
|
|
|
|
GitHub Actions will:
|
|
1. Build Docker image
|
|
2. Push to Gitea registry
|
|
3. Connect via Tailscale
|
|
4. Deploy to Kubernetes
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Pods in CrashLoopBackOff
|
|
|
|
```bash
|
|
# View logs
|
|
kubectl logs -l app=turbovault -n turbovault
|
|
|
|
# Common issues:
|
|
# - Database connection failed (check configmap/secrets)
|
|
# - Missing SECRET_KEY_BASE (check secrets)
|
|
# - Migration not run (check migration job logs)
|
|
```
|
|
|
|
### Migration Job Failed
|
|
|
|
```bash
|
|
# View migration logs
|
|
kubectl logs job/turbovault-migrate -n turbovault
|
|
|
|
# Re-run migration
|
|
kubectl delete job turbovault-migrate -n turbovault
|
|
kubectl apply -f k8s/migrate-job.yaml
|
|
```
|
|
|
|
### Can't Pull Image
|
|
|
|
```bash
|
|
# Check image pull secret
|
|
kubectl get secrets -n turbovault
|
|
|
|
# Re-run deploy script to create secret
|
|
./scripts/deploy-k8s.sh
|
|
```
|
|
|
|
### Database Connection Failed
|
|
|
|
```bash
|
|
# Test from pod
|
|
kubectl exec -it deployment/turbovault -n turbovault -- \
|
|
rails runner "puts ActiveRecord::Base.connection.execute('SELECT 1').first"
|
|
|
|
# Check environment variables
|
|
kubectl exec -it deployment/turbovault -n turbovault -- env | grep DATABASE
|
|
```
|
|
|
|
---
|
|
|
|
## Next Steps
|
|
|
|
After successful initial deployment:
|
|
|
|
1. ✅ Application is running in Kubernetes
|
|
2. ✅ GitHub Actions configured for automated deployments
|
|
3. 🚀 **Daily workflow:** Just push tags to deploy!
|
|
|
|
```bash
|
|
# Make changes
|
|
git add .
|
|
git commit -m "Feature: new functionality"
|
|
git push
|
|
|
|
# Deploy
|
|
git tag v1.0.2
|
|
git push origin v1.0.2
|
|
|
|
# GitHub Actions automatically builds and deploys! ✅
|
|
```
|
|
|
|
---
|
|
|
|
## Quick Reference
|
|
|
|
```bash
|
|
# View status
|
|
kubectl get all -n turbovault
|
|
|
|
# View logs
|
|
kubectl logs -f -l app=turbovault -n turbovault
|
|
|
|
# Restart deployment
|
|
kubectl rollout restart deployment/turbovault -n turbovault
|
|
|
|
# Rollback deployment
|
|
kubectl rollout undo deployment/turbovault -n turbovault
|
|
|
|
# Delete everything (start over)
|
|
kubectl delete namespace turbovault
|
|
```
|
|
|
|
---
|
|
|
|
## Files You Modified
|
|
|
|
Keep these files safe (they're gitignored):
|
|
|
|
- `k8s/secrets.yaml` - Contains sensitive data (SECRET_KEY_BASE, passwords)
|
|
- `~/.kube/config` - Your Kubernetes access
|
|
|
|
**DO NOT** commit these to git!
|
|
|
|
---
|
|
|
|
**Need help?** Check logs first:
|
|
```bash
|
|
kubectl describe pod -l app=turbovault -n turbovault
|
|
kubectl logs -l app=turbovault -n turbovault
|
|
```
|