Compare commits
30 Commits
fix/ci-onl
...
7aa81c4e7c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7aa81c4e7c | ||
|
|
b318345fdf | ||
|
|
cc5ab41da4 | ||
|
|
c54069ad99 | ||
|
|
04420dbd12 | ||
|
|
f538c60f3d | ||
|
|
1524153cfb | ||
|
|
4c31357428 | ||
|
|
b3e67d1483 | ||
|
|
3d081ee01f | ||
|
|
9942a5638f | ||
|
|
b40bab0391 | ||
|
|
de70fb47f9 | ||
|
|
c5d618698b | ||
|
|
54943ea1b7 | ||
|
|
ba1c385937 | ||
|
|
2231f06234 | ||
|
|
fe29e548fb | ||
|
|
3d72f04b14 | ||
|
|
36eb377583 | ||
|
|
b8f0c7ecba | ||
|
|
0034e0b8b3 | ||
|
|
d9a7409f9c | ||
|
|
358e07b1d5 | ||
|
|
5df914a40f | ||
|
|
1f8002629f | ||
|
|
ff2e4586f3 | ||
|
|
019867f1fa | ||
|
|
48d49a068a | ||
| 11f81cfd8e |
34
.gitea/workflows/build-devpod.yml
Normal file
34
.gitea/workflows/build-devpod.yml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
name: Build Devpod
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
paths:
|
||||||
|
- Dockerfile.devpod
|
||||||
|
- entrypoint-devpod.sh
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
REGISTRY: registry.digitalocean.com/lunarfront
|
||||||
|
DOCKER_HOST: tcp://localhost:2375
|
||||||
|
VERSION: devpod-0.1.${{ github.run_number }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Login to DOCR
|
||||||
|
run: echo "${{ secrets.DOCR_TOKEN }}" | docker login registry.digitalocean.com -u token --password-stdin
|
||||||
|
|
||||||
|
- name: Build and push devpod
|
||||||
|
run: |
|
||||||
|
docker build \
|
||||||
|
-t $REGISTRY/manager:$VERSION \
|
||||||
|
-t $REGISTRY/manager:devpod-latest \
|
||||||
|
-f Dockerfile.devpod .
|
||||||
|
docker push $REGISTRY/manager:$VERSION
|
||||||
|
docker push $REGISTRY/manager:devpod-latest
|
||||||
|
|
||||||
@@ -12,53 +12,20 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: "!startsWith(github.event.head_commit.message, 'chore: bump version')"
|
|
||||||
env:
|
env:
|
||||||
REGISTRY: registry.digitalocean.com/lunarfront
|
REGISTRY: registry.digitalocean.com/lunarfront
|
||||||
GIT_REMOTE: git2.lunarfront.tech
|
|
||||||
DOCKER_HOST: tcp://localhost:2375
|
DOCKER_HOST: tcp://localhost:2375
|
||||||
|
VERSION: 0.1.${{ github.run_number }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
token: ${{ secrets.BOT_TOKEN }}
|
|
||||||
|
|
||||||
- name: Determine version bump
|
|
||||||
id: bump
|
|
||||||
run: |
|
|
||||||
COMMIT_MSG=$(git log -1 --pretty=%s)
|
|
||||||
if echo "$COMMIT_MSG" | grep -qiE "^breaking(\(.+\))?:|^.+!:"; then
|
|
||||||
echo "type=major" >> $GITHUB_OUTPUT
|
|
||||||
elif echo "$COMMIT_MSG" | grep -qiE "^feat(\(.+\))?:"; then
|
|
||||||
echo "type=minor" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "type=patch" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Bump version in package.json
|
|
||||||
id: version
|
|
||||||
run: |
|
|
||||||
VERSION=$(node -e "
|
|
||||||
const fs = require('fs');
|
|
||||||
const pkg = JSON.parse(fs.readFileSync('packages/backend/package.json', 'utf8'));
|
|
||||||
const [major, minor, patch] = pkg.version.split('.').map(Number);
|
|
||||||
const type = '${{ steps.bump.outputs.type }}';
|
|
||||||
if (type === 'major') pkg.version = \`\${major + 1}.0.0\`;
|
|
||||||
else if (type === 'minor') pkg.version = \`\${major}.\${minor + 1}.0\`;
|
|
||||||
else pkg.version = \`\${major}.\${minor}.\${patch + 1}\`;
|
|
||||||
fs.writeFileSync('packages/backend/package.json', JSON.stringify(pkg, null, 2) + '\n');
|
|
||||||
console.log(pkg.version);
|
|
||||||
")
|
|
||||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Login to DOCR
|
- name: Login to DOCR
|
||||||
run: echo "${{ secrets.DOCR_TOKEN }}" | docker login registry.digitalocean.com -u token --password-stdin
|
run: echo "${{ secrets.DOCR_TOKEN }}" | docker login registry.digitalocean.com -u token --password-stdin
|
||||||
|
|
||||||
- name: Build and push backend
|
- name: Build and push backend
|
||||||
run: |
|
run: |
|
||||||
VERSION=${{ steps.version.outputs.version }}
|
|
||||||
SHA=$(git rev-parse --short HEAD)
|
SHA=$(git rev-parse --short HEAD)
|
||||||
docker build \
|
docker build \
|
||||||
--build-arg APP_VERSION=$VERSION \
|
--build-arg APP_VERSION=$VERSION \
|
||||||
@@ -72,7 +39,6 @@ jobs:
|
|||||||
|
|
||||||
- name: Build and push frontend
|
- name: Build and push frontend
|
||||||
run: |
|
run: |
|
||||||
VERSION=${{ steps.version.outputs.version }}
|
|
||||||
SHA=$(git rev-parse --short HEAD)
|
SHA=$(git rev-parse --short HEAD)
|
||||||
docker build \
|
docker build \
|
||||||
-t $REGISTRY/lunarfront-frontend:$VERSION \
|
-t $REGISTRY/lunarfront-frontend:$VERSION \
|
||||||
@@ -84,31 +50,17 @@ jobs:
|
|||||||
docker push $REGISTRY/lunarfront-frontend:latest
|
docker push $REGISTRY/lunarfront-frontend:latest
|
||||||
|
|
||||||
- name: Install Helm
|
- name: Install Helm
|
||||||
run: |
|
run: curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
|
||||||
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
|
|
||||||
|
|
||||||
- name: Package and push Helm chart
|
- name: Package and push Helm chart
|
||||||
run: |
|
run: |
|
||||||
VERSION=${{ steps.version.outputs.version }}
|
|
||||||
# Update chart version to match app version
|
|
||||||
sed -i "s/^version:.*/version: $VERSION/" chart/Chart.yaml
|
sed -i "s/^version:.*/version: $VERSION/" chart/Chart.yaml
|
||||||
sed -i "s/^appVersion:.*/appVersion: \"$VERSION\"/" chart/Chart.yaml
|
sed -i "s/^appVersion:.*/appVersion: \"$VERSION\"/" chart/Chart.yaml
|
||||||
# Update default image tags in values.yaml to this version
|
sed -i "s|tag: .*|tag: $VERSION|g" chart/values.yaml
|
||||||
sed -i "s|tag: latest|tag: $VERSION|g" chart/values.yaml
|
|
||||||
helm registry login registry.digitalocean.com -u token --password "${{ secrets.DOCR_TOKEN }}"
|
helm registry login registry.digitalocean.com -u token --password "${{ secrets.DOCR_TOKEN }}"
|
||||||
helm package chart/
|
helm package chart/
|
||||||
helm push lunarfront-$VERSION.tgz oci://registry.digitalocean.com/lunarfront
|
helm push lunarfront-$VERSION.tgz oci://registry.digitalocean.com/lunarfront
|
||||||
|
|
||||||
- name: Commit version bump
|
|
||||||
run: |
|
|
||||||
git config user.name "lunarfront-bot"
|
|
||||||
git config user.email "bot@lunarfront.tech"
|
|
||||||
git remote set-url origin https://lunarfront-bot:${{ secrets.BOT_TOKEN }}@$GIT_REMOTE/ryan/lunarfront-app.git
|
|
||||||
git add packages/backend/package.json
|
|
||||||
git commit -m "chore: bump version to v${{ steps.version.outputs.version }}"
|
|
||||||
git pull --rebase origin main
|
|
||||||
git push origin main
|
|
||||||
|
|
||||||
- name: Logout
|
- name: Logout
|
||||||
if: always()
|
if: always()
|
||||||
run: docker logout registry.digitalocean.com
|
run: docker logout registry.digitalocean.com
|
||||||
|
|||||||
112
CLAUDE.md
112
CLAUDE.md
@@ -63,3 +63,115 @@
|
|||||||
- API routes are thin — validate with Zod, call a service, return result
|
- API routes are thin — validate with Zod, call a service, return result
|
||||||
- All financial events must be auditable (append-only audit records)
|
- All financial events must be auditable (append-only audit records)
|
||||||
- JSON structured logging with request IDs on every log line
|
- JSON structured logging with request IDs on every log line
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Infrastructure
|
||||||
|
|
||||||
|
### Overview
|
||||||
|
LunarFront runs on DigitalOcean Kubernetes (DOKS). Each customer gets an isolated namespace, database, and Helm release managed by ArgoCD.
|
||||||
|
|
||||||
|
### Key Services
|
||||||
|
- **Cluster:** `lunarfront` DOKS cluster, region NYC
|
||||||
|
- **Registry:** `registry.digitalocean.com/lunarfront` (DOCR) — stores Docker images and Helm charts
|
||||||
|
- **Git:** `git.lunarfront.tech` — self-hosted Gitea, source of truth for code and charts
|
||||||
|
- **CI:** Gitea Actions — builds Docker images and Helm charts on push to `main`
|
||||||
|
- **CD:** ArgoCD at `argocd.lunarfront.tech` — deploys from `lunarfront-charts` repo
|
||||||
|
- **Database:** DO Managed PostgreSQL — one database per customer, plus manager DB
|
||||||
|
- **Cache/Queue:** DO Managed Valkey — shared across all customers (key-prefixed per customer)
|
||||||
|
- **Ingress:** nginx ingress controller with Cloudflare proxy in front
|
||||||
|
- **TLS:** cert-manager with Let's Encrypt (letsencrypt-prod cluster issuer)
|
||||||
|
- **DNS:** Cloudflare — wildcard `*.lunarfront.tech` → cluster LB IP `167.99.21.170`
|
||||||
|
|
||||||
|
### Node Pools
|
||||||
|
- `system` — 2x s-2vcpu-4gb, runs ingress, ArgoCD, manager, pgbouncer
|
||||||
|
- `customers` — autoscales 0→N, s-4vcpu-8gb, runs customer app pods (tainted `role=customer`)
|
||||||
|
- `dev` — autoscales 0→1, s-4vcpu-8gb, runs dev pod only (tainted `dedicated=dev:NoSchedule`)
|
||||||
|
|
||||||
|
### Repos
|
||||||
|
- `lunarfront-app` — main application code (this repo)
|
||||||
|
- `lunarfront-charts` — Helm charts and ArgoCD app definitions
|
||||||
|
- `lunarfront-infra` — Terraform for DO infrastructure (DOKS, managed DBs, registry, DNS)
|
||||||
|
- `lunarfront-manager` — internal ops tool for provisioning/deprovisioning customers
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Build & Deploy Pipeline
|
||||||
|
|
||||||
|
### How it works
|
||||||
|
1. Push code to `main` on `lunarfront-app`
|
||||||
|
2. Gitea Actions runs `.gitea/workflows/build.yml`:
|
||||||
|
- Builds `lunarfront-app` Docker image → pushes as `0.1.{run_number}`, `{sha}`, `latest`
|
||||||
|
- Builds `lunarfront-frontend` Docker image → same tags
|
||||||
|
- Packages Helm chart → pushes as `0.1.{run_number}` to DOCR OCI registry
|
||||||
|
3. ArgoCD image updater detects new image digests → updates customer deployments
|
||||||
|
4. New customer provisions always get the latest chart version (queried from DOCR at provision time)
|
||||||
|
5. Existing customers upgraded via `POST /customers/:slug/upgrade` or `POST /customers/upgrade-all` in the manager
|
||||||
|
|
||||||
|
### Versioning
|
||||||
|
- Version format: `0.1.{gitea_run_number}` — always incrementing, no git commit-back needed
|
||||||
|
- No version stored in git — source of truth is DOCR tags
|
||||||
|
- Chart version and app version are kept in sync
|
||||||
|
|
||||||
|
### Key files
|
||||||
|
- `Dockerfile` — backend image (bun runtime, runs `packages/backend/src/main.ts` directly)
|
||||||
|
- `Dockerfile.frontend` — frontend nginx image
|
||||||
|
- `chart/` — Helm chart for customer app deployments
|
||||||
|
- `.gitea/workflows/build.yml` — CI pipeline
|
||||||
|
- `.gitea/workflows/build-devpod.yml` — builds dev box image on Dockerfile.devpod changes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dev Box
|
||||||
|
|
||||||
|
### What it is
|
||||||
|
A persistent development pod running in the `dev` namespace on the cluster. Provides a full remote dev environment accessible from anywhere.
|
||||||
|
|
||||||
|
- **VS Code in browser:** `dev.lunarfront.tech` (Cloudflare Access protected, OTP to email)
|
||||||
|
- **SSH:** `ssh -p 2222 root@dev-ssh.lunarfront.tech`
|
||||||
|
- **Storage:** 100GB DO block storage PVC mounted at `/root` — everything in home dir persists
|
||||||
|
- **Image:** `registry.digitalocean.com/lunarfront/manager:devpod-latest`
|
||||||
|
- **Tools:** bun, Claude Code CLI, code-server, kubectl, helm, k9s, doctl, psql, redis-cli, git
|
||||||
|
|
||||||
|
### Managing the dev pod
|
||||||
|
```bash
|
||||||
|
# Scale up (provisions node automatically)
|
||||||
|
kubectl scale deployment dev -n dev --replicas=1
|
||||||
|
|
||||||
|
# Scale down (node auto-terminates after ~15 min)
|
||||||
|
kubectl scale deployment dev -n dev --replicas=0
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running the app locally on the dev box (no containers)
|
||||||
|
The dev box runs the app as plain Bun processes, connecting to the same DO managed services as production.
|
||||||
|
|
||||||
|
**Required env vars** (create a `.env` file in the repo root or export in `.bashrc`):
|
||||||
|
```bash
|
||||||
|
DATABASE_URL=postgresql://... # DO managed postgres, lunarfront database
|
||||||
|
REDIS_URL=rediss://... # DO managed valkey
|
||||||
|
JWT_SECRET=... # any random hex string for local dev
|
||||||
|
PORT=8000
|
||||||
|
```
|
||||||
|
|
||||||
|
**Start the app:**
|
||||||
|
```bash
|
||||||
|
cd ~/lunarfront-app
|
||||||
|
bun run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Access the running backend at `dev.lunarfront.tech/proxy/8000/` in the browser (code-server proxy), or via SSH port forward:
|
||||||
|
```bash
|
||||||
|
ssh -p 2222 -L 8000:localhost:8000 root@dev-ssh.lunarfront.tech
|
||||||
|
```
|
||||||
|
|
||||||
|
**Run migrations against the dev database:**
|
||||||
|
```bash
|
||||||
|
bunx drizzle-kit migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
### Workflow
|
||||||
|
1. Edit code in VS Code at `dev.lunarfront.tech` or via SSH
|
||||||
|
2. Run and test locally with `bun run dev` — app connects to DO managed postgres/valkey
|
||||||
|
3. Push to `main` → Gitea Actions builds and pushes new Docker image + Helm chart
|
||||||
|
4. ArgoCD deploys to the cluster automatically
|
||||||
|
5. Use manager at `manager.lunarfront.tech` to upgrade customer instances if needed
|
||||||
|
|||||||
14
Dockerfile
14
Dockerfile
@@ -6,8 +6,9 @@ COPY packages/backend/package.json packages/backend/
|
|||||||
COPY packages/admin/package.json packages/admin/
|
COPY packages/admin/package.json packages/admin/
|
||||||
RUN bun install --frozen-lockfile
|
RUN bun install --frozen-lockfile
|
||||||
|
|
||||||
FROM oven/bun:1.3.11-alpine AS build
|
FROM oven/bun:1.3.11-alpine
|
||||||
ARG APP_VERSION=dev
|
ARG APP_VERSION=dev
|
||||||
|
ENV APP_VERSION=${APP_VERSION}
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=deps /app/node_modules ./node_modules
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
COPY --from=deps /app/packages/shared/node_modules ./packages/shared/node_modules
|
COPY --from=deps /app/packages/shared/node_modules ./packages/shared/node_modules
|
||||||
@@ -16,18 +17,11 @@ COPY packages/shared ./packages/shared
|
|||||||
COPY packages/backend ./packages/backend
|
COPY packages/backend ./packages/backend
|
||||||
COPY package.json ./
|
COPY package.json ./
|
||||||
COPY tsconfig.base.json ./
|
COPY tsconfig.base.json ./
|
||||||
WORKDIR /app/packages/backend
|
|
||||||
RUN bun build src/main.ts --compile --outfile /app/server \
|
|
||||||
--define "process.env.APP_VERSION='${APP_VERSION}'"
|
|
||||||
|
|
||||||
FROM alpine:3.21
|
|
||||||
RUN addgroup -S app && adduser -S app -G app
|
RUN addgroup -S app && adduser -S app -G app
|
||||||
WORKDIR /app
|
COPY packages/backend/src/db/migrations ./migrations
|
||||||
COPY --from=build /app/server ./server
|
|
||||||
COPY --from=build /app/packages/backend/src/db/migrations ./migrations
|
|
||||||
ENV MIGRATIONS_DIR=/app/migrations
|
ENV MIGRATIONS_DIR=/app/migrations
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
||||||
CMD wget -qO- http://localhost:8000/v1/health || exit 1
|
CMD wget -qO- http://localhost:8000/v1/health || exit 1
|
||||||
USER app
|
USER app
|
||||||
CMD ["./server"]
|
CMD ["bun", "run", "packages/backend/src/main.ts"]
|
||||||
|
|||||||
46
Dockerfile.devpod
Normal file
46
Dockerfile.devpod
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
FROM ubuntu:24.04
|
||||||
|
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
ENV HOME=/root
|
||||||
|
ENV PATH="/root/.bun/bin:$PATH"
|
||||||
|
|
||||||
|
# Base tools
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
curl wget git openssh-server ca-certificates gnupg \
|
||||||
|
build-essential unzip jq tmux zsh ripgrep \
|
||||||
|
postgresql-client redis-tools haproxy \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Bun
|
||||||
|
RUN curl -fsSL https://bun.sh/install | bash
|
||||||
|
|
||||||
|
# Claude Code CLI
|
||||||
|
RUN curl -fsSL https://claude.ai/install.sh | bash
|
||||||
|
|
||||||
|
# code-server (VS Code in browser)
|
||||||
|
RUN curl -fsSL https://code-server.dev/install.sh | sh
|
||||||
|
|
||||||
|
# kubectl
|
||||||
|
RUN curl -fsSL "https://dl.k8s.io/release/$(curl -fsSL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" \
|
||||||
|
-o /usr/local/bin/kubectl && chmod +x /usr/local/bin/kubectl
|
||||||
|
|
||||||
|
# doctl
|
||||||
|
RUN curl -fsSL https://github.com/digitalocean/doctl/releases/download/v1.119.0/doctl-1.119.0-linux-amd64.tar.gz \
|
||||||
|
| tar xz -C /usr/local/bin
|
||||||
|
|
||||||
|
# helm
|
||||||
|
RUN curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
|
||||||
|
|
||||||
|
# k9s
|
||||||
|
RUN curl -fsSL https://github.com/derailed/k9s/releases/latest/download/k9s_Linux_amd64.tar.gz \
|
||||||
|
| tar xz -C /usr/local/bin k9s
|
||||||
|
|
||||||
|
# SSH setup — host keys generated at runtime via entrypoint
|
||||||
|
RUN mkdir -p /run/sshd /root/.ssh && chmod 700 /root/.ssh
|
||||||
|
|
||||||
|
COPY entrypoint-devpod.sh /entrypoint.sh
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
|
WORKDIR /root
|
||||||
|
EXPOSE 8080 22
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
@@ -2,5 +2,5 @@ apiVersion: v2
|
|||||||
name: lunarfront
|
name: lunarfront
|
||||||
description: LunarFront small business management platform
|
description: LunarFront small business management platform
|
||||||
type: application
|
type: application
|
||||||
version: 0.1.0
|
version: 0.1.1
|
||||||
appVersion: "0.0.0"
|
appVersion: "0.1.1"
|
||||||
|
|||||||
@@ -38,6 +38,36 @@ spec:
|
|||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: lunarfront-secrets
|
name: lunarfront-secrets
|
||||||
key: redis-url
|
key: redis-url
|
||||||
|
- name: REDIS_KEY_PREFIX
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: lunarfront-secrets
|
||||||
|
key: redis-key-prefix
|
||||||
|
- name: SPACES_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: lunarfront-secrets
|
||||||
|
key: spaces-key
|
||||||
|
- name: SPACES_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: lunarfront-secrets
|
||||||
|
key: spaces-secret
|
||||||
|
- name: SPACES_BUCKET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: lunarfront-secrets
|
||||||
|
key: spaces-bucket
|
||||||
|
- name: SPACES_ENDPOINT
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: lunarfront-secrets
|
||||||
|
key: spaces-endpoint
|
||||||
|
- name: SPACES_PREFIX
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: lunarfront-secrets
|
||||||
|
key: spaces-prefix
|
||||||
- name: JWT_SECRET
|
- name: JWT_SECRET
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: {{ .Release.Name }}-valkey
|
|
||||||
namespace: {{ .Release.Namespace }}
|
|
||||||
labels:
|
|
||||||
{{- include "lunarfront.labels" . | nindent 4 }}
|
|
||||||
spec:
|
|
||||||
replicas: 1
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: {{ .Release.Name }}-valkey
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: {{ .Release.Name }}-valkey
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: valkey
|
|
||||||
image: "{{ .Values.valkey.image.repository }}:{{ .Values.valkey.image.tag }}"
|
|
||||||
ports:
|
|
||||||
- containerPort: {{ .Values.valkey.port }}
|
|
||||||
resources:
|
|
||||||
{{- toYaml .Values.valkey.resources | nindent 12 }}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: {{ .Release.Name }}-valkey
|
|
||||||
namespace: {{ .Release.Namespace }}
|
|
||||||
labels:
|
|
||||||
{{- include "lunarfront.labels" . | nindent 4 }}
|
|
||||||
spec:
|
|
||||||
selector:
|
|
||||||
app: {{ .Release.Name }}-valkey
|
|
||||||
ports:
|
|
||||||
- port: {{ .Values.valkey.port }}
|
|
||||||
targetPort: {{ .Values.valkey.port }}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
backend:
|
backend:
|
||||||
image:
|
image:
|
||||||
repository: registry.digitalocean.com/lunarfront/lunarfront-app
|
repository: registry.digitalocean.com/lunarfront/lunarfront-app
|
||||||
tag: latest
|
tag: 0.0.27
|
||||||
pullPolicy: Always
|
pullPolicy: Always
|
||||||
port: 8000
|
port: 8000
|
||||||
resources:
|
resources:
|
||||||
@@ -15,7 +15,7 @@ backend:
|
|||||||
frontend:
|
frontend:
|
||||||
image:
|
image:
|
||||||
repository: registry.digitalocean.com/lunarfront/lunarfront-frontend
|
repository: registry.digitalocean.com/lunarfront/lunarfront-frontend
|
||||||
tag: latest
|
tag: 0.0.27
|
||||||
pullPolicy: Always
|
pullPolicy: Always
|
||||||
port: 80
|
port: 80
|
||||||
resources:
|
resources:
|
||||||
@@ -26,19 +26,6 @@ frontend:
|
|||||||
cpu: 200m
|
cpu: 200m
|
||||||
memory: 128Mi
|
memory: 128Mi
|
||||||
|
|
||||||
valkey:
|
|
||||||
image:
|
|
||||||
repository: valkey/valkey
|
|
||||||
tag: "8"
|
|
||||||
port: 6379
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: 50m
|
|
||||||
memory: 64Mi
|
|
||||||
limits:
|
|
||||||
cpu: 200m
|
|
||||||
memory: 128Mi
|
|
||||||
|
|
||||||
ingress:
|
ingress:
|
||||||
host: ""
|
host: ""
|
||||||
className: nginx
|
className: nginx
|
||||||
|
|||||||
77
entrypoint-devpod.sh
Normal file
77
entrypoint-devpod.sh
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Generate SSH host keys if not present
|
||||||
|
ssh-keygen -A
|
||||||
|
|
||||||
|
# Write authorized keys from env if provided
|
||||||
|
if [ -n "$SSH_AUTHORIZED_KEYS" ]; then
|
||||||
|
mkdir -p /root/.ssh
|
||||||
|
chmod 700 /root/.ssh
|
||||||
|
echo "$SSH_AUTHORIZED_KEYS" > /root/.ssh/authorized_keys
|
||||||
|
chmod 600 /root/.ssh/authorized_keys
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Bootstrap home dir on fresh PVC
|
||||||
|
if [ ! -f /root/.bashrc ]; then
|
||||||
|
cp /etc/skel/.bashrc /root/.bashrc 2>/dev/null || true
|
||||||
|
cat >> /root/.bashrc <<'EOF'
|
||||||
|
export PATH="/root/.bun/bin:$PATH"
|
||||||
|
export HISTFILE=/root/.bash_history
|
||||||
|
export HISTSIZE=10000
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f /root/.profile ]; then
|
||||||
|
cat > /root/.profile <<'EOF'
|
||||||
|
export PATH="/root/.bun/bin:$PATH"
|
||||||
|
[ -f /root/.bashrc ] && . /root/.bashrc
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f /root/.gitconfig ]; then
|
||||||
|
cat > /root/.gitconfig <<'EOF'
|
||||||
|
[user]
|
||||||
|
name = ryan
|
||||||
|
email = ryan@lunartech.com
|
||||||
|
[init]
|
||||||
|
defaultBranch = main
|
||||||
|
[core]
|
||||||
|
editor = code --wait
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Allow root login via SSH key, listen on internal port 2222
|
||||||
|
echo "PermitRootLogin yes" >> /etc/ssh/sshd_config
|
||||||
|
echo "Port 2222" >> /etc/ssh/sshd_config
|
||||||
|
|
||||||
|
# Start SSH daemon on internal port 2222
|
||||||
|
/usr/sbin/sshd
|
||||||
|
|
||||||
|
# Start haproxy on port 22 to accept PROXY protocol from nginx and forward to sshd:2222
|
||||||
|
cat > /etc/haproxy/haproxy.cfg <<'EOF'
|
||||||
|
global
|
||||||
|
daemon
|
||||||
|
maxconn 256
|
||||||
|
|
||||||
|
defaults
|
||||||
|
mode tcp
|
||||||
|
timeout connect 5s
|
||||||
|
timeout client 60s
|
||||||
|
timeout server 60s
|
||||||
|
|
||||||
|
frontend ssh
|
||||||
|
bind *:22 accept-proxy
|
||||||
|
default_backend sshd
|
||||||
|
|
||||||
|
backend sshd
|
||||||
|
server local 127.0.0.1:2222
|
||||||
|
EOF
|
||||||
|
haproxy -f /etc/haproxy/haproxy.cfg
|
||||||
|
|
||||||
|
# Start code-server
|
||||||
|
exec code-server \
|
||||||
|
--bind-addr 0.0.0.0:8080 \
|
||||||
|
--auth none \
|
||||||
|
--disable-telemetry \
|
||||||
|
/root
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@lunarfront/backend",
|
"name": "@lunarfront/backend",
|
||||||
"version": "0.0.26",
|
"version": "0.1.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ declare module 'fastify' {
|
|||||||
|
|
||||||
export const redisPlugin = fp(async (app) => {
|
export const redisPlugin = fp(async (app) => {
|
||||||
const redisUrl = process.env.REDIS_URL ?? 'redis://localhost:6379'
|
const redisUrl = process.env.REDIS_URL ?? 'redis://localhost:6379'
|
||||||
const redis = new Redis(redisUrl)
|
const keyPrefix = process.env.REDIS_KEY_PREFIX ? `${process.env.REDIS_KEY_PREFIX}:` : ''
|
||||||
|
const redis = new Redis(redisUrl, { keyPrefix })
|
||||||
|
|
||||||
app.decorate('redis', redis)
|
app.decorate('redis', redis)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user