manifests/ and the droplet script go

manifests/{devnet,production,testnet}.yml claimed to be "source of truth for
what is deployed on lux-k8s", last edited 2026-04-20, listing tag: latest and
sha: latest per service. Nothing has read them since; the ApplicationSet reads
deploy/, and the only writer that touched them was update-image.yml, which was
sed-ing into a tree CD does not open.

manifests/safes.yaml was the one live file in there and is not a deployment
manifest at all — it is Lux's Safe topology. It moves to SAFES.yaml, beside
NETWORKS.yaml and chain.yaml, where this repo keeps its fact tables.

scripts/deploy-do.sh creates three DigitalOcean droplets, cloud-inits docker on
them and runs compose over ssh. That is the arrangement DOKS replaced.
sync-pars-universe.sh no longer copies it into the Pars bundle.

renovate.json stops matching manifests/. It still does not match deploy/, and
that is now on purpose rather than an oversight: pin.sh resolves a tag and its
digest from one registry read, and a second writer offering a bare tag would
leave the pair disagreeing — which deploys the digest.

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
2026-09-01 12:44:44 -07:00
co-authored by Hanzo Dev
parent 0734789c4e
commit 756628f3ec
8 changed files with 8 additions and 283 deletions
+7 -5
View File
@@ -16,11 +16,13 @@
# manual-only, because a schedule that cannot succeed is not a schedule, it is
# a red mark that teaches people to ignore red marks.
#
# One more thing to settle before turning it back on: renovate.json matches
# `k8s/`, `infra/k8s/`, `manifests/` and the compose files, and NOT `deploy/`.
# `deploy/` is what the CD Applications actually read (each one names
# `$values/deploy/<ns>/<app>.yaml`), so even a working renovate would not see
# the image pins that decide what runs.
# renovate.json matches `k8s/`, `infra/k8s/` and the compose files, and NOT
# `deploy/`. That gap used to be the whole problem — deploy/ is what CD reads —
# and it is now the arrangement: deploy/pin.sh writes those pins, resolving a
# tag and its digest from one registry read. Renovate offers a tag; the chart
# refuses a claimed name carrying no digest, and for everything else a bare tag
# beside a stale digest deploys the digest. Two writers, one field. So deploy/
# stays renovate's blind spot deliberately, and it keeps the compose stack.
name: Renovate
on:
View File
-40
View File
@@ -1,40 +0,0 @@
# Lux Universe -- Devnet Service Manifest
# Deployed to lux-dev-k8s (dev branch)
# Domains: *.devnet.lux.network, *.lux-dev.network
services:
gateway:
image: ghcr.io/luxfi/gateway
tag: dev
sha: latest
namespace: lux
deployment: gateway
port: 8000
tier: infra
validators:
image: ghcr.io/luxfi/node
tag: dev
sha: latest
namespace: lux
deployment: validators
port: 9650
tier: core
explorer:
image: ghcr.io/luxfi/explorer
tag: dev
sha: latest
namespace: lux
deployment: explorer
port: 4000
tier: app
markets:
image: ghcr.io/luxfi/markets
tag: dev
sha: latest
namespace: lux
deployment: markets
port: 3000
tier: app
-44
View File
@@ -1,44 +0,0 @@
# Lux Universe -- Production Service Manifest
#
# Source of truth for what is deployed on lux-k8s.
# Updated by CI on successful deploy. Do not edit manually during
# an active deploy.
services:
# -- Tier 0: Infrastructure --
gateway:
image: ghcr.io/luxfi/gateway
tag: latest
sha: latest
namespace: lux
deployment: gateway
port: 8000
tier: infra
# -- Tier 1: Core Services --
validators:
image: ghcr.io/luxfi/node
tag: latest
sha: latest
namespace: lux
deployment: validators
port: 9650
tier: core
markets:
image: ghcr.io/luxfi/markets
tag: latest
sha: latest
namespace: lux
deployment: markets
port: 3000
tier: core
cloud:
image: ghcr.io/luxfi/cloud
tag: latest
sha: latest
namespace: lux
deployment: lux-cloud
port: 3000
tier: app
-40
View File
@@ -1,40 +0,0 @@
# Lux Universe -- Testnet Service Manifest
# Deployed to lux-test-k8s (test branch)
# Domains: *.testnet.lux.network, *.lux-test.network
services:
gateway:
image: ghcr.io/luxfi/gateway
tag: test
sha: latest
namespace: lux
deployment: gateway
port: 8000
tier: infra
validators:
image: ghcr.io/luxfi/node
tag: test
sha: latest
namespace: lux
deployment: validators
port: 9650
tier: core
explorer:
image: ghcr.io/luxfi/explorer
tag: test
sha: latest
namespace: lux
deployment: explorer
port: 4000
tier: app
markets:
image: ghcr.io/luxfi/markets
tag: test
sha: latest
namespace: lux
deployment: markets
port: 3000
tier: app
+1 -1
View File
@@ -8,7 +8,7 @@
"customManagers": [
{
"customType": "regex",
"fileMatch": ["^manifests/.*\\.yml$", "compose.*\\.yml$", "(^k8s|^infra/k8s)/.+\\.yaml$"],
"fileMatch": ["compose.*\\.yml$", "(^k8s|^infra/k8s)/.+\\.yaml$"],
"matchStrings": [
"image:\\s*(?<depName>[\\w.\\-/]+):(?<currentValue>[\\w][\\w.\\-]+)"
],
-152
View File
@@ -1,152 +0,0 @@
#!/bin/bash
# Deploy Lux Networks to DigitalOcean
# Creates 3 separate 8-core droplets for mainnet, testnet, devnet
set -e
# Configuration
SSH_KEY_NAME="ra"
REGION="sfo3"
SIZE="s-8vcpu-16gb-amd" # 8 vCPU, 16GB RAM, 320GB disk, $112/month
IMAGE="docker-20-04" # Docker pre-installed on Ubuntu 20.04
# Get SSH key ID
SSH_KEY_ID=$(doctl compute ssh-key list --output json | jq -r '.[] | select(.name == "'"$SSH_KEY_NAME"'") | .id')
if [ -z "$SSH_KEY_ID" ]; then
echo "Error: SSH key '$SSH_KEY_NAME' not found"
exit 1
fi
echo "Using SSH key: $SSH_KEY_NAME (ID: $SSH_KEY_ID)"
# Create user data script for cloud-init
USER_DATA='#!/bin/bash
set -e
# Update system
apt-get update
apt-get install -y docker-compose-plugin git jq curl
# Create lux user
useradd -m -s /bin/bash lux || true
usermod -aG docker lux
# Clone universe repo
cd /home/lux
sudo -u lux git clone https://github.com/luxfi/universe.git
cd universe
# Initialize submodules (only needed files)
sudo -u lux git submodule update --init --depth 1 node cli geth evm genesis netrunner
# Create data directories
mkdir -p /data/lux/{chains,plugins,runs,snapshots}
chown -R lux:lux /data/lux
# Create .env file
cat > /home/lux/universe/.env <<EOF
DATA_DIR=/data/lux
NETWORK_TYPE=NETWORK_PLACEHOLDER
EOF
chown lux:lux /home/lux/universe/.env
echo "Setup complete for NETWORK_PLACEHOLDER"
'
# Create droplets for each network
echo "Creating droplets..."
create_droplet() {
local network=$1
local name="lux-$network"
# Check if droplet exists
existing=$(doctl compute droplet list --output json | jq -r '.[] | select(.name == "'"$name"'") | .id')
if [ -n "$existing" ]; then
echo "Droplet '$name' already exists (ID: $existing)"
return 0
fi
echo "Creating droplet: $name ($network)"
# Replace placeholder in user data
user_data_actual=$(echo "$USER_DATA" | sed "s/NETWORK_PLACEHOLDER/$network/g")
doctl compute droplet create "$name" \
--region "$REGION" \
--size "$SIZE" \
--image "$IMAGE" \
--ssh-keys "$SSH_KEY_ID" \
--user-data "$user_data_actual" \
--tag-names "lux,$network,blockchain" \
--enable-monitoring \
--wait
echo "Created: $name"
}
# Create all three droplets
create_droplet "mainnet"
create_droplet "testnet"
create_droplet "devnet"
# Wait for droplets to be ready
echo "Waiting for droplets to initialize..."
sleep 30
# Get droplet IPs
echo ""
echo "=== Droplet Information ==="
show_droplet_info() {
local network=$1
local name="lux-$network"
info=$(doctl compute droplet list --output json | jq -r '.[] | select(.name == "'"$name"'") | "\(.id) \(.networks.v4[] | select(.type == "public") | .ip_address)"')
id=$(echo "$info" | cut -d' ' -f1)
ip=$(echo "$info" | cut -d' ' -f2)
if [ -n "$ip" ]; then
echo "$network: $name"
echo " ID: $id"
echo " IP: $ip"
echo " SSH: ssh root@$ip"
# Add to ~/.ssh/config
if ! grep -q "Host $name" ~/.ssh/config 2>/dev/null; then
cat >> ~/.ssh/config <<EOF
Host $name
HostName $ip
User root
IdentityFile ~/.ssh/id_rsa
EOF
echo " Added to ~/.ssh/config"
fi
fi
}
show_droplet_info "mainnet"
show_droplet_info "testnet"
show_droplet_info "devnet"
echo ""
echo "=== Next Steps ==="
echo "1. Wait 2-3 minutes for cloud-init to complete"
echo "2. SSH into each droplet and start the network:"
echo ""
echo " # For mainnet:"
echo " ssh lux-mainnet"
echo " cd /home/lux/universe"
echo " docker compose -f compose.mainnet.yml up -d"
echo ""
echo " # For testnet:"
echo " ssh lux-testnet"
echo " cd /home/lux/universe"
echo " docker compose -f compose.testnet.yml up -d"
echo ""
echo " # For devnet:"
echo " ssh lux-devnet"
echo " cd /home/lux/universe"
echo " docker compose -f compose.devnet.yml up -d"
echo ""
echo "3. Monitor with: docker compose logs -f"
-1
View File
@@ -15,7 +15,6 @@ cp -R "${src_root}/k8s/bootnode" "${target_root}/k8s/"
# Deployment automation
cp "${src_root}/scripts/check-tracked-chains.sh" "${target_root}/scripts/"
cp "${src_root}/scripts/ensure-tracked-chains.sh" "${target_root}/scripts/"
cp "${src_root}/scripts/deploy-do.sh" "${target_root}/scripts/"
cp "${src_root}/Makefile" "${target_root}/Makefile"
cat > "${target_root}/README.md" <<'README'