diff --git a/argocd/manifests/devpi/Dockerfile b/argocd/manifests/devpi/Dockerfile index 31e7d7c..6c9cdc8 100644 --- a/argocd/manifests/devpi/Dockerfile +++ b/argocd/manifests/devpi/Dockerfile @@ -6,14 +6,14 @@ RUN pip install --no-cache-dir devpi-server devpi-web # Create non-root user RUN useradd -r -u 1000 devpi && mkdir -p /devpi && chown devpi:devpi /devpi +# Add startup script +COPY --chown=devpi:devpi start.sh /usr/local/bin/start.sh +RUN chmod +x /usr/local/bin/start.sh + USER devpi WORKDIR /devpi # Expose default port EXPOSE 3141 -# Use ENTRYPOINT for flexibility -ENTRYPOINT ["devpi-server"] - -# Default args (can be overridden) -CMD ["--serverdir", "/devpi", "--host", "0.0.0.0", "--port", "3141"] +ENTRYPOINT ["/usr/local/bin/start.sh"] diff --git a/argocd/manifests/devpi/README.md b/argocd/manifests/devpi/README.md index b68de74..a349853 100644 --- a/argocd/manifests/devpi/README.md +++ b/argocd/manifests/devpi/README.md @@ -6,36 +6,33 @@ devpi-server running in Kubernetes, providing: ## Setup -### 1. Deploy via ArgoCD +### 1. Create the root password secret -```bash +```fish +kubectl create namespace devpi +op inject -i argocd/manifests/devpi/secret-root.yaml.tpl | kubectl apply -f - +``` + +### 2. Deploy via ArgoCD + +```fish argocd app sync apps argocd app sync devpi ``` -### 2. Initialize devpi (first time only) +The container will auto-initialize on first startup using the root password from the secret. -After the StatefulSet is running, initialize devpi with a root password: +### 3. Create user and index (first time only) -```bash -# Get the root password from 1Password -ROOT_PASSWORD=$(op --vault blumeops item get --fields password --reveal) +After the pod is running: -# Initialize devpi -kubectl -n devpi exec -it devpi-0 -- devpi-init --serverdir /devpi --root-passwd "$ROOT_PASSWORD" - -# Restart the pod to pick up the initialized state -kubectl -n devpi rollout restart statefulset devpi -``` - -### 3. Create user and index - -```bash -# Login to devpi +```fish +# Login to devpi as root uvx devpi use https://pypi.tail8d86e.ts.net uvx devpi login root +# Enter root password when prompted -# Create user +# Create eblume user (prompts for password - use the one from 1Password) uvx devpi user -c eblume email=blume.erich@gmail.com # Create private index inheriting from PyPI @@ -56,8 +53,7 @@ trusted-host = pypi.tail8d86e.ts.net ### Upload private packages -```bash -# Build and publish +```fish cd ~/code/personal/your-package uv build uv publish --publish-url https://pypi.tail8d86e.ts.net/eblume/dev/ @@ -68,3 +64,9 @@ uv publish --publish-url https://pypi.tail8d86e.ts.net/eblume/dev/ - Web UI: https://pypi.tail8d86e.ts.net - PyPI cache: https://pypi.tail8d86e.ts.net/root/pypi/+simple/ - Private index: https://pypi.tail8d86e.ts.net/eblume/dev/+simple/ + +## Credentials + +Stored in 1Password vault `blumeops`, item `kyhzfifryqnuk7jeyibmmjvxxm`: +- `root password` - devpi root user +- `password` - eblume user password diff --git a/argocd/manifests/devpi/secret-root.yaml.tpl b/argocd/manifests/devpi/secret-root.yaml.tpl new file mode 100644 index 0000000..d69f9a8 --- /dev/null +++ b/argocd/manifests/devpi/secret-root.yaml.tpl @@ -0,0 +1,12 @@ +# Template for devpi root password secret +# Create the secret before deploying: +# kubectl create namespace devpi +# op inject -i argocd/manifests/devpi/secret-root.yaml.tpl | kubectl apply -f - +apiVersion: v1 +kind: Secret +metadata: + name: devpi-root + namespace: devpi +type: Opaque +stringData: + password: "{{ op://vg6xf6vvfmoh5hqjjhlhbeoaie/kyhzfifryqnuk7jeyibmmjvxxm/root password }}" diff --git a/argocd/manifests/devpi/start.sh b/argocd/manifests/devpi/start.sh new file mode 100644 index 0000000..faf3139 --- /dev/null +++ b/argocd/manifests/devpi/start.sh @@ -0,0 +1,30 @@ +#!/bin/bash +set -e + +SERVERDIR="${DEVPI_SERVERDIR:-/devpi}" +HOST="${DEVPI_HOST:-0.0.0.0}" +PORT="${DEVPI_PORT:-3141}" +OUTSIDE_URL="${DEVPI_OUTSIDE_URL:-}" + +# Check if devpi is initialized +if [ ! -f "$SERVERDIR/.serverversion" ]; then + echo "Initializing devpi server..." + + if [ -z "$DEVPI_ROOT_PASSWORD" ]; then + echo "ERROR: DEVPI_ROOT_PASSWORD environment variable must be set for initialization" + exit 1 + fi + + devpi-init --serverdir "$SERVERDIR" --root-passwd "$DEVPI_ROOT_PASSWORD" + echo "Devpi initialized successfully" +fi + +# Build command +CMD="devpi-server --serverdir $SERVERDIR --host $HOST --port $PORT" + +if [ -n "$OUTSIDE_URL" ]; then + CMD="$CMD --outside-url $OUTSIDE_URL" +fi + +echo "Starting devpi-server..." +exec $CMD diff --git a/argocd/manifests/devpi/statefulset.yaml b/argocd/manifests/devpi/statefulset.yaml index 21dac52..79a7770 100644 --- a/argocd/manifests/devpi/statefulset.yaml +++ b/argocd/manifests/devpi/statefulset.yaml @@ -19,15 +19,14 @@ spec: containers: - name: devpi image: registry.tail8d86e.ts.net/blumeops/devpi:latest - args: - - "--serverdir" - - "/devpi" - - "--host" - - "0.0.0.0" - - "--port" - - "3141" - - "--outside-url" - - "https://pypi.tail8d86e.ts.net" + env: + - name: DEVPI_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: devpi-root + key: password + - name: DEVPI_OUTSIDE_URL + value: "https://pypi.tail8d86e.ts.net" ports: - containerPort: 3141 name: http