Adds pixelfed app.

This commit is contained in:
2026-06-19 21:33:23 +00:00
parent c2efed5937
commit bd1116048d
11 changed files with 485 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
# Pixelfed
Pixelfed is a federated, self-hosted photo sharing platform — a privacy-respecting alternative to Instagram, compatible with the ActivityPub protocol.
## Dependencies
- **PostgreSQL** - Database for storing posts and accounts
- **Redis** - Used for caching and job queuing
- **SMTP** - For account verification and notifications
## Configuration
Key settings in `config.yaml`:
- **domain** - Where Pixelfed will be accessible
- **storage** - Persistent volume size (default: `2Gi`)
- **db.name** - Database name (default: `pixelfed`)
- **smtp** - Email settings inherited from your Wild Cloud SMTP service
## First-Time Setup
1. Add and deploy the app:
```bash
wild app add pixelfed
wild app deploy pixelfed
```
2. Create the admin user by running an artisan command in the pod:
```bash
kubectl exec -n pixelfed deploy/pixelfed -- php artisan user:create \
--name="Admin" \
--username="admin" \
--email="your@email.com" \
--password="yourpassword" \
--is_admin=1 \
--confirm_email=1
```
3. Visit the app URL and log in with the credentials you just created.
## Notes
- This package uses the `ghcr.io/mattlqx/docker-pixelfed` community image (port 80, nginx) since the official image requires authentication to pull
- Federation with Mastodon and other ActivityPub platforms is enabled by default
- User registration can be set to open, invite-only, or closed via **Admin → Settings**

View File

@@ -0,0 +1,59 @@
apiVersion: batch/v1
kind: Job
metadata:
name: pixelfed-db-init
labels:
component: db-init
spec:
template:
metadata:
labels:
component: db-init
spec:
restartPolicy: OnFailure
securityContext:
runAsNonRoot: true
runAsUser: 999
runAsGroup: 999
seccompProfile:
type: RuntimeDefault
containers:
- name: postgres-init
image: postgres:16
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: false
env:
- name: PGHOST
value: {{ .db.host }}
- name: PGUSER
value: postgres
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: pixelfed-secrets
key: postgres.password
- name: DB_NAME
value: {{ .db.name }}
- name: DB_USER
value: {{ .db.user }}
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: pixelfed-secrets
key: dbPassword
command:
- /bin/bash
- -c
- |
set -e
until pg_isready; do sleep 2; done
psql -c "CREATE DATABASE ${DB_NAME};" || echo "Database already exists"
psql -c "CREATE USER ${DB_USER} WITH PASSWORD '${DB_PASSWORD}';" || echo "User already exists"
psql -c "ALTER USER ${DB_USER} WITH PASSWORD '${DB_PASSWORD}';"
psql -c "GRANT ALL PRIVILEGES ON DATABASE ${DB_NAME} TO ${DB_USER};"
psql -d ${DB_NAME} -c "GRANT ALL ON SCHEMA public TO ${DB_USER};"
echo "Done"

View File

@@ -0,0 +1,112 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: pixelfed-worker
namespace: {{ .namespace }}
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
component: worker
template:
metadata:
labels:
component: worker
spec:
securityContext:
runAsNonRoot: true
runAsUser: 33
runAsGroup: 33
fsGroup: 33
seccompProfile:
type: RuntimeDefault
containers:
- name: pixelfed-worker
image: ghcr.io/mattlqx/docker-pixelfed:v0.12.7-nginx
command:
- php
- artisan
- horizon
env:
- name: APP_NAME
value: Pixelfed
- name: APP_ENV
value: production
- name: APP_DEBUG
value: "false"
- name: APP_URL
value: https://{{ .domain }}
- name: APP_DOMAIN
value: {{ .domain }}
- name: APP_KEY
valueFrom:
secretKeyRef:
name: pixelfed-secrets
key: appKey
- name: DB_CONNECTION
value: pgsql
- name: DB_HOST
value: {{ .db.host }}
- name: DB_PORT
value: "{{ .db.port }}"
- name: DB_DATABASE
value: {{ .db.name }}
- name: DB_USERNAME
value: {{ .db.user }}
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: pixelfed-secrets
key: dbPassword
- name: REDIS_CLIENT
value: predis
- name: REDIS_HOST
value: {{ .redis.host }}
- name: REDIS_PORT
value: "6379"
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: pixelfed-secrets
key: redis.password
- name: CACHE_DRIVER
value: redis
- name: SESSION_DRIVER
value: redis
- name: QUEUE_DRIVER
value: redis
- name: ACTIVITY_PUB
value: "1"
- name: AP_REMOTE_FOLLOW
value: "1"
- name: AP_INBOX
value: "1"
- name: AP_OUTBOX
value: "1"
- name: AP_SHAREDINBOX
value: "1"
resources:
limits:
cpu: 1000m
ephemeral-storage: 512Mi
memory: 1Gi
requests:
cpu: 50m
ephemeral-storage: 50Mi
memory: 256Mi
volumeMounts:
- name: pixelfed-storage
mountPath: /var/www/html/storage
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: false
volumes:
- name: pixelfed-storage
persistentVolumeClaim:
claimName: pixelfed-storage
restartPolicy: Always

View File

