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