diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml new file mode 100644 index 0000000..0e900d2 --- /dev/null +++ b/.forgejo/workflows/build.yaml @@ -0,0 +1,42 @@ +name: Build and Push + +on: + push: + branches: [main] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Login to Forgejo Registry + uses: docker/login-action@v3 + with: + registry: git.mcintire.me + username: ${{ secrets.REGISTRY_USER }} + password: ${{ secrets.REGISTRY_PASSWORD }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Generate image tags + id: tags + run: | + TIMESTAMP=$(date +%s) + SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7) + TAG="main-${TIMESTAMP}-${SHORT_SHA}" + echo "tag=${TAG}" >> $GITHUB_OUTPUT + echo "Building image with tag: ${TAG}" + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: | + git.mcintire.me/graham/aprs.me:${{ steps.tags.outputs.tag }} + git.mcintire.me/graham/aprs.me:latest + cache-from: type=registry,ref=git.mcintire.me/graham/aprs.me:latest + cache-to: type=inline diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml new file mode 100644 index 0000000..526cae0 --- /dev/null +++ b/k8s/deployment.yaml @@ -0,0 +1,140 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: aprs + namespace: aprs +spec: + replicas: 2 + strategy: + type: RollingUpdate + rollingUpdate: + maxSurge: 100% + maxUnavailable: 0 + minReadySeconds: 10 + selector: + matchLabels: + app: aprs + template: + metadata: + labels: + app: aprs + spec: + priorityClassName: system-cluster-critical + terminationGracePeriodSeconds: 90 + imagePullSecrets: + - name: forgejo-registry + securityContext: + runAsNonRoot: true + runAsUser: 1001 + fsGroup: 1001 + seccompProfile: + type: RuntimeDefault + containers: + - name: aprs + image: git.mcintire.me/graham/aprs.me:main-0000000000-0000000 # {"$imagepolicy": "flux-system:aprs-me"} + imagePullPolicy: IfNotPresent + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + runAsUser: 1001 + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + ports: + - containerPort: 4000 + name: http + - containerPort: 4369 + name: epmd + - containerPort: 9000 + name: dist + lifecycle: + preStop: + exec: + command: + - /bin/sh + - -c + - sleep 20 + env: + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: RELEASE_DISTRIBUTION + value: "name" + - name: RELEASE_NODE + value: "aprsme@$(POD_IP)" + - name: CLUSTER_ENABLED + value: "true" + - name: PORT + value: "4000" + - name: PHX_HOST + value: "aprs.me" + - name: MIX_ENV + value: "prod" + - name: POOL_SIZE + value: "5" + - name: PACKET_RETENTION_DAYS + value: "1" + - name: APRS_CALLSIGN + value: "w5isp-1" + - name: APRS_PORT + value: "10152" + - name: RELEASE_COOKIE + valueFrom: + secretKeyRef: + name: aprs-secrets + key: RELEASE_COOKIE + - name: SECRET_KEY_BASE + valueFrom: + secretKeyRef: + name: aprs-secrets + key: SECRET_KEY_BASE + - name: APRS_PASSCODE + valueFrom: + secretKeyRef: + name: aprs-secrets + key: APRS_PASSCODE + envFrom: + - secretRef: + name: aprs-db + resources: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "512Mi" + cpu: "500m" + startupProbe: + httpGet: + path: /health + port: 4000 + initialDelaySeconds: 10 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 12 + livenessProbe: + httpGet: + path: /health + port: 4000 + periodSeconds: 10 + timeoutSeconds: 3 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /health + port: 4000 + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 2 + successThreshold: 1 + failureThreshold: 2 diff --git a/k8s/flux/gitrepository.yaml b/k8s/flux/gitrepository.yaml new file mode 100644 index 0000000..4237e8f --- /dev/null +++ b/k8s/flux/gitrepository.yaml @@ -0,0 +1,12 @@ +apiVersion: source.toolkit.fluxcd.io/v1 +kind: GitRepository +metadata: + name: aprs-me + namespace: flux-system +spec: + interval: 1m + url: https://git.mcintire.me/graham/aprs.me.git + ref: + branch: main + secretRef: + name: forgejo-git-credentials diff --git a/k8s/flux/imagepolicy.yaml b/k8s/flux/imagepolicy.yaml new file mode 100644 index 0000000..87e50a2 --- /dev/null +++ b/k8s/flux/imagepolicy.yaml @@ -0,0 +1,14 @@ +apiVersion: image.toolkit.fluxcd.io/v1beta2 +kind: ImagePolicy +metadata: + name: aprs-me + namespace: flux-system +spec: + imageRepositoryRef: + name: aprs-me + filterTags: + pattern: '^main-(?P[0-9]+)-[a-f0-9]+$' + extract: '$ts' + policy: + numerical: + order: asc diff --git a/k8s/flux/imagerepository.yaml b/k8s/flux/imagerepository.yaml new file mode 100644 index 0000000..27b4fc4 --- /dev/null +++ b/k8s/flux/imagerepository.yaml @@ -0,0 +1,10 @@ +apiVersion: image.toolkit.fluxcd.io/v1beta2 +kind: ImageRepository +metadata: + name: aprs-me + namespace: flux-system +spec: + image: git.mcintire.me/graham/aprs.me + interval: 1m + secretRef: + name: forgejo-registry diff --git a/k8s/flux/imageupdateautomation.yaml b/k8s/flux/imageupdateautomation.yaml new file mode 100644 index 0000000..f317030 --- /dev/null +++ b/k8s/flux/imageupdateautomation.yaml @@ -0,0 +1,24 @@ +apiVersion: image.toolkit.fluxcd.io/v1beta2 +kind: ImageUpdateAutomation +metadata: + name: aprs-me + namespace: flux-system +spec: + interval: 1m + sourceRef: + kind: GitRepository + name: aprs-me + git: + checkout: + ref: + branch: main + push: + branch: main + commit: + author: + name: FluxCD + email: fluxcd@aprs.me + messageTemplate: 'chore: update aprs.me image to {{range .Changed.Changes}}{{.NewValue}}{{end}} [skip ci]' + update: + path: ./k8s + strategy: Setters diff --git a/k8s/flux/kustomization.yaml b/k8s/flux/kustomization.yaml new file mode 100644 index 0000000..27eac96 --- /dev/null +++ b/k8s/flux/kustomization.yaml @@ -0,0 +1,13 @@ +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: aprs-app + namespace: flux-system +spec: + interval: 5m + sourceRef: + kind: GitRepository + name: aprs-me + path: ./k8s + prune: true + targetNamespace: aprs diff --git a/k8s/kustomization.yaml b/k8s/kustomization.yaml new file mode 100644 index 0000000..ef23ab3 --- /dev/null +++ b/k8s/kustomization.yaml @@ -0,0 +1,8 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: aprs +resources: + - namespace.yaml + - deployment.yaml + - service.yaml + - service-headless.yaml diff --git a/k8s/namespace.yaml b/k8s/namespace.yaml new file mode 100644 index 0000000..c9b9181 --- /dev/null +++ b/k8s/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: aprs diff --git a/k8s/service-headless.yaml b/k8s/service-headless.yaml new file mode 100644 index 0000000..fec27fd --- /dev/null +++ b/k8s/service-headless.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: aprs-headless + namespace: aprs +spec: + clusterIP: None + selector: + app: aprs + ports: + - name: epmd + port: 4369 + targetPort: 4369 + - name: dist + port: 9000 + targetPort: 9000 diff --git a/k8s/service.yaml b/k8s/service.yaml new file mode 100644 index 0000000..75051d9 --- /dev/null +++ b/k8s/service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: aprs + namespace: aprs +spec: + selector: + app: aprs + ports: + - name: http + port: 4000 + targetPort: 4000 + type: ClusterIP