2026-06-16 06:41:37 +02:00
name : fluxer
x-fluxer-env : &fluxer-env
FLUXER_ENV : production
NODE_ENV : production
FLUXER_SELF_HOSTED : "true"
FLUXER_BASE_DOMAIN : ${FLUXER_DOMAIN:?set FLUXER_DOMAIN in .env}
FLUXER_PUBLIC_SCHEME : ${FLUXER_PUBLIC_SCHEME:-https}
FLUXER_PUBLIC_PORT : ${FLUXER_PUBLIC_PORT:-443}
FLUXER_TRUST_CLIENT_IP_HEADER : "true"
FLUXER_CLIENT_IP_HEADER_NAME : x-forwarded-for
FLUXER_DATABASE_BACKEND : postgres
FLUXER_POSTGRES_HOST : postgres
FLUXER_POSTGRES_PORT : "5432"
FLUXER_POSTGRES_DATABASE : fluxer
FLUXER_POSTGRES_USERNAME : fluxer
FLUXER_POSTGRES_PASSWORD : ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}
FLUXER_POSTGRES_SSL : "false"
FLUXER_KV_URL : redis://valkey:6379/0
FLUXER_NATS_URL : nats://nats:4222
FLUXER_NATS_JETSTREAM_URL : nats://nats:4222
FLUXER_SVC_NATS_URL : nats://nats:4222
FLUXER_SVC_SHARD_COUNT : "1"
FLUXER_SEARCH_ENGINE : meilisearch
FLUXER_SEARCH_URL : http://meilisearch:7700
FLUXER_SEARCH_API_KEY : ${MEILI_MASTER_KEY:?set MEILI_MASTER_KEY in .env}
FLUXER_S3_ENDPOINT : http://seaweedfs:8333
FLUXER_S3_PUBLIC_ENDPOINT : http://seaweedfs:8333
FLUXER_S3_REGION : us-east-1
FLUXER_S3_ACCESS_KEY_ID : ${FLUXER_S3_ACCESS_KEY:?set FLUXER_S3_ACCESS_KEY in .env}
FLUXER_S3_SECRET_ACCESS_KEY : ${FLUXER_S3_SECRET_KEY:?set FLUXER_S3_SECRET_KEY in .env}
FLUXER_S3_FORCE_PATH_STYLE : "true"
FLUXER_S3_BUCKET_CDN : fluxer
FLUXER_S3_BUCKET_UPLOADS : fluxer-uploads
FLUXER_S3_BUCKET_DOWNLOADS : fluxer-downloads
FLUXER_S3_BUCKET_REPORTS : fluxer-reports
FLUXER_S3_BUCKET_HARVESTS : fluxer-harvests
AWS_ACCESS_KEY_ID : ${FLUXER_S3_ACCESS_KEY:?}
AWS_SECRET_ACCESS_KEY : ${FLUXER_S3_SECRET_KEY:?}
AWS_DEFAULT_REGION : us-east-1
AWS_EC2_METADATA_DISABLED : "true"
FLUXER_LIVEKIT_ENABLED : "true"
FLUXER_LIVEKIT_API_KEY : ${LIVEKIT_API_KEY:?set LIVEKIT_API_KEY in .env}
FLUXER_LIVEKIT_API_SECRET : ${LIVEKIT_API_SECRET:?set LIVEKIT_API_SECRET in .env}
FLUXER_LIVEKIT_WEBHOOK_URL : http://api:8080/webhooks/livekit
2026-06-30 01:23:36 +02:00
FLUXER_LIVEKIT_DEFAULT_REGION : '{"id":"default","name":"Default","emoji":"🌍","latitude":0,"longitude":0}'
2026-06-16 06:41:37 +02:00
2026-06-30 01:19:57 +02:00
FLUXER_KLIPY_API_KEY : ${FLUXER_KLIPY_API_KEY:-}
2026-06-16 06:41:37 +02:00
FLUXER_EMAIL_ENABLED : ${FLUXER_EMAIL_ENABLED:-false}
FLUXER_EMAIL_PROVIDER : ${FLUXER_EMAIL_PROVIDER:-none}
FLUXER_EMAIL_FROM_EMAIL : ${FLUXER_EMAIL_FROM_EMAIL:-noreply@localhost}
FLUXER_EMAIL_FROM_NAME : ${FLUXER_EMAIL_FROM_NAME:-Fluxer}
FLUXER_EMAIL_SMTP_HOST : ${FLUXER_EMAIL_SMTP_HOST:-}
FLUXER_EMAIL_SMTP_PORT : ${FLUXER_EMAIL_SMTP_PORT:-587}
FLUXER_EMAIL_SMTP_USERNAME : ${FLUXER_EMAIL_SMTP_USERNAME:-}
FLUXER_EMAIL_SMTP_PASSWORD : ${FLUXER_EMAIL_SMTP_PASSWORD:-}
FLUXER_EMAIL_SMTP_SECURE : ${FLUXER_EMAIL_SMTP_SECURE:-true}
FLUXER_SMS_ENABLED : "false"
FLUXER_CAPTCHA_ENABLED : ${FLUXER_CAPTCHA_ENABLED:-false}
FLUXER_CAPTCHA_PROVIDER : ${FLUXER_CAPTCHA_PROVIDER:-none}
FLUXER_STRIPE_ENABLED : "false"
FLUXER_NCMEC_ENABLED : "false"
FLUXER_CLAMAV_ENABLED : "false"
FLUXER_DISCOVERY_ENABLED : ${FLUXER_DISCOVERY_ENABLED:-true}
FLUXER_SUDO_MODE_SECRET : ${FLUXER_SUDO_MODE_SECRET:?set FLUXER_SUDO_MODE_SECRET in .env}
FLUXER_CONNECTION_INITIATION_SECRET : ${FLUXER_CONNECTION_INITIATION_SECRET:?set FLUXER_CONNECTION_INITIATION_SECRET in .env}
FLUXER_VAPID_PUBLIC_KEY : ${FLUXER_VAPID_PUBLIC_KEY:?set FLUXER_VAPID_PUBLIC_KEY in .env}
FLUXER_VAPID_PRIVATE_KEY : ${FLUXER_VAPID_PRIVATE_KEY:?set FLUXER_VAPID_PRIVATE_KEY in .env}
FLUXER_VAPID_EMAIL : ${FLUXER_VAPID_EMAIL:-admin@${FLUXER_DOMAIN}}
FLUXER_GATEWAY_RPC_AUTH_TOKEN : ${FLUXER_GATEWAY_RPC_AUTH_TOKEN:?set FLUXER_GATEWAY_RPC_AUTH_TOKEN in .env}
FLUXER_MEDIA_PROXY_SECRET_KEY : ${FLUXER_MEDIA_PROXY_SECRET_KEY:?set FLUXER_MEDIA_PROXY_SECRET_KEY in .env}
FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64 : ${FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64:?set FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64 in .env}
FLUXER_ADMIN_SECRET_KEY_BASE : ${FLUXER_ADMIN_SECRET_KEY_BASE:?set FLUXER_ADMIN_SECRET_KEY_BASE in .env}
FLUXER_ADMIN_OAUTH_CLIENT_SECRET : ${FLUXER_ADMIN_OAUTH_CLIENT_SECRET:?set FLUXER_ADMIN_OAUTH_CLIENT_SECRET in .env}
FLUXER_INTERNAL_API_ENDPOINT : http://api:8080
FLUXER_INTERNAL_GATEWAY_ENDPOINT : http://gateway:8080
FLUXER_INTERNAL_MEDIA_PROXY_ENDPOINT : http://media-proxy:8080
FLUXER_MARKETING_ENDPOINT : ${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}
FLUXER_MEDIA_PROXY_ENDPOINT : http://media-proxy:8080
FLUXER_MEDIA_ENDPOINT : ${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}/media
FLUXER_MEDIA_PROXY_UPLOAD_RELAY_ENDPOINT : ${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}/media
x-fluxer-service : &fluxer-service
restart : unless-stopped
networks : [ fluxer]
services :
caddy :
image : caddy:2.10-alpine
restart : unless-stopped
networks : [ fluxer]
ports :
- "80:80"
- "443:443"
- "443:443/udp"
environment :
FLUXER_CADDY_SITE_ADDRESS : ${FLUXER_CADDY_SITE_ADDRESS:?set FLUXER_CADDY_SITE_ADDRESS in .env}
volumes :
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
- caddy-config:/config
depends_on : [ api, gateway, media-proxy, static-proxy, admin]
postgres :
image : postgres:16-alpine
restart : unless-stopped
networks : [ fluxer]
environment :
POSTGRES_DB : fluxer
POSTGRES_USER : fluxer
POSTGRES_PASSWORD : ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}
volumes :
- postgres-data:/var/lib/postgresql/data
healthcheck :
test : [ "CMD-SHELL" , "pg_isready -U fluxer -d fluxer" ]
interval : 10s
timeout : 5s
retries : 10
valkey :
image : valkey/valkey:8.1-alpine
restart : unless-stopped
networks : [ fluxer]
command : [ "valkey-server" , "--save" , "" , "--appendonly" , "no" ]
healthcheck :
test : [ "CMD" , "valkey-cli" , "ping" ]
interval : 10s
timeout : 5s
retries : 10
nats :
image : nats:2.14-alpine
restart : unless-stopped
networks : [ fluxer]
command : [ "-js" , "-sd" , "/data" , "-m" , "8222" ]
volumes :
- nats-data:/data
meilisearch :
image : getmeili/meilisearch:v1.12
restart : unless-stopped
networks : [ fluxer]
environment :
MEILI_ENV : production
MEILI_NO_ANALYTICS : "true"
MEILI_MASTER_KEY : ${MEILI_MASTER_KEY:?set MEILI_MASTER_KEY in .env}
volumes :
- meilisearch-data:/meili_data
seaweedfs :
image : chrislusf/seaweedfs:4.34
restart : unless-stopped
networks : [ fluxer]
command : [ "server" , "-s3" , "-dir=/data" ]
volumes :
- seaweedfs-data:/data
seaweedfs-init :
image : chrislusf/seaweedfs:4.34
networks : [ fluxer]
depends_on : [ seaweedfs]
restart : "no"
entrypoint :
- /bin/sh
- -c
- >
for i in $$(seq 1 60); do
echo "s3.bucket.create -name fluxer" | weed shell -master=seaweedfs:9333 >/dev/null 2>&1 && break || sleep 2;
done;
for b in fluxer fluxer-uploads fluxer-downloads fluxer-reports fluxer-harvests; do
echo "s3.bucket.create -name $$b" | weed shell -master=seaweedfs:9333 || true;
done;
echo "buckets ready";
livekit :
image : livekit/livekit-server:v1.12.0
restart : unless-stopped
networks : [ fluxer]
command : [ "--config" , "/etc/livekit.yaml" ]
environment :
LIVEKIT_KEYS : "${LIVEKIT_API_KEY:?set LIVEKIT_API_KEY in .env}: ${LIVEKIT_API_SECRET:?set LIVEKIT_API_SECRET in .env}"
volumes :
- ./livekit.yaml:/etc/livekit.yaml:ro
ports :
- "${FLUXER_LIVEKIT_TCP_PORT:-7881}:7881"
- "${FLUXER_LIVEKIT_UDP_PORT:-7882}:7882/udp"
api :
<< : *fluxer-service
image : ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-api:${FLUXER_IMAGE_TAG:-v1}
environment :
<< : *fluxer-env
FLUXER_API_PORT : "8080"
FLUXER_API_PRESIGNED_ATTACHMENT_UPLOADS_ENABLED : "true"
healthcheck :
test : [ "CMD-SHELL" , "node -e \"fetch('http://127.0.0.1:8080/_health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\"" ]
interval : 10s
timeout : 5s
retries : 30
start_period : 90s
depends_on :
postgres : {condition : service_healthy}
valkey : {condition : service_healthy}
nats : {condition : service_started}
meilisearch : {condition : service_started}
seaweedfs-init : {condition : service_completed_successfully}
2026-06-30 01:19:57 +02:00
gifs : {condition : service_started}
gifs-shard : {condition : service_started}
2026-06-16 06:41:37 +02:00
snowflakes : {condition : service_started}
snowflakes-shard : {condition : service_started}
messages : {condition : service_started}
messages-shard : {condition : service_started}
users : {condition : service_started}
users-shard : {condition : service_started}
worker :
<< : *fluxer-service
image : ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-api:${FLUXER_IMAGE_TAG:-v1}
working_dir : /usr/src/app/fluxer_api
command : [ "./node_modules/.bin/tsx" , "src/WorkerEntrypoint.ts" ]
environment :
<< : *fluxer-env
FLUXER_API_WORKER_MODE : all_lanes
FLUXER_API_WORKER_ENABLE_CRON_SCHEDULER : "true"
FLUXER_API_WORKER_ENABLE_VOICE_RECONCILIATION : "true"
depends_on :
postgres : {condition : service_healthy}
valkey : {condition : service_healthy}
nats : {condition : service_started}
seaweedfs-init : {condition : service_completed_successfully}
snowflakes-shard : {condition : service_started}
messages-shard : {condition : service_started}
users-shard : {condition : service_started}
gateway :
<< : *fluxer-service
image : ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-gateway:${FLUXER_IMAGE_TAG:-v1}
environment :
<< : *fluxer-env
FLUXER_GATEWAY_PORT : "8080"
FLUXER_GATEWAY_MEDIA_PROXY_ENDPOINT : ${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}/media
FLUXER_GATEWAY_STATIC_CDN_ENDPOINT : ${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}
FLUXER_GATEWAY_LOGGER_LEVEL : info
depends_on :
nats : {condition : service_started}
valkey : {condition : service_healthy}
media-proxy :
<< : *fluxer-service
image : ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-media-proxy:${FLUXER_IMAGE_TAG:-v1}
environment :
<< : *fluxer-env
FLUXER_MEDIA_PROXY_HOST : 0.0.0.0
FLUXER_MEDIA_PROXY_PORT : "8080"
FLUXER_MEDIA_PROXY_MODE : upload
FLUXER_MEDIA_PROXY_STORAGE_BACKEND : s3
healthcheck :
disable : true
depends_on :
seaweedfs-init : {condition : service_completed_successfully}
nats : {condition : service_started}
static-proxy :
<< : *fluxer-service
image : ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-static:${FLUXER_IMAGE_TAG:-v1}
app-proxy :
<< : *fluxer-service
image : ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-app-proxy-self-hosted:${FLUXER_IMAGE_TAG:-v1}
environment :
FLUXER_APP_PROXY_HOST : 0.0.0.0
FLUXER_APP_PROXY_PORT : "8080"
DISCOVERY_UPSTREAM_URL : http://caddy:8088/api/.well-known/fluxer
PUBLIC_BOOTSTRAP_API_ENDPOINT : /api
PUBLIC_BOOTSTRAP_API_PUBLIC_ENDPOINT : ${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}/api
depends_on :
api : {condition : service_healthy}
caddy : {condition : service_started}
snowflakes :
<< : *fluxer-service
image : ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-snowflakes:${FLUXER_IMAGE_TAG:-v1}
environment :
<< : *fluxer-env
FLUXER_SVC_MODE : router
depends_on :
nats : {condition : service_started}
snowflakes-shard :
<< : *fluxer-service
image : ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-snowflakes:${FLUXER_IMAGE_TAG:-v1}
environment :
<< : *fluxer-env
FLUXER_SVC_MODE : shard
FLUXER_SVC_SHARD_ID : "0"
depends_on :
nats : {condition : service_started}
users :
<< : *fluxer-service
image : ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-users:${FLUXER_IMAGE_TAG:-v1}
environment :
<< : *fluxer-env
FLUXER_SVC_MODE : router
depends_on :
nats : {condition : service_started}
users-shard :
<< : *fluxer-service
image : ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-users:${FLUXER_IMAGE_TAG:-v1}
environment :
<< : *fluxer-env
FLUXER_SVC_MODE : shard
FLUXER_SVC_SHARD_ID : "0"
depends_on :
nats : {condition : service_started}
2026-06-30 01:19:57 +02:00
gifs :
<< : *fluxer-service
image : ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-gifs:${FLUXER_IMAGE_TAG:-v1}
environment :
<< : *fluxer-env
FLUXER_SVC_NAME : gifs
FLUXER_SVC_MODE : router
FLUXER_MEDIA_PROXY_PUBLIC_ENDPOINT : ${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}/media
depends_on :
nats : {condition : service_started}
gifs-shard :
<< : *fluxer-service
image : ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-gifs:${FLUXER_IMAGE_TAG:-v1}
environment :
<< : *fluxer-env
FLUXER_SVC_NAME : gifs
FLUXER_SVC_MODE : shard
FLUXER_SVC_SHARD_ID : "0"
FLUXER_MEDIA_PROXY_PUBLIC_ENDPOINT : ${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}/media
depends_on :
nats : {condition : service_started}
2026-06-16 06:41:37 +02:00
messages :
<< : *fluxer-service
image : ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-messages:${FLUXER_IMAGE_TAG:-v1}
environment :
<< : *fluxer-env
FLUXER_SVC_MODE : router
depends_on :
nats : {condition : service_started}
messages-shard :
<< : *fluxer-service
image : ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-messages:${FLUXER_IMAGE_TAG:-v1}
environment :
<< : *fluxer-env
FLUXER_SVC_MODE : shard
FLUXER_SVC_SHARD_ID : "0"
depends_on :
nats : {condition : service_started}
postgres : {condition : service_healthy}
unfurl :
<< : *fluxer-service
image : ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-unfurl:${FLUXER_IMAGE_TAG:-v1}
environment :
<< : *fluxer-env
FLUXER_SVC_MODE : router
depends_on :
nats : {condition : service_started}
unfurl-shard :
<< : *fluxer-service
image : ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-unfurl:${FLUXER_IMAGE_TAG:-v1}
environment :
<< : *fluxer-env
FLUXER_SVC_MODE : shard
FLUXER_SVC_SHARD_ID : "0"
depends_on :
nats : {condition : service_started}
admin :
<< : *fluxer-service
image : ${FLUXER_REGISTRY:-ghcr.io/${FLUXER_REGISTRY_OWNER:-fluxerapp}}/fluxer-admin:${FLUXER_IMAGE_TAG:-v1}
environment :
<< : *fluxer-env
FLUXER_ADMIN_HOST : 0.0.0.0
FLUXER_ADMIN_PORT : "8080"
FLUXER_ADMIN_BASE_PATH : /admin
FLUXER_API_ENDPOINT : http://api:8080
FLUXER_ADMIN_ENDPOINT : ${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}/admin
FLUXER_APP_ENDPOINT : ${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}
FLUXER_MEDIA_ENDPOINT : ${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}/media
FLUXER_STATIC_CDN_ENDPOINT : ${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}
FLUXER_ADMIN_OAUTH_REDIRECT_URI : ${FLUXER_PUBLIC_SCHEME:-https}://${FLUXER_DOMAIN}/admin/oauth2_callback
depends_on :
api : {condition : service_healthy}
networks :
fluxer :
driver : bridge
volumes :
caddy-data :
caddy-config :
postgres-data :
nats-data :
meilisearch-data :
seaweedfs-data :