Det här sätter du upp
Fluxer är en chattapp i samma stil som Discord: man går med i communityn, som har textkanaler, röstkanaler och roller, och man kan också skicka direktmeddelanden till varandra. I röstkanalerna pratar man med ljud, video och skärmdelning. Fluxer körs i webbläsaren, och det finns appar för Windows, macOS, Linux, Android och iOS som kan ansluta till din egen server.
Fluxer görs av Fluxer Platform AB, ett självfinansierat bolag i Sverige som utvecklaren Hampus Kraft startade. Fluxer är öppen källkod under GNU AGPL v3, och bolaget skriver att det ska fortsätta vara gratis att köra Fluxer själv. Fluxer ger ut egna containeravbilder och dokumenterar hur du kör en egen instans. Den här guiden följer den uppsättningen, skriven som Quadlet-filer för Podman i stället för Docker Compose.
En Fluxer-instans består av många små program som arbetar tillsammans, 25 containrar sammanlagt, under en egen användare som heter fluxer, bakom Caddy från Podman-guiden:
- Fluxers egna tjänster: API:t, en bakgrundsprocess, gatewayen som alla appar håller kontakt med, en mediaproxy för uppladdningar och bilder, adminpanelen, webbappen och fem små interna tjänster, var och en med en router och en shard;
- PostgreSQL för datan, Valkey som cache, NATS för meddelanden mellan tjänsterna och Meilisearch för sökningen;
- Garage för uppladdade filer, S3-lagringen från Garage-guiden, här inuti Fluxer-uppsättningen i stället för Fluxers standardval SeaweedFS;
- LiveKit, mediaservern för röst och video;
- en liten Caddy, som kallas edge, som skickar varje anrop till rätt tjänst.
Varje steg nedan har körts på en nyinstallerad Melonslab VC-P Alloy (2 vCPU, 8 GB) med Debian 13:
- Webbplatsen var ute på nätet innan administratörskontot fanns, och en registrering utifrån nekades med "This instance is not set up yet". Administratörskontot skapades med installationstoken från Fluxers logg.
- Med registreringen stängd visade registreringssidan "Registration is currently closed". En andra person registrerade sig med en engångslänk från adminpanelen och gick med i communityn via en inbjudningslänk.
- En community skapades med en andra textkanal och rollen Moderator, som den andra personen fick. Meddelanden gick åt båda hållen, ett direktmeddelande kom fram, sökningen hittade ett ord, en bild visades med förhandsvisning, och filer på 3 MB och 150 MB laddades ner med samma kontrollsumma.
- Två webbläsare höll ett videosamtal i en röstkanal, över UDP och, med UDP blockerat, över TCP, med ljud och bild åt båda hållen.
- Adminpanelen visade varje persons riktiga IPv4-adress.
- Appen visades på svenska, både när det valdes och i en webbläsare inställd på svenska.
- Via en testserver för e-post på port 587 kom ett mejl för återställning av lösenord fram, på svenska, och länken i det satte ett nytt lösenord.
- En säkerhetskopia återställdes till en ny instans med alla konton, meddelanden och filer, Fluxer uppdaterades med
podman auto-update, och allt startade igen av sig självt efter en omstart av servern.
Fluxer använde omkring 850 MB minne i vila och omkring 1 GB med två personer i ett videosamtal. Avbilderna tar omkring 4 GB disk. Fluxers egen dokumentation vill ha 8 GB minne, som i paketet Alloy, och 16 GB för en liten, aktiv community.
Innan du börjar
Du behöver:
- en server uppsatt som i Podman-guiden, med Caddy igång, och med ufw som i säkerhetsguiden;
- en A-post och en AAAA-post för
chat.example.comsom pekar på din server; - för e-post, ett konto hos din e-postleverantör som kan skicka via SMTP (steg 12).
Exemplen använder chat.example.com för Fluxer och 203.0.113.10 för serverns IPv4-adress, som ip -brief address show eth0 visar. Byt ut dem genomgående.
1. Öppna portarna för samtal och skapa användaren
Som root höjer du gränsen för hur mycket inkommande UDP som Linux håller åt ett program. LiveKit tar emot samtal över UDP och varnar när den startar om gränsen är lägre:
echo "net.core.rmem_max = 5000000" > /etc/sysctl.d/60-livekit.conf
sysctl --system
Öppna de två portar som LiveKit använder för samtal:
ufw allow 7891/tcp
ufw allow 7892/udp
Ljud och bild går över UDP-port 7892. TCP-port 7891 används när ett nät blockerar UDP. Förutom HTTPS är det de enda portar Fluxer behöver. Fluxers egen uppsättning använder 7881 och 7882, samma som samtal i Matrix, så den här guiden flyttar upp dem tio steg för att båda ska kunna köras på samma server.
Skapa sedan användaren:
useradd -m -s /bin/bash fluxer
loginctl enable-linger fluxer
machinectl shell fluxer@
Allt fram till steg 6 körs som fluxer.
2. Skapa hemligheterna
Fluxer behöver en lång rad nycklar och lösenord, som tjänsterna använder för att lita på varandra och för att signera inloggningar. Skapa alla som slumpade värden. Podman lagrar dem, inte filerna nedan:
for s in db-password meili-key garage-rpc sudo-mode-secret connection-secret pseudonym-secret gateway-rpc-token erlang-cookie media-proxy-key admin-key-base admin-oauth-secret; do
openssl rand -hex 32 | tr -d '\n' | podman secret create $s -
done
openssl rand -base64 32 | tr -d '\n' | podman secret create upload-relay-secret -
secret=$(openssl rand -hex 32)
printf 'fluxer: %s' "$secret" | podman secret create livekit-keys -
printf %s "$secret" | podman secret create livekit-secret -
unset secret
LiveKit och Fluxer delar den sista: livekit-keys är nyckeln som LiveKit kontrollerar, med namnet fluxer, och livekit-secret samma hemlighet för Fluxer.
Aviseringar i webbläsaren behöver ett eget nyckelpar, som Fluxer kräver även om ingen slår på aviseringar:
openssl ecparam -name prime256v1 -genkey -noout -out vapid.pem
openssl ec -in vapid.pem -outform DER 2>/dev/null | tail -c +8 | head -c 32 | openssl base64 -A | tr '+/' '-_' | tr -d '=' | podman secret create vapid-private-key -
openssl ec -in vapid.pem -pubout -outform DER 2>/dev/null | tail -c 65 | openssl base64 -A | tr '+/' '-_' | tr -d '=' | podman secret create vapid-public-key -
rm vapid.pem
Den publika nyckeln är inte hemlig, men när den ligger bredvid den privata hör de alltid ihop, också i en säkerhetskopia.
3. Skriv konfigurationen
Skapa ~/fluxer.env, inställningarna som alla Fluxers tjänster delar:
FLUXER_ENV=production
FLUXER_SELF_HOSTED=true
FLUXER_BASE_DOMAIN=chat.example.com
FLUXER_PUBLIC_SCHEME=https
FLUXER_PUBLIC_PORT=443
FLUXER_TRUST_CLIENT_IP_HEADER=true
FLUXER_APP_ENDPOINT=https://chat.example.com
FLUXER_MARKETING_ENDPOINT=https://chat.example.com
FLUXER_ADMIN_ENDPOINT=https://chat.example.com/admin
FLUXER_MEDIA_ENDPOINT=https://chat.example.com/media
FLUXER_MEDIA_PROXY_PUBLIC_ENDPOINT=https://chat.example.com/media
FLUXER_MEDIA_PROXY_UPLOAD_RELAY_ENDPOINT=https://chat.example.com/media
FLUXER_LIVEKIT_URL=wss://chat.example.com/livekit
FLUXER_PASSKEY_RP_ID=chat.example.com
FLUXER_PASSKEY_ADDITIONAL_ALLOWED_ORIGINS=https://chat.example.com
FLUXER_VAPID_EMAIL=admin@chat.example.com
FLUXER_INTERNAL_API_ENDPOINT=http://api:8080
FLUXER_INTERNAL_MEDIA_PROXY_ENDPOINT=http://media-proxy:8080
FLUXER_MEDIA_PROXY_ENDPOINT=http://media-proxy:8080
FLUXER_DATABASE_BACKEND=postgres
FLUXER_POSTGRES_HOST=postgres
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_S3_ENDPOINT=http://garage:3900
FLUXER_S3_PUBLIC_ENDPOINT=http://garage:3900
FLUXER_S3_REGION=garage
FLUXER_S3_FORCE_PATH_STYLE=true
FLUXER_S3_BUCKET_CDN=fluxer
FLUXER_S3_BUCKET_UPLOADS=fluxer-uploads
FLUXER_S3_BUCKET_REPORTS=fluxer-reports
FLUXER_S3_BUCKET_HARVESTS=fluxer-harvests
FLUXER_API_PRESIGNED_ATTACHMENT_UPLOADS_ENABLED=true
FLUXER_API_PRESIGNED_HARVEST_DOWNLOADS_ENABLED=false
FLUXER_LIVEKIT_ENABLED=true
FLUXER_LIVEKIT_API_KEY=fluxer
FLUXER_LIVEKIT_INTERNAL_URL=http://livekit:7880
FLUXER_LIVEKIT_DEFAULT_REGION={"id":"default","name":"Default","emoji":"🌍","latitude":0,"longitude":0}
FLUXER_ACCOUNT_IDENTITY=email
FLUXER_GIFS_SHARD_CACHE_MAX_BYTES=134217728
Skapa ~/garage.toml, konfigurationen för fillagringen:
metadata_dir = "/var/lib/garage/meta"
data_dir = "/var/lib/garage/data"
db_engine = "sqlite"
metadata_fsync = true
replication_factor = 1
rpc_bind_addr = "127.0.0.1:3901"
rpc_public_addr = "127.0.0.1:3901"
[s3_api]
s3_region = "garage"
api_bind_addr = "[::]:3900"
Skapa ~/livekit.yaml, med serverns IPv4-adress:
port: 7880
rtc:
tcp_port: 7891
udp_port: 7892
use_external_ip: false
node_ip: 203.0.113.10
webhook:
api_key: fluxer
urls:
- http://api:8080/webhooks/livekit
Och ~/Caddyfile.edge, vägarna i edge, samma som i Fluxers egen uppsättning:
{
admin off
servers {
trusted_proxies static private_ranges
trusted_proxies_strict
}
}
:8080 {
encode zstd gzip
handle /_health {
respond "OK" 200
}
handle_path /api/* {
reverse_proxy api:8080
}
handle /gateway {
rewrite * /
reverse_proxy gateway:8080
}
handle_path /gateway/* {
reverse_proxy gateway:8080
}
handle_path /media/* {
reverse_proxy media-proxy:8080
}
handle_path /livekit/* {
reverse_proxy livekit:7880
}
handle /admin {
rewrite * /
reverse_proxy admin:8080
}
handle_path /admin/* {
reverse_proxy admin:8080
}
@static path /web/* /emoji/* /libs/* /avatars/* /badges/* /desktop/*
handle @static {
reverse_proxy static-proxy:8080
}
handle /.well-known/fluxer {
reverse_proxy api:8080
}
handle {
reverse_proxy app-proxy:8080
}
}
:8088 {
handle /.well-known/fluxer {
reverse_proxy api:8080
}
}
Vad inställningarna gör:
- Fluxer bygger varje adress som apparna får från
FLUXER_BASE_DOMAIN, schemat och porten, och raderna medhttps://chat.example.comskriver ut dem. De måste vara den publikahttps://-adressen, även om Caddy pratar med Fluxer över vanlig HTTP. FLUXER_TRUST_CLIENT_IP_HEADER=truelåter Fluxer läsa varje besökares adress från den header som edge sätter. Edge litar bara på den headern från privata adresser, som Caddys anslutning genom Podman.- Namnen som
postgres,garageochapiär containrarna i nästa steg, som når varandra med namn på ett eget nätverk. FLUXER_S3_REGIONmåste stämma meds3_regionigarage.toml, annars nekar Garage anropen. Uppladdningar går genom Fluxers mediaproxy, så webbläsare pratar aldrig med Garage.FLUXER_ACCOUNT_IDENTITY=emailgör att man loggar in med sin e-postadress, så att Fluxer kan skicka mejl för att återställa lösenord när e-posten fungerar (steg 12). Alternativet,username, behöver ingen e-post alls och ger i stället var och en en återställningsnyckel. Valet låses när det första kontot skapas.- I
livekit.yamlärnode_ipadressen som LiveKit ger apparna för samtal. Fluxers egen uppsättning frågar i stället en STUN-server hos Google efter den; när den står här behövs inte den uppslagningen. FLUXER_GIFS_SHARD_CACHE_MAX_BYTESkommer från Fluxers inställningar för en server med 8 GB.
4. Definiera containrarna
Podman startar varje container som en tjänst från en Quadlet-fil, som i Podman-guiden. Skapa katalogerna:
mkdir -p ~/.config/systemd/user ~/.config/containers/systemd/container.d ~/.config/containers/systemd/fluxer-.container.d
cd ~/.config/containers/systemd
Ett target samlar containrarna, så att ett enda kommando startar eller stoppar hela Fluxer. Skapa ~/.config/systemd/user/fluxer.target:
[Unit]
Description=Fluxer
[Install]
WantedBy=default.target
Sedan nätverket som containrarna delar. Skapa fluxer.network:
[Network]
NetworkName=fluxer
Inställningar i en .d-katalog läggs till i flera filer på en gång. De i container.d gäller varje container för den här användaren, som bara kör Fluxer. Skapa container.d/10-all.conf:
[Unit]
PartOf=fluxer.target
[Container]
Network=fluxer.network
AutoUpdate=registry
[Service]
Restart=always
TimeoutStartSec=900
[Install]
WantedBy=fluxer.target
De i fluxer-.container.d gäller varje fil vars namn börjar med fluxer-, alltså Fluxers egna tjänster. Alla får de gemensamma inställningarna och hemligheterna. Skapa fluxer-.container.d/20-fluxer.conf:
[Unit]
Wants=postgres.service valkey.service nats.service meilisearch.service garage.service livekit.service
After=postgres.service valkey.service nats.service meilisearch.service garage.service livekit.service
[Container]
EnvironmentFile=%h/fluxer.env
Secret=db-password,type=env,target=FLUXER_POSTGRES_PASSWORD
Secret=meili-key,type=env,target=FLUXER_SEARCH_API_KEY
Secret=s3-key-id,type=env,target=FLUXER_S3_ACCESS_KEY_ID
Secret=s3-secret-key,type=env,target=FLUXER_S3_SECRET_ACCESS_KEY
Secret=livekit-secret,type=env,target=FLUXER_LIVEKIT_API_SECRET
Secret=sudo-mode-secret,type=env,target=FLUXER_SUDO_MODE_SECRET
Secret=connection-secret,type=env,target=FLUXER_CONNECTION_INITIATION_SECRET
Secret=pseudonym-secret,type=env,target=FLUXER_PROFILE_PSEUDONYM_SECRET
Secret=gateway-rpc-token,type=env,target=FLUXER_GATEWAY_RPC_AUTH_TOKEN
Secret=erlang-cookie,type=env,target=FLUXER_ERLANG_COOKIE
Secret=media-proxy-key,type=env,target=FLUXER_MEDIA_PROXY_SECRET_KEY
Secret=upload-relay-secret,type=env,target=FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64
Secret=admin-key-base,type=env,target=FLUXER_ADMIN_SECRET_KEY_BASE
Secret=admin-oauth-secret,type=env,target=FLUXER_ADMIN_OAUTH_CLIENT_SECRET
Secret=vapid-private-key,type=env,target=FLUXER_VAPID_PRIVATE_KEY
Secret=vapid-public-key,type=env,target=FLUXER_VAPID_PUBLIC_KEY
Nu tjänsterna som Fluxer lagrar sin data i. Skapa postgres.container:
[Container]
ContainerName=postgres
Image=docker.io/library/postgres:16-alpine
Exec=postgres -c max_connections=150 -c shared_buffers=384MB -c effective_cache_size=1536MB -c jit=off -c shared_preload_libraries=pg_stat_statements
ShmSize=1g
PodmanArgs=--memory=2560m
Volume=fluxer-postgres:/var/lib/postgresql/data
Environment=POSTGRES_DB=fluxer POSTGRES_USER=fluxer
Secret=db-password,type=env,target=POSTGRES_PASSWORD
HealthCmd=pg_isready -U fluxer -d fluxer
HealthInterval=10s
Notify=healthy
valkey.container:
[Container]
ContainerName=valkey
Image=docker.io/valkey/valkey:9.1-alpine
Exec=valkey-server --appendonly yes --appendfsync everysec --dir /data --maxmemory 192mb --maxmemory-policy noeviction
Volume=fluxer-valkey:/data
HealthCmd=valkey-cli ping
HealthInterval=10s
Notify=healthy
nats.container:
[Container]
ContainerName=nats
Image=docker.io/library/nats:2.14-alpine
Exec=-js -sd /data -m 8222
Volume=fluxer-nats:/data
HealthCmd=wget -q -O /dev/null http://127.0.0.1:8222/healthz
HealthInterval=10s
Notify=healthy
meilisearch.container:
[Container]
ContainerName=meilisearch
Image=docker.io/getmeili/meilisearch:v1.53
PodmanArgs=--memory=1g
Volume=fluxer-meilisearch:/meili_data
Environment=MEILI_ENV=production MEILI_NO_ANALYTICS=true MEILI_MAX_INDEXING_MEMORY=192mb MEILI_MAX_INDEXING_THREADS=2
Secret=meili-key,type=env,target=MEILI_MASTER_KEY
HealthCmd=wget -q -O /dev/null http://127.0.0.1:7700/health
HealthInterval=10s
Notify=healthy
garage.container:
[Container]
ContainerName=garage
Image=docker.io/dxflrs/garage:v2.4.1
Exec=/garage server --single-node
Volume=%h/garage.toml:/etc/garage.toml:ro
Volume=fluxer-s3-meta:/var/lib/garage/meta
Volume=fluxer-s3-data:/var/lib/garage/data
Secret=garage-rpc,type=env,target=GARAGE_RPC_SECRET
StopTimeout=30
Och livekit.container, den enda förutom edge som har portar på servern:
[Container]
ContainerName=livekit
Image=docker.io/livekit/livekit-server:v1.12.0
PublishPort=7891:7891/tcp
PublishPort=7892:7892/udp
PodmanArgs=--memory=512m
Volume=%h/livekit.yaml:/etc/livekit.yaml:ro
Exec=--config /etc/livekit.yaml
Secret=livekit-keys,type=env,target=LIVEKIT_KEYS
Det är samma versioner som Fluxers egen uppsättning använder. Podman uppdaterar PostgreSQL, Valkey, NATS och Meilisearch inom de versionerna (steg 15). Garage och LiveKit har sin version utskriven.
Därefter Fluxers fem interna tjänster. Var och en körs två gånger, som router och som shard, från samma avbild, så två mallfiler räcker för alla tio. %i i dem byts ut mot tjänstens namn. Skapa fluxer-svc@.container:
[Unit]
Description=Fluxer %i service, router
[Container]
ContainerName=%i
Image=ghcr.io/fluxerapp/fluxer-%i:v1
Environment=FLUXER_SVC_NAME=%i FLUXER_SVC_MODE=router
Och fluxer-shard@.container:
[Unit]
Description=Fluxer %i service, shard
[Container]
ContainerName=%i-shard
Image=ghcr.io/fluxerapp/fluxer-%i:v1
Environment=FLUXER_SVC_NAME=%i FLUXER_SVC_MODE=shard FLUXER_SVC_SHARD_ID=0
En länk med tjänstens namn i gör en mall till en tjänst:
for s in snowflakes users messages gifs unfurl; do
ln -s fluxer-svc@.container fluxer-svc@$s.container
ln -s fluxer-shard@.container fluxer-shard@$s.container
done
Nu huvudtjänsterna. Skapa fluxer-api.container:
[Unit]
Description=Fluxer API
Wants=fluxer-svc@snowflakes.service fluxer-shard@snowflakes.service fluxer-svc@users.service fluxer-shard@users.service fluxer-svc@messages.service fluxer-shard@messages.service fluxer-svc@gifs.service fluxer-shard@gifs.service
After=fluxer-svc@snowflakes.service fluxer-shard@snowflakes.service fluxer-svc@users.service fluxer-shard@users.service fluxer-svc@messages.service fluxer-shard@messages.service fluxer-svc@gifs.service fluxer-shard@gifs.service
[Container]
ContainerName=api
Image=ghcr.io/fluxerapp/fluxer-api:v1
PodmanArgs=--memory=1280m
Environment=FLUXER_API_PORT=8080 FLUXER_POSTGRES_MAX_CONNECTIONS=25
HealthCmd=["node", "-e", "fetch('http://127.0.0.1:8080/_health').then(r => process.exit(r.ok ? 0 : 1), () => process.exit(1))"]
HealthInterval=10s
HealthStartPeriod=90s
Notify=healthy
fluxer-worker.container, bakgrundsjobben:
[Unit]
Description=Fluxer background worker
Wants=fluxer-svc@snowflakes.service fluxer-shard@snowflakes.service fluxer-svc@users.service fluxer-shard@users.service fluxer-svc@messages.service fluxer-shard@messages.service
After=fluxer-svc@snowflakes.service fluxer-shard@snowflakes.service fluxer-svc@users.service fluxer-shard@users.service fluxer-svc@messages.service fluxer-shard@messages.service
[Container]
ContainerName=worker
Image=ghcr.io/fluxerapp/fluxer-api:v1
Exec=node dist/WorkerEntrypoint.js
PodmanArgs=--memory=1280m
Environment=FLUXER_API_WORKER_MODE=all_lanes FLUXER_API_WORKER_ENABLE_CRON_SCHEDULER=true FLUXER_POSTGRES_MAX_CONNECTIONS=25
fluxer-gateway.container, som varje app håller en anslutning till:
[Container]
ContainerName=gateway
Image=ghcr.io/fluxerapp/fluxer-gateway:v1
PodmanArgs=--memory=512m
Environment=FLUXER_GATEWAY_PORT=8080
fluxer-media-proxy.container, för uppladdningar, bilder och filer:
[Container]
ContainerName=media-proxy
Image=ghcr.io/fluxerapp/fluxer-media-proxy:v1
PodmanArgs=--memory=512m
Environment=FLUXER_MEDIA_PROXY_PORT=8080 FLUXER_MEDIA_PROXY_MODE=upload FLUXER_MEDIA_PROXY_STORAGE_BACKEND=s3
Environment=FLUXER_MEDIA_PROXY_CORS_ALLOWED_ORIGINS=https://chat.example.com
fluxer-push.container, för aviseringar:
[Unit]
Wants=fluxer-api.service
After=fluxer-api.service
[Container]
ContainerName=push
Image=ghcr.io/fluxerapp/fluxer-push:v1
fluxer-admin.container, adminpanelen:
[Unit]
Wants=fluxer-api.service
After=fluxer-api.service
[Container]
ContainerName=admin
Image=ghcr.io/fluxerapp/fluxer-admin:v1
Environment=FLUXER_ADMIN_PORT=8080 FLUXER_ADMIN_BASE_PATH=/admin FLUXER_API_ENDPOINT=http://api:8080
Environment=FLUXER_STATIC_CDN_ENDPOINT=https://chat.example.com
Sist de tre som serverar webbappen och skickar vidare anropen. Deras namn börjar inte med fluxer-, eftersom de inte behöver några av de gemensamma inställningarna. Skapa app-proxy.container:
[Unit]
Wants=fluxer-api.service
After=fluxer-api.service
[Container]
ContainerName=app-proxy
Image=ghcr.io/fluxerapp/fluxer-app-proxy-self-hosted:v1
Environment=FLUXER_APP_PROXY_PORT=8080 DISCOVERY_UPSTREAM_URL=http://edge:8088/.well-known/fluxer
static-proxy.container:
[Container]
ContainerName=static-proxy
Image=ghcr.io/fluxerapp/fluxer-static:v1
Och edge.container:
[Container]
ContainerName=edge
Image=docker.io/library/caddy:2.11-alpine
# Only Caddy, on this server, can reach Fluxer: the port is not open to the internet.
PublishPort=127.0.0.1:8125:8080
Volume=%h/Caddyfile.edge:/etc/caddy/Caddyfile:ro
Minnesgränserna är de som Fluxer rekommenderar för en server med 8 GB. De är tak, inte reserveringar, och hindrar en upptagen tjänst från att ta minnet från de andra. v1 är taggen som följer varje kompatibel version av Fluxer.
5. Skapa lagringen och starta Fluxer
Starta Garage för sig och ge dess kommando ett kort namn:
systemctl --user daemon-reload
systemctl --user start garage
echo "alias garage='podman exec -e RUST_LOG=warn garage /garage'" >> ~/.bashrc
source ~/.bashrc
garage status
garage status visar en frisk nod. Står det "Connection refused" håller Garage fortfarande på att starta: vänta några sekunder och kör det igen. Skapa de fyra buckets som Fluxer använder och en nyckel för Fluxer med åtkomst till dem, och spara nyckeln som två hemligheter till:
garage key create fluxer
for b in fluxer fluxer-uploads fluxer-reports fluxer-harvests; do
garage bucket create $b
garage bucket allow --read --write --owner $b --key fluxer
done
garage key info fluxer --show-secret | awk '/^Key ID/ {printf "%s", $3}' | podman secret create s3-key-id -
garage key info fluxer --show-secret | awk '/^Secret key/ {printf "%s", $3}' | podman secret create s3-secret-key -
Starta allt:
systemctl --user enable --now fluxer.target
systemctl --user enable --now podman-auto-update.timer
Första starten laddar ner omkring 4 GB avbilder och tar några minuter. enable gör att Fluxer startar vid varje uppstart. Fluxer är klar när det här skriver ut 200 för varje adress:
for p in /_health /api/_health /gateway/_health /media/_health /.well-known/fluxer /; do
printf '%s %s\n' "$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8125$p)" "$p"
done
podman ps listar 25 containrar. Ta sedan fram installationstoken, som du behöver i steg 7:
journalctl --user -u fluxer-api | grep -o '"setup_token":"[^"]*"' | tail -1
6. Sätt Caddy framför
Gå tillbaka till root med exit, byt till Caddys användare med machinectl shell caddy@ och lägg till det här blocket sist i ~/Caddyfile:
chat.example.com {
reverse_proxy 127.0.0.1:8125
}
Starta om Caddy med systemctl --user restart caddy.
7. Skapa administratörskontot
Öppna https://chat.example.com. En ny instans visar sin installation, och ingen kan skapa ett konto utan installationstoken från steg 5: i vårt test nekades en registrering utifrån med "This instance is not set up yet. Finish setup in a web browser with the setup token before creating accounts." Därför kan webbplatsen vara ute på nätet innan administratörskontot finns. En SSH-tunnel till servern hjälper inte här, eftersom webbappen alltid pratar med https://chat.example.com.
Gå igenom installationen:
- Välj språk och Next, och klistra sedan in installationstoken.
- Välj ett tema. Under Choose how people sign in är Email och No tags redan valda, från
fluxer.env. - Skapa administratörskontot med din e-postadress, ett användarnamn och ett lösenord. Det första kontot blir administratör.
- Under Make the instance yours ger du instansen ett Product name, som appen och mejlen visar i stället för Fluxer.
- Under Who can join väljer du Closed. Steg 8 släpper in folk via inbjudan.
- Låt Single community mode och Disable direct messages and friend requests vara avstängda, om du inte bara vill ha en enda community, vilket bara går att välja nu.
- Låt Enable attachment expiration vara avstängt, så att filer finns kvar tills någon tar bort dem. Stegen för GIF-sökning, YouTube, e-post, Bluesky och mobilaviseringar kan vänta. Godkänn inte informationen om push relay än; steg 13 förklarar den.
- Under Choose the premium model ger Everyone is premium alla de högsta gränserna, som filer på upp till 500 MB enligt Fluxers dokumentation; vi laddade upp 150 MB. Fluxer säljer inget premium på din instans om du inte sätter upp Stripe.
- Kontrollera sammanfattningen och välj Finish setup.
Adminpanelen finns på https://chat.example.com/admin. Du loggar in i den med ditt Fluxer-konto, och där finns användare, communityn, anmälningar, avstängningar och alla instansens inställningar.
8. Bjud in folk
Med registreringen stängd visar https://chat.example.com/register "Registration is currently closed. Use a registration link from an admin to create an account."
För att släppa in någon öppnar du adminpanelen, Instance Config, och under Create Admin-Issued Registration URL ger du länken en Label, till exempel personens namn, Expires in days och Max uses, till exempel 7 och 1, och väljer Create Registration URL. Länken, https://chat.example.com/register?registration_url=..., visas under Existing Registration URLs. Skicka den till personen; den låter dem skapa ett konto, och Revoke stoppar den. Kryssa i Approval required för att godkänna varje konto innan det kan användas.
Vill du hellre öppna registreringen ändrar du Registration Policy på samma sida till Open, eller till Approval required, där varje registrering väntar under Pending Registrations.
9. Communityn, kanaler och roller
En community är det som Discord kallar en server: en plats med egna kanaler, medlemmar och roller.
- Välj + (Create or join a community) till vänster, Create community, ge den ett namn och välj Create community. Den börjar med en textkanal,
#general, och en röstkanal, General. - Öppna menyn under communityns namn. Create channel lägger till en text-, röst-, nyhets-, forum- eller mediakanal, och Private channel begränsar den till de medlemmar och roller du väljer.
- Invite members i samma meny ger en inbjudningslänk, giltig i sju dagar, för dem som redan har ett konto.
- Community settings > Roles > Create role lägger till en roll, till exempel
Moderator, med sina behörigheter. Save changes sparar den. För att ge någon rollen markerar du personen i medlemslistan och väljer Add role.
Meddelanden kommer fram direkt till alla i kanalen. + bredvid meddelanderutan har Upload file, och bilder visas med förhandsvisning. För att skicka ett direktmeddelande markerar du en person och väljer Message. Sökrutan högst upp söker i communityns meddelanden.
Uppladdade filer kan nås av den som har filens exakta adress, utan att logga in, ungefär som på Discord. Tänk på det innan du delar lösenord eller kunddata som filer.
10. Röst och video
Markera en röstkanal för att gå med i den. Fältet längst ner har mikrofonen, Turn on camera och Share your screen, och Disconnect lämnar kanalen. Alla i kanalen hör och ser varandra, genom LiveKit på din server.
I vårt test ringde två webbläsare varandra med ljud och bild över UDP-port 7892, och över TCP-port 7891 när UDP var blockerat, utan förlorade paket. Kommer ett samtal inte igång, se Felsökning.
Desktop- och mobilapparna fungerar också: när de frågar efter en instans skriver du chat.example.com. Vi testade bara webbappen.
11. Använd Fluxer på svenska
Fluxer är översatt till svenska och visar svenska för alla vars webbläsare är inställd på det. För att välja det själv öppnar du inställningarna med kugghjulet bredvid ditt namn, sedan Language > Interface language, och väljer Svenska. Mejl från Fluxer, som återställning av lösenord, följer varje persons språk.
12. E-post
Fluxer skickar e-post för att bekräfta nya adresser och för att återställa lösenord. Utan e-post:
- har inloggningssidan ingen länk Forgot your password?, och Send Password Reset för en användare i adminpanelen skickar också ett mejl, så ingen kan återställa ett glömt lösenord;
- godkänns adresser utan bekräftelse.
Tänker du inte sätta upp e-post väljer du FLUXER_ACCOUNT_IDENTITY=username i steg 3, innan det första kontot finns: då loggar man in med ett användarnamn och får en återställningsnyckel för ett glömt lösenord, och en administratör kan skapa en länk för att återställa det. Det har vi inte testat.
Som fluxer sparar du SMTP-lösenordet för ditt e-postkonto som en hemlighet:
printf %s 'the-smtp-password' | podman secret create smtp-password -
Lägg till de här raderna i ~/fluxer.env, med din egen server, ditt konto och din avsändaradress:
FLUXER_EMAIL_ENABLED=true
FLUXER_EMAIL_PROVIDER=smtp
FLUXER_EMAIL_FROM_EMAIL=chat@example.com
FLUXER_EMAIL_SMTP_HOST=mail.example.com
FLUXER_EMAIL_SMTP_PORT=587
FLUXER_EMAIL_SMTP_USERNAME=chat@example.com
FLUXER_EMAIL_SMTP_TLS_MODE=starttls
Och den här raden under [Container] i både fluxer-api.container och fluxer-worker.container, de två tjänster som skickar e-post:
Secret=smtp-password,type=env,target=FLUXER_EMAIL_SMTP_PASSWORD
Starta om dem:
systemctl --user daemon-reload
systemctl --user restart fluxer-api fluxer-worker
Port 587 med starttls krypterar anslutningen före inloggningen; för port 465 använder du implicit. När e-posten är på visas Forgot your password? vid inloggningen. I vårt test kom mejlet för återställning fram på personens språk, och länken i det satte ett nytt lösenord och loggade ut personens andra sessioner. Vi skickade det till en testserver för e-post på själva servern, utan kryptering, så inställningarna för leverantören ovan är inte testade.
13. Externa tjänster
Vi avlyssnade serverns DNS-uppslagningar och utgående anslutningar medan Fluxer startade, medan två personer skrev, laddade upp filer och höll ett videosamtal, och medan den stod oanvänd i 25 minuter. Fluxer skickade inga användningsdata och letade inte efter uppdateringar. Det här såg vi:
- När någon skriver en länk hämtar servern sidan för att visa en förhandsvisning, så den länkade webbplatsen ser din servers adress. I vår avlyssning gav en länk till
www.debian.orgen uppslagning och en anslutning dit. - Medan Fluxer startade om slogs namnen på dess egna containrar, som
nats, upp hos serverns DNS-server i några sekunder, tills containrarna var tillbaka.
Andra tjänster är avstängda tills du slår på dem:
- Mobilaviseringar: de officiella apparna för Android och iOS får aviseringar bara via Fluxers push relay, som Fluxer driver och som lämnar dem vidare till Apple och Google. Den används först när du har godkänt dess integritetsinformation, i installationen eller i adminpanelen. Utan den får mobilapparna inga aviseringar när de är stängda. Webbläsare använder sin egen push-tjänst, som Googles för Chrome, när någon slår på aviseringar.
- GIF-sökning kräver en nyckel från Klipy, och förhandsvisning av YouTube en nyckel till YouTube Data API, båda i adminpanelen.
- Fluxer kan kontrollera lösenord mot listan Have I Been Pwned och blockera länkar och filer från offentliga blocklistor. Båda är avstängda på en egen instans.
Fluxers egen uppsättning låter LiveKit fråga Googles STUN-servrar efter serverns adress när den startar; node_ip i livekit.yaml ersätter det. Avbilderna kommer från GitHubs register, ghcr.io, och Docker Hub, som Podman kontaktar för att uppdatera dem.
14. Säkerhetskopiera
Som fluxer:
umask 077
mkdir -p ~/backup/secrets
podman exec postgres pg_dump -U fluxer -d fluxer --format=custom > ~/backup/fluxer.dump
for s in $(podman secret ls --format '{{.Name}}'); do
printf %s "$(podman secret inspect --showsecret --format '{{.SecretData}}' $s)" > ~/backup/secrets/$s
done
systemctl --user stop fluxer.target
until [ -z "$(podman ps -aq)" ]; do sleep 1; done
for v in fluxer-s3-meta fluxer-s3-data fluxer-valkey fluxer-nats fluxer-meilisearch; do
podman volume export $v > ~/backup/$v.tar
done
systemctl --user start fluxer.target
tar -cf ~/backup/config.tar fluxer.env garage.toml livekit.yaml Caddyfile.edge .config/containers/systemd .config/systemd/user/fluxer.target
Det sparar det som Fluxers egna råd om säkerhetskopiering kräver, och lite till:
fluxer.dumpinnehåller alla konton, communityn, meddelanden och inställningar. Dumpen körs medan Fluxer fortsätter att fungera.systemctl --user stop fluxer.targetkommer tillbaka innan alla containrar har stannat, så raden meduntilväntar på dem.- Garage-volymerna innehåller uppladdade filer, profilbilder och bilder. Valkey och NATS innehåller köat arbete, som filer som väntar på att tas bort, och Meilisearch sökindexet, som tar lång tid att bygga om. De kopieras medan Fluxer är stoppad, i ungefär en minut.
secretsinnehåller alla nycklar från steg 2, i klartext: utan dem kan Fluxer inte använda den återställda datan.config.tarinnehåller filerna från steg 3 och 4.
Kopiera ~/backup till en annan maskin, till exempel med restic, och förvara den säkert.
För att återställa, som fluxer, med säkerhetskopian i ~/backup. På en ny server gör du först steg 1, sedan tar -xf ~/backup/config.tar -C ~ i stället för steg 2 till 4, och ändrar node_ip i livekit.yaml om servern har en ny adress. Sedan:
systemctl --user stop fluxer.target
until [ -z "$(podman ps -aq)" ]; do sleep 1; done
podman volume rm fluxer-postgres fluxer-s3-meta fluxer-s3-data fluxer-valkey fluxer-nats fluxer-meilisearch
for f in ~/backup/secrets/*; do podman secret rm $(basename $f) 2>/dev/null; podman secret create $(basename $f) $f; done
for v in fluxer-s3-meta fluxer-s3-data fluxer-valkey fluxer-nats fluxer-meilisearch; do
podman volume create $v
podman volume import $v ~/backup/$v.tar
done
systemctl --user daemon-reload
systemctl --user start postgres
podman exec -i postgres pg_restore -U fluxer -d fluxer --no-owner < ~/backup/fluxer.dump
systemctl --user enable --now fluxer.target
På en befintlig server tar podman volume rm bort instansens nuvarande data, så ta en säkerhetskopia först. På en ny server klagar de första raderna på volymer och ett target som inte finns än, och det gör inget. När PostgreSQL startar för sig får den en tom databas, som dumpen fyller innan Fluxer startar. På en ny server avslutar du med steg 6, systemctl --user enable --now podman-auto-update.timer och raden med alias från steg 5.
I vårt test återställdes säkerhetskopian av en instans till en nyinstallerad, och alla konton, communityn, roller, meddelanden, direktmeddelanden, filer och sökträffar kom tillbaka. En andra säkerhetskopia återställdes som på en ny server, under en nyskapad användare fluxer, och man kunde logga in och läsa och ladda ner allt igen.
15. Uppdatera
podman auto-update letar en gång om dagen efter nya avbilder för varje container och startar om dem som har ändrats. Fluxer ger ut nya avbilder flera gånger om dagen under v1, och uppdaterar sin databas själv när den startar. För att uppdatera direkt:
podman auto-update
Läs versionsinformationen på Fluxers GitHub-sida och ta en säkerhetskopia före större uppdateringar. Vill du stanna på en version byter du v1 mot en versionstagg, till exempel 2026.1014.3120 för API:t, och byter tagg när du vill uppdatera; varje avbild från Fluxer har sina egna versionsnummer. Fluxers uppsättning flyttar PostgreSQL till en ny huvudversion bara för hand, med dump och återställning, som dess dokumentation beskriver.
Felsökning
En tjänst startar inte. systemctl --user status fluxer-api och journalctl --user -u fluxer-api visar varför, och likadant för alla andra containrar. podman ps -a listar alla.
Installationen frågar efter en token som du inte har kvar. Ta fram den igen med raden med journalctl från steg 5. Fluxer loggar den en gång, vid första starten.
Ett samtal kopplas upp, men ingen hör eller ser någon. Portarna 7891 och 7892 går inte att nå. Kontrollera reglerna från steg 1 med ufw status, och att node_ip i livekit.yaml är serverns IPv4-adress. podman logs livekit visar samtalen.
Uppladdningar misslyckas. podman logs media-proxy visar felet. Nekar Garage nyckeln jämför du garage key info fluxer med podman secret inspect --showsecret s3-key-id. FLUXER_S3_REGION måste vara garage.