@@ -0,0 +1,161 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: pixelfed
namespace: {{ .namespace }}
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
component: web
template:
metadata:
labels:
component: web
spec:
securityContext:
runAsNonRoot: true
runAsUser: 33
runAsGroup: 33
fsGroup: 33
seccompProfile:
type: RuntimeDefault
containers:
- name: pixelfed
image: ghcr.io/mattlqx/docker-pixelfed:v0.12.7-nginx
ports:
- name: http
containerPort: 80
protocol: TCP
env:
- name: APP_NAME
value: Pixelfed
- name: APP_ENV
value: production
- name: APP_DEBUG
value: "false"
- name: APP_PORT
value: "80"
- name: APP_URL
value: https://{{ .domain }}
- name: APP_DOMAIN
value: {{ .domain }}
- name: ADMIN_DOMAIN
value: {{ .domain }}
- name: SESSION_DOMAIN
value: {{ .domain }}
- name: APP_KEY
valueFrom:
secretKeyRef:
name: pixelfed-secrets
key: appKey
- name: DB_CONNECTION
value: pgsql
- name: DB_HOST
value: {{ .db.host }}
- name: DB_PORT
value: "{{ .db.port }}"
- name: DB_DATABASE
value: {{ .db.name }}
- name: DB_USERNAME
value: {{ .db.user }}
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: pixelfed-secrets
key: dbPassword
- name: REDIS_CLIENT
value: predis
- name: REDIS_HOST
value: {{ .redis.host }}
- name: REDIS_PORT
value: "6379"
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: pixelfed-secrets
key: redis.password
- name: CACHE_DRIVER
value: redis
- name: SESSION_DRIVER
value: redis
- name: QUEUE_DRIVER
value: redis
- name: MAIL_MAILER
value: smtp
- name: MAIL_HOST
value: {{ .smtp.host }}
- name: MAIL_PORT
value: "{{ .smtp.port }}"
- name: MAIL_USERNAME
value: {{ .smtp.user }}
- name: MAIL_PASSWORD
valueFrom:
secretKeyRef:
name: pixelfed-secrets
key: smtpPassword
- name: MAIL_FROM_ADDRESS
value: {{ .smtp.from }}
- name: MAIL_ENCRYPTION
value: tls
- name: ACTIVITY_PUB
value: "1"
- name: AP_REMOTE_FOLLOW
value: "1"
- name: AP_INBOX
value: "1"
- name: AP_OUTBOX
value: "1"
- name: AP_SHAREDINBOX
value: "1"
- name: OAUTH_ENABLED
value: "true"
- name: OPEN_REGISTRATION
value: "true"
- name: FORCE_HTTPS
value: "true"
- name: PHP_POST_MAX_SIZE
value: 500M
- name: PHP_UPLOAD_MAX_FILE_SIZE
value: 500M
resources:
limits:
cpu: "1"
ephemeral-storage: 1Gi
memory: 1Gi
requests:
cpu: 50m
ephemeral-storage: 50Mi
memory: 256Mi
volumeMounts:
- name: pixelfed-storage
mountPath: /var/www/html/storage
livenessProbe:
httpGet:
path: /api/v1/instance
port: 80
initialDelaySeconds: 120
timeoutSeconds: 10
periodSeconds: 30
failureThreshold: 6
readinessProbe:
httpGet:
path: /api/v1/instance
port: 80
initialDelaySeconds: 60
timeoutSeconds: 5
periodSeconds: 15
failureThreshold: 3
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: false
volumes:
- name: pixelfed-storage
persistentVolumeClaim:
claimName: pixelfed-storage
restartPolicy: Always

View File

@@ -0,0 +1,26 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: pixelfed
namespace: {{ .namespace }}
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: pixelfed
port:
number: 80
tls:
- hosts:
- {{ .domain }}
secretName: {{ .tlsSecretName }}

View File

@@ -0,0 +1,17 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: {{ .namespace }}
labels:
- includeSelectors: true
pairs:
app: pixelfed
managedBy: kustomize
partOf: wild-cloud
resources:
- namespace.yaml
- db-init-job.yaml
- deployment.yaml
- deployment-worker.yaml
- service.yaml
- ingress.yaml
- pvc.yaml

View File

@@ -0,0 +1,32 @@
version: 0.12.7-1
requires:
- name: postgres
- name: redis
- name: smtp
defaultConfig:
namespace: pixelfed
externalDnsDomain: '{{ .cloud.domain }}'
domain: pixelfed.{{ .cloud.domain }}
tlsSecretName: wildcard-wild-cloud-tls
storage: 2Gi
db:
host: '{{ .apps.postgres.host }}'
port: '{{ .apps.postgres.port }}'
name: pixelfed
user: pixelfed
redis:
host: '{{ .apps.redis.host }}'
smtp:
host: '{{ .apps.smtp.host }}'
port: '{{ .apps.smtp.port }}'
from: '{{ .apps.smtp.from }}'
user: '{{ .apps.smtp.user }}'
defaultSecrets:
- key: appKey
- key: dbPassword
- key: dbUrl
default: 'postgresql://{{ .app.db.user }}:{{ .secrets.dbPassword }}@{{ .app.db.host }}:{{ .app.db.port }}/{{ .app.db.name }}?sslmode=disable'
- key: smtpPassword
requiredSecrets:
- postgres.password
- redis.password

View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: {{ .namespace }}

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pixelfed-storage
namespace: {{ .namespace }}
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: {{ .storage }}

View File

@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: pixelfed
namespace: {{ .namespace }}
spec:
selector:
component: web
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP