Adds mobilizon app.

This commit is contained in:
2026-06-19 21:33:14 +00:00
parent a2e3031b84
commit 855fb03e17
10 changed files with 334 additions and 0 deletions

5
mobilizon/app.yaml Normal file
View File

@@ -0,0 +1,5 @@
name: mobilizon
is: mobilizon
description: Mobilizon is a federated event hosting platform that lets you organize events, groups, and discussions without relying on corporate social networks.
icon: https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/mobilizon.svg
latest: "5"

View File

@@ -0,0 +1,40 @@
# Mobilizon
Mobilizon is a federated events and groups platform, an ActivityPub alternative to Facebook Events and Meetup.
## Dependencies
- **PostgreSQL** - Database for storing events, groups, and accounts
- **SMTP** - For account verification and event notifications
## Configuration
Key settings in `config.yaml`:
- **domain** - Where Mobilizon will be accessible
- **storage** - Persistent volume size (default: `2Gi`)
- **instanceName** - Display name for the instance (default: `Mobilizon`)
- **instanceEmail** - Contact email shown on the instance (defaults to your operator email)
- **smtp** - Email settings inherited from your Wild Cloud SMTP service
## First-Time Setup
1. Add and deploy the app:
```bash
wild app add mobilizon
wild app deploy mobilizon
```
2. Create the admin user via the Elixir console:
```bash
kubectl exec -n mobilizon deploy/mobilizon -- ./bin/mobilizon_web eval \
"Mobilizon.CLI.create_admin(\"Your Name\", \"admin@example.com\", \"yourpassword\")"
```
3. Visit the app URL and log in with the credentials you just created.
## Notes
- Mobilizon is federated via ActivityPub — events and groups are discoverable by Mastodon users and other Mobilizon instances
- The `secretKeyBase` and `secretKey` are auto-generated in `secrets.yaml`
- After logging in, complete the instance configuration under **Admin → Settings** (instance description, terms of service, etc.)

View File

@@ -0,0 +1,65 @@
apiVersion: batch/v1
kind: Job
metadata:
name: mobilizon-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: db-init
image: postgres:17
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: false
command: ["/bin/bash", "-c"]
args:
- |
PGPASSWORD=${POSTGRES_ADMIN_PASSWORD} psql -h ${DB_HOSTNAME} -U postgres <<EOF
DO \$\$
BEGIN
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '${DB_USERNAME}') THEN
CREATE USER ${DB_USERNAME} WITH ENCRYPTED PASSWORD '${DB_PASSWORD}';
ELSE
ALTER USER ${DB_USERNAME} WITH ENCRYPTED PASSWORD '${DB_PASSWORD}';
END IF;
END
\$\$;
SELECT 'CREATE DATABASE ${DB_DATABASE_NAME}' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${DB_DATABASE_NAME}')\gexec
ALTER DATABASE ${DB_DATABASE_NAME} OWNER TO ${DB_USERNAME};
GRANT ALL PRIVILEGES ON DATABASE ${DB_DATABASE_NAME} TO ${DB_USERNAME};
\c ${DB_DATABASE_NAME}
CREATE EXTENSION IF NOT EXISTS postgis;
EOF
env:
- name: POSTGRES_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secrets
key: password
- name: DB_HOSTNAME
value: "{{ .db.host }}"
- name: DB_DATABASE_NAME
value: "{{ .db.name }}"
- name: DB_USERNAME
value: "{{ .db.user }}"
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: mobilizon-secrets
key: dbPassword

View File

