-
Notifications
You must be signed in to change notification settings - Fork 6
feat: add K3S single-node deployment scripts for self-hosted EnvSync #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jmac052002
wants to merge
5
commits into
EnvSync-Cloud:main
Choose a base branch
from
jmac052002:feature/k3s-deploy-scripts
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
8ed30be
feat: add backup.sh for postgres dump and local rotation
jmac052002 ce07f5d
feat: add init.sh for K3S single-node deployment with domain config
jmac052002 d9f921f
fix: update namespace to envsync in backup.sh
jmac052002 ce101a8
feat: add upgrade.sh for rolling K3S image updates with auto rollback
jmac052002 e7e3222
fix: add Kubernetes deployment and service manifests for all EnvSync …
jmac052002 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| #!/bin/bash | ||
| # backup.sh - PostgreSQL backup script for EnvSync K3S deployment | ||
| # Dumps the database to local disk and prunes backups older than 7 days | ||
| set -euo pipefail | ||
|
|
||
| # Timestamp used for the backup folder name e.g. 2026-03-23_11-55-00 | ||
| DATE=$(date +%Y-%m-%d_%H-%M-%S) | ||
|
|
||
| # Full path where this backup will be stored | ||
| BACKUP_DIR="/var/backups/envsync/${DATE}" | ||
|
|
||
| # Kubernetes namespace where EnvSync pods are running | ||
| NAMESPACE="envsync" | ||
|
|
||
| # Dynamically find the postgres pod name — never hardcode pod names, | ||
| # Kubernetes regenerates them on every restart | ||
| POSTGRES_POD=$(kubectl get pod -n "$NAMESPACE" \ | ||
| -l app=postgres \ | ||
| --no-headers \ | ||
| -o custom-columns=":metadata.name") | ||
|
|
||
| echo "Starting EnvSync backup: ${DATE}" | ||
|
|
||
| # -p creates parent directories if they don't exist | ||
| # and won't error if the folder already exists | ||
| mkdir -p "${BACKUP_DIR}" | ||
|
|
||
| echo "Dumping PostgreSQL..." | ||
|
|
||
| # kubectl exec runs a command inside the running postgres pod | ||
| # The -- separates kubectl flags from the command being run inside the pod | ||
| # Output is redirected into a .sql file in our backup directory | ||
| kubectl exec -n "$NAMESPACE" "$POSTGRES_POD" -- \ | ||
| pg_dump -U postgres envsync \ | ||
| > "${BACKUP_DIR}/envsync_db.sql" | ||
|
|
||
| echo "Pruning backups older than 7 days..." | ||
|
|
||
| # find options explained: | ||
| # -maxdepth 1 only look one level deep, don't recurse into backup folders | ||
| # -type d only match directories, not files | ||
| # -mtime +7 only match directories older than 7 days | ||
| # -exec rm -rf {} + delete each match | ||
| find /var/backups/envsync -maxdepth 1 -type d -mtime +7 -exec rm -rf {} + | ||
|
|
||
| echo "Backup complete: ${BACKUP_DIR}" | ||
|
|
||
| # Show what was saved with human-readable file sizes | ||
| ls -lh "${BACKUP_DIR}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| #!/bin/bash | ||
| # init.sh - Initializes a fresh Linux server with K3S and deploys EnvSync | ||
| # Platform agnostic - works on any Ubuntu/Debian server | ||
| # Usage: sudo bash init.sh | ||
| set -euo pipefail | ||
|
|
||
| # Ask the operator for the root domain at runtime | ||
| # All subdomains will be generated from this e.g. api.envsync.cloud | ||
| echo "============================================" | ||
| echo " EnvSync K3S Deployment Setup " | ||
| echo "============================================" | ||
| read -rp "Enter your root domain (e.g. envsync.cloud): " ROOT_DOMAIN | ||
|
|
||
| # Confirm before proceeding | ||
| echo "" | ||
| echo "Deploying EnvSync to the following subdomains:" | ||
| echo " API: api.${ROOT_DOMAIN}" | ||
| echo " Auth: auth.${ROOT_DOMAIN}" | ||
| echo " S3: s3.${ROOT_DOMAIN}" | ||
| echo " Web app: app.${ROOT_DOMAIN}" | ||
| echo "" | ||
| read -rp "Continue? (y/n): " CONFIRM | ||
| if [[ "$CONFIRM" != "y" ]]; then | ||
| echo "Aborted." | ||
| exit 0 | ||
| fi | ||
|
|
||
| echo "Installing K3S..." | ||
|
|
||
| # K3S is a lightweight single-node Kubernetes distribution | ||
| # --write-kubeconfig-mode 644 makes the kubeconfig readable without sudo | ||
| curl -sfL https://get.k3s.io | sh -s - \ | ||
| --write-kubeconfig-mode 644 | ||
|
|
||
| echo "Waiting for K3S to be ready..." | ||
|
|
||
| # Loop until the node reports Ready status | ||
| # This usually takes 20-30 seconds on first boot | ||
| until kubectl get node | grep -q "Ready"; do | ||
| echo " ...waiting for node" | ||
| sleep 5 | ||
| done | ||
|
|
||
| echo "K3S is ready." | ||
|
|
||
| # Directory where our manifests live relative to this script | ||
| MANIFEST_DIR="$(dirname "$0")/manifests" | ||
|
|
||
| echo "Injecting domain into manifests..." | ||
|
|
||
| # sed replaces the PLACEHOLDER values in the manifest files | ||
| # with the actual domain the operator entered | ||
| # -i edits the files in place | ||
| sed -i "s/PLACEHOLDER_API_DOMAIN/api.${ROOT_DOMAIN}/g" "$MANIFEST_DIR/13-ingress.yaml" | ||
| sed -i "s/PLACEHOLDER_APP_DOMAIN/app.${ROOT_DOMAIN}/g" "$MANIFEST_DIR/13-ingress.yaml" | ||
| sed -i "s/PLACEHOLDER_AUTH_DOMAIN/auth.${ROOT_DOMAIN}/g" "$MANIFEST_DIR/13-ingress.yaml" | ||
| sed -i "s/PLACEHOLDER_S3_DOMAIN/s3.${ROOT_DOMAIN}/g" "$MANIFEST_DIR/13-ingress.yaml" | ||
|
|
||
| # Also inject the auth domain into zitadel so it knows its external URL | ||
| sed -i "s/PLACEHOLDER_AUTH_DOMAIN/auth.${ROOT_DOMAIN}/g" "$MANIFEST_DIR/10-zitadel.yaml" | ||
|
|
||
| # Also inject the api domain into envsync-web so it knows where the API is | ||
| sed -i "s/PLACEHOLDER_API_DOMAIN/api.${ROOT_DOMAIN}/g" "$MANIFEST_DIR/12-envsync-web.yaml" | ||
|
|
||
| echo "Applying manifests in dependency order..." | ||
|
|
||
| # Apply each manifest in numbered order | ||
| # Each number prefix ensures correct dependency sequencing | ||
| for manifest in "$MANIFEST_DIR"/*.yaml; do | ||
| echo " Applying $(basename "$manifest")..." | ||
| kubectl apply -f "$manifest" | ||
| done | ||
|
|
||
| echo "Waiting for core pods to be ready..." | ||
|
|
||
| # Wait for postgres first since everything depends on it | ||
| kubectl wait --namespace envsync \ | ||
| --for=condition=ready pod \ | ||
| --selector=app=postgres \ | ||
| --timeout=120s | ||
|
|
||
| # Wait for envsync-api last since it depends on all other services | ||
| kubectl wait --namespace envsync \ | ||
| --for=condition=ready pod \ | ||
| --selector=app=envsync-api \ | ||
| --timeout=180s | ||
|
|
||
| echo "Pods are ready." | ||
|
|
||
| # Run EnvSync's own initialization sequence | ||
| # This creates Zitadel OIDC apps and writes client IDs to .env | ||
| echo "Running EnvSync init..." | ||
| bun run cli init | ||
|
|
||
| echo "" | ||
| echo "============================================" | ||
| echo " EnvSync deployed successfully!" | ||
| echo "============================================" | ||
| echo " API: https://api.${ROOT_DOMAIN}" | ||
| echo " Auth: https://auth.${ROOT_DOMAIN}" | ||
| echo " S3: https://s3.${ROOT_DOMAIN}" | ||
| echo " Web app: https://app.${ROOT_DOMAIN}" | ||
| echo "============================================" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| apiVersion: v1 | ||
| kind: Secret | ||
| metadata: | ||
| name: envsync-secrets | ||
| namespace: envsync | ||
| type: Opaque | ||
| stringData: | ||
| MINIKMS_ROOT_KEY: "changeme-replace-with-real-32-char-key" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| apiVersion: v1 | ||
| kind: Namespace | ||
| metadata: | ||
| name: envsync |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| apiVersion: apps/v1 | ||
| kind: Deployment | ||
| metadata: | ||
| name: postgres | ||
| namespace: envsync | ||
| spec: | ||
| replicas: 1 | ||
| selector: | ||
| matchLabels: | ||
| app: postgres | ||
| template: | ||
| metadata: | ||
| labels: | ||
| app: postgres | ||
| spec: | ||
| containers: | ||
| - name: postgres | ||
| image: postgres:17 | ||
| env: | ||
| - name: POSTGRES_USER | ||
| value: postgres | ||
| - name: POSTGRES_PASSWORD | ||
| value: postgres | ||
| - name: POSTGRES_DB | ||
| value: envsync | ||
| ports: | ||
| - containerPort: 5432 | ||
| --- | ||
| apiVersion: v1 | ||
| kind: Service | ||
| metadata: | ||
| name: postgres | ||
| namespace: envsync | ||
| spec: | ||
| selector: | ||
| app: postgres | ||
| ports: | ||
| - port: 5432 | ||
| targetPort: 5432 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| apiVersion: apps/v1 | ||
| kind: Deployment | ||
| metadata: | ||
| name: redis | ||
| namespace: envsync | ||
| spec: | ||
| replicas: 1 | ||
| selector: | ||
| matchLabels: | ||
| app: redis | ||
| template: | ||
| metadata: | ||
| labels: | ||
| app: redis | ||
| spec: | ||
| containers: | ||
| - name: redis | ||
| image: redis:latest | ||
| ports: | ||
| - containerPort: 6379 | ||
| --- | ||
| apiVersion: v1 | ||
| kind: Service | ||
| metadata: | ||
| name: redis | ||
| namespace: envsync | ||
| spec: | ||
| selector: | ||
| app: redis | ||
| ports: | ||
| - port: 6379 | ||
| targetPort: 6379 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| apiVersion: apps/v1 | ||
| kind: Deployment | ||
| metadata: | ||
| name: zitadel-db | ||
| namespace: envsync | ||
| spec: | ||
| replicas: 1 | ||
| selector: | ||
| matchLabels: | ||
| app: zitadel-db | ||
| template: | ||
| metadata: | ||
| labels: | ||
| app: zitadel-db | ||
| spec: | ||
| containers: | ||
| - name: zitadel-db | ||
| image: postgres:17 | ||
| env: | ||
| - name: POSTGRES_USER | ||
| value: postgres | ||
| - name: POSTGRES_PASSWORD | ||
| value: postgres | ||
| - name: POSTGRES_DB | ||
| value: zitadel | ||
| ports: | ||
| - containerPort: 5432 | ||
| --- | ||
| apiVersion: v1 | ||
| kind: Service | ||
| metadata: | ||
| name: zitadel-db | ||
| namespace: envsync | ||
| spec: | ||
| selector: | ||
| app: zitadel-db | ||
| ports: | ||
| - port: 5432 | ||
| targetPort: 5432 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| apiVersion: apps/v1 | ||
| kind: Deployment | ||
| metadata: | ||
| name: minikms-db | ||
| namespace: envsync | ||
| spec: | ||
| replicas: 1 | ||
| selector: | ||
| matchLabels: | ||
| app: minikms-db | ||
| template: | ||
| metadata: | ||
| labels: | ||
| app: minikms-db | ||
| spec: | ||
| containers: | ||
| - name: minikms-db | ||
| image: postgres:17 | ||
| env: | ||
| - name: POSTGRES_USER | ||
| value: postgres | ||
| - name: POSTGRES_PASSWORD | ||
| value: postgres | ||
| - name: POSTGRES_DB | ||
| value: minikms | ||
| ports: | ||
| - containerPort: 5432 | ||
| --- | ||
| apiVersion: v1 | ||
| kind: Service | ||
| metadata: | ||
| name: minikms-db | ||
| namespace: envsync | ||
| spec: | ||
| selector: | ||
| app: minikms-db | ||
| ports: | ||
| - port: 5432 | ||
| targetPort: 5432 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| apiVersion: apps/v1 | ||
| kind: Deployment | ||
| metadata: | ||
| name: openfga-db | ||
| namespace: envsync | ||
| spec: | ||
| replicas: 1 | ||
| selector: | ||
| matchLabels: | ||
| app: openfga-db | ||
| template: | ||
| metadata: | ||
| labels: | ||
| app: openfga-db | ||
| spec: | ||
| containers: | ||
| - name: openfga-db | ||
| image: postgres:17 | ||
| env: | ||
| - name: POSTGRES_USER | ||
| value: openfga | ||
| - name: POSTGRES_PASSWORD | ||
| value: openfga | ||
| - name: POSTGRES_DB | ||
| value: openfga | ||
| ports: | ||
| - containerPort: 5432 | ||
| --- | ||
| apiVersion: v1 | ||
| kind: Service | ||
| metadata: | ||
| name: openfga-db | ||
| namespace: envsync | ||
| spec: | ||
| selector: | ||
| app: openfga-db | ||
| ports: | ||
| - port: 5432 | ||
| targetPort: 5432 |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This script only creates the reverse proxy, It also needs to create pods for older container like postgres, clickstack, zetadel, etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review you're right, the deployment and service manifests for postgres, Zitadel, Redis, RustFS, and the app containers are missing. I'll add those to init.sh now.