Aptly and community search.
This commit is contained in:
6
aptly/app.yaml
Normal file
6
aptly/app.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
name: aptly
|
||||||
|
is: aptly
|
||||||
|
description: Aptly is a Debian/Ubuntu APT repository management tool for mirroring, snapshotting, and publishing package repositories.
|
||||||
|
icon: https://github.com/aptly-dev.png
|
||||||
|
category: infrastructure
|
||||||
|
latest: "1"
|
||||||
123
aptly/versions/1/README.md
Normal file
123
aptly/versions/1/README.md
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
# Aptly
|
||||||
|
|
||||||
|
Aptly is a Debian/Ubuntu APT repository management tool. Use it to mirror upstream repositories, create package snapshots, and publish private or curated APT repositories that your machines can install from.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Key settings in your instance's `config.yaml`:
|
||||||
|
|
||||||
|
- **domain** - Where aptly will be accessible (default: `aptly.{your-cloud-domain}`)
|
||||||
|
- **storage** - Persistent volume size for packages and mirrors (default: `50Gi` — adjust based on how many packages you plan to mirror)
|
||||||
|
|
||||||
|
## Access
|
||||||
|
|
||||||
|
After deployment:
|
||||||
|
- `https://aptly.{your-cloud-domain}` — Published repository root (for APT clients, no auth required)
|
||||||
|
- `https://aptly.{your-cloud-domain}/api` — REST API for managing repos, mirrors, and snapshots (requires credentials)
|
||||||
|
|
||||||
|
## Credentials
|
||||||
|
|
||||||
|
The API is protected by HTTP basic authentication. The username defaults to `aptly` (configurable via `apiUser` in `config.yaml`). The password is auto-generated and stored in your instance's `secrets.yaml` under `apps.aptly.apiPassword`.
|
||||||
|
|
||||||
|
To retrieve it:
|
||||||
|
```bash
|
||||||
|
wild secret get aptly apiPassword
|
||||||
|
# or directly:
|
||||||
|
grep apiPassword path/to/secrets.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
To use the API with curl:
|
||||||
|
```bash
|
||||||
|
curl -u aptly:{your-api-password} https://aptly.{your-cloud-domain}/api/version
|
||||||
|
```
|
||||||
|
|
||||||
|
The published repository at `/` does not require credentials — APT clients can install packages without authenticating.
|
||||||
|
|
||||||
|
## First-Time Setup
|
||||||
|
|
||||||
|
1. Add and deploy:
|
||||||
|
```bash
|
||||||
|
wild app add aptly
|
||||||
|
wild app deploy aptly
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Verify the API is responding:
|
||||||
|
```bash
|
||||||
|
curl -u aptly:{your-api-password} https://aptly.{your-cloud-domain}/api/version
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Workflows
|
||||||
|
|
||||||
|
Aptly is managed entirely through its REST API or the `aptly` CLI (run inside the pod). The REST API docs are at https://www.aptly.info/doc/api/.
|
||||||
|
|
||||||
|
### Running aptly commands inside the pod
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n aptly exec -it deploy/aptly -- bash
|
||||||
|
```
|
||||||
|
|
||||||
|
### Mirror a Debian repository
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create a mirror (run inside the pod, or via the REST API)
|
||||||
|
aptly mirror create debian-bookworm-main http://deb.debian.org/debian bookworm main
|
||||||
|
|
||||||
|
# Download packages
|
||||||
|
aptly mirror update debian-bookworm-main
|
||||||
|
|
||||||
|
# Snapshot the mirror
|
||||||
|
aptly snapshot create bookworm-snap from mirror debian-bookworm-main
|
||||||
|
|
||||||
|
# Publish the snapshot
|
||||||
|
aptly publish snapshot bookworm-snap
|
||||||
|
```
|
||||||
|
|
||||||
|
The published repo will be available at `https://aptly.{your-cloud-domain}/debian bookworm main`.
|
||||||
|
|
||||||
|
### Create a private package repository
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create a local repo
|
||||||
|
aptly repo create my-packages
|
||||||
|
|
||||||
|
# Add packages
|
||||||
|
aptly repo add my-packages /path/to/package.deb
|
||||||
|
|
||||||
|
# Publish
|
||||||
|
aptly publish repo my-packages
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configure a machine to use the repository
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Add the repo to sources.list
|
||||||
|
echo "deb https://aptly.{your-cloud-domain}/ bookworm main" | \
|
||||||
|
sudo tee /etc/apt/sources.list.d/my-aptly.list
|
||||||
|
|
||||||
|
# Import the signing key (generate one first if needed — see GPG section below)
|
||||||
|
curl -s https://aptly.{your-cloud-domain}/public.key | sudo apt-key add -
|
||||||
|
|
||||||
|
sudo apt update
|
||||||
|
```
|
||||||
|
|
||||||
|
## GPG Signing
|
||||||
|
|
||||||
|
Published repositories should be signed with a GPG key. On first use, generate a key inside the pod:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n aptly exec -it deploy/aptly -- bash
|
||||||
|
|
||||||
|
# Generate a signing key (stored in /opt/aptly/gpg)
|
||||||
|
gpg --gen-key
|
||||||
|
|
||||||
|
# Export the public key for clients to import
|
||||||
|
gpg --export --armor > /opt/aptly/public/public.key
|
||||||
|
```
|
||||||
|
|
||||||
|
Then include `--distribution`, `--component`, and signing options in your `aptly publish` commands. See https://www.aptly.info/doc/aptly/publish/snapshot/ for details.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- GPG keys and all aptly data (database, package pool, published repos) are stored on the persistent volume at `/opt/aptly`.
|
||||||
|
- The REST API (port 8080) and the nginx file server (port 80) both run inside the pod via supervisord. The ingress routes to nginx (port 80).
|
||||||
|
- `storage` defaults to `50Gi`. A full Debian mirror for a single architecture is ~50–100 GiB; plan accordingly.
|
||||||
56
aptly/versions/1/deployment.yaml
Normal file
56
aptly/versions/1/deployment.yaml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: aptly
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
component: server
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
component: server
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
initContainers:
|
||||||
|
- name: init-htpasswd
|
||||||
|
image: httpd:alpine
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- htpasswd -bc /opt/aptly/api.htpasswd "$API_USER" "$API_PASSWORD"
|
||||||
|
env:
|
||||||
|
- name: API_USER
|
||||||
|
value: "{{ .apiUser }}"
|
||||||
|
- name: API_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: aptly-secrets
|
||||||
|
key: apiPassword
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: /opt/aptly
|
||||||
|
containers:
|
||||||
|
- name: aptly
|
||||||
|
image: urpylka/aptly:1.6.2
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
name: http
|
||||||
|
- containerPort: 8080
|
||||||
|
name: api
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: /opt/aptly
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: aptly-pvc
|
||||||
25
aptly/versions/1/ingress.yaml
Normal file
25
aptly/versions/1/ingress.yaml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: aptly
|
||||||
|
annotations:
|
||||||
|
external-dns.alpha.kubernetes.io/target: {{ .externalDnsDomain }}
|
||||||
|
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
||||||
|
external-dns.alpha.kubernetes.io/ttl: "60"
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik
|
||||||
|
rules:
|
||||||
|
- host: {{ .domain }}
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: aptly
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- {{ .domain }}
|
||||||
|
secretName: {{ .tlsSecretName }}
|
||||||
15
aptly/versions/1/kustomization.yaml
Normal file
15
aptly/versions/1/kustomization.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
namespace: "{{ .namespace }}"
|
||||||
|
labels:
|
||||||
|
- includeSelectors: true
|
||||||
|
pairs:
|
||||||
|
app: aptly
|
||||||
|
managedBy: kustomize
|
||||||
|
partOf: wild-cloud
|
||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- deployment.yaml
|
||||||
|
- service.yaml
|
||||||
|
- ingress.yaml
|
||||||
|
- pvc.yaml
|
||||||
10
aptly/versions/1/manifest.yaml
Normal file
10
aptly/versions/1/manifest.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
version: 1.6.2
|
||||||
|
defaultConfig:
|
||||||
|
namespace: aptly
|
||||||
|
externalDnsDomain: "{{ .cloud.domain }}"
|
||||||
|
domain: "aptly.{{ .cloud.domain }}"
|
||||||
|
tlsSecretName: wildcard-wild-cloud-tls
|
||||||
|
storage: 50Gi
|
||||||
|
apiUser: aptly
|
||||||
|
defaultSecrets:
|
||||||
|
- key: apiPassword
|
||||||
4
aptly/versions/1/namespace.yaml
Normal file
4
aptly/versions/1/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: "{{ .namespace }}"
|
||||||
12
aptly/versions/1/pvc.yaml
Normal file
12
aptly/versions/1/pvc.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: aptly-pvc
|
||||||
|
spec:
|
||||||
|
storageClassName: longhorn
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
volumeMode: Filesystem
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .storage }}
|
||||||
14
aptly/versions/1/service.yaml
Normal file
14
aptly/versions/1/service.yaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: aptly
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 80
|
||||||
|
name: http
|
||||||
|
- port: 8080
|
||||||
|
targetPort: 8080
|
||||||
|
name: api
|
||||||
|
selector:
|
||||||
|
component: server
|
||||||
4
community-search/app.yaml
Normal file
4
community-search/app.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
name: community-search
|
||||||
|
is: community-search
|
||||||
|
description: Community Search is a federated, self-hosted search engine built on community-curated indexes rather than global web crawling.
|
||||||
|
latest: "0"
|
||||||
84
community-search/versions/0/deployment.yaml
Normal file
84
community-search/versions/0/deployment.yaml
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: community-search
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
type: Recreate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
component: web
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
component: web
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 999
|
||||||
|
runAsGroup: 999
|
||||||
|
fsGroup: 999
|
||||||
|
seccompProfile:
|
||||||
|
type: RuntimeDefault
|
||||||
|
containers:
|
||||||
|
- name: community-search
|
||||||
|
image: payneio/community-search:0.1.1
|
||||||
|
imagePullPolicy: Always
|
||||||
|
securityContext:
|
||||||
|
allowPrivilegeEscalation: false
|
||||||
|
capabilities:
|
||||||
|
drop:
|
||||||
|
- ALL
|
||||||
|
readOnlyRootFilesystem: false
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 8080
|
||||||
|
env:
|
||||||
|
- name: COMMUNITY_SEARCH_BIND_ADDR
|
||||||
|
value: "0.0.0.0"
|
||||||
|
- name: COMMUNITY_SEARCH_PORT
|
||||||
|
value: "8080"
|
||||||
|
- name: COMMUNITY_SEARCH_DATA_DIR
|
||||||
|
value: "/data"
|
||||||
|
- name: COMMUNITY_SEARCH_INDEX_PATH
|
||||||
|
value: "/data/index"
|
||||||
|
- name: COMMUNITY_SEARCH_ADMIN_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: community-search-secrets
|
||||||
|
key: adminToken
|
||||||
|
- name: SELF_URL
|
||||||
|
value: "{{ .selfUrl }}"
|
||||||
|
- name: SELF_NAME
|
||||||
|
value: "{{ .selfName }}"
|
||||||
|
- name: RUST_LOG
|
||||||
|
value: "community_search=info,tower_http=warn"
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: /data
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
limits:
|
||||||
|
cpu: 1
|
||||||
|
memory: 1Gi
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /api/collections
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
timeoutSeconds: 5
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /api/collections
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 30
|
||||||
|
timeoutSeconds: 5
|
||||||
|
volumes:
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: community-search-data
|
||||||
25
community-search/versions/0/ingress.yaml
Normal file
25
community-search/versions/0/ingress.yaml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: community-search
|
||||||
|
annotations:
|
||||||
|
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false"
|
||||||
|
external-dns.alpha.kubernetes.io/target: {{ .externalDnsDomain }}
|
||||||
|
external-dns.alpha.kubernetes.io/ttl: "60"
|
||||||
|
spec:
|
||||||
|
ingressClassName: traefik
|
||||||
|
rules:
|
||||||
|
- host: {{ .domain }}
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: community-search
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- {{ .domain }}
|
||||||
|
secretName: {{ .tlsSecretName }}
|
||||||
15
community-search/versions/0/kustomization.yaml
Normal file
15
community-search/versions/0/kustomization.yaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
namespace: community-search
|
||||||
|
labels:
|
||||||
|
- includeSelectors: true
|
||||||
|
pairs:
|
||||||
|
app: community-search
|
||||||
|
managedBy: kustomize
|
||||||
|
partOf: wild-cloud
|
||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- deployment.yaml
|
||||||
|
- service.yaml
|
||||||
|
- ingress.yaml
|
||||||
|
- pvc.yaml
|
||||||
12
community-search/versions/0/manifest.yaml
Normal file
12
community-search/versions/0/manifest.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
version: 0.1.1-1
|
||||||
|
requires: []
|
||||||
|
defaultConfig:
|
||||||
|
namespace: community-search
|
||||||
|
externalDnsDomain: '{{ .cloud.domain }}'
|
||||||
|
domain: search.{{ .cloud.domain }}
|
||||||
|
tlsSecretName: wildcard-wild-cloud-tls
|
||||||
|
storage: 10Gi
|
||||||
|
selfUrl: 'https://search.{{ .cloud.domain }}'
|
||||||
|
selfName: 'Community Search'
|
||||||
|
defaultSecrets:
|
||||||
|
- key: adminToken
|
||||||
4
community-search/versions/0/namespace.yaml
Normal file
4
community-search/versions/0/namespace.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: "{{ .namespace }}"
|
||||||
10
community-search/versions/0/pvc.yaml
Normal file
10
community-search/versions/0/pvc.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: community-search-data
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .storage }}
|
||||||
13
community-search/versions/0/service.yaml
Normal file
13
community-search/versions/0/service.yaml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: community-search
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 80
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 8080
|
||||||
|
selector:
|
||||||
|
component: web
|
||||||
Reference in New Issue
Block a user