@@ -0,0 +1,124 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: mobilizon
namespace: {{ .namespace }}
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
component: web
template:
metadata:
labels:
component: web
spec:
securityContext:
runAsNonRoot: true
runAsUser: 65534
runAsGroup: 65534
fsGroup: 65534
seccompProfile:
type: RuntimeDefault
containers:
- name: mobilizon
image: docker.io/kaihuri/mobilizon:5.2.3
ports:
- name: http
containerPort: 4000
protocol: TCP
env:
- name: MOBILIZON_DATABASE_HOST
value: {{ .db.host }}
- name: MOBILIZON_DATABASE_PORT
value: "{{ .db.port }}"
- name: MOBILIZON_DATABASE_DBNAME
value: {{ .db.name }}
- name: MOBILIZON_DATABASE_USERNAME
value: {{ .db.user }}
- name: MOBILIZON_DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: mobilizon-secrets
key: dbPassword
- name: MOBILIZON_DATABASE_SSL
value: "false"
- name: MOBILIZON_INSTANCE_NAME
value: {{ .instanceName }}
- name: MOBILIZON_INSTANCE_HOST
value: {{ .domain }}
- name: MOBILIZON_INSTANCE_PORT
value: "4000"
- name: MOBILIZON_INSTANCE_LISTEN_IP
value: "0.0.0.0"
- name: MOBILIZON_INSTANCE_EMAIL
value: {{ .instanceEmail }}
- name: MOBILIZON_REPLY_EMAIL
value: {{ .instanceEmail }}
- name: MOBILIZON_INSTANCE_REGISTRATIONS_OPEN
value: "false"
- name: MOBILIZON_INSTANCE_SECRET_KEY_BASE
valueFrom:
secretKeyRef:
name: mobilizon-secrets
key: secretKeyBase
- name: MOBILIZON_INSTANCE_SECRET_KEY
valueFrom:
secretKeyRef:
name: mobilizon-secrets
key: secretKey
- name: MOBILIZON_SMTP_SERVER
value: {{ .smtp.host }}
- name: MOBILIZON_SMTP_PORT
value: "{{ .smtp.port }}"
- name: MOBILIZON_SMTP_USERNAME
value: {{ .smtp.user }}
- name: MOBILIZON_SMTP_PASSWORD
valueFrom:
secretKeyRef:
name: mobilizon-secrets
key: smtp.password
- name: MOBILIZON_SMTP_TLS
value: "if_available"
- name: MOBILIZON_SMTP_SSL
value: "false"
- name: MOBILIZON_SMTP_AUTH
value: "if_available"
volumeMounts:
- name: mobilizon-data
mountPath: /app/uploads
startupProbe:
httpGet:
path: /
port: http
initialDelaySeconds: 60
timeoutSeconds: 5
periodSeconds: 10
failureThreshold: 60
livenessProbe:
httpGet:
path: /
port: http
timeoutSeconds: 10
periodSeconds: 30
failureThreshold: 3
readinessProbe:
httpGet:
path: /
port: http
timeoutSeconds: 5
periodSeconds: 15
failureThreshold: 3
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: false
volumes:
- name: mobilizon-data
persistentVolumeClaim:
claimName: mobilizon-data
restartPolicy: Always

View File

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

View File

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

View File

@@ -0,0 +1,30 @@
version: 5.2.3-3
requires:
- name: postgres
- name: smtp
defaultConfig:
namespace: mobilizon
externalDnsDomain: '{{ .cloud.domain }}'
domain: mobilizon.{{ .cloud.domain }}
tlsSecretName: wildcard-wild-cloud-tls
storage: 2Gi
instanceName: Mobilizon
instanceEmail: '{{ .operator.email }}'
db:
host: '{{ .apps.postgres.host }}'
port: '{{ .apps.postgres.port }}'
name: mobilizon
user: mobilizon
smtp:
host: '{{ .apps.smtp.host }}'
port: '{{ .apps.smtp.port }}'
user: '{{ .apps.smtp.user }}'
from: '{{ .apps.smtp.from }}'
defaultSecrets:
- key: dbPassword
- key: secretKeyBase
- key: secretKey
- key: smtpPassword
requiredSecrets:
- postgres.password
- smtp.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: mobilizon-data
namespace: {{ .namespace }}
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ .storage }}

View File

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